본문 바로가기

카테고리 없음

TIL - Tomcat 운영 원리

1. Tomcat 개요

더보기
  • Tomcat Java EE(Servlet/JSP) 애플리케이션을 실행하는 웹 서버이자 서블릿 컨테이너입니다. 이 서버는 HTTP 요청을 받아 Java 서블릿을 실행하고, 그 결과를 HTTP 응답으로 반환하는 역할을 합니다.
  • HTTP와 HTTPS 요청 처리: Tomcat은 HTTP HTTPS 요청을 모두 처리할 수 있습니다. 이를 통해 웹 애플리케이션은 안전하고 안정적인 통신을 제공합니다.
  • 동기식 및 비동기식 처리: 요청에 대한 처리는 동기식 또는 비동기식 방식으로 처리할 수 있습니다. 예를 들어, 비동기 처리는 클라이언트 요청에 대해 서버가 즉시 응답하지 않고, 내부적으로 비동기 처리를 통해 다른 작업을 동시에 처리할 수 있도록 도와줍니다.
  • 핸들러 (Handler):
    • Tomcat은 요청을 내부적으로 Connector → Engine → Host → Context → Wrapper(Servlet) 순으로 전달합니다. 실질적으로 요청 처리는 서블릿이 담당하며, Spring에서는 이 서블릿으로 DispatcherServlet을 등록하여 HTTP 요청을 Spring MVC 체계에서 처리합니다.
    • DispatcherServlet은 Spring MVC의 중심 서블릿으로서 모든 요청을 받아 HandlerMapping을 통해 적절한 컨트롤러를 찾고, HandlerAdapter를 통해 해당 컨트롤러를 실행합니다. 이 후 결과를 적절한 방식(JSON, View 등)으로 응답합니다.
    • 핸들러 매핑(Handler Mapping): Spring Boot에서 핸들러 매핑은 요청 URL과 매핑되는 컨트롤러 메서드를 찾아 요청을 해당 메서드에 전달하는 역할을 합니다. 주로 @RequestMapping, @GetMapping, @PostMapping 등의 어노테이션을 사용하여 매핑을 설정합니다.
    • JSON 응답: 요청 처리 후, 컨트롤러는 @RestController 또는 @ResponseBody 어노테이션을 사용하여 JSON 형식으로 데이터를 반환합니다. 이는 주로 RESTful API 개발 시 사용됩니다.
    • 핸들러 인터셉터: 요청 처리 전후에 추가적인 작업을 할 수 있는 핸들러 인터셉터를 설정할 수 있습니다. 예를 들어, 인증, 로깅, 요청/응답 수정 등의 작업을 수행할 수 있습니다. Spring에서는 HandlerInterceptor를 사용하여 이를 구현합니다.
  • Spring Boot 내장 Tomcat:
    • Spring Boot 애플리케이션은 기본적으로 내장 Tomcat 서버를 제공하여, 별도의 외부 서버 없이 독립적으로 실행할 수 있습니다. 이는 Spring Boot의 핵심 장점 중 하나로, 개발자가 서버 설정에 신경을 쓰지 않고, 간단하게 웹 애플리케이션을 배포하고 실행할 수 있게 합니다.
    • 내장 Tomcat을 사용하면 애플리케이션을 실행할 때 별도로 서버 설치 배포 과정을 거치지 않아도 되며, java -jar 명령으로 바로 실행할 수 있습니다.

2. Tomcat의 핵심 역할

더보기
  • Servlet 컨테이너: Tomcat은 클라이언트의 요청을 받아 서블릿으로 전달하여 처리합니다. 서블릿은 Java 클래스이며, 클라이언트의 요청에 맞는 로직을 실행하고 결과를 반환합니다.
  • JSP (JavaServer Pages): JSP는 동적인 웹 페이지를 생성하기 위해 사용하는 기술입니다. Tomcat은 JSP 파일을 서블릿으로 변환하여 실행합니다. JSP는 HTML 코드 내에 Java 코드를 삽입할 수 있어, 서버에서 동적으로 페이지를 생성할 때 유용합니다.
  • Tomcat은 클라이언트의 요청을 처리한 후 HTTP 응답을 반환하며, 이를 통해 클라이언트는 웹 페이지를 볼 수 있게 됩니다.

