본문 바로가기
Back-end/Spring 개념

15. Bean 생명주기 콜백

by devraphy 2022. 2. 16.

0. 개요

- 실제로 Web App을 운영하면 App 실행 전에 Server는 미리 DB와 연결해두고, 일정량의 Data를 로드해놓는다.

- 더불어 종료 시점에는 모든 작업을 종료하는 과정에서 객체의 초기화와 종료 작업을 필요로 한다.

- 이처럼 운영하는 이유는, 최초에 App을 실행했을 때 Client의 요청에 빠르게 응답하기 위함이다.

- 이 과정을 구현하기 위해 필요한 Spring Bean의 초기화와 종료 과정을 알아보자. 


1. Spring Bean의 생명주기

- 최초에 App이 빌드되는 과정에서, Spring Bean은 객체의 생성을 통해 Spring Container에 등록된 후 의존관계를 형성(주입)한다.

- 이 준비가 완료되어야 Bean을 이용해 다양한 data를 주고받을 수 있다.

- 그러므로 초기화 작업은 의존관계가 형성된 후에 수행되어야 한다.

- 그렇다면 개발자는 이 초기화 작업을 수행하는 시점을 어떻게 알 수 있을까?

 

a) Lifecycle

- Bean이 형성되고 종료될 때까지의 모든 과정을 생명주기라고 한다.

- 기본적인 Bean의 생명주기는 다음과 같은 과정을 거친다.

 

  Continer 생성 → Bean 등록 → DI 주입 → 초기화 → Bean 사용 → 소멸 → Spring 종료 

 

b) Bean 생성과 초기화 작업을 분리하는 이유 

- 생성자 주입을 호출하여 객체의 생성과 초기화를 함께 하도록 하면 되지 않을까?라고 생각할 수 있다.

- 이 경우 생성자는 객체를 생성과 객체의 초기화를 책임지고 있으므로, 이는 SOLID의 SRP에 위배된다.

- 단순히 객체의 내부 값만을 초기화하는 작업이라면, 생성자에서 한 번에 처리하는 것이 효율적일 수 있다.

- 그러나, Spring Bean은 여러 객체 간의 유기적인 연결을 생성하므로 초기화 작업이 단순하지 않다. 

- 이와 같은 이유로 Bean의 생성과 초기화를 분리한다.


2. Bean 생명주기 callback 

- Spring은 Bean의 초기화와 소멸 시점에서 사용할 수 있는 callback 함수를 제공한다.

- 즉, callback 함수는 Spring에 의해 특정 시점에서 호출되는 함수다. 

 

a) Bean 생명주기 callback의 종류

- Spring은 크게 3가지 방법의 생명주기 callback을 지원한다. 

  → InitializingBean, DisposableBean 인터페이스를 이용한 방법

  → 설정 정보에 초기화/종료 메서드를 지정하는 방법

  → @PostConstruct(초기화), @PreDestroy(소멸) 어노테이션을 이용한 방법


3. InitializingBean, DisposableBean

a) InitializingBean 

- DI 주입이 완료된 시점에서 사용할 수 있는 메서드를 제공하는 인터페이스

- afterPropertySet() 메서드를 Override 하여 초기화 시점에서 수행할 작업을 명시할 수 있다.

- Bean 생성 및 DI 주입이 완료된 시점에서 Spring에 의해 자동호출(callback)된다.

 

b) DisposableBean

- Bean 소멸 시 사용할 수 있는 메서드를 제공하는 인터페이스 

- destroy() 메서드를 Override 하여 Bean 소멸 시점에서 수행할 작업을 명시할 수 있다.

- Bean의 소멸 시점에서 Spring에 의해 자동호출(callback)된다. 

 

c) InitializingBean, DisposableBean 사용의 단점

- 해당 인터페이스는 모두 Spring에서만 사용할 수 있는, Spring 전용 인터페이스다.

- 그러므로 외부 라이브러리에서는 해당 메서드를 사용할 수 없다. 

