프록시 방식을 사용
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {
...
}
· proxyMode = ScopedProxyMode.TARGET_CLASS
적용 대상이 클래스면, TARGET_CLASS
적용 대상이 인터페이스면, INTERFACES
· MyLogger 의 가짜 프록시 클래스를 만들어 다른 빈에 미리 주입 가능 (HTTP request 와 상관 없이 주입 가능)
ObjectProvider 적용 이전으로 코드를 돌린다.
- src/main/java/hello/core/web/LogDemoController.java
package hello.core.web;
import hello.core.common.MyLogger;
import hello.core.logdemo.LogDemoService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
private final MyLogger myLogger;
// private final ObjectProvider<MyLogger> myLoggerProvider;
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request) {
String requestURL = request.getRequestURL().toString();
// MyLogger myLogger = myLoggerProvider.getObject(); // request 빈 생성
myLogger.setRequestURL(requestURL);
myLogger.log("controller test");
// Thread.sleep(1000);
logDemoService.logic("testId");
return "OK";
}
}
- src/main/java/hello/core/logdemo/LogDemoService.java
package hello.core.logdemo;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class LogDemoService {
private final MyLogger myLogger;
// private final ObjectProvider<MyLogger> myLoggerProvider;
public void logic(String id) {
// MyLogger myLogger = myLoggerProvider.getObject();
myLogger.log("service id = " + id);
}
}
CoreApplication 에서 main() 메서드로 스프링을 실행하고 브라우저에서 http://localhost:8080/log-demo 로 접속한다.
- 콘솔
[134c70a6-b533-49bd-9204-66154384e9fc] request scope bean create: hello.core.common.MyLogger@c3fa824
[134c70a6-b533-49bd-9204-66154384e9fc][http://localhost:8080/log-demo] controller test
[134c70a6-b533-49bd-9204-66154384e9fc][http://localhost:8080/log-demo] service id = testId
[134c70a6-b533-49bd-9204-66154384e9fc] request scope bean close: hello.core.common.MyLogger@c3fa824
1. 웹 스코프와 프록시 동작 원리
주입된 myLogger 를 확인한다.
- src/main/java/hello/core/web/LogDemoController.java
...
String requestURL = request.getRequestURL().toString();
// MyLogger myLogger = myLoggerProvider.getObject(); // request 빈 생성
System.out.println("myLogger = " + myLogger.getClass());
myLogger.setRequestURL(requestURL);
...
- 콘솔
myLogger = class hello.core.common.MyLogger$$SpringCGLIB$$0
CGLIB 라이브러리로 원본 클래스(MyLogger)를 상속 받은 가짜 프록시 객체를 만들어서 주입
· @Scope 의 proxyMode = ScopedProxyMode.TARGET_CLASS 설정시, 스프링 컨테이너는 CGLIB 라는 바이트 코드를 조작하는 라이브러리를 사용해 원본 클래스(MyLogger)를 상속받은 가짜 프록시 객체를 생성한다.
따라서 의존관계 주입시, 가짜 프록시 객체가 주입된다.
· 콘솔에도 직접 등록한 MyLogger 클래스가 아닌 CGLIB 라이브러리로 만들어진 객체가 대신 등록된 것을 확인할 수 있다.
스프링 컨테이너에 "myLogger" 이름으로 가짜 프록시 객체가 등록됨
ac.getBean("myLogger", MyLogger.class) 로 조회해도 가짜 프록시 객체가 조회됨

가짜 프록시 객체는 요청이 오면 그 때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있음
실제 request 스코프와는 관계 없이, 내부에 단순 위임 로직만 있고, 싱글톤처럼 동작함
· 가짜 프록시 객체 내부에 "myLogger" 를 찾는 방법을 알고 있다.
클라이언트가 myLogger.log() 호출시, 가짜 프록시 객체 메서드를 호출한 것이다.
가짜 프록시 객체는 request 스코프의 진짜 myLogger.log() 를 호출한다.
· 가짜 프록시 객체는 원본 클래스를 상속받아 만들어졌기 때문에, 이 객체를 사용하는 클라이언트 입장에서는 원본인지 아닌지도 모르게 동일하게 사용 가능(다형성)
프록시 객체 덕분에 클라이언트는 싱글톤 빈을 사용하듯 편리하게 request scope 사용 가능
2. 핵심
#1 Provider 를 사용하든, 프록시를 사용하든 핵심 아이디어는 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점!
#2 어노테이션 설정 변경만으로 원본 객체를 프록시 객체로 대체 : 다형성, DI 컨테이너가 가진 큰 강점
#3 웹 스코프가 아니어도 프록시 사용 가능
3. 주의점
#1 싱글톤을 사용하는 것 같지만 다르게 동작하기 때문에 주의해서 사용해야 함 (request 요청마다 따로 생성됨)
#2 이렇게 특별한 scope는 꼭 필요한 곳에 최소화해서 사용
무분별하게 사용시, 유지보수 어려워짐
참고링크 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8?cid=325969
스프링 핵심 원리 - 기본편| 김영한 - 인프런 강의
현재 평점 5.0점 수강생 49,609명인 강의를 만나보세요. 스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다. 스프링 기본 기능, 스프
www.inflearn.com
'강의 실습 > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
| 스코프와 Provider (0) | 2026.05.11 |
|---|---|
| request 스코프 예제 만들기 (0) | 2026.05.10 |
| 웹 스코프 (0) | 2026.05.09 |
| 프로토타입 스코프 - 싱글톤 빈과 함께 사용시 Provider로 문제 해결 (0) | 2026.05.09 |
| 프로토타입 스코프 - 싱글톤 빈과 함께 사용시 문제점 (0) | 2026.05.07 |
댓글