ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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

    댓글

Designed by Tistory.