본문 바로가기
Spring

[스프링] 프록시(Proxy)

by jeonghaemin 2021. 3. 8.
728x90

프록시의 사전적 정의는 '대리인'으로, 간단하게 설명하면 내가 어떤 객체를 사용하려고 할 때 해당 객체에 직접 요청하는 것이 아닌 중간에 가짜 프록시 객체(대리인)를 두어서 프록시 객체가 대신해서 요청을 받아 실제 객체를 호출해 주도록 하는 것이다.

  • 프록시 모드를 설정하게 되면, 의존성 주입을 통해 주입되는 빈은 실제 빈이 아닌 해당 빈을 상속받은 가짜 프록시 객체이다.
  • 스프링은 CGLIB이라는 바이트 코드를 조작하는 라이브러리를 사용해서 프록시 객체를 주입해준다.
  • 프록시 객체 내부에는 실제 빈을 요청하는 로직이 들어있어, 클라이언트의 요청이 오면 그때 실제 빈을 호출해준다.(실제 빈의 조회를 필요한 시점까지 지연 처리)
  • 프록시 객체는 원래 빈을 상속받아서 만들어지기 때문에 클라이언트 입장에서는 실제 빈을 사용하는 것과 똑같은 방법으로 사용하면 된다.
  • @Scope 애노테이션의 proxyMode 옵션을 사용하여 설정할 수 있다.
@Component
//클래스가 아닌 인터페이스라면 ScopedProxyMode.INTERFACE
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) //프록시 설정
public class HelloBean {

    public void hello() { ... }
}

@Service
public class HelloService {

        //실제 HelloBean 객체가 아닌 가짜 프록시 객체
    @Autowired HelloBean helloBean; 

    public void method() {
                //실제 요청이 일어날 때 프록시 객체는 실제 HelloBean의 메서드를 호출해준다.
                helloBean.hello();
    }
}

그렇다면 정말로 주입 받는 빈이 실제 빈이 아닌 프록시 객체인지 확인해보도록 하자.

@Component
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class HelloBean {

    public void printRealBean() {
        System.out.println("RealHelloBean: " + this.getClass().getSimpleName());
    }
}

@Service
public class HelloService {

    @Autowired HelloBean helloBean;

    public void printProxyBean() {
        System.out.println("ProxyHelloBean: " + helloBean.getClass().getSimpleName());
        helloBean.printRealBean();
    }
}

printProxyBean() 메서드를 호출해보면 자동 의존 주입을 통해 받은 HelloBean객체는 가짜 프록시 객체임을 알 수 있다.

//printProxyBean 메서드 호출 결과
ProxyHelloBean: HelloBean$$EnhancerBySpringCGLIB$$35c7aa62
RealHelloBean: HelloBean

댓글