SpringApplication.run()은 Spring Boot 애플리케이션의 시작점으로, 애플리케이션을 실행하고 스프링 컨테이너를 초기화하는 역할을 해. 이 메서드는 Spring Boot의 핵심 중 하나로, 다양한 설정을 자동으로 해주고 애플리케이션을 간편하게 실행할 수 있게 해줘.
SpringApplication.run()의 주요 역할:
1. SpringApplication 객체 생성
• SpringApplication.run() 메서드는 내부적으로 SpringApplication 객체를 생성해. 이 객체는 애플리케이션의 실행 환경을 설정하고, 그 설정을 바탕으로 애플리케이션을 부트스트랩(시작)하는 역할을 해.
2. 애플리케이션 컨텍스트 생성
• SpringApplication 객체가 생성되면 Spring 애플리케이션 컨텍스트를 만드는데, 이 컨텍스트는 스프링의 핵심 개념인 IOC 컨테이너 역할을 해. 이 컨텍스트 안에서 모든 스프링 빈(Bean)이 관리되고 의존성이 주입돼.
• AnnotationConfigApplicationContext, ServletWebServerApplicationContext 같은 컨텍스트가 상황에 따라 선택돼. 웹 애플리케이션이라면 웹 컨텍스트가 생성되고, 일반 Java 애플리케이션이라면 일반 컨텍스트가 생성돼.
3. 애플리케이션 설정 및 초기화
• 스프링 부트의 자동 설정(Auto Configuration)이 이 단계에서 활성화돼. @SpringBootApplication 어노테이션이 이 과정에서 중요한 역할을 하는데, 이 어노테이션이 있는 클래스는 자동으로 컴포넌트 스캔을 실행해, 프로젝트의 모든 스프링 빈을 찾아서 등록해.
• 또한, 이 단계에서 **프로파일(Profile)**과 **환경 설정(Environment)**이 초기화돼. application.properties나 application.yml 파일에 정의된 설정들이 읽혀지고, 필요한 설정이 적용돼.
4. 내장 웹 서버(Tomcat, Jetty 등) 실행
• 만약 웹 애플리케이션을 실행하고 있다면, 이 과정에서 내장 웹 서버가 자동으로 시작돼. 기본적으로 Spring Boot는 내장 Tomcat 서버를 사용하지만, 설정에 따라 Jetty나 Undertow 같은 다른 서버로 변경할 수도 있어.
• 내장 웹 서버는 8080 포트에서 애플리케이션을 실행하고 클라이언트의 요청을 받을 준비를 해.
5. CommandLineRunners 및 ApplicationRunners 실행
• 만약 애플리케이션에 CommandLineRunner나 ApplicationRunner 인터페이스를 구현한 빈이 있다면, 이 단계에서 그들이 실행돼. 이를 통해 애플리케이션이 시작된 직후에 어떤 로직을 실행할 수 있어.
• 예를 들어, 특정 데이터를 초기화하거나 로깅을 설정하는 작업을 할 수 있어.
6. ApplicationContext 반환
• SpringApplication.run() 메서드는 실행된 애플리케이션의 ApplicationContext 객체를 반환해. 이 컨텍스트는 애플리케이션의 전체 상태와 모든 빈을 관리하는 역할을 하는데, 필요하면 이 컨텍스트를 통해 빈에 접근할 수 있어.
SpringApplication.run() 실행 과정:
1. 애플리케이션 부트스트랩 (Bootstrap):
• 애플리케이션을 실행하고 필요한 설정을 읽어들이며 초기화 과정을 시작해.
2. 애플리케이션 컨텍스트 생성:
• 스프링 애플리케이션 컨텍스트를 생성하고, 빈을 등록하며 의존성을 주입해.
3. 내장 웹 서버 실행 (웹 애플리케이션일 경우):
• 내장된 톰캣이나 젯티 서버를 실행해서 애플리케이션이 HTTP 요청을 처리할 수 있도록 준비해.
4. 스프링 컨테이너 초기화 완료:
• 모든 설정이 완료되면 애플리케이션이 시작되고, 요청을 받을 준비를 마쳐.
코드 예시:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
위 코드에서 SpringApplication.run(MyApplication.class, args)는 다음 역할을 수행해:
• MyApplication 클래스를 기준으로 스프링 부트를 시작
• args는 커맨드라인에서 입력된 인자들을 전달
• 애플리케이션 실행 및 모든 설정 자동화
요약:
• SpringApplication.run()은 스프링 부트 애플리케이션의 시작점으로, 애플리케이션을 실행하고 컨텍스트를 초기화하는 핵심 메서드야.
• 자동 설정, 내장 웹 서버 실행, 빈 초기화 등의 작업을 수행하고, 애플리케이션이 요청을 받을 수 있도록 모든 준비를 마쳐.
SpringApplication.run()에 대해 좀 더 깊이 들어가 보면, 추가적인 동작이 있고, 다양한 커스터마이징 포인트가 있어.
1. Banner 설정
• 기본적으로 SpringApplication.run()은 실행될 때 아까 말한 Spring Boot 배너를 표시하는데, 이 배너는 커스터마이징할 수 있어. 배너를 끄거나 커스텀 텍스트로 변경할 수 있어.
• 배너를 끄는 방법:
spring.main.banner-mode=off
• 배너를 커스텀하기:
• src/main/resources/banner.txt 파일을 만들고, 원하는 텍스트나 ASCII 아트를 넣으면 실행 시 이 배너가 표시돼.
2. Application Event and Listeners
• SpringApplication.run()이 실행되는 동안 여러 가지 이벤트가 발생해. 애플리케이션이 시작되기 전, 시작된 후, 컨텍스트가 준비된 후 등 다양한 시점에 이벤트가 발생하며, 이를 ApplicationListener로 처리할 수 있어.
• 몇 가지 주요 이벤트:
• ApplicationStartingEvent: 애플리케이션이 시작될 때 발생
• ApplicationEnvironmentPreparedEvent: 환경(Environment)이 준비된 후 발생
• ApplicationPreparedEvent: 애플리케이션 컨텍스트가 준비된 후 발생
• ApplicationStartedEvent: 애플리케이션이 완전히 시작된 후 발생
• ApplicationReadyEvent: 애플리케이션이 사용 준비된 상태에서 발생
• ApplicationFailedEvent: 애플리케이션이 시작 중에 실패할 때 발생
• 이벤트 리스너를 추가하려면:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.addListeners(new MyApplicationListener());
app.run(args);
}
}
3. CommandLineRunner와 ApplicationRunner
• Spring Boot는 CommandLineRunner와 ApplicationRunner 인터페이스를 통해 애플리케이션이 완전히 시작된 후 추가 작업을 할 수 있어. SpringApplication.run() 메서드 이후, 초기화 코드나 데이터를 넣을 때 유용하게 사용할 수 있지.
• CommandLineRunner: 문자열 배열 args로 명령어 인수를 받아서 처리
• ApplicationRunner: ApplicationArguments 객체를 받아 더 구조화된 형태로 명령어 인수를 처리
예시:
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("애플리케이션 실행 후 추가 작업 수행");
}
}
4. Failure Analyzer
• SpringApplication.run()이 실패할 경우, 스프링 부트는 FailureAnalyzer를 통해 구체적인 오류 메시지를 제공해. 일반적인 애플리케이션 오류에서 사용자가 이해하기 쉬운 형태로 정보를 제공하는 것이 목적이야.
• 예를 들어, 데이터베이스 연결 오류나 잘못된 환경 설정이 있을 경우 오류 메시지가 친절하게 설명돼서 문제를 해결하는 데 도움이 돼.
5. SpringApplicationBuilder를 통한 커스터마이징
• SpringApplication.run() 대신에 SpringApplicationBuilder를 사용할 수 있어. 이 빌더는 더 세부적인 설정을 할 수 있는 방법을 제공하지.
• SpringApplicationBuilder로 애플리케이션의 여러 설정을 체인 방식으로 추가하거나 다른 설정을 쉽게 할 수 있어.
new SpringApplicationBuilder(MyApplication.class)
.bannerMode(Banner.Mode.OFF)
.profiles("prod")
.run(args);
6. Application Arguments
• SpringApplication.run()에 전달된 명령줄 인수는 ApplicationArguments로 접근할 수 있어. 이를 통해 명령어로 전달된 인수들을 처리할 수 있어.
• @Autowired로 ApplicationArguments를 받아서 사용할 수 있지.
@Autowired
public MyRunner(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
}
7. Default Properties 설정
• SpringApplication.run()은 실행될 때 기본 프로퍼티를 설정할 수 있어. application.properties 파일 외에도, 코드를 통해서 기본값을 설정할 수 있지.
SpringApplication app = new SpringApplication(MyApplication.class);
Map<String, Object> defaultProperties = new HashMap<>();
defaultProperties.put("server.port", "8083");
app.setDefaultProperties(defaultProperties);
app.run(args);
8. Exit 코드 처리
• 스프링 부트 애플리케이션이 종료될 때 종료 코드를 설정할 수 있어. 예를 들어, 애플리케이션이 정상적으로 종료되었는지, 또는 에러가 발생했는지에 따라 종료 코드를 반환할 수 있어.
• SpringApplication.exit() 메서드를 사용해서 애플리케이션 종료 시 적절한 종료 코드를 반환할 수 있지.
ConfigurableApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
System.exit(SpringApplication.exit(ctx, () -> 0));
요약:
• 배너 커스터마이징: 배너를 끄거나 커스텀할 수 있어.
• 이벤트 리스너: 애플리케이션의 다양한 상태에서 발생하는 이벤트를 처리할 수 있어.
• CommandLineRunner와 ApplicationRunner: 애플리케이션 시작 후 실행할 로직을 정의할 수 있어.
• Failure Analyzer: 친절한 오류 메시지로 문제를 해결하는 데 도움을 줘.
• SpringApplicationBuilder: 더 세밀하게 애플리케이션을 설정할 수 있어.
• 명령어 인수 처리: ApplicationArguments로 명령어 인수를 처리할 수 있어.
• 기본 프로퍼티 설정: 실행 중에 기본 프로퍼티를 설정할 수 있어.
• Exit 코드 처리: 종료 시 적절한 종료 코드를 반환할 수 있어.
전체적인 SpringApplication 동작 흐름
1. 시작 시간 기록
• 애플리케이션이 실행되는 시간을 계산하기 위해 시작 시간을 기록해 두는 단계야.
long startTime = System.nanoTime();
2. Bootstrap 컨텍스트 생성
• Spring Boot 초기화 과정에서 필요한 리소스와 설정을 제공하는 부트스트랩 컨텍스트를 생성해.
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
3. Headless 모드 설정
• 서버 환경에서 불필요한 GUI 리소스를 차단하기 위해 Headless 모드를 설정해. 서버 환경에서는 GUI 관련 리소스가 필요 없으니까, 이를 비활성화하는 거야.
configureHeadlessProperty();
4. Run Listener 초기화 및 시작 알림
• 애플리케이션 실행 중 특정 이벤트를 감지하는 리스너들을 초기화하고, 애플리케이션이 시작된다는 사실을 알리는 단계야.
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
5. 애플리케이션 아규먼트 처리
• main() 메서드에서 전달된 아규먼트를 처리하는 단계야. 전달된 값들이 애플리케이션의 설정에 영향을 줄 수 있어.
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
7. 배너 출력
• Spring Boot를 실행하면 보이는 그 멋진 ASCII 아트 배너를 출력하는 단계야. 이 배너는 사용자 정의도 가능해.
Banner printedBanner = printBanner(environment);
8. ApplicationContext 생성
• 실제로 애플리케이션에서 빈(Bean)들을 관리하고 조립하는 핵심 컨텍스트를 생성해. 이 컨텍스트는 Spring의 기본 기능을 담당하는 중요한 부분이야.
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
9. ApplicationContext 초기화 준비
• ApplicationContext를 실제로 사용할 수 있도록 초기화하고, 환경 설정, 리스너, 아규먼트를 전달하는 단계야.
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
10. ApplicationContext 새로 고침
• ApplicationContext를 새로 고침해서 모든 빈들을 로딩하고, 의존성을 주입해.
refreshContext(context);
11. 애플리케이션 시작 후 처리
• 컨텍스트가 완전히 초기화된 후에 추가적으로 필요한 작업들을 처리하는 단계야.
afterRefresh(context, applicationArguments);
12. 시작 정보 로깅
• 애플리케이션이 시작하는 데 걸린 시간을 계산해서, 그 정보를 로그로 남기는 단계야.
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
13. 리스너에게 시작 완료 알림
• 리스너들에게 애플리케이션이 성공적으로 시작되었다고 알리는 단계야.
listeners.started(context, timeTakenToStartup);
14. CommandLineRunner 및 ApplicationRunner 실행
• Spring Boot 애플리케이션에서 특정 작업을 수행하기 위한 CommandLineRunner 또는 ApplicationRunner를 실행해.
callRunners(context, applicationArguments);
15. 예외 처리
• 애플리케이션 실행 중에 발생할 수 있는 예외를 처리하는 단계야. 예외가 발생하면 리스너에게 실패 이벤트를 알리고, 필요하면 예외를 다시 던져.
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
16. 애플리케이션 준비 완료 알림
• 애플리케이션이 준비 완료되었음을 리스너에게 알리고, 필요한 후속 작업을 수행할 수 있게 해.
if (context.isRunning()) {
listeners.ready(context, Duration.ofNanos(System.nanoTime() - startTime));
}
17. 컨텍스트 반환
• 최종적으로 애플리케이션 컨텍스트를 반환해서, 애플리케이션이 계속 실행되도록 하고, 외부에서 상태를 확인할 수 있게 해.
return context;
이 과정에서 중요한 점은 ApplicationContext가 모든 빈을 관리하고 애플리케이션 로직을 수행하기 위해 모든 단계가 준비된다는 거야.
'Spring Boot' 카테고리의 다른 글
@Import (0) | 2024.10.21 |
---|---|
Spring Boot의 Auto-Configuration (2) | 2024.10.21 |
@SpringBootApplication (0) | 2024.10.21 |
Spring Native (0) | 2024.10.21 |
Spring Boot (2) | 2024.10.21 |