수업 복습

Spring XML 기반 AOP 실습 정리

_김영인 2026. 1. 23. 18:35

 

1. 실습 구조: “코드 확인 → 설정으로 결합” 흐름

 

이번 실습은 콘솔 기반이다.

  • BoardClient가 applicationContext.xml을 읽어서 스프링 컨테이너를 올리고
  • 컨테이너에서 bs (BoardServiceImpl) 빈을 꺼내 호출한다.
  • 호출 시점에 AOP 설정이 붙어 있으면 공통 로직이 자동으로 끼워진다.

AOP 검증은 콘솔 실행 로그로 바로 확인할 수 있다.


 

2. 사전 준비: AOP는 “설정으로” 적용되기 때문에 준비물이 있다

 

AOP를 쓰려면 “공통 로직을 끼워 넣는 기반”이 필요하다.

  • pom.xml에 AOP (AspectJ) 관련 의존성 추가 (수업에서 진행)
  • applicationContext.xml에서 aop 네임스페이스 사용

핵심은 코드에서 직접 호출하지 않고 설정으로만 연결이라는 점이다.


 

3. Step 1) Advice (공통 로직) 클래스 만들기

 

공통 로직은 로그를 예제로 한다.

 

(1) Before용 기본 로그 (LogAdvice)

package com.example.biz.common;

public class LogAdvice {
    public void printLog() {
        System.out.println("작은티모님의 로그");
    }
}

 

(2) AfterThrowing용 예외 로그 (AfterThrowingAdvice)

 
package com.example.biz.common;

public class AfterThrowingAdvice {
    public void printLog() {
        System.out.println("예외발생시 출력되는 로그");
    }
}

 

(3) Around용 전 / 후 감싸기 (AroundAdvice)

 

Around는 구조가 조금 특별하다.

핵심은 ProceedingJoinPoint와 proceed()이다.

  • proceed()가 호출되는 순간에 “핵심 메서드”가 실제 실행된다.
  • Around는 전 / 후 모두 제어할 수 있어 가장 강력하다.
 
package com.example.biz.common;

import org.aspectj.lang.ProceedingJoinPoint;

public class AroundAdvice {
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("비즈니스 메서드 수행 전");

        Object returnObj = pjp.proceed();

        System.out.println("비즈니스 메서드 수행 후");
        return returnObj;
    }
}

 

 

Step 2) 핵심 로직 (서비스)은 AOP를 모르게 유지한다

 

AOP의 장점은 핵심 로직이 공통 로직을 모른 채 본업만 한다는 것이다.

예외 테스트를 위해 글 작성 메서드에서 일부러 예외를 터뜨리는 구간이 있다.

@Override
public boolean insertBoard(BoardDTO dto) {
    if (dto.getBid() == 0) {
        throw new NullPointerException("런타임 에러");
    }
    return boardDAO.insertBoard(dto);
}

 

이 구조 덕분에

  • 예외가 발생했을 때 AfterThrowingAdvice가 정말로 실행되는지
  • “설정만으로 예외 로그가 붙는지”

를 바로 확인할 수 있다.

 

 

Step 3) 포인트컷 (Pointcut) 설계: “어디에 붙일지” 선택 규칙 만들기

 

이번 실습은 포인트컷을 2개로 나눈다.

(1) aPointcut: *Impl.*(..) → Impl의 모든 메서드

  • CRUD 전체에 적용하고 싶을 때 (예: before, after, after-throwing)

(2) bPointcut: *Impl.get*(..) → 조회(get*)만

  • 조회 계열만 전 / 후 감싸고 싶을 때 (around)

포인트컷 표현식은 메서드 시그니처 (리턴 / 클래스 / 메서드 / 파라미터) 기반으로 선택한다고 이해하면 된다.

 

 

Step 4) XML AOP 설정: “포인트컷 파트 + 애스펙트 결합 파트” 

AOP 설정은 2파트로 나뉜다.

  1. Pointcut 정의 (선택 규칙 만들기)
  2. Aspect로 결합 (무엇을 / 언제 실행할지 붙이기)

그리고 이 결합 규칙이 실무에서 가장 중요한 문법 포인트다.

  • ref : 어드바이스 객체 (bean)
  • method : 그 객체의 실행할 메서드
  • pointcut-ref : 적용할 포인트컷
  • (after-returning이면) returning : 반환값 바인딩

 

