백앤드/SpringBoot + Java 스프링 기본

[SpringBoot + Java] 스프링 기본(Bean 의 생명주기 콜백)

맏리믓 2023. 8. 8. 17:59

들어가며

- 인프런 김영한 님의 빈 생명주기 강의 정리 입니다.

- 강의의 예시를 가져와 보자면 외부 네트워크에 연결 해야 하는 객체를 생성 한다고 가정 할 때 다음 문제가 발생 할 수 있습니다.

 . 객체가 생성 됨과 동시에 모든 의존 주입을 마친다면 url 과 같이 외부에서 데이터를 받아서 주입 해야 하는 데이터의 경우 원치 않는 값으로 생성 되게 됩니다.

 . 또한 스프링 컨테이너가 종료 되기 직전에 스프링 빈을 안전하게 소멸 시켜야 안전한 종료가 가능 합니다.


스프링 빈의 생명주기

- 스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸전 콜백 -> 스프링 종료

- 위의 생명주기를 따르게 되면 빈이 생성 된 후 의존 관계를 주입 하게 되고 사용 준비가 끝난 후 콜백을 호출 해 사용 할 수 있기 때문에 위의 문제를 해결 할 수 있습니다.

- 또한 종료 시점에도 소멸전 콜백을 호출 하기 때문에 안전한 종료가 가능 합니다.


스프링의 생명주기 콜백

- 이러한 생명주기 콜백을 보장 하기 위해 스프링은 크게 3가지 콜백을 지원 합니다.

 . 인터페이스(InitailizingBean, DisposableBean) 을 사용

 . 설정 정보에 초기화, 종료 메소드를 지정

 . 관련 에노테이션을 지원


인터페이스 사용

- 아래 코드와 같이 (InitailizingBean, DisposableBean) 인터페이스를 Override 하여 초기화 메소드인 connect와 소멸 메소드인 disconnect 를 실행 시킬 수 있습니다.

- 단점

 . 하지만 해당 인터 페이스는 스프링에서만 사용 가능하며 코드를 수정 해야 하기 때문에 외부 라이브러리에는 적용이 불다능 합니다.

Public class NetworkClient implements InitializingBean, DisposableBean{
	//...
    public void connect(){ // 서비스 시작 시 연결 관리
    	//...
    }

    public void disconnect(){ // 서비스 종료 시 연결 해제
    	//...
    }
    
    @Override 
    public void afterPropertiesSet() throws Exception {
    	connect();
	}
    
    @Override 
    public void destroy() throws Exception {
    	disconnect();
	}
    

}

설정 정보를 이용

- 설정 정보에 initMethod 와 destroyMethod 를 지정 하는 방법 입니다.

- 특징

 . 콜백 메서드의 이름을 자유롭게 설정 할 수 있고 코드를 수정 하지 않아도 되기 때문에 외부 라이브러리에도 적용이 가능 합니다.

public class NetworkClient {
	//...

	public void init() {
		System.out.println("NetworkClient.init");
		connect();
		call("초기화 연결 메시지");
	}
	public void close() {
		System.out.println("NetworkClient.close");
		disConnect()	
	}
}
@Configuration
static class LifeCycleConfig {
	@Bean(initMethod = "init", destroyMethod = "close")
	public NetworkClient networkClient() {
		NetworkClient networkClient = new NetworkClient();
		networkClient.setUrl("~~~");
		return networkClient;
	}
}

에노테이션 사용

- @PostConstruct, @PreDestroy 에노테이션을 사용 하는 방법입니다.

 . 코드를 수정 한다는 점에서 인터페이스 사용과 비슷하게 보일 수 있지만 해당 애노테이션은 자바 표준이기 때문에 스프링이 아니여도 동작이 가능 합니다.

 . 하지만 결국 코드를 수정 해야 하기 때문에 외부 라이브러리에서 사용이 불가능 합니다.

public class NetworkClient {
	//...
	@PostConstruct
	public void init() {
		System.out.println("NetworkClient.init");
		connect();
		call("초기화 연결 메시지");
	}
	@PreDestroy
	public void close() {
		System.out.println("NetworkClient.close");
		disConnect()	
	}
}

마치며

- 스프링 빈의 생명주기인 "스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸전 콜백 -> 스프링 종료"를 보장 하기 위한 방법 3가지를 알아 보았습니다.

- 요즘엔 마지막 방법이었던 에노테이션을 주로 사용하며 일부 코드를 수정 해야 할 경우 Bean 을 통한 설정 지정 방식을 사용 한다고 합니다.