WeeklyPaper 주제: Spring에서 AOP(Aspect Oriented Programming)가 필요한 이유와 이를 활용한 실제 애플리케이션 개발 사례에 대해 설명하세요.
AOP - Aspect Oriented Programming
개발을 하다 보면 여러 비즈니스 로직에서 생기는 공통 기능들이 있다.OOP는 역할을 기준으로 책임을 분리하는 효율적인 패러다임이지만 로깅이나 보안같은 반복되는 기능들을 완전히 분리시키기 어렵다. 그래서 AOP는 바로 이런 문제를 해결하기 위해서 등장을 했는데, AOP는 여러 클래스에서 나타다는 반복 기능들을 깔끔하게 모듈화 시켜준다.
AOP = 관점 지향 프로그래밍
- 부가 기능(횡단 관심사, Cross-Cutting Concerns)을 분리하여 개발하는 프로그래밍 기법
- AOP의 핵심 목표는 관심사의 분리(Separation of Concerns)인데, Spring에서는 이 AOP는 Aspect라는 별도의 모듈로 뽑아내고 필요한 시점에 자동으로 적용시킴
AOP 적용 전
예시 코드:
@Service
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
public void join(Member member) {
long start = System.currentTimeMillis(); // Non-core logic
try {
// Core Logic
memberRepository.save(member);
} finally {
long end = System.currentTimeMillis(); // Non-core logic
long time = end - start;
System.out.println("MemberService.join execution time = " + time + "ms"); // Non-core logic
}
}
}
join 메서드는 사실 보면 memberRepository.save()이 기능이 메인인데, 그 의외에 코드 (System.currentTimeMillis, 로깅 기능 등)이 앞뒤로 붙어서 꽤 지저분해졌다. 만약에 이 시간 측정/로깅 코드를 여러 메서드에 반복하려면 그냥 복붙해서 해결하는 수 밖에 없다.
AOP 적용 후
@Service
public class MemberService {
// ...
public void join(Member member) {
// 순수한 핵심 비즈니스 로직
memberRepository.save(member);
}
}
@Aspect // 이 클래스가 Aspect임을 선언
@Component // Spring Bean으로 등록
public class TimeTraceAspect {
// Pointcut: com.example 패키지와 그 하위의 모든 메서드를 대상으로 함
@Around("execution(* com.example..*(..))")
public Object trace(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis(); // advice
try {
// 실제 대상 메서드(Join Point)를 실행
return joinPoint.proceed();
} finally {
// advice 수행
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("[Execution Time] " + joinPoint.getSignature() + " = " + time + "ms");
}
}
}
이제 비즈니스로직은 깔끔하게 분리가 되었다! MemberService의 코드를 단 한 줄도 수정하지 않고, 애플리케이션의 모든 서비스 메서드에 실행 시간 측정 기능을 자동으로 적용할 수 있다 (엄청 편리해진다).
- @Aspect: 이 클래스가 AOP의 Aspect 역할을 한다는 것을 나타냄
- @Around("..."): Advice의 한 종류로, Pointcut으로 지정된 메서드의 실행 전후에 개입하여 조작한다. execution(* com.example..*(..))은 Pointcut 표현식으로, com.example 패키지와 그 하위 패키지의 모든 메서드를 대상으로 지정한다.
- MemberService는 법위 안에 있으므로 자동으로 AOP 대상이
흐름은 이렇게 된다:
- 개발자가 코드에서 memberService.join() 호출함
- 하지만 Spring은 원본 MemberService 대신, TimeTraceAspect 로직이 씌워진 프록시 MemberService 를 연결해 줍니다.
- trace() 메서드가 실행되다가 joinPoint.proceed()를 만나는 순간, 그제서야 원본 MemberService 객체의 join() 메서드가 실제로 호출됨!
- joinPoint.proceed()는 프록시가 잠시 자신의 일을 멈추고, 원본 객체에게 제어권을 넘겨 일을 시키는 '스위치' 같은 역할을
- 원본 join() 메서드의 실행이 끝나면, 다시 trace() 메서드로 돌아와 finally 블록의 나머지 코드를 실행
간단한 용어 정리

- 애스펙트 (Aspect)
- 흩어진 부가 기능(Advice)과 적용 위치(Pointcut)를 합친 모듈
- 어드바이스 (Advice)
- 실행될 부가 기능의 실제 코드 (예: 로그를 남기는 코드)
- 포인트컷 (Pointcut)
- 어드바이스를 어디에 적용할지 지정하는 규칙 (예: '모든 Service 클래스의 모든 메서드')
- 위빙 (Weaving)
- 애스펙트를 실제 코드에 끼워 넣는 과정
'Spring' 카테고리의 다른 글
| [JPA] N+1 문제 (4) | 2025.07.21 |
|---|---|
| [SpringBoot] @Controller와 @RestController의 차이점과 요청 처리 흐름 (0) | 2025.07.03 |
| [SpringBoot] 웹 서버와 WAS의 차이, 그리고 스프링 부트 내장 톰캣 (1) | 2025.06.24 |
| [SpringBoot] Spring Boot의 다양한 Bean 등록 방법 (0) | 2025.06.23 |
| [Spring] 프레임워크 vs 라이브러리: 제어 흐름과 사용 방식 비교 (Spring 예시 포함) (1) | 2025.06.16 |