본문 바로가기
카테고리 없음

톰캣 서블릿 (OSI 7계층, HTTP 서블릿, 로그인 구현)

by ricepuppy9733 2026. 6. 20.

솔직히 처음 톰캣을 접했을 때, "이걸 왜 쓰는 거지?"라는 생각부터 들었습니다. 소켓 통신으로 서버를 직접 만들 수 있다는 걸 배웠는데, 또 다른 도구를 쓴다고 하니 순간 머릿속이 복잡해졌습니다. 그런데 막상 직접 손을 대보니, 톰캣이 왜 존재하는지 자연스럽게 납득이 됐습니다. 소켓 통신부터 HTTP 파싱, 파일 입출력까지 직접 짜야 한다면 서비스 기능을 만들 시간이 없다는 걸 바로 체감했기 때문입니다.

톰캣 tomcat

소켓 통신과 OSI 7계층, 톰캣이 필요한 이유

웹 서버를 이해하려면 OSI 7계층 모델을 먼저 짚어야 합니다. OSI 7계층이란 네트워크 통신 과정을 역할별로 7단계로 나눈 국제 표준 모델로, 물리 계층부터 응용 계층까지 단계적으로 데이터를 처리합니다. 우리가 흔히 쓰는 HTTP, FTP, SSH 같은 프로토콜은 가장 위쪽인 응용 계층(7계층)에 해당합니다.

그렇다면 소켓 통신은 어디에 위치할까요? 소켓 통신은 1계층(물리)부터 4계층(전송)까지의 동작을 객체로 구현해둔 것입니다. 여기서 소켓 통신이란 네트워크상에서 두 프로그램이 데이터를 주고받을 수 있도록 연결 통로를 만들어주는 기술로, TCP 3-Way Handshake 방식으로 연결을 맺습니다. TCP 3-Way Handshake란 클라이언트와 서버가 실제로 데이터를 주고받기 전에 "연결해도 될까요 → 됩니다 → 확인했습니다"의 세 단계 신호를 교환하며 신뢰할 수 있는 연결을 수립하는 절차입니다.

소켓의 입출력 스트림, 즉 데이터가 오가는 통로에 어떤 프로토콜을 얹느냐에 따라 서버의 종류가 결정됩니다.

  • HTTP 프로토콜을 주고받으면 → 웹 서버와 웹 클라이언트
  • FTP 프로토콜을 주고받으면 → FTP 서버와 FTP 클라이언트
  • SSH 프로토콜을 주고받으면 → SSH 서버와 SSH 클라이언트

이걸 직접 다 구현하려면 엄청난 시간이 필요합니다. 톰캣은 이 작업을 미리 다 해둔 서버입니다. 제가 직접 써봤는데, 덕분에 소켓 처리나 HTTP 파싱 코드를 한 줄도 짜지 않고 바로 서비스 로직에 집중할 수 있었습니다. 톰캣이 WAS(Web Application Server), 즉 단순히 파일을 전달하는 웹 서버와 달리 코드를 실행해 결과를 반환하는 서버로 분류되는 이유가 바로 여기에 있습니다(출처: Apache Tomcat 공식 문서).

HTTP 서블릿의 동작 구조

톰캣 위에서 실제로 요청을 처리하는 단위가 서블릿(Servlet)입니다. 서블릿이란 클라이언트의 HTTP 요청을 받아 처리하고, 그 결과를 응답으로 돌려주는 자바 클래스입니다. 단순히 자바 파일을 하나 만드는 게 아니라, HttpServlet 클래스를 상속받아 doGet이나 doPost 같은 메서드를 오버라이드하는 방식으로 작성합니다.

여기서 오버라이드(Override)란 부모 클래스에 이미 정의된 메서드를 자식 클래스에서 자신만의 방식으로 재정의하는 것을 의미합니다. 톰캣이 doGet 메서드를 기본으로 갖고 있지만, 우리가 오버라이드하면 클라이언트 요청이 들어왔을 때 우리 코드가 실행됩니다. 처음 이 흐름을 이해했을 때 "아, 그래서 extends HttpServlet을 쓰는 거구나"라는 말이 절로 나왔습니다.

