스코프와 프록시
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
//@Scope(value = "request")
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {
private String uuid;
private String requestURL;
public void setRequestURL(String requestURL) {
this.requestURL = requestURL;
}
public void log(String message) {
System.out.println("[" + uuid + "] [" + requestURL + "] " + message);
}
@PostConstruct
public void init() {
uuid = UUID.randomUUID().toString();
System.out.println("[" + uuid + "] request scope bean create: " + this);
}
@PreDestroy
public void close() {
System.out.println("[" + uuid + "] request scope bean close: " + this);
}
}
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
처럼 프록시 모드를 사용하면 어떻게 될까?
- 원래라면
@Scope
의 옵션을request
방식으로 설정하면, 각 request마다 별도의 전용 객체가 생성이 된다. - request 요청이 되는 시점에 스프링 컨테이너에서 빈이 생성되기 때문에, 조회를 하려면 lazy 방식을 사용해야한다. 그러므로
ObjectProvider<>
를 사용해야한다.
하지만, ObjectProvider<>
를 사용하지 않는 방식이 있다. 그것은 proxyMode
방식이다.
proxyMode
를 적용하면 MyLogger$$SpringCGLIB$$0
처럼 MyLogger
클래스를 바이트 코드를 조작하여 SpringCGLIB
이 위임받는 것을 볼 수 있다.
즉, CGLIB라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입한다.
그러므로 싱글톤처럼 스프링 컨테이너 후 자동 주입 시점에 가짜 프록시가 들어오게 되는 것이다.
가짜 프록시 객체는 요청이 오면 그때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있다.
- 가짜 프록시 객체가
myLogger.log()
를 호출하면 내부에서 실제 빈을 요청하는 위임 로직으로 인해 진짜MyLogger
클래스의log()
메소드를 호출하는 것이다. - 가짜 프록시 객체는 원본 클래스를 상속 받아서 만들어졌기 때문에 이 객체를 사용하는 클라이언트 입장에서는 사실 원본인지 아닌지도 모르게, 동일하게 사용할 수 있다(다형성)
동작 정리
- CGLIB라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입한다.
- 이 가짜 프록시 객체는 실제 요청이 오면 그때 내부에서 실제 빈을 요청하는 위임 로직이 들어있다.
- 가짜 프록시 객체는 실제 request scope와는 관계가 없다. 그냥 가짜이고, 내부에 단순한 위임 로직만 있고, 싱글톤 처럼 동작한다.
요점 정리
- 사실 Provider를 사용하든, 프록시를 사용하든 핵심 아이디어는 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점이다.
- 단지 애노테이션 설정 변경만으로 원본 객체를 프록시 객체로 대체할 수 있다. 이것이 바로 다형성과 DI 컨테이너가 가진 큰 강점이다.
- 꼭 웹 스코프가 아니어도 프록시는 사용할 수 있다.
주의 사항
- 마치 싱글톤을 사용하는 것 같지만 다르게 동작하기 때문에 결국 주의해서 사용해야 한다.
- 이런 특별한 scope는 꼭 필요한 곳에만 최소화해서 사용하자, 무분별하게 사용하면 유지보수하기 어려워진다.
'Study > Spring' 카테고리의 다른 글
Spring. ObjectProvider (0) | 2024.09.08 |
---|---|
Spring. @Configuration (0) | 2024.09.07 |
Spring. 입문 (0) | 2024.08.16 |