본문 바로가기
Spring/ETC

동적 프록시란 ?

by YoonJong 2023. 8. 11.
728x90

먼저, Spring Boot 2.0 이상부터 CGLIB 가 기본으로 적용되어 사용되고 있다.

Spring AOP 에는 JDK proxy 를 기본으로 사용한다. 

단, 인터페이스가 없는 경우에는 CGLIB 을 사용한다.

 

CGLIB 을 디폴트로 사용하고 있는 이유는

인터페이스 기반의 프록시 ( JDK proxy ) 는 때때로, ClassCast Exceptions 를 추적하기 어렵다고 한다.

( 단순히 생각해도, 인터페이스보다 구현하고 있는 클래스를 기반으로 프록시를 만드는 것이 더 정확할 것. )

 

Spring AOP 는 기본적으로 프록시 방식을 사용한다.

프록시는 객체를 직접적으로 참조하는게 아닌, 해당 객체를 대신하는 객체를 통해 객체에 접근하는 방식.

프록시 객체없이 타겟에 접근하게 되면, 직접 호출하는것은 위험하기 때문에, 프록시 객체에서 부가기능을 처리한다.

정리하면, 접근 권한을 부여할 수 있고, 부가 기능을 추가할 수 있다.

 

프록시를 적용해야 할 클래스가 수백개라면 프록시 클래스를 해당 개수만큼 반복해서 생성해주어야 한다.

다이나믹 프록시(동적 프록시) 는 이런 불편함을 해소시켜준다.

동적인 시점 (런타임) 에 프록시를 자동으로 만들어 적용해준다.

 

동적프록시는 대표적으로 2가지를 가지고 있다. 

  1. JDK Proxy ( Dynamic Proxy : 동적프록시 )
  2. CGLIB 

 

JDK 동적 프록시

 - 인터페이스 기반으로 프록시 생성

 - 리플랙션을 사용하여 프록시를 생성

 

CGLIB

  • 클래스 기반으로 프록시를 생성
  • ASM 프레임워크를 활용하여 바이트코드를 조작하여 프록시 생성

 

 

동적 프록시가 만들어지는 과정

  • 자바 컴파일 이후 바이트코드를 만드는 시점이나 JVM 에 모든 정보가 올라가서 실행하는 시점에 코드 정보를 가져온다.
  • 즉 , 런타임 환경에서 자동으로 만들어진다.

 

 

1. JDK 동적 프록시 적용

InvocationHandler 인터페이스를 구현 : 인터페이스를 기반으로 하므로, 예상치 못한 구현을 확인하기 위해서

invoke() 메서드를 사용한다

 - 타겟을 Invocation Handler 에서 적용해주어야 한다 

 

 

2. CGLIB 적용

스프링 내부에 CGLIB 소스가 포함되어있다.

프록시의 부가 기능을 MethodInterceptor 인터페이스를 구현하여 추가한다.

 

 

3. Spring ProxyFactory 적용

스프링 프레임워크에서는 동적 프록시를 편리하게 사용하기 위해서 ProxyFactory 클래스로 추상화하여 사용한다.

JDK 프록시와 CGLIB 를 사용하지만 구체적으로 몰라도 사용가능.

MethodInterceptor 인터페이스를 구현하는데, CGLIB 의 MethodInterceptor 와 패키지가 다르다.

공통적으로 사용가능하다.

MethodInterceptor 구조는 -> Interceptor -> Advice 로 되어있는데, Advice 는 부가기능을 뜻한다.

 

+ @Transactional 은 Spring AOP 를 통해 트랜잭션의 관리를 한다. ( 디폴트 프록시는 따로 없다 )

Spring AOP 는 프록시를 이용하는데, @Transactional 을 사용하기 위해 프록시가 생성되는 시점은 Spring 컨테이너가 Bean 을 초기화하는 시점이다.

메서드를 실행할 때 프록시가 생성되는 것이 아니다.

@Transactional 어노테이션을 사용하고 있는 메서드가 인터페이스를 구현하고 있는지 여부에 따라 Spring AOP 가 프록시의 종류가 결정한다.

 

 

+ 레거시에서는 아직 디폴트가 JDK 프록시를 사용하고 있다.

Spring Boot 2.0 이후에 CGLIB 으로 변경되었는데, 그 이유는 오픈소스여서 검증할 시간이 필요했다는 것과, CGLIB 을 이용하게 되면, 디폴트 생성자가 필요하기 때문이었다.

 

 

— 프록시를 학습하면서 추가적으로 알아볼 내용 

  1. @Transactional 에는 Spring AOP 의 Proxy 가 사용되는 방식
  2. @Transactional 의 사용 주의점 

 

 

— 참고블로그 

https://velog.io/@chullll/Transactional-과-PROXY

https://yeonyeon.tistory.com/289

https://www.youtube.com/watch?v=MFckVKrJLRQ

Chat GPT

 

 

728x90

댓글