스프링 프록시, 제대로 알고 쓰자!
프록시 패턴(Proxy Pattern)은 실제 객체에 대한 접근을 제어하고 부가 기능을 추가하는 구조적 디자인 패턴으로, 트랜잭션, 로깅, 캐싱 등에 활용됨
스프링 프레임워크(Spring Framework)는 AOP, @Transactional, Lazy Loading 등에서 프록시를 적극적으로 활용하며, CGLIB 또는 JDK 동적 프록시를 사용
스프링에서 프록시는 빈 생성 단계에서 결정되며, @Transactional, @Async, @Cacheable 등의 어노테이션(Annotation)이 적용된 빈에 생성됨
셀프 인보케이션(Self-Invocation) 문제는 프록시를 거치지 않고 실제 객체 내부에서 메서드를 호출하여 트랜잭션이 적용되지 않는 상황을 의미함
스프링 프록시의 동작 원리
스프링은 빈(Bean) 생성 과정에서 프록시를 적용할지 여부를 결정하며, @Transactional, @Async, @Cacheable 등의 어노테이션(Annotation)이 프록시 생성의 트리거(Trigger)가 된다.
컴포넌트 스캔(Component Scan): @Service, @Component 어노테이션이 붙은 빈 정의(Bean Definition)를 컨테이너에 등록
빈 생성(Bean Creation): new OrderService()를 통해 실제 객체(Target) 생성
프록시 적용 판단: AOP Pointcut 매칭 여부에 따라 프록시 생성 결정
프록시 생성: 기존 객체를 감싸는 프록시 객체 생성 (OrderServiceProxy → OrderService)
최종적으로 스프링 컨테이너에는 프록시 빈(Proxy Bean)이 등록되며, 클라이언트 요청은 프록시를 통해 실제 객체로 전달된다.
JDK 동적 프록시 vs CGLIB
스프링은 인터페이스(Interface)가 존재하면 JDK 동적 프록시(Dynamic Proxy)를, 없으면 CGLIB를 사용한다. CGLIB는 서브클래싱(Subclassing)을 통해 프록시를 생성하므로 final 클래스(Final Class)나 final 메서드(Final Method)에는 적용할 수 없다.
JDK 프록시: 인터페이스 기반, 리플렉션(Reflection) 사용, 프록시 객체 생성
CGLIB: 바이트코드 조작(Bytecode Manipulation) 기반, 서브클래스 생성, final 제약
성능: CGLIB가 JDK보다 빠르지만, 바이트코드 조작으로 인해 디버깅(Debugging) 난이도가 높음
Spring Boot 2.x 이후부터 CGLIB가 기본으로 사용되며, JDK 프록시를 사용하려면 별도의 설정을 해야 한다.
셀프 인보케이션(Self-Invocation) 문제 해결
프록시 객체를 거치지 않고 실제 객체 내부에서 메서드를 호출하는 셀프 인보케이션(Self-Invocation)은 트랜잭션(Transaction)이 적용되지 않는 대표적인 문제 상황이다. 이는 프록시가 가로채지 못하기 때문이다.
문제 상황: OrderApplication 클래스 내에서 this.generateOrder() 호출
원인: 프록시가 아닌 실제 객체(Real Object) 내부에서 메서드 호출
해결 방법: 자기 자신(this) 대신 스프링 컨테이너에서 빈(Bean)을 주입받아 호출하거나, 별도의 서비스 계층으로 분리
결과적으로 프록시를 통한 메서드 호출을 보장해야 트랜잭션, AOP 등 스프링의 핵심 기능을 활용할 수 있다.
프록시 vs 리버스 프록시
프록시(Forward Proxy)는 클라이언트의 대리인, 리버스 프록시(Reverse Proxy)는 서버의 대리인 역할을 한다. 프록시는 익명성, 접근 제어, 캐싱 등에 사용되며, 리버스 프록시는 로드 밸런싱, 보안, SSL 종료, 캐싱 등에 활용된다.
프록시: 클라이언트 IP 숨김, VPN, Tor, 접근 제어, 캐싱
리버스 프록시: 로드 밸런싱, 서버 IP 은닉, SSL 종료, 정적 리소스 처리
대표적인 예시: Nginx, Apache, API Gateway, AWS ALB
리버스 프록시는 서버의 부하를 줄이고 보안을 강화하는 데 기여하며, 현대 웹 아키텍처(Web Architecture)에서 필수적인 요소이다.