3. Tomcat의 요청 처리 흐름

더보기
  • 클라이언트 요청: 사용자가 웹 브라우저에서 URL을 입력하면, HTTP 요청이 Tomcat 서버로 전송됩니다.
  • Tomcat Connector: Tomcat의 Connector가 HTTP 요청을 받아 해당 요청을 Servlet Container로 전달합니다. Connector는 HTTP 요청을 처리하고, 적절한 서블릿을 찾아 요청을 전달하는 역할을 합니다.
  • Servlet Container: Servlet Container는 요청에 해당하는 서블릿을 찾고 실행합니다. 서블릿은 클라이언트의 요청을 처리하고, 응답을 작성하여 반환합니다.
  • HTTP 응답: 서블릿은 처리 결과를 HTTP 응답으로 반환하며, 이 응답은 다시 클라이언트로 전달됩니다. 클라이언트는 웹 페이지 또는 다른 형식의 응답을 볼 수 있습니다.

이 과정에서 중요한 점은, Servlet Container가 요청을 서블릿에 전달하고 서블릿이 이를 처리하는 방식입니다. Tomcat은 Servlet API를 구현하여 이를 관리합니다.

4. Tomcat의 멀티쓰레딩

더보기

 

  • 멀티쓰레딩: Tomcat은 여러 클라이언트의 요청을 동시에 처리하기 위해 멀티쓰레딩 방식을 사용합니다. 각 요청은 별도의 쓰레드에서 처리되며, 이를 통해 여러 요청을 동시에 처리할 수 있어 서버의 성능과 응답 속도가 향상됩니다.
  • 쓰레드 풀 (Thread Pool): Tomcat은 요청에 대해 미리 생성된 쓰레드 풀을 관리하여, 요청이 들어오면 그에 맞는 쓰레드를 할당하여 처리합니다. 이를 통해 매번 새로운 쓰레드를 생성하는 비용을 줄이고, 서버 성능을 최적화할 수 있습니다.
  • 쓰레드 수 최적화: Tomcat의 기본 설정에서는 최대 쓰레드 수(server.tomcat.max-threads)나 최소 여유 쓰레드 수(server.tomcat.min-spare-threads)를 조정할 수 있어, 서버의 성능을 최적화할 수 있습니다. 예를 들어, 너무 많은 쓰레드가 생성되면 메모리나 CPU 자원을 과도하게 소비할 수 있기 때문에 적절한 쓰레드 수를 설정하는 것이 중요합니다.
  • 동시성 처리 고려:
    • 장점: Tomcat에서 멀티쓰레딩을 사용하는 이유는 동시성 처리입니다. 요청이 다수일 때 각 요청을 독립적으로 처리하고, 이를 빠르게 응답하기 위해서는 동시성 처리가 매우 중요합니다. 이를 통해 여러 사용자가 동시에 요청을 보내더라도 시스템이 안정적으로 작동할 수 있습니다.
    • 문제점: 하지만 동시성 처리에는 몇 가지 문제점도 존재합니다.
      • 쓰레드 충돌: 여러 쓰레드가 동시에 동일한 자원에 접근할 때, 적절한 동기화 없이 실행되면 경쟁 조건(Race Condition)이나 데드락(Deadlock)이 발생할 수 있습니다. 이로 인해 데이터가 손상되거나 서버가 응답하지 않게 될 수 있습니다.
      • 자원 소모: 너무 많은 쓰레드를 생성하고 동시에 처리하려 할 경우, CPU나 메모리 자원을 과도하게 사용하게 되어 서버 성능 저하리소스 부족 문제가 발생할 수 있습니다. 이를 해결하려면 쓰레드 풀 크기를 적절히 설정하고, 쓰레드 관리를 신중히 해야 합니다.
      • 컨텍스트 스위칭 오버헤드: 다수의 쓰레드가 동시에 실행되면, 운영 체제는 각 쓰레드 간의 컨텍스트 스위칭을 처리해야 합니다. 너무 많은 쓰레드가 동시에 동작할 경우, 이로 인한 오버헤드가 성능에 영향을 줄 수 있습니다.
  • 추후 동시성에 대한 추가 정리 예정: 이번에 다룬 내용은 Tomcat의 멀티쓰레딩에 관한 기초적인 부분으로, 추후 동시성병렬 처리에 대해 더 깊이 다룰 예정입니다. 이와 관련하여 Java의 동시성 처리멀티스레딩 관리에 대해 구체적으로 정리할 예정이므로, 해당 부분도 함께 참고하시기 바랍니다

 Tomcat의 성능 최적화

  • 쓰레드 수 조정 (server.tomcat.max-threads, server.tomcat.min-spare-threads):
    • 멀티쓰레딩을 통해 Tomcat은 여러 클라이언트 요청을 동시에 처리할 수 있습니다. 이때 중요한 점은 적절한 쓰레드 수 조정입니다. server.tomcat.max-threads와 server.tomcat.min-spare-threads 설정을 통해 동시 요청 처리 성능을 최적화할 수 있습니다.
    • max-threads를 너무 낮게 설정하면 동시 요청을 처리하지 못해 성능이 떨어질 수 있으며, 너무 높게 설정하면 자원 소모가 과도해져서 서버의 성능이 저하될 수 있습니다. 따라서 쓰레드 수는 서버의 하드웨어 성능과 예상되는 트래픽에 맞게 조정하는 것이 중요합니다.
    • 이 설정은 멀티쓰레딩 환경에서 동시에 실행되는 쓰레드 수를 제어하는 것으로, 쓰레드 관리가 잘 되어야 서버가 효율적으로 동시 요청을 처리할 수 있습니다.
  • 커넥션 타임아웃 설정 (server.tomcat.connection-timeout):
    • 요청이 처리되는데 시간이 너무 오래 걸리면, 이는 쓰레드 자원을 과도하게 점유할 수 있습니다. 이로 인해 다른 요청을 처리하는 데 필요한 쓰레드가 부족해져 성능에 악영향을 미칠 수 있습니다.
    • connection-timeout을 적절하게 설정하면, 일정 시간 내에 응답을 받지 못한 요청에 대해 커넥션을 종료시켜 해당 쓰레드 자원을 다른 요청에 재사용할 수 있도록 합니다. 이는 쓰레드 풀의 효율성을 높이는 데 기여하며, 멀티쓰레딩 환경에서 쓰레드 자원을 효율적으로 관리할 수 있게 해줍니다.
  • 커넥션 풀:
    • Tomcat은 데이터베이스 연결 시 커넥션 풀을 사용하여 여러 개의 데이터베이스 연결을 재사용할 수 있습니다. 이를 통해 매번 새로운 커넥션을 생성하는 비용을 줄이고, 성능을 최적화합니다.
    • 멀티쓰레딩 환경에서 다수의 요청이 동시에 데이터베이스에 접근할 때, 커넥션 풀을 통해 동시성을 잘 관리할 수 있습니다. 커넥션 풀을 사용하지 않으면 각 쓰레드가 데이터베이스에 연결할 때마다 새로운 연결을 생성하게 되어 리소스 낭비와 성능 저하를 초래할 수 있습니다. 커넥션 풀을 사용하면 이 문제를 해결하고, 자원 낭비를 줄여 성능을 향상시킬 수 있습니다.

