spring
Spring Boot 애플리케이션이 초기화되는 과정
Lee_SJ
2025. 2. 17. 17:07
⚙️ 1️⃣ JVM 내부에서의 초기 작업
- 클래스 로딩 (Metaspace)
- @SpringBootApplication이 붙은 메인 클래스와 참조된 의존 클래스가 Metaspace에 로드됩니다.
- 클래스 로더가 SpringApplication.run()을 호출할 때 필요한 ApplicationContext, BeanFactory 등도 함께 로딩됩니다.
- 이 단계에서 Reflection과 ClassLoader가 작동합니다.
- JIT(Just-In-Time) Compiler 준비
- 성능 최적화를 위해 HotSpot VM이 frequently used 코드(메인 메서드, 스프링 컨테이너 생성 코드)를 네이티브 코드로 변환.
🚀 2️⃣ Spring Boot 애플리케이션 시작
SpringApplication.run() 실행
SpringApplication.run(MyApplication.class, args)가 실행되면 아래 흐름이 진행됩니다.
🌱 Step 1: SpringApplication 생성
- SpringApplication 객체를 생성하며 SpringApplicationRunListeners를 준비.
- SpringFactoriesLoader를 통해 application.properties를 기반으로 환경 설정을 읽어들임.
- ApplicationContextInitializer와 ApplicationListener들을 메모리에 로드.
메모리 변화:
- Heap: SpringApplication 객체, 설정 파일 데이터(Environment)가 힙 메모리에 올라감.
- Metaspace: 설정된 클래스의 메타데이터 저장.
🛠️ Step 2: Environment 준비
- ConfigurableEnvironment를 생성하고 application.properties나 application.yml 파일을 파싱.
- 활성화된 Profile 정보를 확인하고 설정을 메모리에 로드.
- System properties, OS environment variables도 함께 준비.
메모리 변화:
- Heap: Environment 객체 생성 및 프로퍼티 키-값 저장.
- Thread Stack: 프로퍼티 파싱 작업 중, 호출 메서드들의 Stack Frame 생성/소멸.
🏗️ Step 3: ApplicationContext 생성
- AnnotationConfigApplicationContext 또는 GenericWebApplicationContext를 생성.
- BeanDefinition 생성: 설정 파일(클래스)을 분석하여 Bean 정보를 메모리에 등록.
메모리 변화:
- Heap: ApplicationContext, BeanDefinition 객체가 올라감.
- Metaspace: @Configuration, @Bean, @Component로 정의된 클래스 메타데이터 유지.
🔍 3️⃣ Component Scan & Bean 등록
🧬 Step 4: @ComponentScan 작동
- @SpringBootApplication은 **@ComponentScan**을 포함하므로, basePackages 경로에서 **@Component, @Service, @Repository, @Controller**를 찾아 메모리에 등록.
작동 과정:
- Reflection을 통해 클래스의 애너테이션 정보를 조회.(애노테이션은 리플렉션과 프록시를 활용하여 런타임시 작동)
- BeanDefinition 생성 → BeanFactory에 등록.
- 의존성 주입(DI): @Autowired, @Inject, @Resource 등을 처리.
메모리 변화:
- Heap: Spring Bean 인스턴스 생성.
- Metaspace: 스캔된 클래스의 메타데이터 유지.
⚙️ 4️⃣ @Configuration과 @Bean 처리
⚙️ Step 5: @Configuration 클래스 처리
- @Configuration 클래스는 CGLIB을 이용해 프록시 객체로 변환.
- 내부의 @Bean 메서드를 호출하여 빈을 등록할 때 싱글톤 보장.
@Configuration public class AppConfig { @Bean public UserService userService() { return new UserService(); } } |
메모리 변화:
- Heap: UserService 객체 생성 및 등록.
- Metaspace: AppConfig 클래스와 CGLIB 프록시 메타정보 유지.
⚙️ 5️⃣ AOP 프록시 생성
🔍 Step 6: AOP 적용
- @EnableAspectJAutoProxy(SpringBoot 자동 활성화)로 AOP를 위한 프록시 객체 생성.
- JDK Dynamic Proxy(인터페이스 기반) 또는 CGLIB Proxy(클래스 기반) 사용.
동작 원리:
- BeanPostProcessor가 @Aspect를 탐지.
- ProxyFactory가 프록시 객체를 생성.
- @Around, @Before, @After Advice를 메서드 호출 시 연결.
메모리 변화:
- Heap: 프록시 객체 생성.
- Metaspace: Proxy 클래스의 메타정보 저장.
🌐 6️⃣ Web Server 기동 (내장 톰캣)
🛠️ Step 7: 내장 WAS(Tomcat) 실행
- SpringApplication이 WebApplicationType을 감지하고 내장 톰캣 서버를 구동.
- DispatcherServlet을 생성하여 HTTP 요청을 처리.
- HTTP 포트, 컨텍스트 경로 설정을 기반으로 네트워크 포트 바인딩.
메모리 변화:
- Heap: ServletContext, Request, Response 객체 생성.
- Kernel Space: socket을 통해 네트워크 포트 바인딩.
🔄 7️⃣ ApplicationContext 초기화 완료
✅ 최종 단계
- ApplicationContext 초기화 이벤트 발행(ApplicationReadyEvent).
- CommandLineRunner 및 ApplicationRunner 실행.
- 애플리케이션 준비 완료 → HTTP 요청 대기.
🧠 정리: 메모리상의 주요 변화
단계 | 메모리 영역 | 주요 작업 |
클래스 로딩 | Metaspace | 클래스 및 메타정보 로드 |
환경 설정 로드 | Heap | Environment 객체 생성 |
Bean 등록 및 DI | Heap | BeanFactory, BeanDefinition, Bean 인스턴스 생성 |
AOP 프록시 생성 | Heap | 프록시 객체 생성 및 메타정보 등록 |
웹 서버 기동 | Heap | ServletContext, DispatcherServlet 생성 |