https://sundaland.tistory.com/380
[ ▶ SpringApplication.run ]
SpringApplication.run()은 Spring Boot 애플리케이션의 시작점에서 사용되는 메서드로, Spring Boot 애플리케이션을 실행하고 부트스트랩(초기화)하는 역할을 한다. 이 메서드는 애플리케이션의 실행을 위한 여러 초기화 작업을 수행하며, Spring 컨텍스트를 생성하고 설정을 적용한 후에 애플리케이션을 실행할 준비를 마친다.
[ ▷ SpringApplication.run()의 주요 역할 ]
△ SpringApplication 객체 생성
- SpringApplication.run()은 내부적으로 SpringApplication 객체를 생성하고 이를 통해 애플리케이션을 부트스트랩한다.
- 이 객체는 애플리케이션 실행 중 필요한 환경 설정을 관리하고, 필요한 여러 가지 리스너, 초기화 작업, 애플리케이션 이벤트 등을 처리한다.
△ 애플리케이션 유형 결정
- SpringApplication은 애플리케이션이 웹 애플리케이션인지 비웹 애플리케이션인지 자동으로 감지한다.
- Spring Boot는 클래스패스에 서블릿 관련 라이브러리가 있는지 확인한 후, 웹 애플리케이션이면 내장된 톰캣, 제티 등의 서블릿 컨테이너를 설정하고 시작한다.
△ Spring 컨텍스트 생성
- Spring Boot는 애플리케이션의 ApplicationContext를 생성합니다. 이 컨텍스트는 Spring 프레임워크에서 빈(Bean)을 관리하고, 애플리케이션의 모든 설정과 컴포넌트들을 관리하는 중심 역할을 한다.
- AnnotationConfigApplicationContext(비웹) 또는 AnnotationConfigServletWebServerApplicationContext(웹 애플리케이션)의 형태로 컨텍스트를 생성한다.
△ 애플리케이션 이벤트 및 리스너 처리
- Spring Boot는 애플리케이션의 수명주기 동안 발생하는 여러 이벤트를 처리하기 위해 ApplicationEvent와 ApplicationListener를 사용한다.
- 애플리케이션이 시작되기 전에 필요한 이벤트를 발생시키고, 이를 처리하는 리스너들이 동작하여 초기화 작업을 수행하거나, 상태를 로깅하거나, 환경 설정을 변경할 수 있다.
- 예를 들어, ApplicationStartingEvent, ApplicationEnvironmentPreparedEvent, ApplicationPreparedEvent, ApplicationStartedEvent, ApplicationReadyEvent 등이 있다.
△ 환경 설정 준비
- SpringApplication.run()은 Spring Environment를 초기화한다. 이는 application.properties 또는 application.yml 파일로부터 애플리케이션 설정을 로드하고 이를 기반으로 프로파일, 속성 등을 설정한다.
- 개발자는 이 환경 설정을 통해 애플리케이션이 실행될 때 필요한 값을 지정하거나, 특정 환경(production, development 등)에 따라 애플리케이션이 다르게 동작하도록 설정할 수 있다.
△ 빈 등록 및 의존성 주입
- @ComponentScan을 통해 애플리케이션의 패키지를 스캔하고, 빈으로 등록된 클래스들을 찾아서 Spring 컨텍스트에 등록한다.
- 또한 빈 간의 의존성을 자동으로 주입하여, 각 빈이 정상적으로 동작할 수 있도록 설정합니다. 이를 통해 Spring의 DI(의존성 주입) 컨테이너가 동작한다.
△ 내장 서버 구동 (웹 애플리케이션)
- 만약 애플리케이션이 웹 애플리케이션이라면, SpringApplication.run()은 내장된 웹 서버(Tomcat, Jetty)를 자동으로 시작한다.
- 이를 통해 외부에 별도의 웹 서버를 설치하거나 설정할 필요 없이 애플리케이션이 HTTP 요청을 받을 수 있는 환경을 자동으로 구성헌다.
△ 명령어 라인 파싱
- SpringApplication.run()은 명령어 라인에서 전달된 인자들을 파싱하여 애플리케이션의 실행에 반영한다.
- 이는 애플리케이션 실행 시 환경을 동적으로 변경하거나, 설정 파일을 덮어쓸 때 유용한다.
△ CommandLineRunner 및 ApplicationRunner 실행
- Spring Boot는 CommandLineRunner나 ApplicationRunner 인터페이스를 구현한 빈을 찾아 실행합니다. 이를 통해 애플리케이션이 시작된 후 특정 초기화 작업을 수행할 수 있다.
- 이 두 인터페이스는 애플리케이션의 실행 직후 원하는 코드를 동작시키는 데 사용된다.
[ ▷ SpringApplication.run()의 실행 과정 ]
△ 1. 애플리케이션 클래스의 기본 설정
애플리케이션 클래스(즉, @SpringBootApplication이 있는 클래스)를 전달받아 SpringApplication 객체를 생성합니다.
△ 2. 애플리케이션 준비 단계
- run() 메서드는 초기 애플리케이션 환경을 구성하고, 애플리케이션 컨텍스트를 만들 준비를 한다.
- ApplicationContextInitializer를 호출하여 초기화 작업을 수행한다.
△ 3. 환경 설정 및 프로파일 적용
ApplicationEnvironmentPreparedEvent 이벤트를 발생시켜, 환경 설정이 준비되고 프로파일이 적용된다.
△ 4. 빈 스캐닝 및 컨텍스트 초기화
- 애플리케이션의 빈(Bean)을 스캔하고 등록한다.
- @ComponentScan을 통해 애플리케이션의 패키지를 탐색하고, 필요한 빈을 찾아 Spring 컨텍스트에 등록한다.
△ 5. 애플리케이션 컨텍스트 준비
컨텍스트가 초기화되면, ApplicationPreparedEvent 이벤트를 발생시켜 준비 과정을 마무리한다.
△ 6. 애플리케이션 컨텍스트 리프레시
- 컨텍스트를 리프레시(refresh)하여 실제 애플리케이션이 실행될 준비가 완료된다.
- 여기서 웹 애플리케이션의 경우 서블릿 컨테이너를 시작한다. (Tomcat, Jetty 등)
△ 7. 애플리케이션 시작
- 애플리케이션이 본격적으로 실행된다. 이 시점에서 CommandLineRunner나 ApplicationRunner가 실행된다.
- ApplicationStartedEvent가 발생하여 애플리케이션이 시작되었음을 알린다.
△ 8. 애플리케이션 준비 완료
마지막으로 ApplicationReadyEvent가 발생하여 애플리케이션이 정상적으로 시작되고 준비되었음을 알다.
[ ▷ SpringApplication.run ]
SpringApplication.run()은 Spring Boot 애플리케이션의 시작점으로, 애플리케이션의 모든 설정 및 실행 과정을 자동화하여 처리한다. 이 메서드는 애플리케이션의 환경 설정, 빈 등록, 이벤트 처리, 웹 서버 구동 등의 다양한 작업을 수행하여, 개발자가 애플리케이션을 신속하게 실행하고 동작할 수 있도록 도와준다.
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments =
new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
bootstrapContext, applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners,
applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup =
Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
SpringApplication.run() 메서드는 Spring Boot 애플리케이션의 시작점으로, 애플리케이션 컨텍스트를 생성하고 초기화하며, 애플리케이션을 실행하는 데 필요한 모든 설정과 구성을 처리한다. 주어진 코드는 SpringApplication 클래스의 run 메서드로, 이 메서드의 내부 동작을 매우 상세하게 설명한다.
- Start 시간 기록
- Bootstrap 컨텍스트 생성
- Headless 속성 설정
- RunListeners 초기화 및 시작 알림
- 애플리케이션 아규먼트 처리
- ConfigurableEnvironment 준비
- Banner 출력
- ApplicationContext 생성
- Context 준비
- Context 새로 고침
- 애플리케이션 시작 후 처리
- 시작 정보 로깅
- Listener에게 시작 완료 알림
- CommandLineRunner 및 ApplicationRunner 실행
- 예외 처리
- 애플리케이션 준비 완료 알림
- Context 반환
△ 1. Start 시간 기록
long startTime = System.nanoTime();
애플리케이션의 시작 시간을 기록하여, 애플리케이션이 시작하는 데 걸린 시간을 계산하는 데 사용된다.
△ 2. Bootstrap 컨텍스트 생성
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
- 부트스트랩 컨텍스트: Spring Boot의 초기화 과정에서 사용되는 컨텍스트로, 초기 환경 설정 및 필요한 리소스를 제공한다. 초기 부트스트랩 과정에서 사용되는 임시 컨텍스트이다.
- createBootstrapContext(): DefaultBootstrapContext 객체를 생성하여 초기화 단계에서 필요한 리소스를 준비한다.
△ 3. Headless 속성 설정
configureHeadlessProperty();
- 헤드리스 모드: GUI 환경 없이 애플리케이션을 실행할 때 사용하는 설정입니다. 헤드리스 모드는 GUI 환경이 없는 서버에서 실행될 때 유용하며, 디스플레이, 키보드, 마우스 등의 하드웨어에 접근하지 않는 환경에서 사용된다.
- configureHeadlessProperty(): 시스템 속성 java.awt.headless를 설정하여, GUI 관련 리소스를 사용하지 않도록 한다. 이는 서버 환경에서 불필요한 리소스 로딩을 방지한다.
△ 4. Run Listener 초기화 및 시작 알림
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
- 런 리스너: 애플리케이션 실행 과정 중 특정 시점에 호출되는 리스너입니다. 이는 애플리케이션 실행 단계에서 발생하는 여러 이벤트(시작, 환경 설정, 준비 완료 등)에 대한 리스너들을 관리하는 역할을 한다.
- getRunListeners(args): 애플리케이션 실행 시 사용할 리스너 목록을 가져온다.
- listeners.starting(): 애플리케이션 시작을 알리는 이벤트를 리스너에게 전달합니다. 이 시점에서 리스너는 초기화 작업을 수행할 수 있다.
△ 5. 애플리케이션 아규먼트 처리
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
- 애플리케이션 인자: main 메서드에서 전달된 커맨드 아규먼트를 처리한다.
- DefaultApplicationArguments: 커맨드 아규먼트를 파싱하여 ApplicationArguments 객체로 변환한다.
△ 6. Environment 구성 준비
ConfigurableEnvironment environment
= prepareEnvironment(listeners, bootstrapContext, applicationArguments);
- 환경 설정: 애플리케이션의 설정 및 프로파일을 관리하는 Environment 객체를 준비한다. 이 객체는 애플리케이션의 프로파일, 속성, 시스템 환경 변수 등을 관리한다.
- prepareEnvironment(...): 리스너, 부트스트랩 컨텍스트, 애플리케이션 아규먼트를 기반으로 환경 설정을 초기화한다. 이 과정에서 설정 파일(application.properties 또는 application.yml)과 시스템 속성, 환경 변수가 로드된다.
△ 7. 배너 출력
Banner printedBanner = printBanner(environment);
- 배너: 애플리케이션 시작 시 콘솔에 출력되는 ASCII 아트나 텍스트입니다. 스프링 부트는 애플리케이션이 실행될 때 터미널에 Spring 배너(기본적으로 Spring 로고)를 출력하는, 이는 이 메서드에서 처리된다.
- printBanner(environment): 환경 설정을 기반으로 배너를 출력합니다. 배너는 사용자 정의하거나 기본 배너를 사용할 수 있다.
△ 8. Application Context 생성
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
- 애플리케이션 컨텍스트: Spring의 핵심으로, 빈(Bean)들을 관리하고 애플리케이션의 구성 요소를 조립한다.
- createApplicationContext(): 적절한 타입의 ApplicationContext ( AnnotationConfigServletWebServerApplicationContext 또는 AnnotationConfigApplicationContext)를 생성한다.
- setApplicationStartup(...): 애플리케이션 시작 정보를 추적할 수 있도록 ApplicationStartup을 설정한다.
△ 9. Context 초기화 준비
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
- 컨텍스트 준비: 애플리케이션 컨텍스트를 설정하고, 필요한 리소스와 빈을 등록한다.
- prepareContext(...): 부트스트랩 컨텍스트, 애플리케이션 컨텍스트, 환경 설정, 리스너, 애플리케이션 아규먼트, 배너를 사용하여 컨텍스트를 준비한다. 이 과정에서 자동 구성, 빈 스캔, 프로퍼티 설정 등이 이루어진다.
△ 10. Context 새로 고침
refreshContext(context);
- 컨텍스트 새로 고침: 애플리케이션 컨텍스트를 초기화하여 모든 빈을 로드하고, 의존성을 주입한다.
- refreshContext(context): ApplicationContext의 refresh() 메서드를 호출하여 컨텍스트를 초기화한다. 이 과정에서 모든 빈이 생성되고 초기화된다.
△ 11. 애플리케이션 시작 후 처리
afterRefresh(context, applicationArguments);
- 애플리케이션 시작 후 처리: 컨텍스트가 새로 고침된 후 추가적인 초기화 작업을 수행한다.
- afterRefresh(...): 애플리케이션 컨텍스트가 완전히 초기화된 후 필요한 후처리를 수행한다.
△ 12. 시작 정보 로깅
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(),
timeTakenToStartup);
}
- 시작 시간 계산: 애플리케이션이 시작되는 데 걸린 시간을 계산한다.
- 시작 정보 로깅: 설정에 따라 애플리케이션 시작 정보를 로그로 출력한다. 이 정보에는 시작 시간, 애플리케이션 클래스 등이 포함될 수 있다.
△ 13. 리스너에게 시작 완료 알림
listeners.started(context, timeTakenToStartup);
- 리스너 알림: 애플리케이션이 성공적으로 시작되었음을 리스너에게 알린다.
- listeners.started(...): ApplicationStartedEvent를 리스너에게 전달하여, 리스너가 애플리케이션 시작 완료 시점에서 추가 작업을 수행할 수 있도록 한다.
△ 14. CommandLineRunner 및 ApplicationRunner 실행
callRunners(context, applicationArguments);
- 런너 실행: CommandLineRunner 및 ApplicationRunner 인터페이스를 구현한 빈들을 실행한다.
- callRunners(...): 애플리케이션 컨텍스트에서 해당 인터페이스를 구현한 빈들을 찾아 순차적으로 실행한다. 이를 통해 애플리케이션 시작 시점에 특정 로직을 실행할 수 있다.
△ 15. 예외 처리
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
- 예외 처리: 애플리케이션 실행 중 발생한 예외를 처리한다.
- AbandonedRunException: 특정 예외 타입은 다시 던지고, 다른 예외는 handleRunFailure(...) 메서드를 통해 처리한다.
- handleRunFailure(...): 예외 발생 시 리스너에게 실패 이벤트를 전달하고, 추가적인 예외 처리를 수행한다.
- IllegalStateException: 예외를 래핑하여 다시 던진다.
△ 16. 애플리케이션 준비 완료 알림
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() -
startTime);
listeners.ready(context, timeTakenToReady);
}
}
- 준비 완료 알림: 애플리케이션이 성공적으로 준비되었음을 리스너에게 알린다.
- context.isRunning(): 애플리케이션 컨텍스트가 실행 중인지 확인한다.
- listeners.ready(...): ApplicationReadyEvent를 리스너에게 전달하여, 리스너가 애플리케이션이 완전히 준비되었음을 알 수 있도록 한다.
- 예외 처리: 준비 완료 알림 중 발생한 예외도 동일하게 처리한다.
△ 17. 컨텍스트 반환
return context;
- 컨텍스트 반환: 초기화되고 실행된 ApplicationContext를 반환한다. 이를 통해 애플리케이션 상태를 외부에서 확인하거나 추가 작업을 수행할 수 있다.
'Spring Boot > Auto-Configuration' 카테고리의 다른 글
@EnableAutoConfiguration (0) | 2024.10.21 |
---|---|
Spring Boot Starter (0) | 2024.10.21 |
Spring Boot DevTools (0) | 2024.10.21 |
Spring Native (0) | 2024.10.21 |
Spring Boot Auto-Configuration (0) | 2024.10.21 |