-
Spring @RequestScope 빈 스코프spring/core 2022. 8. 7. 16:48
스프링에서 관리하는 빈의 스코프는 기본값이 싱글톤이다. 웹애플리케이션을 운영하는 경우 사용자마다 다른 데이터를 갖고 서버에 진입할 수 있고 다른 데이터를 갖는다면 싱글턴빈으로는 그 값을 표현할 수 없다. 사용자마다 다른 데이터를 갖는 빈을 마치 스프링이 관리하는 싱글턴 빈처럼 사용할 수는 없을까?
@RequestScope 사용
@Component @RequestScope @Setter @Getter public class HttpRequest{ private String headerMessage; private int count; }
@Slf4j @RequiredArgsConstructor @RequestMapping @RestController public class TestController { private final HttpRequest request; @GetMapping public void test(){ request.setCount(request.getCount()+1); log.info("count : {} ", request.getCount()); } }
HttpRequest에 @RequestScope 애너테이션을 붙여 스코프를 명시해주고 @Component를 붙여 빈으로 등록해준다. 그다음 빈을 주입받길 원하는 빈 TestController에 원래 하던 것처럼 HttpRequest를 주입해주고 매핑할 메서드에 request의 카운트를 늘려준다.
TestController에 주입해준 HttpRequest가 싱글턴이라면 count의 값은 매 요청마다 1씩 늘어나면서 출력할 거고, 매번 새로운 빈이라면 아무리 요청을 계속 넣어도 1만 출력할 거다.
curl을 이용해 테스트해보면 count는 계속 1로 찍히는 걸 확인할 수 있다.
의문점
근데 곰곰이 생각해보면 TestController에 final키워드로 붙은 HttpRequest에 매번 새로운 빈을 컨테이너가 주입해주는 게 말이 될까? 말 안된다. 로그에 HttpRequest의 해시코드를 추가로 출력해보자.
@Slf4j @RequiredArgsConstructor @RequestMapping @RestController public class TestController { private final HttpRequest request; @GetMapping public void test(){ request.setCount(request.getCount()+1); log.info("hashCode : {}, count : {} ", request.hashCode(), request.getCount()); } }
...?
HttpRequest의 해시코드값이 매번 같은 값으로 나온다. 즉, TestController에 최초로 주입된 HttpRequest는 분명 싱글턴으로 동작하고 있다. 생각해보면 curl로 요청이 들어갈 때 HttpRequest의 생명주기가 시작되는데 TestController는 애플리케이션이 부팅되는 시점에 생성되고 그에 맞게 최초 HttpRequest또한 생겨야 정상인 거다.
엄밀히 말하면
디버거를 통해 주입된 HttpRequest를 까보면 이상한 걸 알 수 있다. 결론부터 말하자면 TestController 에 주입된 HttpRequest는 스프링이 HttpRequest에 붙은 애너테이션 @RequestScope를 보고 프록시 싱글턴빈을 생성해 주입한 빈이다. 실제로 우리가 의도한 대로 사용할 HttpRequest(count = 1을 응답해주는)는 빈 사용 시점까지 생성을 지연시킨다.
마치며
@RequestScope와 Intercepter를 잘 활용하면 웹 애플리케이션의 유저 별 정보나 로그찍기를 깔끔하게 할 수 있을 것 같다. 다만, 비지니스 코드에 직접 빈을 주입하는 건 스프링에 대한 지식이 많이 필요하므로 부적절한 것 같기도 하다.(애초에 스프링 애너테이션은...?)
프록시를 생성하는 과정을 좀 더 파보고 싶지만 이 과정 또한 문맥에 맞게 Lazy Propagation하도록 하자 ^^....
'spring > core' 카테고리의 다른 글
Spring 에러 핸들링 (0) 2021.10.02 Spring @Scheduled 사용 및 동작원리 (1) 2021.05.19 Spring Interceptor 사용 및 동작 정리 (0) 2021.05.14 스프링 DI 방법 (0) 2021.05.06 스프링 부트 자동설정 과정 (0) 2021.04.06