초보 웹 개발자를 위한 스프링 5 프로그래밍 입문을 더 잘 이해하기 위해 정리하기 위한 포스팅입니다.
이번 포스팅은 스프링5 프로그래밍 입문 - ch7. AOP 프로그래밍 - (1) 프록시와 이어집니다.
목차
0. AOP를 배워야 하는 이유
1. 스프링 AOP
2. 스프링 AOP 구현
0. AOP를 배워야 하는 이유
사견입니다. AOP를 배워야 하는 이유는 생각보다 간단한 것 같다.
1. 여기저기서 많이 쓴다.
많이 사용하는 것들은 자세하게 알수록 좋다. 그 이유는 3번 때문이다.
2. 공통 처리가 가능하다.
공통 처리가 가능하다는 것은 코드 중복을 제거할 수 있다는 의미이다. 그리고 코드 중복이 없다는 것은 대체로 변경이 일어났을 때 강점을 가지게 된다. 10곳을 수리하는 것보다는 1곳을 수리하는게 편하고 실수를 줄일 수 있다.
3. AOP는 만능이 아니다. 그래서 문제가 발생했을 때 해결할 줄 알아야 한다.
1. 스프링 AOP
Aspect Oriented Programming, 여러 객체에 공통으로 적용할 수 있는 기능을 분리해서 재사용성을 높여주는 프로그래밍 기법이다.데이터 접근 기술을 사용해본 사람이라면 알 것이다. DB에 접근하기 위해 커넥션 풀에 접근하고 트랜잭션 시작 및 커밋/롤백, 커넥션 반환까지 여러 작업을 해야한다. 이러한 작업을 DB 접근이 필요한 부분마다 매번 작성하는 것은 매우 따분한 작업이다. 그래서 스프링 진영에서는 @Transactional 애노테이션을 통해 해당 문제를 해결해주었다. @Transactional 도 스프링 AOP 중 하나이다.
AOP의 기본 개념은 핵심 기능에 공통 기능을 삽입하는 것이다. 그런데 여기서 핵심 기능의 코드를 수정하지 않으면서 공통 기능의 구현을 추가하는 것이 AOP의 중요한 포인트이다. 핵심 기능에 공통 기능을 삽입하는 방법에는 다음 세 가지가 있다.
- 컴파일 시점에 코드에 공통 기능을 삽입하는 방법
- 클래스 로딩 시점에 바이트 코드에 공통 기능을 삽입하는 방법
- 런타임에 프록시 객체를 생성해서 공통 기능을 삽입하는 방법
첫 번째, 두 번째 방법은 스프링 AOP에서 지원하는 방법은 아니라고 한다. AspectJ와 같은 AOP 전용 도구를 사용해서 적용할 수 있다고 합니다. 스프링이 제공하는 AOP 방식은 프록시를 이용한 세 번째 방식입니다.
프록시 방식은 이전 포스팅(스프링5 프로그래밍 입문 - ch7. AOP 프로그래밍 - (1) 프록시)에서 실습한 것처럼 중간에 프록시 객체를 생성한다. 그리고 위 그림처럼 실제 객체의 ㅅ기능을 실행하기 전(1.1), 후(1.4)에 공통 기능을 호출한다.
앞서 포스팅에서는 프록시 객체를 직접 만들어줬는데 스프링 AOP는 프록시 객체를 자동으로 만들어준다. 우리가 할 일은 공통 기능을 구현한 클래스만 알맞게 구현하면 된다.
AOP에서 공통 기능을 Aspect라고 부른다. 이외에도 알아두어야 할 용어가 몇 가지 존재한다.
Advice
언제 공통 관심 기능을 핵심 로직에 적용할 지 정의한다. 예를 들면 메서드 호출 전 혹은 호출 후, 혹은 호출 전,후 둘다. 공통 기능을 적용한다는 것이다.
Joinpoint
Advice를 적용할 수 있는 지점을 말한다. 메서드 호출, 필드 값 변경 등이 Joinpoint에 해당한다. 스프링은 프록시를 이용해서 AOP를 구현하기 때문에 메서드 호출에 대한 Joinpoint만 지원한다.
Pointcut
실제 Adivce가 적용되는 Joinpoint를 말한다. 무슨 말인고 하면 AOP를 적용할 메서드를 선택할 수 있는 표현식이라고 보면 된다. 한 가지 예시를 들면 create(), read(), readAll() 메서드가 있을 때 read가 들어가는 메서드에만 AOP를 적용할 수 있다.
Weaving
Advice를 핵심 로직 코드에 적용하는 것을 말한다.
Aspect
여러 객체에 공통으로 적용되는 기능을 Aspect라 한다. 예외 처리, 트랜잭션 등이 Aspect의 예이다.
Advice 종류
Spring AOP · studybook에 깔끔하게 정리되어 있다. 참고로 이 책에서는 Around Advice 기준으로 설명한다. 그 이유는 Around Advice는 대상 객체의 메서드를 실행하기 전/후, 익셉션 발생 시점 등 다양한 시점에 원하는 기능을 삽입할 수 있기 때문이다.
2. 스프링 AOP 구현
구현 방법
1. Aspect로 사용할 클래스에 @Aspect 애노테이션을 붙인다.
2. @Pointcut 애노테이션으로 공통 기능을 적용한 Pointcout을 정의한다.
3. 공통 기능을 구현한 메서드에 @Around 애노테이션을 적용한다.
구현은 위와 같이 하면 된다. 하나하나 살펴보자.
1. @Aspect
Aspect로 사용하기 위해 붙였다. Aspect는 여러 객체에 공통으로 적용되는 기능을 의미한다고 앞서 설명했다.
2. @Pointcut
공통 기능을 적용할 대상을 설정한다.
3. @Around 애노테이션은 Advice가 Around Advice 라는 것을 설정한다. 그리고 publicTarget() 매서드에 정의한 Pointcut에 공통 기능을 적용하겠다는 의미이다. Around 애노테이션 내부에 포인트컷 파라미터가 존재하기 때문에 아래와 같이 pointcut을 내부에 설정해도 된다.
@Around("execution(public * com.jxx.springstart.chap07..*(..))")
4. AOP를 사용할 때 반드시 수행해야되는 것은 proceed()이다. 이를 통해 공통 기능에서 핵심 비즈니스 로직으로 넘어갈 수있다.
이제 결과를 확인해보자.

3행에서는 객체의 이름을 출력하는데 조금 생소한 객체명이 나왔다. 이 타입은 스프링이 생성한 프록시 타입이다. 앞서 스프링 AOP는 프록시를 이용한다고 했다. 그래서 이러한 출력이 나온 것이다.
실제 위 calculator.factorial(20) 이 실행되는 과정은 아래와 같다.
'Spring > core' 카테고리의 다른 글
프록시 내부 호출 문제 해결 방법 - 자기 주입, 지연 조회, 구조 변경 (0) | 2023.03.26 |
---|---|
스프링 빈 순환 참조 예외 BeanCurrentlyInCreationException (0) | 2023.03.26 |
스프링5 프로그래밍 입문 - ch7. AOP 프로그래밍 - (1) 프록시 (0) | 2023.03.25 |
스프링5 프로그래밍 입문 - ch6.빈 라이프사이클 (0) | 2023.03.24 |
스프링5 프로그래밍 입문 - ch5.컴포넌트 스캔 (0) | 2023.03.24 |