웹 스코프
웹 스코프는 웹 환경에서만 동작한다. 웹 스코프는 소멸될 때까지 관리를 해준다. (PreDestroy 메서드 실행된다.)
4가지 종류가 있는데 첫번째인 request 스코프만 강의에서 설명해주었다.
- request: HTTP 요청 하나가 들어오고 나갈 때까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고,
관리된다. - session: HTTP Session과 동일한 생명주기를 가지는 스코프
- application: 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프
- websocket: 웹 소켓과 동일한 생명주기를 가지는 스코프
request 스코프는 HTTP요청이 들어올 때마다 새로운 빈이 생성된다. 하지만 같은 HTTP의 요청은 하나의 빈으로
관리한다. 즉 각각의 클라이언트의 요청에 대응하는 하나의 빈이 존재하는 것이다. 소멸되기 전까지 하나의
클라이언트만 바라본다(?)
request 스코프를 테스트하는 예제에서 controller에 MyLogger를 의존 관계 주입을 하여 사용한다. 지금까지 배운 방법으로 그냥 작성하면 이유가 생긴다. 이유는??? MyLogger는 request스코프이다. request스코프는 HTTP요청이 들어올 때 생성한다. 처음에 컨테이너만 뛰우는 상황에서는 요청이 없기때문에 MyLogger는 생성되지 않고 그러기에 DI가 일어날 수 없다.
해결 방법은 두 가지가 존재한다. 우선 전에 배웠던 Provider를 사용하는 것이다. ObjectProvider<MyLogger>로 등록하고 요청이 왔을 때 .getObject()를 사용해서 그때 MyLogger를 꺼내면 된다. 같은 HTTP 요청일 경우 어디서 .getObject()를 사용해도 같은 스프링 빈이 반환된다.
프록시
두 번째 해결 방법이다. 프록시 방식을 사용하는 것이다. 가짜를 사용하는 것이다.
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger{
}
옵션에서 적용 대상이 인터페이스이면 TARGET_CLASS 대신 INTERFACES를 사용하면 된다.
@Scope에 proxyMode 옵션을 작성해준 후 원래대로 코드를 작성하면 된다. 이러면 HTTP요청이 없어도 가짜 클래스를 만들어서 주입을 해준다. 그런 후 요청이 있을 때 실제 클래스로 바꾸어 사용한다. 가짜 프록시 클래스는 request scope와는 관계 없다. '가짜'이며 그저 클라이언트 입장에서는 진짜인지 가짜인지 모르게 동일하게 사용 가능하다. 프록시 클래스는 CGLIB 라이브러리로 진짜 클래스를 상속받은 클래스다.
두 개의 방법 모두 진짜 객체 조회를 꼭 필요한 시점까지 지연 처리한다. 싱글톤을 사용하는 것 같지만 다르게 동작하기 때문에 주의를 해주어야 한다.
이러한 특별한 scope를 무분별하게 사용하면 유지 보수하기 힘들어지므로 필요한 곳에서만 사용하도록 하자~~
(log 찍을 때 http별 id를 부여하기 위해 자바 util에 있는 UUID.randomUUID()를 사용하였다. 같은 것이 나올 확률 로또 300개 맞을 확률로 (그냥 대충) 랜덤 아이디를 생성해준다.)
스프링 기본 편 다 들었다~~~ 빨리 다음 거 들어야지..... 겨울에 해커톤 나가야지........ dmalon 함께 하도록. 아이디 이거 맞냐?
'Spring' 카테고리의 다른 글
[Spring] @JoinColumn & 연관관계 맵핑 @Mappedby (외래키 주인? 연관관계 주인?) (1) | 2023.01.13 |
---|---|
[Spring] Gradle vs Maven (빌드? 빌드 도구?) (0) | 2022.12.29 |
[Spring] 빈 스코프 (프로토타입) (0) | 2022.08.09 |
[Spring] @Qualifier, @Primary & 빈 생명주기 콜백 (2) | 2022.08.06 |
[Spring] 의존관계 자동 주입 방법 & 옵션 처리 & LOMBOK(롬복) (0) | 2022.08.01 |