[Spring] Application Context

Woo Yong·2024년 1월 22일
1

Spring

목록 보기
13/15
post-thumbnail

Application Context

Application Context는 스프링 프레임워크에서 제공하는 핵심 컨테이너이며, IoC(Inversion of Control) 컨테이너의 한 종류이다.

이러한 Application Context는 스프링에서 객체(빈)의 생성, 관리, 의존성 주입 등을 담당하며, 다양한 기능과 서비스를 제공합니다.

초기화 방법

1. web.xml을 이용하여 ContextLoaderListener 사용

ContextLoaderListener를 사용하여 웹 애플리케이션 컨텍스트를 초기화할 수 있습니다.

<!-- 변경전 -->
<listener>
    <listener-class>mycom.test.MyListener</listener-class>
</listener>

<!-- 변경후 -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.ContextLoader</param-value>
</context-param>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

ServletListener를 직접 구현한 클래스의 패키지 경로를 작성했던 코드에서 스프링에서 제공해주는 API 경로로 변경한 것을 볼 수 있다.

ContextLoaderListener

  • ServletListener의 구현체
  • Application Context 생성
  • Application Context를 webapp에 등록되어 있는 Servlet들이 사용할 수 있도록 바인딩
    - 웹 애플리케이션이 시작되면 스프링의 ApplicationContext를 초기화하여, 모든 Servlet이 해당 ApplicationContext에 접근이 가능하게 한다는 의미이다. (공유 영역 ??)
  • Servlet에서 IoC 컨테이너를 ServletContext를 통해 꺼내 사용할 수 있다.

이처럼 Spring 프레임워크에서 제공하는 ContextLoaderListener는 웹 응용프로그램을 초기화하고 Spring Context를 설정하기 위한 API를 제공한다.

그리고 ContextLoaderListener를 웹 애플리케이션이 시작될 때 Spring ApplicationContext를 초기화하고 필요한 빈들을 로드하는 역할을 한다.

실제로 ContextLoaderListener가 등록되면 웹 애플리케이션이 호출되고, 내부적으로 WebApplicationContext를 생성하고 ServletContext에 등록한다.

public class MyContextLoaderListener implements ServletContextListener {

    private WebApplicationContext context;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        // WebApplicationContext 생성 및 초기화
        this.context = createWebApplicationContext(event.getServletContext());

        // ServletContext에 WebApplicationContext 등록
        event.getServletContext().setAttribute(WebApplicationContext.ROOT_WEBAPPLICATION_CONTEXT_ATTRIBUTE, this.context);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // 애플리케이션 종료 시의 작업
    }

    private WebApplicationContext createWebApplicationContext(ServletContext servletContext) {
        // 실제 WebApplicationContext 생성 로직
        // 여기서는 예시로 GenericWebApplicationContext를 사용
        GenericWebApplicationContext context = new GenericWebApplicationContext();
        // 설정 등을 추가로 수행할 수 있음
        return context;
    }
}

이때, this.contextApplicationContext를 나타내며, ServletContextWebApplicationContext형태로 생성하고 등록하는 것이다.

자바 설정 클래스

@Configuration
@ComponentScan
public class AppConfig {
}

ApplicationContext를 만들기 위해서는, 자바 설정 클래스 반드시 있어야한다.
왜냐하면 Servlet Context와 연동을 해야하기 때문이다.

자바 설정 클래스를 자세히 살펴보면 @Component어노테이션이 붙어있어 @Compoenent, @Service, @Controller 등 어노테이션이 붙은 클래스들을 찾아서 빈으로 등록한다.

그리고 ContextLoaderListenerAppConfig(자바 설정 클래스)를 가진 상태로 AnnotationConfigWebApplicationContext를 만들고 그 안에, HelloService라는 Bean 객체가 등록되어 있는 것이다.

xml로 자바 설정

<web-app>
    <!-- ContextLoaderListener 등록 -->
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <!-- Spring 설정 파일의 경로 지정 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.example.AppConfig</param-value>
    </context-param>
</web-app>

어노테이션을 이용한 방법이 아니라, web.xml에 명시적으로 선언하여 자바 설정 클래스를 등록할 수 있다.

위 2개 코드는 모두 AppConfig클래스를 로드하고, 그 안에 정의된 HelloService Bean을 등록합니다.

Bean 등록 클래스

@Service
public class HelloService {

    public String getName(){
        return "jinminChoi";
    }
}

ApplicationContext 초기화

방법 1

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

ContextLoaderListener에서 초기화될 때 작성된 코드를 살펴보면 위 코드와 같이 ApplcationContext를 등록되기 때문에 ApplicationContext를 get하여 사용할 수 있다.

왜냐하면, ContextLoaderListener가 초기화될 때, 모든 Servlet이 접근할 수 있도록 바인딩이 이루어지기 때문에 Servlet에서 ApplicationContext를 불러와서 사용이 가능하다.

즉, 위에서 AppConfig 클래스를 생성한 이유가 이와같이 Servlet과 연동하기 위한 것이다.

public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ApplicationContext context = (ApplicationContext) getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        
        HelloService helloService = context.getBean(HelloService.class);
        
        resp.getWriter().println(helloService.getName());
    }
 }

따라서, HTTP 요청을 처리하는 Servlet 객체를 생성한 후, 클라이언트로부터 요청이 들어왔을 때 AppConfig(자바 설정 클래스)를 이용하여 ApplicationContext를 초기화하면 Bean으로 등록 가능한 객체들을 등록하여 사용이 가능하다.

방법 2

public class MainApplication {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // 이제 MyComponent 빈을 가져올 수 있음
        HelloService hs = context.getBean(HelloService.class);
        hs.getName();
    }
}

또 다른 방법으로는 main()를 이용해 AppConfig 클래스를 이용해서 ApplicationContext를 초기화하면, @ComponentScan에 의해서 빈들이 등록된다.

그리고 getBean()메서드를 통해 해당 Bean을 가져와서 사용할 수 있다.

2. Spring Boot프레임워크를 이용한 초기화

Spring Boot 프로젝트에서는 @SpringBootApplication어노테이션을 사용하면 자동으로 ApplicationContext의 초기화가 이루어집니다.

Spring Boot는 내장 톰캣을 사용하고 있습니다. 그렇기 때문에 AppplicationContext를 초기화합니다.

따라서, Spring Boot 애플리케이션은 @SpringBootApplication어노테이션이 붙은 클래스를 기준으로 자동으로 구성되며, @SpringBootApplication어노테이션은 @Configuration, @EnableAutoConfiguration, @ComponentScan을 포함하고 있습니다.

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

위 코드에서 SpringApplication.run() 메서드는 ApplicationContext를 초기화하고 애플리케이션을 실행하는 역할을 합니다.

차이점

크게 SpringBoot는 내부적으로 톰캣을 내장하고 있어서 초기화가 자동으로 이루어지는 반면에 ContextLoaderListener를 사용하는 경우에는 외부 서버(톰캣)에서 애플리케이션 실행하는 경우가 일반적이기 때문에, web.xml에 명시적으로 작성하여 초기화가 이루어집니다.

즉, @SpringBootApplication어노테이션이 선언된 MyApplication클래스는 자바 설정 클래스(@Configuration, @ComponentScan 포함)이며, main()에서 MyApplication클래스를 이용하여 ApplicationContext를 초기화 한것이다

profile
Back-End Developer

0개의 댓글