Post

Spring Servlet

Spring Servlet

Servlet은 Java 기반의 웹 애플리케이션에서 클라이언트의 요청을 처리하고 응답을 생성하는 Server-side components입니다. 다음은 chatgpt 웹사이트 request 요청입니다.

1
2
3
4
5
6
7
POST /v1/chat/completions HTTP/1.1
Host: https://chatgpt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: text/plain;charset=UTF-8
accept: */*
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)
content-length: 3362

HTTP 요청은 클라이언트가 서버에 데이터를 보내는 방식으로, 주요 속성은 다음과 같습니다.

  1. Request Line : POST /v1/chat/completions HTTP/1.1 → 요청 메서드(POST), URL 경로, HTTP 버전 포함.
  2. Headers:
    • Host: 요청 대상 서버 (chatgpt.com)
    • Authorization: 인증 정보 (Bearer 토큰)
    • Content-Type: 데이터 유형 (text/plain; charset=UTF-8)
    • accept: 응답 형식 ex) */*, application/json
    • User-Agent: 요청을 보내는 클라이언트 정보
    • content-length: 요청 본문의 길이

웹 애플리케이션에서 HTTP 요청을 직접 처리하려면 요청을 일일이 파싱하고 응답을 생성해야 합니다. Servlet은 이러한 작업을 자동화하여 개발자가 핵심 로직에 집중할 수 있도록 도와줍니다. Servlet은 HTTP 요청을 받아 적절한 비즈니스 로직을 수행한 후, HTML, JSON 등의 형태로 응답을 반환합니다. 웹 서버(Tomcat, Jetty 등) 내에서 실행되며, HttpServlet 클래스를 상속하여 구현됩니다.

HttpServlet

다음은 Servlet Container 동작 방식입니다.

  1. Client Request: 사용자가 웹 브라우저에서 URL을 입력하거나, API 호출을 보냅니다.
  2. Servlet Container
    1. HttpServletRequest 객체와 HttpServletResponse 객체를 생성합니다.
    2. HttpServletRequest와 HttpServletResponse 객체를 적절한 Servlet 객체로 전달합니다.
      1. ex) “/hello”로 request가 오면 해당하는 Servlet 객체에 전달합니다.
  3. service() 메서드 호출됩니다.
    1. HTTP 메서드 따라 적절한 doGet(), doPost() 메소드 실행됩니다.
  4. HttpServletResponse를 통해 Client에게 응답이 반환됩니다.

아래는 doPost()의 코드입니다. HttpServletReqeust, HttpServletResponse를 받습니다. doGet(), doPost(), 등을 오버라이딩해 핵심 비즈니스 로직을 작성하게 실행합니다.

1
2
3
4
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String msg = lStrings.getString("http.method_post_not_supported");
        this.sendMethodNotAllowed(req, resp, msg);
    }

HttpServletRequest

HTTP 요청 메시지를 개발자가 직접 파싱해서 사용해도 되지만 권장되지 않습니다. 서블릿은 개발자가 HTTP 요청 메시지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메시지를 파싱해줍니다. 아래는 Http Reqeust를 보내는 3가지 방법입니다.

  1. GET
    1. www.hello.com/hi?username=jo&age=20
    2. ? 이후 쿼리파라미터에 데이터를 포함해서 전달합니다.
  2. Post - HTML Form
    1. content-type: application/x-www-form-urlencoded
    2. HTTP Message Body에 쿼리 파리미터 형식으로 전달 username=jo&age=20
  3. HTTP Message Body
    1. ex) JSON, XML, TEXT

Client 입장에서는 두 방식에 차이가 있지만, Server 입장에서는 둘의 형식이 동일하므로, 1번과 2번은 request.getParameter()로 조회할 수 있습니다.

1
2
String username = request.getParameter("username");
String age = request.getParameter("age");

3번은 다음과 같습니다. Response 부분은 HttpServletResponse 부분에서 설명드리겠습니다.

1
2
3
4
5
6
7
8
9
10
@WebServlet("/json")
public class JsonRequestServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        BufferedReader reader = request.getReader();
        String jsonBody = reader.lines().collect(Collectors.joining());
        response.setContentType("application/json");
        response.getWriter().write("{\"received\": " + jsonBody + "}");
    }
}

HttpServletResponse

doPost()에서 HTTP 응답을 반환할 때, response.getOutputStream().write()를 사용합니다. HTML 응답의 경우, Content-Type을 text/html로 설정한 후, HTML 문자열을 UTF-8로 변환하여 OutputStream을 통해 반환합니다. 이렇게 하면 Client (웹 브라우저)가 응답을 HTML로 해석하고 렌더링할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
@WebServlet(name = "responseHtmlServlet", urlPatterns = "/response-html")
public class ResponseHtmlServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        response.setCharacterEncoding("utf-8");

        String htmlResponse = "<html><body><div>POST 요청 응답</div></body></html>";
        response.getOutputStream().write(htmlResponse.getBytes("utf-8"));
    }
}

JSON 응답의 경우, ObjectMapper를 이용해 Java 객체를 JSON 문자열로 변환한 후, response.getOutputStream().write()로 반환합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@WebServlet(name = "responseJsonServlet", urlPatterns = "/response-json")
public class ResponseJsonServlet extends HttpServlet {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");

        HelloData data = new HelloData();
        data.setUsername("jo");
        data.setAge(20);

        String jsonResponse = objectMapper.writeValueAsString(data);
        response.getOutputStream().write(jsonResponse.getBytes("utf-8"));
    }
}

DispatcherServlet

Spring MVC는 내부적으로 Servlet을 기반으로 동작하며, DispatcherServlet이 모든 HTTP 요청을 받아 컨트롤러로 전달하는 역할을 합니다. HttpServletRequestHttpServletResponse 객체를 활용하여, HandlerMapping을 통해 적절한 컨트롤러를 찾습니다. 해당 컨트롤러의 메서드를 실행하고, 이후 ViewResolver를 사용하여 적절한 뷰를 렌더링합니다. 또는 @ResponseBody가 설정된 경우 JSON 응답을 생성합니다.

비교 항목ServletSpring MVC
요청 처리 방식doGet(), doPost() 직접 구현@Controller@RequestMapping 사용
URL 매핑web.xml 또는 @WebServlet@RequestMapping 사용
응답 처리HttpServletResponse 직접 설정@ResponseBody로 설정

다음은 SpringMVC 사용 예시입니다.

1
2
3
4
5
6
7
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(@RequestParam String name) {
    return "Hello, " + name;
  }
}

Servlet은 Java 웹 애플리케이션에서 클라이언트 요청을 처리하고 응답을 반환하는 중요한 역할을 합니다. HttpServlet을 상속하여 직접 구현하면 요청을 파싱하고, 비즈니스 로직을 수행한 뒤, 적절한 응답을 반환할 수 있습니다. 이를 통해 GET, POST 요청을 처리하고, HTML 또는 JSON 데이터를 클라이언트에 제공할 수 있습니다.

나아가 Spring MVCDispatcherServlet을 통해 이러한 과정을 효율적으로 처리할 수 있도록 도와주며, URL 매핑, 요청 처리, 응답 반환을 간결하게 구성할 수 있는 프레임워크를 제공합니다.

This post is licensed under CC BY 4.0 by the author.