이번 단계에서는 Java 콘솔 메모장에서 한 단계 넘어가, 브라우저 요청을 Java Servlet이 처리하도록 만들었다.
먼저 Servlet이 정상적으로 실행되는지 확인하겠다.
지금까지는 콘솔에서 Java 프로그램을 실행했다.
사용자 입력
→ Main
→ MemoService
→ 콘솔 출력
이번 단계부터는 브라우저에서 요청을 보내고, Tomcat이 그 요청을 받아 Servlet을 실행하는 구조로 넘어간다.
브라우저 요청
→ Tomcat
→ Servlet
→ 브라우저 응답
즉, 콘솔에서 직접 실행하던 Java 코드가 아니라, 브라우저 요청을 Java 서버가 받는 구조를 처음 확인하는 것이 목적이었다.
Servlet/JSP 프로젝트 생성
Memo Evolution 프로젝트 안에 새 Maven 모듈을 만들었다.
servlet-jsp-memo/
현재 전체 학습 프로젝트 구조는 다음처럼 발전했다.
Memo Evolution/
├─ react-memo/
├─ java-console-memo/
└─ servlet-jsp-memo/
servlet-jsp-memo는 Servlet/JSP 학습을 위한 Maven 웹 프로젝트다.
기존 java-console-memo가 콘솔에서 Java CRUD 흐름을 연습하기 위한 단계였다면,
이번 servlet-jsp-memo는 브라우저 요청을 Java 코드로 처리하는 단계다.
pom.xml 설정
Servlet을 사용하기 위해 pom.xml에 Servlet API 의존성을 추가했다.
처음에는 jakarta.servlet-api를 사용했지만, 현재 사용 중인 Tomcat 버전이 9였기 때문에 맞지 않았다.
Tomcat 9는 javax.servlet 기반이다.
그래서 최종적으로는 다음 의존성을 사용했다.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
여기서 중요한 점은 Tomcat 버전과 Servlet API 패키지를 맞춰야 한다는 것이다.
Tomcat 9
→ javax.servlet 사용
Tomcat 10 이상
→ jakarta.servlet 사용
이 버전 차이를 맞추지 않으면 Servlet이 정상적으로 등록되지 않아 404가 발생할 수 있다.
Servlet 클래스 만들기
브라우저 요청을 처리하기 위해 MemoServlet 클래스를 만들었다.
파일 위치는 다음과 같다.
servlet-jsp-memo/src/main/java/com/memo/MemoServlet.java
작성한 코드는 다음과 같다.
package com.memo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/memos")
public class MemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>Servlet 메모장</h1>");
response.getWriter().println("<p>Servlet이 정상적으로 실행되었습니다.</p>");
}
}
이번 단계에서는 메모 목록을 출력하거나 저장하지 않았다.
Servlet이 요청을 받고 HTML 응답을 돌려주는지만 확인했다.
HttpServlet 상속
MemoServlet은 HttpServlet을 상속한다.
public class MemoServlet extends HttpServlet
Servlet은 일반 Java 클래스처럼 main()으로 실행되지 않는다.
Java 콘솔 프로그램은 main 메서드가 시작점이었다.
public static void main(String[] args) {
}
하지만 Servlet은 Tomcat 같은 Servlet Container가 실행해준다.
정리하면 다음과 같다.
Java 콘솔
→ main 메서드가 시작점
Servlet
→ Tomcat이 요청에 맞는 Servlet을 실행
이 점이 콘솔 프로그램과 Servlet의 큰 차이였다.
@WebServlet으로 URL 연결하기
@WebServlet은 URL과 Servlet을 연결한다.
@WebServlet("/memos")
이 코드는 다음 의미다.
/memos 요청이 들어오면 MemoServlet이 처리한다.
즉 브라우저에서 다음 주소로 요청하면,
http://localhost:8080/memos
Tomcat은 /memos에 매핑된 MemoServlet을 실행한다.
doGet 메서드
브라우저 주소창으로 접속하는 요청은 보통 GET 요청이다.
그래서 /memos로 접속하면 doGet()이 실행된다.
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
흐름은 다음과 같다.
GET /memos
→ doGet 실행
이번 단계에서는 doGet() 안에서 간단한 HTML 응답을 만들어 브라우저로 보냈다.
request와 response
doGet()에는 두 개의 중요한 객체가 들어온다.
HttpServletRequest request
HttpServletResponse response
request는 브라우저가 보낸 요청 정보를 담고 있다.
예를 들면 다음과 같은 정보가 들어갈 수 있다.
요청 URL
요청 파라미터
form 데이터
요청 방식
response는 브라우저에 돌려줄 응답을 만들 때 사용한다.
예를 들면 다음과 같은 응답을 만들 수 있다.
HTML 응답
문자 인코딩
상태 코드
이번 단계에서는 response를 사용해 간단한 HTML을 보냈다.
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>Servlet 메모장</h1>");
response.getWriter().println("<p>Servlet이 정상적으로 실행되었습니다.</p>");
이 코드는 브라우저에게 HTML 응답을 보내는 코드다.
Tomcat 연결
Servlet은 혼자 실행되지 않기 때문에 Tomcat이 필요하다.
IntelliJ에서 Tomcat 실행 설정을 만들었다.
Run
→ Edit Configurations
→ Tomcat Server
→ Local
그리고 Deployment 탭에서 다음 artifact를 추가했다.
servlet-jsp-memo:war exploded
war → Tomcat에 배포 가능한 웹 애플리케이션 형식
exploded → 압축하지 않고 폴더 형태로 펼쳐진 배포 방식
이라서 보통 개발중에는 exploded를 쓴다.
Tomcat 실행 흐름은 다음과 같다.
Tomcat 실행
→ servlet-jsp-memo 배포
→ 브라우저 요청 대기
→ /memos 요청 처리
여기서 Tomcat은 브라우저 요청을 받아 적절한 Servlet으로 전달하는 역할을 한다.
8080 포트 충돌 문제
처음 Tomcat 실행 시 8080 포트 충돌이 발생했다.
로그에는 다음과 같은 메시지가 있었다.
Caused by: java.net.BindException: Address already in use
뜻은 다음과 같다.
8080 포트를 이미 다른 프로그램이 사용 중이다.
확인해보니 Docker 컨테이너가 8080 포트를 사용하고 있었다.
heartdoor-server-backend-1
0.0.0.0:8080->8080/tcp
그래서 해당 컨테이너를 중지했다.
docker stop heartdoor-server-backend-1
이후 Tomcat이 정상적으로 8080 포트에서 실행되었다.
이번 문제를 통해 서버를 실행할 때는 포트 충돌도 확인해야 한다는 것을 알게 되었다.
404 문제
Tomcat은 정상 실행되고 artifact도 배포되었지만, 처음에는 /memos 접속 시 404가 나왔다.
원인은 Tomcat 버전과 Servlet API 패키지가 맞지 않았기 때문이다.
처음 코드와 의존성은 jakarta.servlet 기준이었다.
import jakarta.servlet.http.HttpServlet;
하지만 사용 중인 Tomcat은 9였다.
Tomcat 9
→ javax.servlet 기반
그래서 import를 아래처럼 수정했다.
import javax.servlet.http.HttpServlet;
그리고 pom.xml도 javax.servlet-api로 변경했다.
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
수정 후 Tomcat을 다시 실행하자 /memos 요청이 정상 처리되었다.
정상 실행 결과
브라우저에서 다음 주소로 접속했다.
http://localhost:8080/memos
정상적으로 다음 화면이 출력되었다.