이렇게, 멀티쓰레딩 환경에서의 쓰레드 수 조정, 커넥션 타임아웃 설정, 커넥션 풀 사용 등은 모두 Tomcat의 성능 최적화에 중요한 요소들입니다. 이들은 서로 밀접하게 연결되어 있어, 효율적인 자원 관리동시성 처리를 위해 모두 적절하게 설정해야 합니다.

 

5. Tomcat의 싱글톤 패턴

더보기

 

  • 싱글톤 패턴(Singleton Pattern): Tomcat은 싱글톤 패턴을 활용하여 객체의 재사용성을 높이고, 메모리 효율성을 극대화합니다. 싱글톤 패턴은 객체를 한 번만 생성하고, 그 객체를 여러 번 재사용하는 방식으로 초기화 비용을 줄이고 애플리케이션의 성능을 향상시킵니다.
  • 애플리케이션 전역 객체: 예를 들어, ServletContextDataSource와 같은 객체는 애플리케이션 전역에서 하나만 생성되어 공유됩니다. 이들은 여러 요청에 걸쳐 재사용되므로, 객체 생성 시 발생할 수 있는 불필요한 오버헤드를 방지하고, 메모리 낭비를 줄이는 데 도움을 줍니다.
  • 서블릿과 필터: Tomcat의 웹 애플리케이션 초기화 시, 서블릿이나 필터 같은 객체들은 싱글톤으로 생성되며, 이후 요청에 대해 동일한 객체를 재사용합니다. 이를 통해 자원 낭비를 줄일 수 있으며, 서버 성능을 최적화할 수 있습니다.
  • 값을 정해주지 않음: 싱글톤 객체는 애플리케이션 전역에서 하나의 인스턴스로 공유되기 때문에, 내부에 상태를 저장할 경우 다수의 요청이 동시에 해당 상태를 변경할 수 있어 동시성 문제가 발생할 수 있습니다. 따라서 상태 저장은 지양하고, 가능하면 요청 스코프나 쓰레드 로컬(ThreadLocal) 등으로 분리해야 합니다. . 즉, 객체는 상태를 공유할 수 있지만, 값이 정해지지 않거나 동적으로 설정되지는 않습니다. 예를 들어, ServletContext와 같은 객체는 애플리케이션의 전역 상태를 담고 있지만, 그 자체로 값이 고정된 것이 아니기 때문에 필요한 상황에 맞춰 동적으로 값이 설정될 수 있습니다. 이러한 점을 염두에 두고, 싱글톤 객체의 사용을 관리해야 합니다.

 