4. 최종 applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.example.biz"/>

    <!-- 기존 Advice bean -->
    <bean class="com.example.biz.common.LogAdvice" id="la"/>
    <bean class="com.example.biz.common.PlusLogAdvice" id="pla"/>
    <bean class="com.example.biz.common.AfterThrowingAdvice" id="ata"/>
    <bean class="com.example.biz.common.AroundAdvice" id="aa"/>

    <!-- 과제: after / after-returning bean -->
    <bean class="com.example.biz.common.AfterAdvice" id="after"/>
    <bean class="com.example.biz.common.AfterReturningAdvice" id="ar"/>

    <aop:config>
        <!-- Pointcut -->
        <aop:pointcut expression="execution(* com.example.biz..*Impl.*(..))" id="aPointcut"/>
        <aop:pointcut expression="execution(* com.example.biz..*Impl.get*(..))" id="bPointcut"/>

        <!-- before -->
        <aop:aspect ref="la">
            <aop:before method="printLog" pointcut-ref="aPointcut"/>
        </aop:aspect>

        <!-- after-throwing -->
        <aop:aspect ref="ata">
            <aop:after-throwing method="printLog" pointcut-ref="aPointcut"/>
        </aop:aspect>

        <!-- around (get*만) -->
        <aop:aspect ref="aa">
            <aop:around method="around" pointcut-ref="bPointcut"/>
        </aop:aspect>

        <!-- after (과제) -->
        <aop:aspect ref="after">
            <aop:after method="printLog" pointcut-ref="aPointcut"/>
        </aop:aspect>

        <!-- after-returning (과제) -->
        <aop:aspect ref="ar">
            <aop:after-returning method="printLog"
                                 pointcut-ref="bPointcut"
                                 returning="returnObj"/>
        </aop:aspect>

    </aop:config>
</beans>

 

5. 과제 코드: AfterAdvice / AfterReturningAdvice

 

(1) AfterAdvice.java

 

After는 “성공 / 예외 여부와 무관하게 종료 시점에 실행”이다.

package com.example.biz.common;

public class AfterAdvice {
    public void printLog() {
        System.out.println("[AFTER] 핵심 메서드 실행 후(성공/예외 무관)");
    }
}

 

(2) AfterReturningAdvice.java

 

After-Returning은 “정상 반환이 있을 때만 실행”이다.
그래서 반환값을 받아 출력하도록 구성했다.

package com.example.biz.common;

public class AfterReturningAdvice {

    // returning="returnObj"와 파라미터 이름 일치 필수
    public void printLog(Object returnObj) {
        System.out.println("[AFTER-RETURNING] 정상 반환 후 return=" + returnObj);
    }
}

 

6. 실행 결과로 확인하기

 

(1) 전체출력 (조회, 정상 반환)

 

정상적으로 실행되면 아래 흐름이 보인다.

  • before: 작은티모님의 로그
  • around 전: 비즈니스 메서드 수행 전
  • after-returning: [AFTER-RETURNING] 정상 반환 후 return=...
  • after: [AFTER] ...
  • around 후: 비즈니스 메서드 수행 후

이게 “설정만으로 공통 로직이 위빙된다”를 가장 명확하게 보여주는 장면이다.

 

(2) 글 작성 (예외 유도 케이스)

 

글 작성은 실습에서 일부러 예외를 던지게 해둔 상태라 아래 흐름이 보이면 정상이다.

  • before 실행
  • after 실행 (예외여도 실행됨)
  • after-throwing 실행 (예외 발생했으니 실행)
  • 예외 종료

After는 무조건, After-Throwing은 예외일 때만이라는 차이가 실행 로그로 확인된다.


 

 

 

1. 공통 정책 변경이 설정 변경으로 끝난다

  • 로깅 정책을 바꿀 때 비즈니스 코드 수정이 아니라 XML에서 ref만 교체하는 방식으로 확장 가능

2. 핵심 로직이 깔끔해진다

  • 서비스 / DAO는 본업에 집중하고 공통 정책은 밖에서 “끼워 넣는다”

3. 정상 흐름 / 예외 흐름에서 실행 타이밍이 명확하다

  • after-returning은 “정상 반환”
  • after-throwing은 “예외”
  • around는 “전 / 후 감싸기”
  • after는 “항상 마무리”

이 차이가 콘솔 출력으로 즉시 검증된다.

 

 

  • AOP는 횡단 관심 (공통 로직)을 핵심 관심 (비즈니스 로직)에서 분리해 유지보수를 쉽게 만든다.
  • JoinPoint 후보 중 Pointcut으로 대상을 선택하고
  • Advice를 원하는 시점 (Before / After / AfterReturning / AfterThrowing / Around)에 결합 (Aspect)하면
  • 스프링이 런타임에 위빙하여 공통 로직을 자동 적용한다.
  • 이번 과제 (after / after-returning)는 정상 반환 흐름과 예외 흐름에서 “동작 시점 차이”를 로그로 확인하는 실습이었다.

'수업 복습' 카테고리의 다른 글

바인드 변수  (0) 2026.01.26
AOP 질의응답  (0) 2026.01.26
XML 기반 AOP 설정 실습 흐름  (0) 2026.01.23
AOP 동작 시점 (Advice 타입) 5가지  (0) 2026.01.23
Spring AOP 개념 / 용어 정리  (0) 2026.01.23