인프런 김영한 님의 강의를 참고했습니다.
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -
www.inflearn.com
스프링 부트를 설정해서 다운로드하여 오고, 추가 설정들을 해준다.
저번에 워낙 많이 해서 그냥 넘어가도록 하겠다.
이번에는 서블릿을 사용하기 때문에 스프링 메인에 @ServletComponentScan annotation을 달아준다.
그러고 같은 패키지 내에 이런 자바 코드를 작성해 보자.
package hello.servlet.basic;
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(name = "hiServlet", urlPatterns = "/hi")
public class HiServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.println("HiServlet");
writer.println("request = " + req);
writer.println("response = " + resp);
writer.println("name = " + req.getParameter("name"));
}
}

실행을 하고 url에 접속한 결과이다.
@WebServlet annotation은 서블릿 어노테이션으로 name에 들어가는 값은 서블릿의 이름이고, urlPatterns에 들어가는 값은 mapping 되는 url이다.
저번에 서블릿 공부 할 때 공부했을 것이다.
그리고 서블릿을 사용하기 위해서는 HttpServlet을 extends 받아야 한다.
메서드 내의 코드를 잠깐 설명해 보자면, 응답의 ContentType을 text/plain으로 설정하고 CharacterEncoding을 utf-8로 설정을 한 후 response에 getWriter로 request와 response 객체를 출력해 보는 것이다.
- HTTPServletRequest 객체
객체의 이름을 보면 알겠지만, HTTP의 Request를 Servlet이 다루기 편하게 만들어주는 객체이다.
이곳을 보면 HTTP 요청 메시지에 대한 정보를 얻어 올 수 있다.
당연히 직접 HTTP 요청 메시지를 사용할 수 있겠지만, 난이도가 매우 어렵다.
HTTPServletRequest 객체를 이용해서 안의 내용들을 출력해 보자.
우선 시작 줄부터이다.
주석으로 설명을 달지 않아도 시작줄의 어떤 내용을 출력하려 하는 것인지 알 수 있을 것이다.
package hello.servlet.basic.request;
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(name = "requestHeaderServlet", urlPatterns = "/requestHeader")
public class RequestHeader extends HttpServlet {
private void printStart(HttpServletResponse httpServletResponse, String string) throws IOException {
httpServletResponse.getWriter().printf("--- %s-Line start ---\n", string);
}
private void printEnd(HttpServletResponse httpServletResponse, String string) throws IOException {
httpServletResponse.getWriter().printf("--- %s-Line end ---\n", string);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StartLine(req, resp);
}
private void StartLine(HttpServletRequest request,HttpServletResponse response)throws IOException{
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
printStart(response, "Request");
writer.println("Method = " + request.getMethod());
writer.println("Protocol = " + request.getProtocol());
writer.println("Scheme = " + request.getScheme());
writer.println("RequestURL = " + request.getRequestURL());
writer.println("RequestURI = " + request.getRequestURI());
writer.println("QueryString = " + request.getQueryString());
writer.println("isSecure = " + request.isSecure());
printEnd(response, "Request");
writer.println();
}
}
실행을 한 후에 접속해 보면

이렇게 요청 메서드에 관한 정보들이 나오게 된다.
이번엔 헤더이다.
package hello.servlet.basic.request;
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(name = "requestHeaderServlet", urlPatterns = "/requestHeader")
public class RequestHeader extends HttpServlet {
private void printStart(HttpServletResponse httpServletResponse, String string) throws IOException {
httpServletResponse.getWriter().printf("--- %s-Line start ---\n", string);
}
private void printEnd(HttpServletResponse httpServletResponse, String string) throws IOException {
httpServletResponse.getWriter().printf("--- %s-Line end ---\n", string);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StartLine(req, resp);
Headers(req, resp);
}
private void Headers(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
printStart(response, "Headers");
request.getHeaderNames().asIterator()
.forEachRemaining(headerName -> writer.println(headerName + " = " + request.getHeader(headerName)));
printEnd(response, "Headers");
writer.println();
}
}
이번엔 Iterator로 빠르게 출력했다.

