[Spring] - 톰켓(Tomcat)의 용도

wonn._.log·2024년 12월 27일

Spring

목록 보기
1/1
post-thumbnail

Tomcat은 무엇인가

Tomcat이 고유하게 갖는 특징

Apache Tomcat은 Java 기반의 오픈 소스 Web Application Server (WAS)로서, 다음과 같은 주요 특징을 갖는다.

  1. Servlet 및 JSP 지원: Tomcat은 Jakarta Servlet과 Jakarta Server Pages 사양을 구현하여 Java 기반의 Web Application 개발과 실행을 지원한다.

    1. Tomcat은 동적 웹 콘텐츠를 위한 안정적이고 확장 가능한 환경을 제공하며, Java 서블릿을 통해 클라이언트 요청을 처리하고 효율적으로 응답을 생성한다.
    2. Tomcat은 WAS의 일부(역할 수행)라고 볼 수 있다.

    ❓ Java Servlet, Java Server Pages가 아니라 Jakarta? Java EE에서 Jakarta EE로 이름이 변경된 후의 명칭이다.

  2. 오픈 소스 SW: Apache Software Foundation에서 개발한 오픈 소스 프로젝트로, 누구나 무료로 사용하고 수정 및 배포할 수 있다. 또한 Java 기반으로 개발되어 있으며, Windows, Linux, macOS 등 다양한 운영체제에서 실행이 가능하다.


Spring Framework 프로젝트에서 Tomat은 어떤 역할을 하는가 (언제, 어느단에서 역할을 하는가)

Spring Framework 프로젝트에서 Tomcat은 다음의 3가지 큰 역할을 갖는다.

  1. Servlet 컨테이너로서의 역할
    1. Spring Framework는 Java EE의 Servlet 스펙을 기반으로 동작한다. Tomcat은 Servlet 컨테이너로서, Spring Framework의 핵심 구성요소인 DispatcherServlet을 실행하고 관리하는 역할을 한다.
    2. DispatcherServlet은 클라이언트의 요청을 받아서 처리하고, 적절한 Controller로 전달한 후, 응답을 생성하는 역할을 한다.

DispatcherServlet 동작 방식


  1. HTTP 요청 및 응답 처리

    1. Tomcat은 HTTP 요청을 수신하고 이를 Spring Framework에 전달한다. 마찬가지로 요청을 처리한 후, Spring Application이 생성한 HTTP 응답을 클라이언트(ex. 브라우저)로 반환한다.
      1. DispatcherServlet이 하는 역할
  2. 애플리케이션 배포 및 실행

    1. Spring Framework 프로젝트는 일반적으로 WAR(Web Application Archive) 파일로 빌드되어 Tomcat 서버에 배포된다. 따라서 Tomcat은 이 WAR 파일을 읽어들이고, Web Application으로써 실행될 수 있도록 설정을 load하고 초기화하는 작업을 진행해준다.
      1. 빌드한다는 것은 애플리케이션을 실행할 준비가 된 상태로 컴파일 및 패키징한다는 뜻
  3. 애플리케이션 생명주기 관리

    1. Tomcat은 Spring Application의 초기화, 실행, 종료 과정을 전부 다 관리한다.
    2. 예를 들어, Tomcat이 시작되면 Spring의 ContextLoaderListener가 초기화되어 Application Context를 생성한다.
      1. ContextLoaderListener는 Spring Web 애플리케이션에서 Root ApplicationContext를 초기화하고, 이를 Servlet Context와 연결한다.
      • ApplicationContext Spring Framework에서 애플리케이션의 설정 정보를 관리하고, 객체(빈, Bean)의 생성과 의존성을 관리하는 컨테이너이다. 애플리케이션 전반에 걸쳐 객체를 생성, 관리, 제공하는 중심적인 역할을 한다. 앞서 ContextLoadListener는 Tomcat 실행만으로 자동으로 동작하는 것은 아니다! Tomcat은 Spring과는 독립적인 Java Servlet 컨테이너이기 때문에 Spring의 설정을 자동으로 인식하지는 못한다. 따라서 기본적으로 web.xml 파일에 아래와 같이 등록(초기화)해야 한다. WEB-INF/web.xml 에 설정한 값
          <!-- Context Parameters -->
          <!-- Application 어디서든 접근할 수 있는 설정값 -->
          <context-param>
          	<param-name>contextConfigLocation</param-name>
          	<param-value>/WEB-INF/applicationContext.xml</param-value>
          </context-param>
          
          <!-- ContextLoadListener -->
          <listener>
          	<listener-class>mysite.web.ContextLoadListener</listener-class>
          </listener>
        이 경우 클래스(여기선 ContextLoadListener)를 따로 만들어서 세부 설정을 조정할 수 있다.
        import jakarta.servlet.ServletContext;
        import jakarta.servlet.ServletContextEvent;
        import jakarta.servlet.ServletContextListener;
        
        public class ContextLoadListener implements ServletContextListener {
        
            public ContextLoadListener() {
            }
        
            public void contextInitialized(ServletContextEvent sce)  { 
            	// 컨텍스트에서 Listener를 가져온다.
            	ServletContext servletContext = sce.getServletContext();
            	String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation"); // /WEB-INF/applicationContext.xml
            	
            	System.out.println("Application[MySite02] starts... " + contextConfigLocation);
            }
        
            public void contextDestroyed(ServletContextEvent sce)  { 
            }
        }
        
        하지만 최신 Spring 버전에서는 Java Config를 통해서 Listener를 등록한다. (@ConfigurationWebApplicationInitializer)
        public class AppInitializer implements WebApplicationInitializer {
            @Override
            public void onStartup(ServletContext servletContext) throws ServletException {
                AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
                context.register(AppConfig.class);
                context.setServletContext(servletContext);
        
                servletContext.addListener(new ContextLoaderListener(context));
            }
        }
        
  4. Static Resource 처리
    1. Spring Application 외에도 정적 자원(HTML, CSS, JS, img 등)을 클라이언트에 제공하는 역할도 수행한다.
    1. WAS는 동적 + 정적 동작을 다 처리한다.



