그동안 비전공 개발자로 SSAFY와 취업 후 프로젝트 개발에만 몰두하다 보니, 기반이 되는 CS 지식이 많이 부족하다고 느꼈다.
특히 AI가 발전하면서 앞으로는 단순히 코드를 작성하는 것보다, 이런 기반 지식들과 아키텍처, 기술의 깊은 동작 과정을 이해하는 것이 개발자에게 더 중요한 역량이 될 거라고 생각한다.
그래서 앞으로 가능하면 하루에 하나씩, 간단한 것부터 심화 지식까지 1일 1CS 학습을 진행해보려 한다.
오늘은 Spring Boot 개발자라면 자주 접하게 되는 기본 지식인 Tomcat과 Servlet에 대해 정리해보았다.
Tomcat은 웹 서버와 웹 컨테이너가 결합된 형태로, 현재 가장 일반적으로 사용되는 WAS다. 컨테이너, 웹 컨테이너, 서블릿 컨테이너라고도 부른다.
주요 역할:
Spring Boot와의 관계:
Spring Boot는 내장 톰캣을 기본으로 사용한다. 덕분에 별도의 톰캣 설치 없이 JAR 파일만으로 애플리케이션을 실행할 수 있고, application.properties에서 포트, 스레드 수 등을 쉽게 커스터마이징할 수 있다.
서블릿은 자바를 이용해 웹 서비스를 만들기 위한 스펙이다. 클라이언트의 요청을 받아 처리하고 응답을 생성하는 역할을 담당한다.
서블릿 매핑:
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
resp.getWriter().write("Hello!");
}
}

상세 동작:
HttpServletRequest, HttpServletResponse 객체를 생성한다.service() 메서드를 호출하고, HTTP 메서드에 따라 doGet(), doPost()를 호출한다.HttpServletResponse 객체로 응답을 생성한다.
생명주기 메서드:
서블릿 컨테이너는 서블릿 인스턴스가 존재하는지 확인하고, 없으면 init()으로 생성한다. 이후 모든 요청은 service()로 처리하며, 종료 시 destroy()를 호출한다.
중요한 포인트: 서블릿 인스턴스는 웹 애플리케이션당 하나만 생성된다. 모든 요청이 동일한 인스턴스를 공유하기 때문에, 멤버 변수를 사용하면 동시성 문제가 발생할 수 있다.
// ❌ 멤버 변수 사용 (여러 요청이 공유 → 문제!)
private int count = 0;
// ✅ 지역 변수 사용 (각 요청마다 독립적)
int count = 0;
Spring MVC는 Front Controller 패턴을 구현한 DispatcherServlet을 사용한다. 모든 HTTP 요청을 먼저 받아 적절한 Controller로 위임하는 중앙 진입점 역할을 한다.
주요 역할: