프록시패턴은 무엇일까?

Patrick YOO·2022년 1월 19일
0
post-thumbnail

일전에 @Transactional 을 사용하며 겪게되는 실수를 정리하며 간략하게 넘어갔었던 프록시 패턴에 대하여 정리해보려고 한다.

프록시패턴 이란?

  • 프록시의 뜻은 원어로 대리 대무의 뜻으로 클라이언트 호출시 실제 객체의 대체역을을 하는 객체를 제공하여 클라이언트의 요청을 수신하고 일부 작업을 엑세스 를 제어하거나 캐싱등의 작업을 수행을 가능하게 하는 패턴이다.

스프링 AOP 프레임워크는 Proxy 기반으로 동작하며 앞서 자주 언급한 @Transactional 도 Proxy 패턴으로 동작한다.

위 코드에서 주석만 띡 달면 메소드 시작전 트랜젝션이 열리게 되며 종료될때까지 데이터의 정합성을 유지하는 상태로 변경또는 수정이 가능하며 트랜젝션이 종료되면 데이터베이스에 커밋까지 해준다 이게 어떻게 가능한 것일까?

앞서 언급한대로 메서드가 시작되기전 트랜젝션 프록시가 changeName 메소드를 인터셉트하여 비즈니스 로직시작 종료 시점에 코드를 삽입하게 된다.

스프링이 제공하는 프록시

스프링은 대표적으로 CGLib 방식과 JDK Dynamic Proxy 두가지 방식을 지원하고 있다.

@Transactional 또한 위에 언급한 두가지 방식중 하나로 동작하고 있다 공식문서에 따르면 Dynamic Proxy 를 이용한다고 되어있지만 디버그모드를 통해 타고들어가다보면 결국 CGLib 방식을 이용해 프록시가 등록되어있다.

두 방식의 차이는 무엇일까?

  • JDK Dynamic Proxy 는 Target(실제 실행데이터) 가 Interface 가 상속되어있어야 하며 실제 프록시 등록시 인터페이스를 프록시 객체 생성할때 이용한다.
  • Dynamic Proxy 는 프록시 등록시 사용할때 무거운 객체인 Reflection 을 이용하여 실제 객체의 메타데이터를 가져오는 방식의 기능을 이용한다 반면 CGLib 는 바이트코드를 조작하여 동적으로 클래스를 생성하는 기술을 이용하여 프록시를 만들어낸다. 나의 레벨에서 조금 딥한 부분이라 생각되어 간단히 적어보면 성능상으로 CGLib 방식이 성능적인 이점을 가져올수 있다 정도로만 이해하고 넘어가겠다.

위의 코드를 실행하자 마자 CGLibAopProxy 객체에서 메소드 시작전 Intercept 하여 객체의 액세스 제어권을 가져간것을 볼 수 있다.

주의

스프링 공식문서에 따르면 CGLib DynamicProxy 둘다 self-invocation 굳이 번역하자면 자가 발동정도로 볼 수 있겠다 뭐 의미야 어찌됐건 self-invocation 을 지원하지 않는다라고 명시되어있다.
매우 중요한 문구인데 무심코 사용하는 경우가 있다 프록시의 정상작동을 원한다면 호출 Target 외부에 있는 다른 객체가 Target 객체를 호출해야지만 원하는 방향으로 동작시킬 수 있다.

References


profile
자유인을 꿈꾸는 개발자

0개의 댓글