본문 바로가기

PROGRAMMING/SPRING

[SPRING] Web Scope

빈 스코프  이전 포스팅

 

[SPRING] Bean Scope 싱글톤과 프로토타입

빈 스코프 빈이 존재할 수 있는 범위를 뜻한다. 크게 싱글톤과 프로토 타입이 있고 웹 스코프로 리퀘스트, 세션, 글로벌 세션이 있다. 스프링에선 따로 지정하지 않으면 디폴트 생성 옵션인 싱글

dvpdvp.tistory.com

 

 

싱글톤과 프로토타입이 아닌 웹 스코프에 대해 포스팅해보려 한다.

 

웹 스코프는 웹 환경에서만 동작하고, 스프링에서 스코프의 종료 시점까지 관리한다.

request, session, global 3종류가 있는데

각자 생명주기만 다를 뿐 동일하게 동작한다.

 

대표적으로 request scope는 http 요청이 들어오고 나갈 때까지 유지된다.

 

활용하기 좋은 예제

동시에 수많은 HTTP 요청이 오면 로그를 남겨도 뭐가 뭔지 구분하기 힘들다.

request scope을 활용하면 요청 별로 UUID를 남겨 쉽게 구분할 수 있다.

 

간단한 예제 코드

request scope의 로깅 클래스 

package hello.core.common;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.UUID;

@Component
@Scope(value = "request")
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);
    }
}

 

로그 호출 컨트롤러

package hello.core.web;

import hello.core.common.MyLogger;
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;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequiredArgsConstructor
public class LogDemoController {

    private final LogDemoService logDemoService;
    private final ObjectProvider<MyLogger> myLoggerProvider;

    @RequestMapping("log-demo")
    @ResponseBody
    public String logDemo(HttpServletRequest request){
        String requestURL = request.getRequestURI().toString();
        MyLogger myLogger = myLoggerProvider.getObject();
        myLogger.setRequestURL(requestURL);

        myLogger.log("controller");
        logDemoService.logic("testId");
        return "OK";
    }
}

(서비스도 이와 비슷하게 구현)

 

로그

로그를 확인해 보면 

Controller에서 로그를 남기던 Service에서 남기던 같은 HTTP안에서는 같은 UUID를 남길 수 있다.

 

Provider 없이 request scope으로 선언하면 에러가 발생하는데

이유는 request 내에서 존재를 하는데 처음 띄울 땐 request자체가 없기 때문이다.

(Provider > 스프링 빈이 실제로 필요할 때까지 요청을 미룬다.)

 

 

 

이 또한 귀찮아지면 ObjectProvider 없이 구현하는 방법으로는 프록시가 있다.

 

다음 포스팅에 계속