개요 Spring 프레임워크에서 부모-자식 컨테이너 구조는 웹 애플리케이션 개발에서 중요한 개념입니다. 이 구조는 서비스 계층과 웹 계층을 분리하여 관리하는 데 기반을 두고 있으며, 다음과 같은 핵심 질문들이 종종 등장합니다:
- 부모-자식 컨테이너 구조의 필요성은 무엇인가요?
- 모든 컴포넌트를 단일 컨테이너에서 관리할 수 있나요?
- Spring MVC 서블릿 컨텍스트에 모든 객체를 등록하는 방식은 적절한가요?
- 두 컨테이너가 동일한 객체를 관리하는 경우 어떤 문제가 발생할 수 있나요?
이 문서는 Spring의 부모 컨테이너(Root WebApplicationContext)와 자식 컨테이너(Servlet WebApplicationContext)의 작동 방식과 실제 적용 사례를 설명합니다.
컨테이너 구조 이해 Spring 웹 애플리케이션은 다음 두 가지 주요 컨테이너로 구성됩니다:
- Root WebApplicationContext: 서비스 계층, DAO 계층, 데이터소스 등 비즈니스 로직을 담당하는 부모 컨테이너. 일반적으로 applicationContext.xml에서 정의됩니다.
- Servlet WebApplicationContext: 컨트롤러, 뷰 리졸버 등 웹 계층을 담당하는 자식 컨테이너. spring-servlet.xml에서 설정됩니다.
컨테이너 초기화 과정 Spring MVC 애플리케이션은 다음 순서로 컨테이너가 초기화됩니다:
- ContextLoaderListener가 Root WebApplicationContext를 생성
- DispatcherServlet이 Servlet WebApplicationContext를 생성
- 자식 컨테이너는 부모 컨테이너를 참조하여 상속 관계를 형성
구현 예제 다음은 컨테이너 관계를 검증하는 코드 예시입니다:
// 부모 컨테이너 확인
public class ServiceComponent implements ApplicationContextAware {
private static ApplicationContext parentContext;
@Override
public void setApplicationContext(ApplicationContext context) {
parentContext = context;
}
}
// 자식 컨테이너 확인
@Controller
public class WebController implements ApplicationContextAware {
private static ApplicationContext childContext;
@Override
public void setApplicationContext(ApplicationContext context) {
childContext = context;
}
}
핵심 원칙
- 역할 분리: 부모 컨테이너는 비즈니스 로직, 자식 컨테이너는 웹 처리를 담당
- 의존 관계: 자식은 부모의 Bean을 참조 가능, 반대는 불가능
- 설정 최적화:
- 부모 컨테이너:
@Service,@Repository스캔 - 자식 컨테이너:
@Controller,@RestController스캔
문제 해결
- 404 오류 발생 원인:
- 자식 컨테이너에서만
@RequestMapping을 처리 - 부모 컨테이너의 컨트롤러는 무시됨
- 트랜잭션 문제:
- AOP 설정은 부모 컨테이너에서 정의되어야 함
- 자식 컨테이너에서 트랜잭션 관리자 설정 시 비정상 작동
- 중복 관리 문제:
- 동일 객체가 두 컨테이너에 등록되면 메모리 낭비 발생
- 부모 컨테이너의 프록시 객체가 자식 컨테이너에 의해 덮어씌워짐
실무 팁
- 부모 컨테이너:
applicationContext.xml에서 전체 스캔 설정
<context:component-scan base-package="com.example.service" />
- 자식 컨테이너:
spring-servlet.xml에서 웹 전용 스캔 설정
<context:component-scan base-package="com.example.web" />