풀스택 백엔드 2026.06.08

syyu21b·2026년 6월 8일

풀스택 - 백엔드

목록 보기
24/49
post-thumbnail

[SECTION 01. Java 웹의 출발점 — 서블릿으로 HTTP 직접 처리하기]

IntelliJ에서 서블릿 프로젝트 만들기

Step 1. 프로젝트 생성

  1. IntelliJ 실행 → New Project 클릭
  2. 왼쪽에서 Java 선택
  3. 설정값 입력
Name        : servlet-basic
Location    : 원하는 경로
Language    : Java
Build System: Maven          ← 꼭 Maven 선택
JDK         : 17 이상 선택
  1. Create 클릭

Step 2. pom.xml 설정

프로젝트 루트의 pom.xml 파일을 아래처럼 작성합니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>servlet-basic</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- war: 서블릿은 Tomcat 위에서 실행되므로 war로 패키징 -->
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

		<!-- 의존성들 -->
    <dependencies>
        <!-- 서블릿 API: 코드 작성 시 필요, 실행은 Tomcat이 제공 -->
        <!-- 하나의 의존성 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>8080</port>
                    <path>/</path>
                    <uriEncoding>UTF-8</uriEncoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

<scope>provided</scope> 의 의미: 코드를 작성할 때만 필요하고, 실제 실행은 Tomcat이 이 라이브러리를 제공해 줍니다. 그래서 우리가 만드는 war 파일 안에는 포함되지 않습니다.


Step 3. 디렉토리 구조 만들기

Maven 웹 프로젝트의 표준 구조를 직접 만들어야 합니다.

servlet-basic/
├── src/
│   └── main/
│       ├── java/           ← Java 코드
│       │   └── com.example/ ← 패키지
│       └── webapp/         ← 웹 관련 파일 디렉토리 (직접 생성!)
│           └── WEB-INF/
│               └── web.xml ← 서블릿 등록 설정 파일 (직접 생성!)
└── pom.xml

webapp 폴더 생성 방법:

  1. src/main 우클릭 → New → Directory
  2. 이름: webapp
  3. webapp 안에 WEB-INF 폴더 생성

web.xml 파일 생성:

WEB-INF 폴더 안에 web.xml 파일을 만들고 아래 내용 작성:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1"
         metadata-complete="false">
</web-app>

Step 4. Tomcat 설치 및 연동

IntelliJ 무료 버전은 Tomcat 플러그인을 직접 지원하지 않습니다. 대신 Maven 플러그인으로 실행합니다.

pom.xml</dependencies> 아래에 추가:

  <build>
      <plugins>
          <plugin>
              <groupId>org.apache.tomcat.maven</groupId>
              <artifactId>tomcat7-maven-plugin</artifactId>
              <version>2.2</version>
              <configuration>
                  <port>8080</port>
                  <path>/</path>
                  <uriEncoding>UTF-8</uriEncoding>
              </configuration>
          </plugin>
      </plugins>
  </build>

실행 방법:

IntelliJ 우측 Maven 탭 → Pluginstomcat7tomcat7:run 더블클릭


첫 번째 서블릿 만들기

  • 서블릿(Servlet) = Server + Applet의 합성어. 서버 측에서 실행되는 작은 Java 프로그램으로, HTTP 요청을 받아 처리하고 응답을 돌려주는 역할을 함

서블릿의 핵심은 HttpServlet 클래스를 상속받는 것입니다.

내가 만든 서블릿
    └── extends HttpServlet
            └── extends GenericServlet
                    └── implements Servlet

HelloServlet 작성

src/main/java/com/example/ 아래에 HelloServlet.java 파일 생성:

package com.example;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

// @WebServlet: 이 서블릿이 어떤 URL을 담당할지 지정
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    // GET 요청이 오면 이 메서드가 실행됨
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 1. 쿼리 파라미터에서 name 값 꺼내기
        String name = request.getParameter("name");
        if (name == null) {
            name = "이름 없음";
        }

        // 2. 응답 설정
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");

        // 3. 응답 본문 작성
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<body>");
        out.println("<h1>안녕하세요, " + name + "님!</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

코드 분석

코드설명
@WebServlet("/hello")/hello URL로 요청이 오면 이 서블릿이 처리
extends HttpServlet서블릿의 핵심 기능을 물려받음
doGet(...)GET 요청 전용 처리 메서드
HttpServletRequest클라이언트가 보낸 요청 정보 전체
HttpServletResponse클라이언트에게 돌려줄 응답
request.getParameter("name")URL의 ?name=값 부분을 꺼냄
response.getWriter()응답 본문을 쓸 수 있는 출력 스트림

실행 및 테스트

Tomcat 실행 후 브라우저에서 접속:

http://localhost:8080/hello?name=김철수

예상 결과:

안녕하세요, 김철수님!

POST 요청 처리하기

HTML 폼 만들기

src/main/webapp/ 아래에 form.html 파일 생성:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>로그인</title>
</head>
<body>
    <h2>로그인</h2>
    <form action="/login" method="post">
        <label>아이디: <input type="text" name="username"></label><br><br>
        <label>비밀번호: <input type="password" name="password"></label><br><br>
        <button type="submit">로그인</button>
    </form>
</body>
</html>

LoginServlet 작성

package com.example;

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;
import java.io.PrintWriter;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest rq, HttpServletResponse rs) throws ServletException, IOException {
        rs.sendRedirect("/form.html");
    }

    @Override
    protected void doPost(HttpServletRequest rq, HttpServletResponse rs) throws ServletException, IOException {
        rq.setCharacterEncoding("utf-8");
        rs.setCharacterEncoding("utf-8");
        rs.setContentType("text/html");

        String username = rq.getParameter("username");
        String password = rq.getParameter("password");

        PrintWriter pw = rs.getWriter();

        if (username.equals("admin") && password.equals("1234")) {
            pw.println("<body>");
            pw.println("<h1>로그인이 완료되었습니다.</h1>");
            pw.println("</body>");
        }else {
            pw.println("<body>");
            pw.println("<h1>로그인이 실패하였습니다.</h1>");
            pw.println("</body>");
        }


    }
}