이렇게 이어서 잘 출력이 되는 것을 볼 수 있다.
나머지 부분들도 request를 보면 찾을 수 있지만, 이 정도만 하고 넘어가 보겠다.
- HTTP request - GET
데이터를 서버로 전송해 보자.
서버로 데이터를 전송할 때는 Postman을 사용하면 된다.
package hello.servlet.basic.request;
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(name = "requestParam", urlPatterns = "/requestParam")
public class RequestParam extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("[파리미터 조회] - start");
req.getParameterNames().asIterator()
.forEachRemaining(paramName -> System.out.println(paramName + " = " + req.getParameter(paramName)));
System.out.println("[파리미터 조회] - end");
System.out.println();
System.out.println("[개별 파라미터 조회]");
System.out.println("name : " + req.getParameter("name"));
System.out.println("age: " + req.getParameter("age"));
System.out.println();
}
}
이렇게 Iterator를 이용하여 전체를 조회할 수 있지만, 보통 getParameter()를 이용해서 개별 조회를 한다.
Postman으로 데이터를 전송하면

이렇게 출력되게 된다.
- HTTP request - POST
이번엔 POST 방식이다.
저번 GET 방식은 URL로 데이터를 보낼 수도 있긴 했지만, 이번 POST 방식은 Postman을 이용해야 할 것이다.
근데 코드는 수정할 필요가 없다.
POST 방식도 GET과 쿼리 파라미터 형식이 같기 때문에 조회 메서드는 동일하게 사용할 수 있다.

이렇게 동일한 결과가 나오는 것을 볼 수 있다.
- HTTP request - 텍스트
package hello.servlet.basic.request;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@WebServlet(name = "requestBodyString", urlPatterns = "/requestBodyString")
public class RequestBodyString extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletInputStream inputStream = req.getInputStream();
String message = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("message = " + message);
}
}
InputStream은 바이트 코드를 반환하기 때문에 UTF_8로 지정을 해주어 바꿔줘야 한다.
Postman으로 POST에 raw로 그냥 메시지를 보내면

이렇게 잘 출력이 되는 것을 볼 수 있다.
- HTTP request - JSON
요즘 많이 사용하는 JSON 형식이다.
우선 Postman에서 JSON으로 데이터를 보내는 방법부터 알아보겠다.
Body에서 raw, JSON을 선택하고 형식에 맞게 작성을 하면 된다.
그러고 JSON 형식으로 데이터를 가져올 수 있게 그에 맞는 객체를 생성한다.
package hello.servlet.basic;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class JsonData {
private String name;
private int age;
}
깔끔하게 Lombok을 사용한다.
package hello.servlet.basic.request;
import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.JsonData;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@WebServlet(name = "requestBodyJson", urlPatterns = "/requestBodyJson")
public class RequestBodyJson extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletInputStream inputStream = req.getInputStream();
String message = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
JsonData jsonData = objectMapper.readValue(message, JsonData.class);
System.out.println(jsonData);
}
}
ObjectMapper를 이용해서 가져온 데이터를 해당 객체로 변환해 준다.

이렇게 잘 출력되는 것을 볼 수 있다.
- HTTP response
HttpServletResponse를 사용하여 응답 메시지를 작성할 수 있다.
package hello.servlet.basic.response;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "responseHeader", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//상태 라인
resp.setStatus(HttpServletResponse.SC_OK);
//response header
resp.setContentType("text/plain");
resp.setCharacterEncoding("utf-8");
resp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
resp.setHeader("Pragma", "no-cache");
resp.setHeader("my-header", "hi");
}
private void redirect(HttpServletResponse response) throws IOException{
response.sendRedirect("/basic/hi-form.html");
}
private void cookie(HttpServletResponse response){
Cookie cookie = new Cookie("myCookie", "good!");
cookie.setMaxAge(60);
response.addCookie(cookie);
}
}
이렇게 response 객체를 이용해서 편하게 응답 메시지를 만들 수 있다.
이번에는 중요한 응답 메시지로 JSON을 작성하는 방법이다.
여기서도 ObjectMapper를 사용한다.
package hello.servlet.basic.response;
import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.JsonData;
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;
@WebServlet(name = "responseJson", urlPatterns = "/responseJson")
public class ResponseJson extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json");
resp.setCharacterEncoding("utf-8");
JsonData jsonData = new JsonData();
jsonData.setName("hi");
jsonData.setAge(20);
String result = objectMapper.writeValueAsString(jsonData);
resp.getWriter().write(result);
}
}
이렇게 객체를 만들고 ObjectMapper를 이용하여 문자열로 바꿔준 후 write로 작성을 해주면 된다.

그러면 이렇게 잘 전달이 되는 것을 볼 수 있다.