[TIL] JPA / MyBatis, AOP가 IoC한테 다 잡아 먹혔다
2025-04-04 TIL
📝 TIL (Today I Learned)
🔗 원본 이슈: #37
📅 작성일: 2025-04-04
🔄 최종 수정: 2025년 04월 09일
🍀 새롭게 배운 것
- JPA / MyBatis
- 둘의 정확한 차이점과 코드 예제를 보기 위해 비교 및 비유를 통해 개념을 알아보았다.
- 블로그에 정리했다.
- JPA / MyBatis
- 강사님이 “AOP가 IoC한테 다 잡아 먹혔다”고 하셨는데, 이게 무슨 뜻인지 모르겠어서 알아보았다. (Spring Boot)
Spring (특히 Spring Boot)에서 AOP와 IoC 컨테이너가 어떻게 결합되어 있는지를 강조하는 말
🎯 용어 정리
✅ IoC (Inversion of Control, 제어의 역전)
- 객체를 내가 직접 만들고 관리하는 게 아니라,
Spring이 대신 생성하고 주입(DI)해주는 개념 - 즉, Spring이 “제어권”을 가짐
- 우리는 클래스만 만들고, Spring 컨테이너가 빈(bean)으로 관리함
✅ AOP (Aspect Oriented Programming, 관점 지향 프로그래밍)
- 핵심 로직과 공통 로직을 분리하기 위한 개념
- 로깅, 트랜잭션, 보안 체크 같은 걸 핵심 비즈니스 로직과 따로 분리해서 관리
- 대표적인 키워드:
@Aspect
,@Before
,@After
,@Around
📌 “AOP가 IoC한테 잡아먹혔다”는 말의 뜻
✔️ 번역하자면…
“이제 AOP가 별도로 동작하는 게 아니라,
전부 Spring의 IoC 컨테이너에서 빈으로 관리되고 제어된다는 의미”
🔍 실제 의미
과거엔?
- AOP가 독립적인 개념처럼 설명됐고,
- 설정도 직접 해야 했고 (
@EnableAspectJAutoProxy
, XML 설정 등)
지금은?
- Spring Boot에서는 AOP 기능이 전부 IoC 컨테이너 안에서 작동함
- 즉, 우리가 작성한
@Aspect
클래스도 Spring이 빈으로 등록해서 관리함
➡ 이제 AOP는 Spring의 IoC 기반에서 움직이는 부가기능이 된 것. ➡ “Spring이 모든 걸 컨트롤한다” = “AOP조차도 IoC의 지배 아래 있다”
🔄 Spring Boot에서 바뀐 점
✅ 설정이 훨씬 단순해짐
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {}
➡ Spring Boot에선 이런 설정 생략 가능!
➡ @Aspect
달고 빈으로 등록만 하면 자동 적용됨
✅ AOP 적용 대상도 빈(bean)만 됨
@Component
@Aspect
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("메서드 실행 전!");
}
}
➡ com.example.service
안의 메서드들이 AOP 대상이 되려면?
➡ 그 클래스들이 전부 빈이어야 함
➡ Spring IoC 컨테이너가 관리하는 객체만 AOP 가능
👉 이게 바로 “AOP가 IoC에게 먹혔다”는 말의 핵심 포인트
📌 쉽게 요약하면
과거 AOP | 지금(Spring Boot 기반 AOP) |
---|---|
독립적으로 설정해야 함 | Spring Boot가 자동 설정 |
AOP가 Spring과 독립적인 느낌 | AOP도 IoC 컨테이너 안에 완전히 포함 |
@EnableAspectJAutoProxy 필요 | 생략 가능 (자동 구성됨) |
AOP 대상 따로 인식 | 빈으로 등록된 객체만 AOP 적용 가능 |
✅ 백엔드 개발자로서 이렇게 말하면 좋다.
“Spring Boot에서는 AOP 기능이 Spring IoC 컨테이너 안에 통합돼 있어서, Aspect도 결국 빈으로 등록되어야 동작합니다. 과거에는 AOP 설정을 별도로 했지만, 지금은 Spring Boot의 자동 설정 덕분에 IoC 중심으로 모두 통합되어 관리되죠. 그래서 AOP도 결국 IoC의 흐름 안에서 작동한다고 볼 수 있습니다.”
🔍 실무에서 AOP를 쓰는 예
- 메서드 실행 시간 측정
- 로그인 체크
- 트랜잭션 처리
- 공통 로그 출력
@Around("execution(* com.example..*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println("실행 시간: " + (end - start) + "ms");
return result;
}