GET vs POST 비교

항목GETPOST
데이터 위치URL (쿼리스트링)요청 바디
보안URL에 노출됨URL에 노출 안 됨
용도데이터 조회데이터 전송/변경
예시검색, 페이지 이동로그인, 회원가입
즐겨찾기가능불가능

web.xml로 서블릿 등록하는 방식 (구식 방법)

지금까지 @WebServlet 어노테이션으로 서블릿을 등록했습니다.
스프링 이전에는 이 모든 것을 web.xml직접 텍스트로 등록하기도 했습니다.

<web-app>

    <!-- 서블릿 정의 -->
    <servlet>
        <servlet-name>helloServlet</servlet-name>
        <servlet-class>com.example.HelloServlet</servlet-class>
    </servlet>

    <!-- URL 매핑 -->
    <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <!-- 서블릿이 10개면 이 블록을 10번 반복해야 함... -->

</web-app>

포인트: 서블릿이 늘어날수록 web.xml도 함께 늘어납니다. URL 하나 추가할 때마다 최소 10줄의 XML을 작성해야 했습니다. 하지만 스프링을 사용하게 되면 @GetMapping 혹은 @PostMapping으로 간단하게 해결 가능합니다.


서블릿 생명주기 — Tomcat(웹 서버)이 서블릿을 어떻게 관리하는가?

서블릿은 우리가 new로 직접 생성하지 않습니다. Tomcat(서블릿 컨테이너) 이 대신 생성하고 관리합니다.

[첫 번째 요청 도착]
        ↓
Tomcat: "이 URL 담당 서블릿 있나?" → HelloServlet 발견
        ↓
① init()    — 서블릿 객체 생성 (딱 1번만)
        ↓
② service() — 요청 처리 (GET이면 doGet, POST면 doPost 호출)
        ↓
   [응답 반환]
        ↓
[두 번째 요청 도착]
        ↓
② service() — 객체 재사용! init() 다시 호출 안 함
        ↓
[서버 종료]
        ↓
③ destroy() — 서블릿 객체 소멸 (딱 1번만)

생명주기 메서드 직접 확인

@WebServlet("/lifecycle")
public class LifeCycleServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("init() 호출 — 서블릿 생성됨 (최초 1회)");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("doGet() 호출 — 요청 처리 중");
        response.getWriter().println("요청 처리 완료!");
    }

    @Override
    public void destroy() {
        System.out.println("destroy() 호출 — 서블릿 소멸됨 (서버 종료 시)");
    }
}

브라우저로 /lifecycle에 여러 번 접속하며 콘솔 출력을 확인해보세요.

중요: 서블릿 객체는 딱 1개만 생성됩니다 (싱글톤). 요청이 1000개 동시에 오면 서블릿 객체 1개가 1000개의 스레드를 처리합니다. 그래서 서블릿 안에 멤버 변수로 상태를 저장하면 절대 안 됩니다.


섹션 정리

개념핵심 내용
HTTP요청(Request) / 응답(Response) 구조를 가진 통신 규약
서블릿Java에서 HTTP 요청을 처리하는 프로그램, HttpServlet을 상속
doGet / doPostGET/POST 요청을 처리하는 메서드
web.xml서블릿을 URL에 매핑하는 XML 설정 파일 (구식 방법)
@WebServletweb.xml 없이 어노테이션으로 URL 매핑 (개선된 방법)
서블릿 생명주기(서버 실행x, 해당 서블릿에 처음 요청이 들어올 때)init → 비즈니스 로직(doGet/doPost) → (서버 종료 )destroy
싱글톤서블릿 객체는 1개만 생성, 멤버 변수에 상태 저장 금지

0개의 댓글