-
Spring AOP에 대한 개념Spring Framework 2023. 10. 5. 13:16
Spring AOP
- 관점 지향 프로그래밍
- 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점을 나눠서 그 관점들을 모듈화하는 것

- 횡단(가로) 관심사를 분리한다. (cross-cutting)
- 다른 로직과 분리할 수 없는 어플리케이션 로직을 분리한다.
- 부가기능을 따로 관리한다.
- 공통적으로 사용하는 기능들을 분리하여 관리할 수 있는 것을 말합니다.
- 프록시 패턴 기반의 AOP 구현체
- 프록시 패턴 : 어떤 객체를 사용하고자 할 때, 객체를 직접적으로 참조하는 것이 아닌, 해당 객체를 대리(Proxy)하는 객체를 통해 대상 객체에 접근하는 방식
- 접근 제어 및 부가기능을 추가하기 위해
- 스프링 bean에만 AOP적용 가능
- 중복 코드 제거, 유지보수 용이, OOP의 문제점 해결
- 핵심 로직과 부가 기능의 명확한 분리로, 핵심 로직은 자신의 목적 외에 사항들에는 신경쓰지 않는다.
- Aspect로 모듈화하고 핵심 비즈니스 로직에서 분리해 재사용한다.

AOP가 프록시 방식을 사용하는 이유
- 프록시 객체를 생성해 런타임 시점에 삽입이 가능
- AOP를 적용하는 대상 클래스의 바이트코드를 수정하지 않고, 부가적인 기능을 주입할 수 있도록 한다.
- 애플리케이션을 실행 중에 동적으로 관심사를 적용할 수 있다.
- 코드 재사용과 모듈화
- 공통적으로 필요한 기능인 로깅, 보안체크, 트랜잭션 관리 등을 하나의 공통 모듈로 분리하여 관리할 수 있다.
- 관심사 분리
- 코드의 응집도 증가, 결합도 감소로 인해 코드의 이해와 관리가 쉬워진다.
- 런타임 선택 가능
- 필요한 관심사를 선택적으로 적용할 수 있다.
주요 용어

- Aspect
- Advice + PointCut
- 흩어진 관심사를 모듈화 한 것
- 부가기능을 모듈화 함 (AOP의 기본 모듈)
- Target
- Advice가 부가기능(Aspect)을 부여할 대상
- Advice가 적용될 비즈니스 로직
- PointCut으로 결정
- 클래스 혹은 메소드
- Advice
- Target에게 제공할 부가기능을 담은 모듈
- 실질적으로 어떤 일을 어느 시점에 주입할 지에 대한 것
- Join Point
- Advice가 적용될 위치나 끼어들 수 있는 위치
- 메서드 진입 지점, 생성자 호출 시점, 필드에서 값 추출 등의 다양한 시점에 적용 가능
- Pointcut
- Join Point의 상세한 스펙을 정의한 것으로 JoinPoint를 선별하는 작업을 한다.
- "어떤 메소드의 어느 시점에 호출" 하는 것처럼 구체적으로 Advice가 실행되는 지점을 정할 수 있음
- Target을 지정하는 정규표현식
- Join Point의 실행 지점과 동일
- Advisor
- Pointcut과 Advice를 하나씩 가지고 있는 Object
- "어떤 메소드에 어느 시점에 어떤 기능을 넣을지"를 정할 수 있음
- Weaving
- Join Point에 Advice를 적용하는 방법
- AOP proxy
- AOP 기능을 구현하기 위해 만든 프록시 객체
- JDK 동적 프록시 혹은 CGLIB 프록시 (기본 값은 CGLIB 프록시)
AOP 적용 방식
- 컴파일 시점
- 모든 지점에 적용 가능
- 컴파일러를 통해 .java -> .class로 만드는 시점에 부가 기능 로직을 추가
- AspectJ가 제공하는 특별한 컴파일러를 사용해야 한다.
- 클래스 로딩 시점
- 모든 지점에 적용 가능
- .class 파일을 JVM 내부의 클래스 로더에 보관하기 전에 조작하여 부가 기능 로직을 추가하는 방식
- 특별한 옵션과 클래스 로더 조작기를 지정해야하므로 운영하기 어려움
- 런타임 시점
- 스프링이 사용하는 방식
- 컴파일이 끝나고 클래스 로더에 이미 올라가 있는 상태에서 자바가 실행된 다음에 동작하는 런타임 방식
- 프록시를 통해 부가 기능이 적용
- 프록시는 메서드 오버라이팅 개념으로 동작하기 때문에 메서드에서만 적용된다.
- 메서드에서만 적용이 되기 때문에 스프링 bean에만 AOP를 적용 가능하다.
- 위의 2가지 시점과 다르게 특별한 환경에서 돌아가지 않는다.
예시
- 사전 작업
<!-- 의존성 추가 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>- @Around("execution(경로)") 예시
/* @Aspect 어노테이션을 붙여 이 클래스가 Aspect를 나타내는 클래스라는 것을 명시 @Component를 붙여 스프링 빈으로 등록 @Around 어노테이션은 타겟 메서드를 감싸서 특정 Advice를 실행한다는 의미 execution(* com.saelobi..*.EventService.*(..))가 의미하는 바는 com.saelobi 아래의 패키지 경로의 EventService 객체의 모든 메서드에 이 Aspect를 적용하겠다는 의미 */ @Component @Aspect public class PerfAspect { @Around("execution(* com.saelobi..*.EventService.*(..))") public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{ long begin = System.currentTimeMillis(); Object retVal = pjp.proceed(); // 메서드 호출 자체를 감쌈 System.out.println(System.currentTimeMillis() - begin); return retVal; } }- @Around("@annotation(어노테이션)") 예시
/* @PerLogging 어노테이션이 붙은 메서드만 Aspect가 적용 */ @Component @Aspect public class PerfAspect { @Around("@annotation(PerLogging)") public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{ long begin = System.currentTimeMillis(); Object retVal = pjp.proceed(); // 메서드 호출 자체를 감쌈 System.out.println(System.currentTimeMillis() - begin); return retVal; } }- 스프링 bean의 모든 메서드에 적용
/* SimpleEventService의 모든 메서드에 해당 Aspect가 추가 */ @Component @Aspect public class PerfAspect { @Around("bean(simpleEventService)") public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{ long begin = System.currentTimeMillis(); Object retVal = pjp.proceed(); // 메서드 호출 자체를 감쌈 System.out.println(System.currentTimeMillis() - begin); return retVal; } }출처)
https://velog.io/@backtony/Spring-AOP-%EC%B4%9D%EC%A0%95%EB%A6%AC
https://engkimbs.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81AOP
'Spring Framework' 카테고리의 다른 글
스프링 어노테이션 정리 (추가 예정) (0) 2023.10.12 스프링(spring) web.xml 기본 설정 (0) 2023.10.05 spring과 spring boot 비교하기 (0) 2023.10.04 스프링 컨테이너에 대한 개념 (0) 2023.10.04 스프링 프레임워크(spring framework)에 대한 기본 개념 (0) 2023.10.04