이로써 브라우저 요청이 Java Servlet까지 도달하고, Servlet이 응답을 만들어 브라우저에 돌려주는 흐름을 확인했다.
이번 단계는 Servlet/JSP 학습의 첫 단계였다.
아직 메모 CRUD를 웹으로 구현한 것은 아니지만, 브라우저 요청이 Tomcat을 거쳐 Java Servlet까지 도달하는 흐름을 확인했다.
이번 단계의 핵심은 다음과 같다.
브라우저 요청
→ Tomcat
→ MemoServlet
→ HTML 응답
이제 Java 코드가 콘솔에서만 실행되는 것이 아니라, 브라우저 요청을 처리하는 서버 코드로 동작하기 시작했다.
다음 단계에서는 이 Servlet 안에서 메모 목록을 다루고, JSP를 이용해 화면을 분리하는 방향으로 확장할 수 있을 것 같다.
'Project > Memo Evolution' 카테고리의 다른 글
| #24 Servlet과 JSP에서 request는 어떻게 사용될까 (0) | 2026.06.22 |
|---|---|
| #23 Servlet에서 JSP로 forward하기 (0) | 2026.06.21 |
| #21 Java 콘솔 메모장: MemoService로 로직 분리하기 (0) | 2026.06.21 |
| #20 Java 콘솔 메모장 : String 배열에서 Memo 클래스로 변경하기 (0) | 2026.06.21 |
| #19 Java 콘솔 메모장: CRUD기능 구현하기 (0) | 2026.06.20 |