요청이 처리되는 흐름을 정리하면 이렇습니다.

  1. 웹 브라우저가 HTTP 요청을 톰캣 서버로 전송합니다.
  2. 톰캣이 소켓 통신과 HTTP 프로토콜 파싱을 처리합니다.
  3. web.xml에 설정된 URL 패턴과 매핑되는 서블릿 클래스를 찾습니다.
  4. 요청 방식(GET/POST)에 맞는 메서드(doGet/doPost)를 실행합니다.
  5. 처리 결과를 HTTP 응답으로 클라이언트에 돌려줍니다.

프로젝트 설정에서 한 가지 놓치기 쉬운 부분이 있었는데, build.gradle에 war 플러그인과 Jakarta Servlet API를 추가해야 한다는 점입니다. WAR(Web Application Archive)란 웹 애플리케이션에 필요한 자바 파일, XML 설정 파일, 리소스 파일을 하나로 묶은 압축 형식입니다. 톰캣은 이 WAR 파일을 전개(deploy)해서 서비스를 실행합니다. 제 경험상 이 부분을 빠뜨리면 톰캣이 클래스 자체를 인식하지 못해서 한참을 헤맸던 기억이 납니다. Jakarta EE 명세에 따르면 서블릿 API는 6.0 버전부터 jakarta.servlet 패키지로 전환되었습니다(출처: Jakarta EE 공식 사이트).

실전 적용 — 프론트엔드와 연결한 로그인 구현

개념만 익히는 것과 실제로 프론트엔드와 연결해보는 것은 완전히 다른 경험입니다. 직접 만든 프론트엔드 프로젝트의 axiosinterceptor.js에서 baseURL을 톰캣 주소인 http://localhost:8080으로 변경하고, login.js에서 POST 방식으로 요청을 보내도록 수정했습니다.

백엔드에서는 doPost 메서드로 JSON 형태의 데이터를 받아야 했는데, 여기서 ObjectMapper가 핵심 역할을 합니다. ObjectMapper란 jackson-databind 라이브러리가 제공하는 클래스로, JSON 문자열을 자바 객체로 변환하거나 그 반대 작업을 수행하는 도구입니다. 직접 문자열을 파싱하지 않아도 되니, User 클래스를 만들고 getter/setter만 준비해두면 자동으로 필드에 값이 채워집니다.

CORS 문제도 빠뜨릴 수 없었습니다. CORS(Cross-Origin Resource Sharing)란 브라우저가 다른 출처의 서버에 요청을 보낼 때 보안상 제한을 걸어두는 정책으로, web.xml에 CorsFilter 설정을 추가해야 프론트엔드에서 톰캣으로 요청이 정상적으로 전달됩니다. 이 설정을 빠뜨렸을 때 브라우저 콘솔에 에러가 가득 찼던 상황이 아직도 기억납니다.

실제로 로그인 요청이 들어오면 ObjectMapper가 JSON을 User 객체로 변환하고, 이메일과 비밀번호를 비교해 로그인 성공 여부를 판단합니다. 지금은 하드코딩된 값과 비교하는 수준이지만, 이 흐름을 손으로 직접 구현해봤다는 것 자체가 중요합니다. DB 연동이나 세션 처리를 붙이면 실제 서비스 수준으로 발전시킬 수 있는 구조이기 때문입니다.

톰캣과 서블릿 구조를 직접 설정해보고 나니, 이후에 스프링이 왜 편한지가 비로소 체감됐습니다. web.xml 설정, WAR 배포, 서블릿 매핑을 일일이 손으로 작성하는 과정을 겪어봤기 때문에, 스프링이 이 작업들을 자동화해준다는 말의 의미가 피부로 와닿습니다. 처음부터 스프링만 배웠다면 마법처럼 느껴졌을 것들이, 지금은 "아, 이게 원래 이렇게 생겼구나"라고 읽힙니다. 다음 단계로 스프링을 공부하기 전에, 이 과정을 직접 손으로 한 번 짜보는 것을 강력히 권합니다.


참고: https://dltldnr2563.tistory.com/entry/%EC%BD%94%EB%94%A9%EA%B3%B5%EB%B6%8020250714-%EC%86%8C%EC%BC%93%ED%86%B5%EC%8B%A0-thread-%ED%86%B0%EC%BA%A3


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 자동식단생성 연관 블로그