Application 등록 과정 - Web 2편

Dev StoryTeller·2021년 2월 11일
0

Spring 시리즈!

목록 보기
14/33

이번 편은 예고했던 대로, Context 등록 과정에 대해 살펴볼 것이다.
앞선 Generic과 크게 다르지 않으니 편하게 보면 된다.

0. 전체 과정

Generic과 동일하게 다음과 같은 과정을 거친다.

1. Context 생성

2. 파일/클래스로부터 Bean 정의 등록

3. Refresh() 실행(Bean 등록)

ROOT-Context와 Servlet-Context의 등록 방법이 크게 다르지 않으니, 동시에 살펴보도록 하겠다


1. Context 생성

ROOT와 Servlet 모두 WebApplicationContext 인터페이스 계열 Context를 생성한다.

이때 어떤 방식이냐에 따라 클래스가 나뉘는데,
Annotation을 사용한다면 AnnotationConfigWebApplicationContext를,
XML을 사용한다면 XmlWebApplicationContext를 사용한다.

  • Annotation 방식
    : AnnotationConfigWebApplicationContext
  • XML 방식
    : XmlWebApplicationContext

2. XML 파일로부터 Bean 정의 등록

(Annotation이나 XML이나 비슷하니, XML에 대해서만 알아볼 것이다.)

여기서부터 ROOT와 Servlet는 다음과 같이 나뉜다.

  • ROOT는 ContextLoaderListener에 의해 로딩
  • Servlet은 FrameworkServlet에 의해 로딩

왜 이렇게 나뉘어지는 걸까?


3. ContextLoaderListener란?

애초에 ROOT Context라는 건 없었다. Context면 다같은 Servlet이지 ROOT가 어디있는가?

따라서 Spring은 따로 ROOT Context를 만들어 내기 위해 기존과는 다른 로딩 방법이 필요했고, 그것이 바로 ContextLoaderListener를 이용한 방법이다.


4. ContextLoader란?

그럼 ContextLoader는 무엇이냐?
ContextLoaderListener는 이름대로 리스너이다.
단지 이벤트를 받아주는 역할을 할 뿐이고 이를 처리해줄 것이 필요한데, 그것이 바로 ContextLoader이다.

즉, ROOT-Context 로딩을 실제로 수행하는 녀석이 되겠다.
다음과 같이 넘겨받는다.


5. 이어서...

자 그럼 다시 로딩 방법에 대해 알아보자.
우선 ROOT의 방법이다.

1. ROOT의 경우

  • initWebApplicationContext()
    ContextLoader의 initWebApplicationContext()를 사용하여 로딩한다.
    다음은 그 과정의 일부분이다.

    앞서 WebContext 설명대로 설정하기 전에 Configure 클래스로 전환하는 모습을 볼 수 있다.

    그리고 해당 Context가 활성화 되어있는지 확인 후, 본격적으로 로딩 작업에 들어간다.


  • 로딩 과정

    잘 살펴보면 get???와 set???의 연속인 것을 볼 수 있다.
    잘 안보이니 해당 부분을 적어보자면,
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
	wac.setId(idParam);
}


String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
	wac.setConfigLocation(configLocationParam);
}


ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
	((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}

이런 식으로 되어있는 것을 볼 수 있는데,
이 부분이 바로 web.xml의 Context 파라미터들을 가져와서 로딩하는 과정이다.
web.xml에서 ROOT-Context를 등록할 땐 <context-param>이라는 태그를 쓰는데, 그 부분을 말하는 것이다.

2. Servlet의 경우

Serlvet은 FrameworkServlet을 사용하는데, ContextLoader와 크게 다르지 않다.
심지어 메소드명 까지 똑같다 : )

  • initWebApplicationContext

    ROOT와 완전히 동일하므로 다음으로 넘어가자.

  • 로딩 과정

    Servlet의 경우 로더가 진행하는 것이 아니기에 getInit~메소드는 없지만,
    대신 setServlet~~메소드가 이를 대신한다.
wac.setServletContext(getServletContext());

wac.setServletConfig(getServletConfig());

위 두 문장은 사실 같은 것이다.
왜냐하면 getServletContext()도 ServletConfig를 불러오기 때문.
이를 통해 ServletConfig가 설정 파일의 본체구나!라는 것을 알 수 있는데,
이를 자세히 들여다보면 다음과 같이 되어있다.

public interface ServletConfig {
    public String getServletName();

    public ServletContext getServletContext();

    public String getInitParameter(String name);

    public Enumeration<String> getInitParameterNames();

}

ServletConfig서블릿의 설정을 가져올 수 있는 인터페이스이다.
이 인터페이스는 거의 대부분의 Servlet 클래스가 구현하고 있으며, FrameworkServlet 역시 이를 구현하고 있다.

따라서 setServletConfig()에선 ServletConfig의 getInitParameter()를 이용하여 XML을 읽어옴을 알 수 있다.


6. Refresh() 과정

이 과정은 둘다 Configurable Context의 refresh()메소드를 사용하는데,
이 메소드를 오버라이드한 클래스는 AbstractApplicationContext 밖에 없다.

앞서 살펴본 Generic과 완전 똑같은 과정이므로, 생략하도록 하겠다.


7. 결론

드디어 Context에 대한 모든 설명이 끝이 났다...!!
다음 편에서는 XML 파일의 작성법에 대해 간단히 알아보고, Container 시리즈를 마칠 것이다.

profile
개발을 이야기하는 개발자입니다

0개의 댓글