Hello Servlet

jihan kong·2022년 7월 7일
0

Spring MVC

목록 보기
6/12
post-thumbnail

본 시리즈는 인프런 학습 사이트의 김영한 강사님의 java spring mvc - 백엔드 웹 개발 핵심 기술 편을 학습한 내용을 바탕으로 정리하였습니다.

실제로 스프링 부트 환경에서 서블릿을 등록하고 사용해보자. 스프링 부트는 톰캣 서버를 내장하고 있기 때문에 톰캣 서버 설치 없이 편리하게 서블릿 코드를 실행할 수 있다.

1. Hello Servlet

1-1. 스프링 부트 서블릿 환경 구성

@ServletComponentScan

스프링 부트는 서블릿을 직접 등록해서 사용할 수 있도록 어노테이션을 지원한다.

hello.servlet.ServletApplication

package hello.servlet;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan //서블릿 자동 등록
@SpringBootApplication
public class ServletApplication {
	public static void main(String[] args) {
		SpringApplication.run(ServletApplication.class, args);
	}
}

실제 동작하는 서블릿 코드는 다음과 같다.

hello.servlet.basic.HelloServlet

package hello.servlet.basic;

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(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {

		@Override
		protected void service(HttpServletRequest request, HttpServletResponse
response)
				throws ServletException, IOException {
		
				System.out.println("HelloServlet.service");
				System.out.println("request = " + request);
				System.out.println("response = " + response);
				String username = request.getParameter("username");
				System.out.println("username = " + username);

				response.setContentType("text/plain");
				response.setCharacterEncoding("utf-8");
				response.getWriter().write("hello " + username);
		}
}
  • @WebServlet : 서블릿 애노테이션 (서블릿을 사용하겠다.)
    • name : 서블릿 이름 (서블릿의 이름을 이것으로 하겠다.)
    • urlPatterns : URL 매핑 (사용자가 쿼리스트링을 이것으로 했을 때)

HTTP 요청을 통해서 매핑된 URL이 호출되면 서블릿 컨테이너는 당연하겠지만 요청과 응답을 처리하기 위해 다음 메서드를 실행한다.

protected void service(HttpServletRequest request, HttpServletResponse response)


콘솔 실행 결과

HelloServlet.service
request = org.apache.catalina.connector.RequestFacade@5e4e72
response = org.apache.catalina.connector.ResponseFacade@37d112b6
username = world

1-2. 서블릿 컨테이너 동작 방식

  • 내장 톰캣 서버 생성
    먼저, 스프링 부트는 내장된 톰캣 서버를 통해 서블릿 컨테이너 안에 우리가 작성한 helloServlet 이라는 이름의 서블릿을 생성한다.

  • HTTP 요청, 응답 메시지 생성
    HTTP 요청 메시지와 응답 메시지를 웹 애플리케이션을 통해 생성한다. HTTP 요청에서는 GET 방식으로 할것인가 혹은 POST 방식으로 할 것인가 등의 메타 정보가 담긴 요청 메서드, HTTP 응답에서는 Content-TypeContent-Length 등에 관한 정보를 담고 있다.

  • 웹 애플리케이션 서버를 통한 요청, 응답
    서블릿 구조에서도 살펴봤듯 웹 애플리케이션 서버에서의 요청-응답 구조는 위와 같다. 웹 브라우저의 HTTP 요청 메시지를 기반으로 요청(request) 메세지가 생성되고 톰캣 서버는 서블릿 컨테이너를 통해 이 요청에 대한 응답(response)을 실행한다. 처리가 끝나면 Servlet을 종료 시키고, 새롭게 생성된 response 객체 정보를 HTTP 응답으로 생성한다. 이는 WAS를 통해 사용자에게 다시 렌더링되어 전달된다.

2. HttpServletRequest - 개요

2-1. HttpServletRequest의 역할

서블릿은 개발자가 HTTP 요청 메세지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메세지를 파싱해준다. 그리고 그 결과를 HttpServletRequest 객체에 담아서 제공한다.

  • HTTP 요청 메시지
    HTTP 요청 메시지에는 다음과 같은 정보가 담긴다.

    	POST /save HTTP/1.1
    	Host: localhost:8080
    	Content-Type: application/x-www-form-urlencoded
    	username=kim&age=20
  • START LINE

    • HTTP 메소드
    • URL
    • 쿼리 스트링
    • 스키마, 프로토콜
  • 헤더

    • 헤더 조회
  • 바디

    • form 파라미터 형식 조회
    • message body 데이터 직접 조회

HttpServletRequest 객체는 추가로 다음과 같이 여러가지 부가 기능도 함께 제공한다.

<임시 저장소 기능>

해당 HTTP 요청이 시작부터 끝날 때 까지 유지되는 임시 저장소 기능

  • 저장 : request.setAttribute(name, value)
  • 조회 : request.getAttribute(name)

세션 관리 기능

  • request.getSession(create: true)

짚고 넘어가야 할 것❗
HttpServletRequest, HttpServletResponse 를 사용할 때 가장 중요한 점은 이 객체들이 HTTP 요청 메시지, HTTP 응답 메시지를 편리하게 사용하도록 도와주는 객체라는 점이다. 따라서 이 기능에 대해서 깊이 있는 이해를 하려면 HTTP 스펙이 제공하는 요청, 응답 메시지 자체를 이해해야 한다. HTTP가 어떤 메소드를 통해 통신하고 어떻게 동작하는지 등을 아는 것은 웹 서버를 구축하는데 있어서 필수이다. (이 포스팅에서는 생략)


2-2. HTTP 요청 데이터 - GET 쿼리 파라미터

다음 데이터를 클라이언트에서 서버로 전송해보자.

전달 데이터

  • username = hello
  • age = 20

메시지 바디 없이 URL의 쿼리 파라미터를 사용해서 데이터를 전달하자. 이는 검색, 필터, 페이징등에서 많이 사용하는 방식이다.

쿼리 파라미터는 URL에 다음과 같이 ? 를 시작으로 보낼 수 있다. 추가 파라미터는 & 로 구분하면 된다.

http://localhost:8080/request-param?username=hello&age=20


서버에서는 HttpServletRequest 가 제공하는 다음 메서드를 통해 쿼리 파라미터를 편리하게 조회할 수 있다.

  • 쿼리 파라미터 조회 메서드
String username = request.getParameter("username"); 
//단일 파라미터 조회

Enumeration<String> parameterNames = request.getParameterNames(); 
//파라미터 이름들 모두 조회

Map<String, String[]> parameterMap = request.getParameterMap(); 
//파라미터를 Map으로 조회

String[] usernames = request.getParameterValues("username"); 
//복수 파라미터 조회

2-3. HTTP 요청 데이터 - POST HTML Form

이번에는 HTML의 Form을 사용해서 클라이언트에서 서버로 데이터를 전송해보자. 주로 회원 가입, 상품 주문 등에서 사용하는 방식이다.

특징

  • content-type: application/x-www-form-urlencoded
    메시지 바디에 쿼리 파리미터 형식으로 데이터를 전달한다.
    username=hello&age=20
일단, POST 방식을 사용하기 위해선 html form을 생성해야한다.
  • src/main/webapp/basic/hello-form.html 생성
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
<form action="/request-param" method="post">
		username: <input type="text" name="username" />
		age: <input type="text" name="age" />
		<button type="submit">전송</button>
</form>
</body>
</html>

POST의 HTML Form을 전송하면 웹 브라우저는 다음 형식으로 HTTP 메시지를 만든다. (웹 브라우저 개발자 모드 확인)

  • 요청 URL : http://localhost:8080/request-param
  • content-type : application/x-www-form-urlencoded
  • message body : username=hello&age=20

application/x-www-form-urlencoded 형식은 앞서 GET에서 살펴본 쿼리 파라미터 형식과 같다. 따라서 쿼리 파라미터 조회 메서드를 그대로 사용하면 된다. 클라이언트 (웹 브라우저) 입장에서는 두 방식에 차이가 있지만, 서버 입장에서는 둘의 형식이 동일하므로 request.getParameter() 로 편리하게 구분없이 조회할 수 있다.

정리하면 request.getParameter()GET URL 쿼리 파라미터 형식도 지원하고, POST HTML Form 형식도 지원한다.

2-4. HTTP 요청 데이터 - API 메시지 바디(JSON)

HTTP 요청 데이터중에는 HTTP API에서 주로 사용하는 JSON 형식으로 데이터를 전달할 수 있다.


JSON 형식 전송

  • POST
    • http://localhost:8080/request-body-json
  • content-type : application/json
    (JSON 형식으로 전송하기 위해선 content-type을 application/json 으로 설정해야한다.)
  • message body : {"username": "hello", "age": 20}
    (메세지 바디에 JSON 형식으로 메세지를 포함하여 전달한다.)
  • 결과 : messageBody = {"username": "hello", "age": 20}

지금까지 HttpRequest 메시지를 살펴보았다. 이제 HttpResponse 메시지를 알아보자.


3. HttpServletResponse - 기본 사용법

HttpServletResponse 는 기본적으로 HTTP 응답 메시지를 생성하는 것이 주 역할이다. 응답메시지는 다음과 같은 내용으로 생성된다.

  • HTTP 응답코드 지정
  • 헤더 생성
  • 바디 생성

또한 Request 메시지처럼 편의 기능도 제공한다.

  • Content-Type, 쿠키, Redirect

3-1. HTTP 응답 데이터 - 단순 텍스트, HTML

HTTP 응답 메시지에는 주로 다음 내용을 담아서 전달할 수 있다.

  • 단순 텍스트 응답 (HTTP 요청 메시지도 단순 텍스트를 message body에 직접 담아서 요청이 가능하다.)
  • HTML 응답
  • HTTP API - MessageBody JSON 응답

HTTP 응답으로 HTML을 반환할 때는 content-typetext/html 로 지정해야 한다.


3-2. HTTP 응답 데이터 - API JSON

Request와 마찬가지로 HTTP Response 로 JSON을 반환할 때는 content-typeapplication/json 로 지정해야 한다.
Jackson 라이브러리가 제공하는 objectMapper.writeValueAsString() 를 사용하면 객체를 JSON 문자로 변경할 수 있다.

profile
학습하며 도전하는 것을 즐기는 개발자

0개의 댓글