Java AOP 프록시와 어노테이션 이해하기
/ 6분 분량
자바 AOP(Aspect-Oriented Programming)의 프록시와 어노테이션 개념이 처음에는 낯설었지만, 점차 명확하게 이해하게 되었습니다. 특히 멀티모듈 프로젝트 환경에서 AOP가 어떻게 동작하고 왜 필요한지에 대한 궁금증을 풀 수 있었습니다.
Java AOP 프록시와 어노테이션 이해하기
자바 AOP(Aspect-Oriented Programming)의 프록시와 어노테이션 개념이 처음에는 낯설었지만, 점차 명확하게 이해하게 되었습니다. 특히 멀티모듈 프로젝트 환경에서 AOP가 어떻게 동작하고 왜 필요한지에 대한 궁금증을 풀 수 있었습니다.
학습 주제
- 공부 주제: Java AOP, 프록시, 어노테이션, 멀티모듈 구조
- 대화 제목: java-AOP-proxy-annotations-classpath-jar-jvm-gradle-build
- 학습 날짜: 2026년 4월 3일
질문과 탐구
처음에는 자바 프로그래밍 경험이 없어 AOP, 프록시, 트랜잭션 어노테이션 등에 대한 이해가 부족했습니다. NGINX 프록시 경험은 있지만, 객체 지향에서의 프록시는 어떻게 작동하는지, 특히 this.method() 호출 시 AOP가 왜 적용되지 않는지, @Transactional이 무엇인지, 그리고 멀티모듈 구조에서 common 모듈의 Aspect가 어떤 역할을 하는지에 대해 깊이 탐구했습니다.
핵심 학습 내용
AOP와 프록시의 원리
AOP는 코드를 수정하지 않고도 공통 기능(로깅, 트랜잭션 등)을 적용할 수 있게 해주는 기법입니다. 이는 스프링이 대상 객체 앞에 '프록시(Proxy)'라는 껍데기 객체를 세워 동작합니다.
- 프록시의 역할: 외부에서 객체로의 호출을 가로채서, 실제 메서드 실행 전후에 로깅, 시간 측정, 트랜잭션 처리 등의 공통 기능을 수행합니다.
this.method()호출의 문제: 같은 클래스 내에서this.otherMethod()를 호출하면, 이는 프록시를 우회하고 실제 객체의 메서드를 직접 호출하게 됩니다. 이 때문에 AOP가 적용되지 않는 현상이 발생합니다.@Transactional역시 프록시 기반으로 동작하므로,self-invocation시 트랜잭션이 정상적으로 동작하지 않을 수 있습니다.@Around어노테이션의 유용성:@Around는 메서드 실행 전, 실행 후, 성공 시, 실패 시 등 모든 단계를 한 곳에서 처리할 수 있어 AOP 구현에 가장 유용합니다.
스프링 어노테이션과 멀티모듈 구조
@Service,@RestController: 스프링이 클래스를 스캔하여 Bean으로 등록하도록 하는 표식입니다.@RestController는 추가적으로 응답을 JSON으로 변환하는 기능도 수행합니다.- Port (Contract)와 구현체: 모듈 간 의존성을 줄이기 위해 인터페이스(Port)로만 정의하고, 실제 구현체는 다른 모듈에서 주입받는 방식입니다.
profile모듈이BlogPort인터페이스만 의존하면,blog모듈의 내부 구현이 변경되어도profile모듈은 영향을 받지 않습니다. - 멀티모듈 모놀리식: 여러 모듈로 코드를 분리하더라도, 하나의 실행 가능한 JAR 파일로 빌드되어 단일 프로세스로 실행되는 구조입니다.
app모듈이 다른 모듈들을 의존하여 최종적으로 모든 Bean을 포함한 스프링 컨테이너를 구성합니다. common모듈의 Aspect: 공통으로 사용되는 AOP 로직을common모듈에 두면, 각 모듈에서 이를 참조하여 중복 없이 AOP 기능을 적용할 수 있습니다.
클래스패스와 Bean 등록
- 클래스패스: JVM이 클래스를 찾기 위한 경로 목록으로, 컴파일타임과 런타임 모두에 존재합니다.
- Bean 등록 과정: 클래스패스에 있어야 JVM/스프링이 클래스를 로딩할 수 있고,
@Service등의 어노테이션으로 스프링이 컴포넌트로 인식하면 Bean으로 등록됩니다. 즉, 클래스패스 포함 → 로딩 가능 → 컴포넌트 인식 → 인스턴스 생성 → Bean 등록의 단계를 거칩니다.
이해한 내용
- AOP는 객체 지향의 단점을 보완하고 코드 중복을 줄여 유지보수성을 높이는 강력한 방법임을 이해했습니다.
- 프록시가 스프링 AOP의 핵심이며, 런타임에 동적으로 생성된다는 것을 알게 되었습니다.
self-invocation의 문제를 프록시의 동작 원리와 연결하여 명확히 이해했습니다.- 멀티모듈 프로젝트에서 Port 패턴과 AOP를 효과적으로 활용하는 방법을 배웠습니다.
jar파일이 자바 실행 가능한 패키지이며,implementation project는 Gradle 의존성을 설정하는 것임을 알게 되었습니다.
실전 적용
- 향후 프로젝트에서 공통적으로 필요한 로깅, 보안 검사, 트랜잭션 관리 등에 AOP를 적극적으로 활용할 수 있습니다.
- 특히 멀티모듈 구조에서 모듈 간 의존성을 최소화하고 재사용성을 높이는 데 Port 패턴과 AOP를 조합하여 적용할 계획입니다.
this.method()호출 시 AOP가 적용되지 않는 부분을 인지하고, 이를 피하기 위한 코드 설계나 대안을 고려할 수 있습니다.
추가 학습 계획
- 스프링 AOP에서 JDK 동적 프록시와 CGLIB 프록시의 차이점과 선택 기준에 대해 더 깊이 공부하고 싶습니다.
- AOP를 활용한 예외 처리 전략이나 성능 모니터링 구현 방안을 탐색할 예정입니다.
- 스프링 부트의 다양한 부가 기능(Spring Security, Spring Batch 등)과 AOP의 연계에 대해 학습하고 싶습니다.
참고 자료
- 대화에서 직접적으로 언급된 참고 자료는 없었으나, AOP, 프록시, 스프링 DI, 멀티모듈 구조 등 관련 개념을 학습하며 맥락을 이해했습니다.