Post

스프링 핵심원리 - 기본편 정리4

스프링 핵심원리 - 기본편 정리4

스프링 핵심원리 - 기본편 강의를 정리하는 마지막 글이다. 이번에는 빈의 생명주기와, 빈 스코프에 대해서 알아볼 것이다.

빈 생명주기와 콜백

  • 스프링 컨테이너에서 빈이 생성되고 사라질 때까지 거치는 특정 단계들을 말한다.

스프링 빈의 라이프 사이클은 다음과 같다. (싱글톤 기준)

1. 스프링 컨테이너 생성
2. 빈 객체 생성
3. 의존관계 주입
4. 생성 후 초기화 콜백
5. 사용
6. 소멸 전 콜백
7. 스프링 컨테이너 소멸

생성과 초기화를 분리하자

- 생성은 객체의 필수적인 값만 받아 메모리를 할당하는 것이고, 초기화는 할당된 값들을 활용하여 외부 커넥션을 연결하는 등 무거운 작업을 수행한다. (초기화 작업이 가벼운 경우, 생성과 동시에 처리 가능)

여기서 4,6번의 콜백함수를 지정하는 방법은 총 3가지가 있다. 3가지 방법에 대해서 알아보자


세가지 방법

1. 인터페이스 이용

- 등록할 빈이 InitializingBean_과 _DisposableBean 인터페이스를 구현한다.

콜백 인터페이스 선언 등록할 빈에 위 인터페이스를 구현한다고 선언하고

콜백 인터페이스 구현

위의 소멸 콜백 로직을 작성할 destroy 메서드, 초기화 콜백 로직을 작성할 afterPropertiesSet 메서드를 오버라이딩 해주면 된다.

단점

  • 스프링 전용 인터페이스이기에 스프링 인터페이스에 의존한다.
  • 콜백 메서드 이름을 변경할 수 없다.
  • 코드를 고칠 수 없는 외부 라이브러리에 적용할 수 없다.

2. 등록 할 때 콜백 메서드 지정

- @Bean 어노테이션으로 등록을 함과 동시에 옵션으로 initMethod, destroyMethod에 콜백함수명을 지정한다.

옵션을 통해 메서드명 지정 위와 같이 등록을 함과 동시에 콜백메서드 명을 지정한다.

지정한 콜백 메서드

만들어 놓은 콜백 메서드이다.

특징

  • 콜백 메서드 이름을 지정할 수 있다.
  • 스프링 인터페이스에 의존하지 않는다.
  • 옵션을 이용한 것이기 때문에 코드를 고칠 수 없는 외부 라이브러리의 초기화, 종료 메서드를 이용할 수 있다.

+ destroyMethod 속성은 디폴트 값(inferred)으로 되어있으면 ‘close’, ‘shotdown’ 이름의 메서드를 찾아(추론) 자동호출한다.

3. 어노테이션 이용

- @PostConstruct, @PreDestroy 어노테이션을 붙혀 콜백 메서드로 지정한다.

어노테이션 이용

위처럼 메서드에 어노테이션만 붙혀 콜백으로 등록한다.

  • 가장 편리하고 메서드명도 자유로우며 자바 표준 기술이다.
  • 일반적으로는 콜백 메서드 등록을 할 때 어노테이션 방법을 사용하되, 외부라이브러리의 콜백이 필요할 때에는 2번 방법(Bean 옵션 등록)을 사용하자

빈 스코프

- 말 그대로, 빈이 존재할 수 있는 범위

빈 스코프는 총 6종류가 있다. 빈 스코프 종류

1. 싱글톤 - 앞에서 설명했듯이 1개의 객체의 생성을 보장해주고, 스프링 컨테이너의 시작과 종료까지 존재한다.

2. 프로토타입 - 조회 시 등록된 빈의 새로운 인스턴스를 반환해주고, 스프링이 생성, 의존관계 주입, 초기화 까지만 관여한다. 이후에는 클라이언트가 관리해야한다.

3 ~. 나머지는 웹과 관련된 스코프다. 대표적으로 request 스코프는 각각의 http 요청이 들어오고 나갈 때마다 생성되고 소멸된다.

