스프링 IoC 컨테이너 계층 구조
스프링 프레임워크에서 IoC(제어의 역전) 컨테이너는 애플리케이션 구성 요소의 생성과 의존성 주입을 관리하는 중요한 역할을 합니다. 특히 대규모 애플리케이션에서는 다양한 빈을 효율적으로 관리하기 위해 IoC 컨테이너의 계층 구조가 필수적입니다. IoC 컨테이너는 부모-자식 관계의 계층 구조를 가지고 있으며, 이를 통해 애플리케이션을 모듈화 하고 빈 관리를 체계적으로 할 수 있습니다. 이러한 구조는 웹 애플리케이션에서 루트 컨텍스트와 서블릿 컨텍스트로 나뉘며, 각 컨텍스트가 서로 다른 역할을 담당합니다.
IoC 컨테이너 계층 구조의 개요
스프링 IoC 컨테이너는 빈(Bean)의 생성, 관리, 의존성 주입을 담당하는 핵심 모듈입니다. 스프링 애플리케이션은 주로 루트 컨텍스트와 서블릿 컨텍스트를 통해 빈을 관리하는데, 이를 통해 애플리케이션의 계층 구조를 분리하고 모듈화할 수 있습니다. 이러한 계층 구조는 대규모 애플리케이션의 효율적인 관리와 성능 향상에 도움을 줍니다.
- 루트 컨텍스트 : 애플리케이션 전반에서 공통적으로 사용되는 빈을 관리하며, 비즈니스 로직과 관련된 빈(서비스, 레포지토리 등)이 여기에 정의됩니다.
- 서블릿 컨텍스트 : 웹 계층에서 사용되는 빈(컨트롤러, 뷰 등)을 관리합니다. 각 서블릿이 고유한 서블릿 컨텍스트를 가지고 루트 컨텍스트의 빈을 참조할 수 있습니다. 하지만 그 반대는 불가능합니다.
이 구조는 스프링의 DispatcherServlet과 함께 동작해 웹 애플리케이션의 요청과 응답을 처리할 때 유용하게 사용됩니다.
루트 컨텍스트와 서블릿 컨텍스트의 역할
루트 컨텍스트(Root Context)
루트 컨텍스트는 애플리케이션 전반에서 공통적으로 사용되는 빈을 관리하는 스프링 IoC(제어의 역전) 컨테이너입니다. 애플리케이션의 비즈니스 로직을 담당하는 서비스(Service) 계층과 데이터 접근(Repository) 계층의 빈이 이곳에 등록됩니다. 모든 서블릿 컨텍스트에서 루트 컨텍스트의 빈을 참조할 수 있기 때문에, 공통적으로 사용되는 객체를 관리하기에 적합합니다.
- 루트 컨텍스트의 특징
- 애플리케이션 전역에서 사용되는 공통 빈을 관리합니다.
- 모든 서블릿 컨텍스트가 루트 컨텍스트의 빈을 공유할 수 있습니다.
- 보통 ContextLoaderListener를 통해 초기화됩니다.
<!-- applicationContext.xml (루트 컨텍스트) -->
<beans>
<!-- 서비스 빈 등록 -->
<bean id="myService" class="com.example.service.MyService" />
</beans>
서블릿 컨텍스트(Servlet Context)
서블릿 컨텍스트는 주로 웹 계층에 속한 빈(컨트롤러, 빈 등)을 관리합니다. 스프링 MVC를 사용하는 웹 애플리케이션에서 각각의 서블릿마다 독립적인 서블릿 컨텍스트가 생성되고, 루트 컨텍스트의 빈을 참조할 수 있지만, 서블릿 컨텍스트에 정의된 빈은 루트 컨텍스트에서 참조할 수 없습니다.
- 서블릿 컨텍스트의 특징
- 각 서블릿에 독립적인 컨텍스트를 생성합니다.
- 웹 계층(컨트롤러, 뷰) 관련 빈을 관리합니다.
- 루트 컨텍스트의 빈을 참조할 수 있습니다.
- 주로 DispatcherServlet을 통해 초기화됩니다.
<!-- dispatcher-servlet.xml (서블릿 컨텍스트) -->
<beans>
<!-- 컨트롤러 빈 등록 -->
<bean id="myController" class="com.example.web.MyController">
<property name="myService" ref="myService" />
</bean>
</beans>
위 설정에서 dispatcher-servlet.xml이 서블릿 컨텍스트를 정의합니다. 이 설정 파일에 있는 빈들은 해당 서블릿에서만 사용되며, 주로 컨트롤러나 뷰 관련 빈들이 등록됩니다.
루트 컨텍스트와 서블릿 컨텍스트의 관계
루트 컨텍스트와 서블릿 컨텍스트는 부모-자식 관계를 가집니다. 즉, 서블릿 컨텍스트는 루트 컨텍스트의 빈을 참조할 수 있지만, 그 반대는 불가능합니다. 이 구조 덕분에 비즈니스 로직과 웹 계층의 역할을 명확히 구분할 수 있습니다. 예를 들어, 서비스 계층의 빈은 루트 컨텍스트에 의해 정의되고, 서블릿 컨텍스트에 정의된 컨트롤러는 해당 빈을 참조할 수 있습니다. 그러나 루트 컨텍스트의 서비스 빈이 서블릿 컨텍스트에 정의된 컨트롤러 빈에 의존하지 않도록 설계됩니다. 이를 통해 모듈화와 의존성 관리가 용이해집니다.
계층 구조의 활용 예시
실전 활용 예시
다음은 루트 컨텍스트와 서블릿 컨텍스트를 활용한 간단한 예시입니다. 루트 컨텍스트에 공통적으로 사용되는 서비스 빈을 등록하고, 서블릿 컨텍스트에 해당 빈을 주입받아 웹 요청을 처리하는 방식입니다.
- 루트 컨텍스트 설정(applicationContext.xml)
<beans>
<bean id="myService" class="com.example.service.MyService" />
</beans>
- 서블릿 컨텍스트(dispatcher-servlet.xml)
<beans>
<bean id="myController" class="com.example.web.MyController">
<property name="myService" ref="myService" />
</bean>
</beans>
- 컨트롤러 클래스(Controller.java)
package com.example.web;
import com.example.service.MyService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
private final MyService myService;
public MyController(MyService myService) {
this.myService = myService;
}
@ResponseBody
@GetMapping("/greet")
public String greet() {
return myService.getGreeting();
}
}
위 예제에서 MyService 빈이 루트 컨텍스트에 등록되어 있으며, 웹 계층의 MyController는 서블릿 컨텍스트에 정의되어 루트 컨텍스트의 MyService 빈을 주입받아 사용합니다.
스프링과 스프링 부트의 IoC 계층 구조 비교
스프링 프레임워크
전통적인 스프링 프레임워크에서는 IoC 컨테이너를 명시적으로 구성하는 경우 많습니다. XML 또는 Java Config를 통해 루트 컨텍스트와 서블릿 컨텍스트를 설정해야 합니다. 이를 통해 개발자는 세부적인 설정을 컨트롤할 수 있지만, 복잡한 설정이 요구됩니다.
스프링 부트의 자동 설정
스프링 부트는 복잡한 설정을 대신해 자동 구성(Auto Configuration) 기능을 제공합니다. 개발자는 @SpringBootApplication 애노테이션을 사용해서 기본 설정만으로도 루트 컨텍스트와 서블릿 컨텍스트가 자동으로 분리 및 관리됩니다.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
스프링 부트에서는 SpringApplication.run() 메서드가 루트 컨텍스트와 서블릿 컨텍스트를 모두 초기화하고, 개발자가 설정 파일을 명시적으로 정의하지 않아도 애플리케이션이 구성됩니다. 또한, @EnableAutoConfiguration 애노테이션이 스프링 부트의 자동 구성을 담당하며, 애플리케이션을 빠르게 애플리케이션을 구성할 수 있습니다.
IoC 컨테이너 계층 구조의 장점
- 모듈화 : 계층 구조를 통해 애플리케이션의 비즈니스 로직과 웹 계층을 분리해서 모듈화를 실현할 수 있습니다. 이를 통해 각 모듈 간의 의존성을 최소화하고, 유지 보수성을 높일 수 있습니다.
- 성능 향상 : 루트 컨텍스트에 공통 빈을 정의하고, 서블릿 컨텍스트에서 해당 빈을 참조함으로써 중복된 빈 생성을 방지하고, 애플리케이션의 성능을 향상시킬 수 있습니다.
- 확장성 : 애플리케이션이 확장됨에 따라 서블릿 컨텍스트를 추가하고, 루트 컨텍스트에 더 많은 공통 서비스를 정의함으로써 확장성을 확보할 수 있습니다.
결론
스프링의 IoC 컨테이너의 계층 구조는 대규모 애플리케이션에서 모듈화를 용이하게 하고, 각 계층 간의 의존성을 효율적으로 관리할 수 있도록 도와줍니다. 루트 컨텍스트와 서블릿 컨텍스트의 분리를 통해 웹 계층과 서비스 계층의 역할을 명확하게 구분하고, 이를 통해 유지보수성과 확장성을 높일 수 있습니다. 특히, 스프링 부트를 사용하면 이러한 계층 구조가 자동으로 설정되지만, 스프링의 동작 원리를 이해하고 이를 적절하게 활용하는 것이 중요합니다.
'🌱Spring[스프링] > SpringBoot[스프링부트]' 카테고리의 다른 글
[Spring] 빈 등록과 관리 방법의 다양한 패턴 (0) | 2024.10.02 |
---|---|
[Spring] 스프링의 다양한 빈 스코프 가이드 : 싱글톤과 프로토타입 (0) | 2024.10.01 |
[Spring] IoC 컨테이너의 동장 방식과 빈의 생명주기 관리 (0) | 2024.09.30 |
[Spring] DI(Dependency Injection, 의존성 주입) 개념과 원리 (0) | 2024.09.26 |
[Spring] 전통과 현재의 IoC 컨테이너 개요 (0) | 2024.09.26 |