6. Spring Boot와 Tomcat의 관계

더보기
  • Spring Boot 내장 Tomcat을 사용하여 애플리케이션을 실행합니다. 이로 인해 Spring Boot 애플리케이션은 외부 Tomcat 서버에 의존하지 않고 독립적으로 실행될 수 있습니다.
  • Spring Boot에서 Tomcat 내장 서버는 기본적으로 org.springframework.boot.web.embedded.tomcat 모듈에 포함되어 있으며, Spring Boot 애플리케이션을 빌드할 때 Tomcat이 자동으로 내장됩니다.
  • Spring Boot에서는 application.properties 또는 application.yml 파일을 통해 Tomcat의 설정을 쉽게 조정할 수 있습니다. 예를 들어, 서버 포트(server.port), 최대 쓰레드 수(server.tomcat.max-threads), 시간 초과 설정(server.tomcat.connection-timeout) 등을 설정할 수 있습니다.

7. Tomcat의 보안 설정

더보기

 

  • SSL/TLS 설정: Tomcat에서 SSL/TLS를 설정하여 HTTPS를 지원할 수 있습니다. 이를 통해 클라이언트와 서버 간의 데이터가 암호화되어 보안이 강화됩니다. Tomcat에서는 server.ssl.key-store와 같은 프로퍼티를 사용하여 SSL 인증서를 설정할 수 있습니다.
  • HTTP 헤더 보안 설정: Tomcat은 HTTP 응답 헤더를 설정하여 보안을 강화할 수 있습니다. 예를 들어, Strict-Transport-Security나 Content-Security-Policy와 같은 보안 헤더를 설정하여 다양한 웹 공격을 방어할 수 있습니다.
  • IP 제한 및 필터링: Tomcat은 특정 IP에서의 접근 제한이나 HTTP 요청 필터링을 통해 보안을 강화할 수 있는 기능을 제공합니다. 이러한 설정은 보안 정책에 따라 필요할 때 설정합니다.
  • 추후 JWT와 Spring Security 사용 예정: 현재는 JWTSpring Security를 사용하여 보안을 강화할 계획이기 때문에, Tomcat의 보안 설정에 대해 깊게 공부하지는 않았습니다. 이 부분은 Spring Security에서 더 다룰 예정이므로, JWT 기반의 인증 및 권한 관리에 집중할 예정입니다.