Spring 프로젝트에서는 우리는 어떻게 사용하고 있을까?

Tomcat은 우리 프로젝트에서 다음 단계로 수행이 된다.

  1. WAR 파일 배포
    1. Spring Framework 프로젝트를 WAR 파일로 빌드하여 Tomcat의 webapps 디렉토리에 배치한다.
      1. webapps 디렉토리는 Tomcat에서 기본적으로 제공하는 애플리케이션 배포 디렉토리이다. 여기에 앞선 정적 자원 (HTML, CSS 등)을 둬서Tomcat 실행과 동시에 자동으로 로드하고 처리한다. (index.html로 기본 접근 가능)
      2. 참고로 webapps 하위에는 일반 파일 외에 WEB-INF 디렉토리가 있는데, 이 곳 내부의 리소스는 애플리케이션 내부에서만 접근 가능하며, 직접 URL로 경로를 쳐서 접근은 할 수 없다. (보안 때문)
      • 정적 자원이 많아지면 별도의 정적 파일 서버 (Nginx, CDN 등)을 사용하는 것이 유리하다.


  1. 서버 시작 시 초기화
    1. web.xml 또는 config에 정의된 리스너(ContextLoaderListener)와 서블릿(DispatcherServlet)이 초기화된다.
    2. Spring의 ApplicationContext가 생성되고, 빈(Bean)이 초기화된다.
  2. 클라이언트 요청 처리
    1. 클라이언트의 HTTP 요청이 Tomcat에 도달하면, Tomcat은 이를 DispatcherServlet에 전달한다. 이는 앞선 내용과 동일. 적절한 Controller 호출 후 응답 반환

하지만 이후에 발전된? Spring Boot에서는 이 톰켓을 내장한 채로 사용하게 된다.

그럼 Spring Boot에서는 톰켓을 내장해서 쓰는데 왜 그런가? 그 이유와 어떻게 내장해서 쓰는지 알아보자.

Spring Boot에서 Tomcat을 내장해서 사용하는 이유

  1. 독립적인 실행형 애플리케이션을 제공하기 위해서
    1. 내장 Tomcat을 통해 우리는 WAR 파일을 외부 애플리케이션 서버에 배포하지 않고, 하나의 단일 실행 파일 자체 (JAR)로 애플리케이션을 바로 실행할 수 있게 된다. 즉, 배포와 실행 과정을 간소화하게 되는 것이다.
      1. WAR vs JAR :
        1. JAR 서버 필요 없음. WAR 외부 애플리케이션 서버 필요 (우리가 따로 Tomcat 서버를 설정을 해줘야 했음)
        2. WAR는 정적 소스들을 담는 WEB-INF 디렉토리를 갖고 있으며 애플리케이션 서버에 배포 시 webapps 디렉토리가 배포된다.
  2. 설정 간소화 및 일관성 보장
    1. 내장 Tomcat은 기본적으로 미리 설정되어 제공되기 때문에, 복잡한 서버 설정 없이 빠르게 애플리케이션을 실행할 수 있다. 또한 동일한 서버 구성을 유지할 수 있어 환경 간의 일관성이 보장된다.

Spring Boot에서 Tomcat을 내장하는 방식

  1. build.gradle 또는 maven xml 파일에 spring-boot-starter-web 의존성을 추가해준다. 이를 통해 톰켓을 내장하게 되며 설정을 초기화 한다.

    1. 이 과정에서 Tomcat은 자동으로 포트 번호 8080을 기본값으로 설정하고 경로는 /로 설정하게 된다.
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
  2. 이후 Spring Boot에서는 바로 run() 메서드를 통해 애플리케이션을 실행만 해주면 된다.

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
    
  3. 추가 ) application.properties 또는 yml에서 커스머마이징이 가능하고 JAR 파일로 실행 가능하다.

    1. 포트 변경 가능
    2. 애플리케이션을 JAR로 패키징하여 Tomcat이 포함된 파일을 생성할 수 있다.
profile
Everytime with sincerity, and best effort✨

0개의 댓글