[Spring] 스프링을 구동하면 일어나는 일 / 생성자 주입을 사용해야 하는 이유 (스프링 빈 라이프사이클)
스프링을 구동 (run) 하면 일어나는 일들을 알아보며 생성자 주입과 필드 주입의 차이를 알아보자.
스프링을 구동하면 스프링은 스프링 빈 라이프사이클을 거치며, 7단계의 순서로 진행이 된다.
스프링 컨테이너 생성 → 빈 생성 → 의존성 주입 → 초기화 콜백 메서드 호출 → 사용 → 소멸 전 콜백 메서드 호출 → 스프링 종료
자세히 알아보자.
1. 스프링 컨테이너 생성
스프링을 구동하면 , 먼저 스프링 컨테이너가 생성이 된다.
컴포넌트스캔이나 @Bean 으로 등록된 클래스 등 빈으로 설정한 아이들을 스프링 컨테이너 생성과 함께 모두 빈으로 등록한다.
2. 빈 생성
스프링 컨테이너는 등록된 빈의 클래스를 기반으로 실제 빈 객체를 생성한다. 스프링을 실행(run) 하자마자 빈 등록과 빈 생성이 바로 이루어진다.
이 때, 필드 주입이나 세터 주입 시에는 실행 시에 빈 생성까지만 진행이 되고 , 런 타임 전까지는 의존성 주입이 되지 않는다.
생성자 주입 시, 빈 생성과 동시에 아래 단계인 의존성이 주입된다.
생성자 주입 시에 의존성 문제 중 하나인 순환 참조가 걸려있으면 실행하자마자 바로 오류가 나는 이유이다.
실행하자마자 생성자 주입 & 의존성 주입이 이루어지니, 의존성 문제인 순환 참조 문제가 바로 들통나버리게 되는 것이다.
그러므로 실행 자체가 되지 않는다. APPLICATION FAILED TO START 가 떠 버리는 것이다.
덕분에 개발자는 실행 시에는 순환 참조 문제가 숨겨져있다가, 런타임 시 오류가 나는 불상사를 예방할 수 있다. 😍
실행이 잘 되서 기쁘다가 런타임시 오류가 나면 짜증나니까.
생성자 주입의 큰 장점이다. 실행하자마자 빈 생성과 동시에 의존성 주입이 된다는 것 !! 😍😍😍 😍
3. 의존성 주입
필드 주입이나 세터 주입의 경우 ,
생성된 빈 객체에 필요한 의존성(다른 객체)이 있다면, 스프링은 빈 생성 이후에 해당 의존성을 주입한다.
필드/ 세터 주입 시, 순환 참조가 걸려있으면 실행하자마자 의존성 주입이 일어나지 않기 때문에 실행 시에는 오류가 안나는 것이다.
그 대신 런타임 시 (http 요청 시) 의존성이 주입되기 때문에, 런타임시 예기치 못한 순환 참조 오류가 나는 것이다. 😱
필드/ 세터 주입을 사용하는 경우, 의존성이 제대로 주입되는 지를 실행 시에 확인을 못하기 때문에,
시한 폭탄 같은 런타임에러를 안고 가야 하는 것이다 😱😱😱😱
그리고 주입 시, 스프링은 우선 빈의 '타입'으로 매칭을 시도하고, 타입으로 빈을 찾지 못하면 '이름'으로 매칭을 시도한다.
4. 빈 초기화 콜백
빈 생성 & 의존성 주입 후에 @PostConstructor가 붙은 초기화메서드가 호출된다. 이 메서드에서 빈의 초기화 로직이 수행된다.
5. 사용
이제서야 드디어 빈을 사용할 수 있다!
6. 소멸 전 콜백 메서드 호출
7. 스프링 종료
끝!
참고
https://docs.spring.io/spring-framework/reference/index.html
https://wildeveloperetrain.tistory.com/m/139
https://jh-labs.tistory.com/108