- 더불어, 메서드의 이름을 변경할 수 없고 Spring에서 명시한 메서드 이름을 그대로 사용해야 한다. 

- 이처럼 두 인터페이스를 사용한 코드는 Spring Framework에 의존적인 코드가 된다.

- 이와 같은 이유로 현재는 사용되지 않는 방법이다. 


4. 설정 파일을 이용한 방법

- 설정 파일에는 @Bean을 이용하여 Bean을 등록한다.

- 이때 @Bean의 옵션을 이용하여 초기화 및 소멸 메서드를 명시할 수 있다. 

 

a) @Bean 옵션 

- @Bean에는 initMethod와 destroyMethod라는 옵션이 존재한다. 

- 다음 예시 코드를 참고하자. 

@Bean(initMethod = "초기화 메서드 이름", destroyMethod = "소멸 메서드 이름")

- 이처럼 해당 Bean에서 사용할 초기화 메서드와 소멸 메서드를 등록할 수 있다.

- Spring은 해당 Bean의 초기화 및 소멸 시점에서 해당 메서드를 호출한다. 

 

b) @Bean 옵션 사용의 장점 

- 메서드의 이름을 자유롭게 명시할 수 있다.

- Spring Framework에 의존적이지 않다.

- 설정 정보를 기반으로 코드를 고칠 수 없는 외부 라이브러리에도 적용할 수 있다.

 

c) destroyMethod 옵션의 특별한 기능 

- destroyMethod의 기본 값은 "(inferred)"로 되어 설정되어있다. 

- 이는 문자열로, "추론"을 의미하는 값이다. 여기에 특별한 기능이 있다.

 

- 기본 값의 이름을 "추론"이라 명시한 이유는...

- 외부 라이브러리가 사용하는 소멸 메서드의 이름을 종료 시점에 알아서 호출하기 때문이다. 

- 일반적으로 외부 라이브러리의 Bean 종료 메서드는  close, shutdown과 같은 이름으로 선언되어 있는데,

   이를 알아서 호출해주는 것이다. 

 

- 이와 같은 이유로 @Bean을 사용하는 경우, 종료 메서드를 따로 명시하지 않는 경우가 많다. 

- 만약 추론기능을 사용하고 싶지 않다면, 다음과 같이 공백을 명시하면 된다.

@Bean(destroyMethod = "")

 


5. @PostContruct, @PreDestroy

- 어노테이션의 이름만 봐도 그 기능이 무엇인지 직관적으로 알 수 있지 않은가?

- @PostContruct는 초기화 메서드에, @PreDestroy 소멸 메서드에 부착하면 된다. 

 

a) 장점 

- 사용이 간단하다. 메서드에 해당 어노테이션을 부착하기만 하면 된다. 

- Spring에서 공식적으로 권장하는 방법이다.

- 두 어노테이션은 Java에서 제공하는 기술이므로, Spring Framework에 의존적이지 않다. (javax.annotation)

 

b) 단점

- 외부 라이브러리에 적용할 수 없다. 

- 그러므로 외부 라이브러리에 초기화 및 종료 메서드를 적용하고 싶다면 @Bean을 이용한 방식을 사용해야 한다.


6. 결론

- 지금까지 Bean 생명주기 callback을 사용하는 방법 세 가지를 알아보았다.

- 이 세 가지 방법을 어떻게 사용하는 것이 가장 효율적인 방법일까?

 

- Java 어노테이션(@PostContruct, @PreDestroy)을 메인으로 사용하자.

- 만약 외부 라이브러리에 의한 실행이 필요하다면, @Bean을 이용한 방법을 함께 운용하자. 

'Back-end > Spring 개념' 카테고리의 다른 글

17. Spring 기본개념 총정리  (2) 2022.02.18
16. Bean Scope에 대하여  (0) 2022.02.17
14. Annotation을 만드는 방법  (0) 2022.02.15
13. @Autowired의 다양한 문제 해결방법  (0) 2022.02.14
12. Dependency Injection 방법  (0) 2022.02.11

댓글