레벨 4 미션 톰캣 구현하기 미션 중 기존 요구사항의 코드는 애플리케이션 단과 서블릿 컨테이너 단이 명확하게 분리되어 있지 않았다.
기왕 톰캣 구현하기를 하는 것이니만큼 서블릿 컨테이너는 애플리케이션이 무엇인지 상관없이 제 역할에만 집중하도록 하고 싶었다.
따라서 아래와 같이 여러 애플리케이션에서 org.apche 를 사용할 수 있도록 패키지를 분리하고자 하였다.
패키지를 분리하면서 Context라는 워딩 때문에 나는 Spring의 Application Context가 저 그림의 Context에 해당하는 것이라고 생각했다.
그런데 ApplicationContext과 ServletContext는 다른 레벨의 개념이라는 것을 알게 되어 명확히 하고자 글을 작성한다.
ServletContext
ServletContext는 웹 애플리케이션의 서블릿 컨테이너와 통신하기 위한 인터페이스로 전체 웹 애플리케이션에 대한 정보를 제공하고 관리한다.
웹 애플리케이션이 시작될 때 생성되어 종료될 때까지 유지되며, 아래의 역할 등을 한다.
- 필터, 리스너, 서블릿 추가 및 관리 (addFilter, addListener, addServlet 메소드)
- 애플리케이션 수준의 초기화 파라미터 접근 (getInitParameter, getInitParameterNames)
- 리소스 접근 (getResource, getRealPath)
- 속성 관리 (getAttribute, setAttribute)
- 세션 추적 모드 설정 (getEffectiveSessionTrackingModes)
- 서블릿 컨테이너 버전 정보 제공 (getMajorVersion, getMinorVersion)
- 요청 디스패처 획득 (getRequestDispatcher) 등등....
ApplicationContext
- Spring 프레임워크의 일부
- 애플리케이션 빈의 생명주기와 구성을 관리
- 의존성 주입(DI)과 제어의 역전(IoC)을 제공
- 웹 애플리케이션뿐만 아니라 모든 Java 애플리케이션에서 사용 가능
- 그 중에서도 WebApplicationContext를 통해 웹 애플리케이션 특화 기능을 제공
주요 차이점
Context(= ServletContext) | ApplicationContext | |
용도 | 서블릿 컨테이너 레벨 | Spring 프레임워크 레벨 |
역할 | Context는 웹 애플리케이션의 기본 실행 환경을 제공 | Spring의 IoC 컨테이너 역할 |
사용 범위 | Context는 웹 애플리케이션에 한정 | 더 넓은 범위의 애플리케이션에서 사용 |
+ ) ContextLoaderListener
찾아보다가 발견한 재미있는 질문
ContextLoaderListener가 WebApplicationContext를 ServletContext에 등록하도록 되어있다.
그 이유가 뭘까?
바로 Spring 빈들을 서블릿에서 접근 가능하게 만들기 위함이다!
WebApplicationContext는 ServletContext를 통해 웹 애플리케이션의 정보에 접근할 수 있고,
서블릿들은 ServletContext를 통해 WebApplicationContext에 접근할 수 있게 되는 것이라고 한다.
서블릿에서 WebApplicationContext에 접근할 수 있다고?
이전에 필터와 인터셉터에 대해 학습하면서 필터와 다르게 인터셉터는 WebApplicationContext에 접근할 수 있다라고 알고 있었다.
따라서 위의 ContextLoaderListener에서 서블릿들은 ServletContext를 통해 WebApplicationContext에 접근할 수 있다 라는 것을 보고 의문이 들었다.
찾아보니 실제로 (필터를 포함해서) 서블릿에서도 WebApplicationContext에 접근이 가능하다.
명시적으로 WebApplicationContextUtils라는 객체를 통해 수동으로 빈을 가져올 수 있다.
public class MyServlet extends HttpServlet {
private WebApplicationContext webApplicationContext;
@Override
public void init() throws ServletException {
super.init();
ServletContext servletContext = getServletContext();
webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// webApplicationContext를 통해 스프링 빈에 접근
MySpringBean myBean = webApplicationContext.getBean(MySpringBean.class);
// myBean 사용...
}
}
하지만 자동 주입은 불가능하고 물론 권장되는 방법도 아니라고 하니 참고만 하자!
'우아한테크코스 6기 > 4단계' 카테고리의 다른 글
API 성능 개선하기 2탄 (feat. 검색 전문 인덱스 적용하기) (1) | 2024.09.28 |
---|---|
API 성능 개선하기 1탄 (feat. N + 1과 불필요한 쿼리 개선) (0) | 2024.09.25 |
Tomcat의 Coyote와 Catalina에 대해 알아보자 (1) | 2024.09.08 |
Tomcat의 전체 구조와 역할에 대해 알아보자 (0) | 2024.09.07 |
Http Status 300 Multiple Choices와 수동 리다이렉션은 언제 사용할까? (0) | 2024.09.04 |