Engineering
7. AOP (Aspect Oriented Programming)
7. AOP (Aspect Oriented Programming) 학습 내용을 정리한 백필 노트입니다.
이 글은 2025년 학습 기록을 블로그 형식으로 정리한 백필 노트입니다.
1️⃣ AOP가 필요한 상황
모든 메소드의 호출 시간을 측정하고 싶을 때, 이를 각 서비스 로직마다 직접 넣는 것은 비효율적이다.
이는 공통 관심 사항(cross-cutting concern) 과 핵심 관심 사항(core concern) 이 섞여 유지보수를 어렵게 만든다.
예시: 회원 가입(join), 회원 조회(findMembers) 시간 측정 기능 추가.
🔹 MemberService 코드 예시
package hello.hellospring.service;
@Transactional
public class MemberService {
/** 회원가입 */
public Long join(Member member) {
long start = System.currentTimeMillis();
try {
validateDuplicateMember(member); // 중복 회원 검증
memberRepository.save(member);
return member.getId();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("join " + timeMs + "ms");
}
}
/** 전체 회원 조회 */
public List<Member> findMembers() {
long start = System.currentTimeMillis();
try {
return memberRepository.findAll();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("findMembers " + timeMs + "ms");
}
}
}
2️⃣ 문제점 요약
- 회원가입/조회 기능의 시간 측정은 핵심 로직이 아닌 공통 관심 사항이다.
- 공통 로직과 핵심 비즈니스 로직이 섞여 코드가 복잡하고 유지보수가 어렵다.
- 시간 측정 로직을 바꾸려면 모든 메소드에서 수정해야 한다.
- 즉, 중복 코드와 결합도가 높음.
3️⃣ AOP 적용
AOP는 공통 관심 사항과 핵심 관심 사항을 분리하기 위한 프로그래밍 기법이다.
✅ 개념
-
AOP (Aspect Oriented Programming)
: 관점 지향 프로그래밍.
공통 로직(시간 측정, 로깅, 트랜잭션 등)을 분리해 모듈화함.
-
cross-cutting concern → 여러 곳에서 공통으로 필요한 기능
-
core concern → 실제 비즈니스 로직
🔹 시간 측정 AOP 등록 코드
package hello.hellospring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeTraceAop {
@Around("execution(* hello.hellospring..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("START: " + joinPoint.toString());
try {
return joinPoint.proceed();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
}
}
}
4️⃣ AOP 적용 후 결과 및 장점
✅ 해결된 점
- 회원가입, 회원조회 등 핵심 로직과 시간 측정 공통 로직 분리
- 시간 측정 코드 한 곳에서 관리 가능
- 핵심 비즈니스 코드가 깔끔하고 집중도 높아짐
- 변경 시 AOP 클래스만 수정하면 됨
- 적용 대상(
@Around의 execution 표현식)을 유연하게 지정 가능
5️⃣ 스프링 AOP 동작 방식
-
AOP 적용 전
: Controller → Service → Repository 구조로 직접 호출
(모든 객체가 실제 인스턴스 직접 참조)
-
AOP 적용 후
: 스프링이 Proxy 객체를 만들어 주입함
(실제 객체 호출 전후에 공통 로직이 자동 실행됨)
즉, 스프링 컨테이너는 프록시 객체를 Bean으로 등록하고,
이 프록시가 내부에서 실제 객체를 호출하며 AOP 로직을 삽입한다.
👉 확인 방법
콘솔에 START, END 로그를 출력하여
프록시 객체가 주입되어 실행되는지 확인 가능.
🧩 정리 요약
| 구분 | 내용 |
| --- | --- |
| 문제 | 모든 메소드에 중복되는 시간 측정 코드 삽입 필요 |
| 원인 | 공통 관심 사항과 핵심 로직이 섞임 |
| 해결책 | AOP 적용으로 공통 로직 분리 |
| 핵심 기술 | @Aspect, @Around, ProceedingJoinPoint, Proxy 객체 |
| 효과 | 코드 간결, 유지보수성 향상, 확장 용이 |