### 싱글톤 빈과 함께 사용 문제 싱글톤과 프로토타입 스코프를 동시에 사용하면 문제가 될 경우가 있다. 싱글톤으로 등록된 빈이 필드로 프로토타입 스코프로 등록된 빈을 가지는데, 등록된 프로토타입 스코프의 빈이 새로운 객체처럼 동작하는 것을 기대할 경우이다.

말이 어려우니 그림을 통해서 보겠다. 싱글톤과 프로토타입1 위와 같이 스프링 컨테이너에 싱글톤으로 등록된 빈은 의존관계 주입 때 새로운 프로토타입 객체에 의존하게 된다.

싱글톤과 프로토타입2 그리고 A클라이언트는 ClientBean을 받아 logic을 호출하여 프로토타입 객체의 필드의 Count가 0에서 1로 올라가게 된다.

싱글톤과 프로토타입3

그런데 여기서 B클라이언트가 또다시 ClientBean을 받아 addCount를 하는 logic을 호출한다.

이 때 PrototypeBean을 프로토타입 스코프로 지정했기 때문에 새로운 객체를 생성하여 카운팅 한다고 생각할 수 도 있지만,

이미 싱글톤에 의존관계를 주입할 때 생성된 객체에 다시 카운팅을 하게된다.

그렇다면 클라이언트가 logic을 호출할 때마다 프로토타입으로 등록된 새로운 객체를 가져오려면 어떻게 해야할까?

가장 먼저 떠오르는 방법은 각각의 logic마다 스프링 컨테이너에 프로토타입을 빈을 달라고 요청하는 것이다.(DL)

하지만 이렇게 되면 스프링 컨테이너를 직접 멤버로 가지고 있어야하는데 이렇게 되면 단위 테스트도 힘들어지고 무거운 느낌이 든다.

이것을 해결해줄 수 있는 것이 Provider이다.

DL

- 외부에서 의존관계를 주입 받는 것은DI, 직접 의존관계를 찾는 것은 DL(Dependency Lookup)이라고 한다.

Provider

Provider를 이용하면 스프링 컨테이너를 멤버로 가질 필요 없이 직접 컨테이너에 빈을 찾도록 요청할 수 있다

스프링에서는 ObjectProvider_과 _ObjectFactory 클래스를 통해 얻을 수 있고, 자바표준으로도 Provider 클래스를 통해 얻을 수 있다.

자바 표준 Provider👆자바표준 Provider 사용법

스프링 ObjectProvider

👆스프링 ObjectProvider/ObjectFactory 사용법



둘 모두 사용법은 비슷하다. 제네릭으로 조회할 타입을 지정하고 get~ 메서드를 이용하여 컨테이너에 직접 요청하는 것이다!

☝ObjectProvider, ObjectFactory 차이점 ObjectProvider 인터페이스 ObjectProvider는 ObjectFactory를 상속한 기존 DL기능에 편의 기능을 더한 것이다.


웹 스코프

웹 스코프는 예제 중심이기 간략하게 정리만 하자면(절대 귀찮아서 그러는거 아님..)

웹 스코프는 http요청, session 등 웹과 관련된 것에 생명주기를 두고있다.

앞에서 싱글톤과 프로토타입 같이 사용할 때의 문제를 Provider를 사용하여 한 것처럼, http request를 기록할 Logger를 만들 때 싱글톤과 request 스코프 같이 사용하는데 Provider를 이용할 수 있다.

그런데 여기서 Provider가 아닌 그냥 미리 싱글톤처럼 등록하고 역할을 위임하는 프록시를 활용해서도 해결할 수 있다.


스프링 핵심원리 기본편 정리가 끝났다. 지난학기 때 아무것도 모를 때 맨땅에 박치기 하는 느낌으로 스프링으로 프로젝트를 했었는데, 지금 다시 돌아가보면 어떤식으로 돌아가는지 이해할 수 있을 것 같다.

그때 했던 프로젝트를 리팩토링하고, 미완성이었던 부분을 보충해서 끝까지 한번 만들어봐야겠다👊👊

자료 출처: 영한님 스프링 기본편 강의 , 스프링 공식 문서

This post is licensed under CC BY 4.0 by the author.