안녕하세요!
지난 9월 19일 오후 7시 EFUB 동아리에서 진행한 “퍼비톡”에서 application context에 대해서 발표를 진행했습니다.
피피티와 함께 발표 내용을 공유하고자 글을 작성하게 되었습니다.
영상링크 -> https://www.youtube.com/watch?v=tAXa8-qWewA&t=65s
저는 스프링의 핵심 개념인 Application context 발표를 맡게 된 권지윤입니다.
🍀 목차
먼저, 들어가기 전 중요한 개념들에 대해서 간단하게 설명하고
-> 스프링컨테이너 종류인 Beanfactory와 Application에 대해서 소개 후
-> springBootApplication 을 실행하면 어떤 일이 일어나는지 applicationContext 중심으로 살펴보겠습니다.
🍀 1. 들어가며
💚[Spring Container]
저는 전적으로 믿어야하는 김주형쌤과 비슷하다고 생각했습니다.
우리가 프레임워크 없이 개발할 때에는 "객체의 생명주기"(객체의 생성, 설정, 초기화, 메소드 호출, 소멸)을 프로그래머가 "직접 관리"해야합니다
이와 같이 "개발자가 작성한 객체나 메서드의 제어를 개발자가 아니라 외부에 위임하는 설계 원칙"을
제어의 역전이라고 한다.
스프링 컨테이너는 자바 객체의 생명주기를 관리하는데 이러한 자바 객체를 “스프링 빈”이라고 합니다.
그렇다면 스프링 빈에 대해서 구체적으로 알아볼까요?
💚[Spring Bean]
그리고 스프링 IOC 컨테이너가 메타정보(BeanDefinition)만을 보고, 이를 기반으로 스프링 빈을 생성합니다.
여기서 의존성이 나왔는데요!
이 의존성은 어떤 객체에 스프링 컨테이너가 또 다른 객체와 의존성을 맺어주는 행위라고 할 수 있습니다.
이 기능에 중점을 둔다면 스프링 컨테이너를 "DI 컨테이너"라고 부르기도 합니다!
여기까지 스프링 컨테이너란, "스프링 빈(Bean)의 생성과 소멸 등의 라이프사이클을 관리하고, 빈들의 의존성을 관리한다"라고 말할 수 있을 것 같습니다.
🍀 2. BeanFactory or ApplicationContext?
이 스프링 컨테이너에는 2가지 종류가 있는데요, BeanFactory와 이를 상속한 application context입니다.
그 이유는 애플리케이션을 개발할 때는 빈 관리, 조회하는 기능외에 수많은 부가 기능이 필요하기 때문입니다.
🍀 3. ApplicationContext?
Applicatoin context는 더 고급 생명 주기관리 기능을 제공합니다.
더 자세히 살펴보겠습니다.
💚 [다양한 설정 형식 지원]
application context의 경우 @Autowired 어노테이션으로도 자동 주입이 가능합니다.
💚 [Spring Bean의 생성 / 로딩 시점]
다음으로는 생성,로딩 시점입니다.
BeanFactory는 빈이 필요한 시점에 생성합니다 미루고 닥쳐서 하는 MBTI로 치면 P와 같은 면을 보입니다.
지연 로딩의 장점으로는 최대한 불러오는 것을 늦춰 메모리 운용의 효율성을 높일 수 있습니다.
즉시로딩은 애플리케이션 구동 시점에서 설정이나 주변 환경의 오류를 즉시 발견할 수 있는 장점이 있습니다.
💚 [ 후처리 ]
다음으로는 후처리 부분입니다.
applicationContext는 BeanFactory와 달리BeanFactoryPostProcessor과 BeanPostprocessor을 "자동으로 등록"해줍니다.
좀 더 자세히 알아보자면,
일반적으로 빈의 스코프, 프로퍼티 값, 설정 메타데이터 등을 변경하거나, 런타임 시에 추가적인 설정이나 처리가 필요할 때 사용합니다.
postProcessBeanFactory메서드를 구현해서 사용하는데, 마지막에 SpringBootApplication.run()을 실행하는 과정 중에 등장할 예정입니다.
이에 대한 예시로 @Value 어노테이션이 있습니다.
이 코드는 제가 지금 하고 있는 프로젝트의 설정 파일과 JWT를 생성하는 클래스입니다.
저희는 보통 application.yml 파일(혹은 프로퍼티스 파일)을 사용하여 애플리케이션의 여러 설정을 관리할 수 있는데요, 이 파일은 자동으로 로드되며 오른쪽 사진과 같이 @Value 애노테이션은 런타임 시에 해당 프로퍼티의 값을 해당 필드에 주입합니다.
💚 [ BeanScope ]
💚 [ 부가 기능 ]
공식 문서에는 'org.springframework.context" 패키지는 애플리케이션 프레임워크 지향적인 스타일의 추가 기능을 제공한다고 작성되어 있습니다. 아까 applicationContext는 빈생성, 의존성 주입 외에 수많은 부가 기능을 제공한다고 말씀 드렸는데 그 "부가 기능"에 해당하는 것이라고 볼 수 있습니다.
application Context는 이러한 관계를 가지고 있고 하나씩 살펴보면
만약 주문을 하면 "주문 처리 후 -> 푸쉬 알림 and 메일 전송"의 기능이 있다면
주문 로직에 푸쉬 알림과 메일 전송 로직의 의존성 주입으로 인해 다음과 같이 의존성 주입이 많아집니다. (주문 로직에는 알림, 메일 전송 뿐만 아니라 다양한 로직이 있으니까 의존성 주입이 많아질 것입니다)
@RequiredArgsConstructor
@Service
public class 주문{
private final 푸쉬알림 pushAlarmService;
private final 메일전송 mailService;
public 주문처리(){
//다른 로직
publicAlarmService.send();
mailService.send();
}
}
하지만 이벤트로 분리된 부분을 이렇게 이벤트로 구현한다면 의존성을 줄일 수 있고 이벤트는 비동기 방식으로 처리하기 때문에 전체 프로세스가 끝나는 시간도 짧아지게 됩니다.
@RequiredArgsConstructor
@Service
public class 주문{
private final ApplicationEventPublisher publisher; //이벤트
public 주문처리(){
//다른 로직
publisher.publishEvent(new OrderedEvent(productName));
}
}
다음으로는 environment capable(케이퍼블)은 로컬, 개발, 운영 등을 구분해서 처리할 수 있게합니다.
4. SpringBootApplication.run() 실행 동작 과정
이거 많이 실행해보셨죠? 실행할 때 어떤 동작 과정이 있는지 순차적으로 살펴보겠습니다.
[ 애플리케이션 컨텍스트 생성 전 ]
1. StopWatch(스탑워치)로 실행 시간 측정 시작합니다.
2. 다음으로 BootStrapContext 생성
이는 애플리케이션 컨텍스트가 준비될 때 까지 임시 컨텍스트로, 환경 변수들을 관리하는 스프링의 Environment 객체를 후처리하기 위한 것입니다.
3. Java AWT Headless Property 설정
4. 스프링 애플리케이션 리스너 조회 및 starting 처리
5. Arguments(아규먼트) 래핑 및 Environment 준비
애플리케이션 타입에 맞게 Environment 구현체를 생성합니다.
6. IgnoreBeanInfo 설정
7. 배너 출력
[ 애플리케이션 컨텍스트 생성 이후 ]
8. 애플리케이션 컨텍스트 생성
애플리케이션 컨텍스트를 생성하는 코드는 다음과 같은데, 팩토리 클래스에게 생성을 위임하는 것을 확인할 수 있습니다.
9. Context 준비 단계를 거쳐
10. Context Refresh 단계가 되면
코드를 통해 자세히 봅시다
1) 먼저 refresh 준비를 합니다.
2) BeanFactory를 준비하고
3) 아까 살펴보았던 BeanFactoryPostProcessor 메소드를 실행합니다.
4) 그리고 빈으로 등록될 객체들의 정보를 등록합니다. (실제 빈등록이 아닙니다)
5) 그 다음 또 아까 살펴보았던 BeanPostProcessor을 등록합니다.
11. Context Refresh 후처리 하고
12. 실행 시간 출력 및 리스너 started 처리합니다.
아래의 로그 많이 보셨죠?
13. 마지막으로 Runners 실행됩니다
callRunners(context, applicationArguments);
참고 자료
- https://docs.spring.io/spring-framework/reference/core/beans/beanfactory.html#context-introduction-ctx-vs-beanfactory
- https://docs.spring.io/spring-framework/reference/core/beans/introduction.html
- https://medium.com/@alexeynovikov_89393/spring-internals-1-applicationcontext-simple-overview-416cbcfc07a3
- https://www.geeksforgeeks.org/spring-applicationcontext/
- https://mangkyu.tistory.com/213
'EFUB' 카테고리의 다른 글
[세션] 온보딩_백엔드 (0) | 2022.03.30 |
---|---|
[세션] 온보딩_프론트엔드 (0) | 2022.03.26 |
[활동] OT (0) | 2022.03.18 |