728x90
핵심 기능(주관심사)과 공통 기능(보조 관심사, 부가기능)을 분리하여 코드의 재사용성, 유지보수성, 가독성을 향상시키는 방법
주 관심사 : 실제 로직 (ADD 함수 등)
보조 관심사 : 보안, 로그, 트랜잭션 등
중간에 'Proxy' 객체를 두어, 보조관심사를 자동으로 끼워 넣는다.
AOP 동작 흐름 (Spring AOP 기준)
- 클라이언트가 메서드 호출 (예: ADD(x, y))
- Proxy 객체가 대신 호출을 가로챔
- 보조관심사 로직 실행 (예: 로그 찍기, 트랜잭션 시작 등)
- 실제 핵심 로직(ADD()) 실행
- 결과를 기반으로 보조관심사 마무리 작업 (예: 트랜잭션 커밋, 로그 종료 등)
- 클라이언트에게 결과 반환
주 사용 목적
로깅 (Logging) | 메서드 실행 시점, 매개변수, 리턴 값 등을 기록 |
보안 (Security) | 인증, 인가 처리 |
트랜잭션 (Transaction) | DB 작업의 일괄 처리, rollback 관리 |
캐싱 (Caching) | 자주 호출되는 메서드 결과 캐싱 |
예외 처리 (Exception Handling) | 예외 발생 시 별도 처리 (예: 알림, 로깅 등) |
Spring AOP 구성요소
- 어드바이스 (Advice): 언제 실행할지 결정
- 포인트컷 (Pointcut): 어디에 적용할지 결정
AOP 용어
JoinPoint | 어드바이스가 적용될 수 있는 프로그램 실행 지점 예: 메서드 호출 시점, 예외 발생 시점 등 |
PointCut | 어떤 JoinPoint에 어드바이스를 적용할지 선택하는 필터 기준 예: 특정 패키지의 모든 get*() 메서드 |
Advice | 실제로 끼워 넣는 코드 (보조 관심사 로직) |
Aspect | PointCut + Advice = 횡단 관심사 모듈 |
Weaving | 어드바이스를 실제 코드 실행 흐름에 적용하는 과정 |
Proxy | 클라이언트와 실제 객체 사이에 위치, 어드바이스를 삽입하는 중간 대리자 역할 |
어드바이스 종류
@Before | 핵심 기능 실행 전 | 유효성 검사, 로깅 |
@After | 핵심 기능 실행 후 (성공/실패 무관) | 리소스 해제, 공통 메시지 출력 |
@AfterReturning | 핵심 기능이 정상 실행 후 | 리턴값 로깅 |
@AfterThrowing | 예외 발생 시 | 예외 처리, 알림 전송 |
@Around | 실행 전/후/예외 모두 처리 | 가장 강력한 방식 – proceed()로 실제 메서드 호출 |
Spring AOP 특징
기반 | 프록시 기반 (JDK 또는 CGLIB) |
위빙 시점 | 런타임 (Runtime) |
JoinPoint 범위 | 메서드 단위만 가능 (메서드 실행 지점만) |
구현 방식 | 표준 자바 클래스 (POJO)를 기반으로 구성 가능 |
AOP 예시코드
로그를 출력하는 AOP (Spring Framework 5 기준, XML 설정)
public class LogAspect {
public void beforeLog(JoinPoint joinPoint) {
System.out.println(">>> 메서드 실행 전: " + joinPoint.getSignature().getName());
}
public void afterLog(JoinPoint joinPoint) {
System.out.println(">>> 메서드 실행 후: " + joinPoint.getSignature().getName());
}
}
applicationContext.xml (XML 기반 AOP 설정)
<beans xmlns="http://www.springframework.org/schema/beans"
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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 서비스 Bean -->
<bean id="myService" class="com.example.service.MyService" />
<!-- Aspect Bean -->
<bean id="logAspect" class="com.example.aspect.LogAspect" />
<!-- AOP 설정 -->
<aop:config>
<aop:aspect ref="logAspect">
<aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))" />
<aop:before method="beforeLog" pointcut-ref="serviceMethods" />
<aop:after method="afterLog" pointcut-ref="serviceMethods" />
</aop:aspect>
</aop:config>
</beans>
AOP 클래스 LogAspect.java
package com.example.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeLog(JoinPoint joinPoint) {
System.out.println(">>> [Before] 메서드 실행 전: " + joinPoint.getSignature().getName());
}
@After("execution(* com.example.service.*.*(..))")
public void afterLog(JoinPoint joinPoint) {
System.out.println(">>> [After] 메서드 실행 후: " + joinPoint.getSignature().getName());
}
}
AppConfig.java
package com.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = "com.example") // com.example 하위 패키지 스캔
@EnableAspectJAutoProxy
public class AppConfig {
}
MainApp.java
package com.example;
import com.example.service.MyService;
import com.example.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
MyService service = context.getBean(MyService.class);
service.doSomething();
context.close();
}
}
'Springboot' 카테고리의 다른 글
[Spring] Filter, Interceptor, AOP의 차이점 (0) | 2025.04.16 |
---|---|
[Security] Spring Security의 흐름 (0) | 2025.04.02 |
[Springboot] Client-Server 구조 정리 (0) | 2025.03.26 |
[Springboot] JWT 0.15.2 (0) | 2024.06.22 |
[Springboot] QueryDSL 2 (0) | 2023.08.09 |