- 해당 게시물은 인프런 - "스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술" 강의를 참고하여 작성한 글 입니다.
- 유료강의이므로 자세한 내용은 없고, 간단한 설명 위주로 정리했습니다.
강의 링크 -> 김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술(유료강의)
프로젝트를 생성하기 위해 스프링 부트 스타터에서 다음과 같이 설정한다.
War를 사용하는 이유는 JSP를 사용하기 위함이다.
프로젝트를 열고, Lombok 라이브러리를 설치하고 어노테이션 처리 활성화를 해준다.
src/main/java/hello/servlet/ServletApplication
스프링이 자동으로 내 패키지를 포함한 모든 하위패키지에 있는 서블릿을 찾아 자동으로 서블릿 등록해주기 위해 @ServletComponentScan
어노테이션을 추가한다.
@ServletComponentScan // 서블릿 자동 등록
public class ServletApplication {
src/main/java/hello/servlet/basic/HelloServlet
서블릿으로 등록하기 위해 @WebServlet
어노테이션을 추가한다.
// name: 서블릿 이름, urlPatterns: URL 매핑
// "/hello" 이 호출되면 서블릿 컨테이너는 해당 메서드 실행
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
본격적으로 코드를 작성하기 위해 서비스 메서드를 추가한다.
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
쿼리 파라미터로 request 요청 메시지을 받기 위해, 쿼리 파라미터를 읽는 코드를 작성한다.
String username = request.getParameter("username");
http://localhost:8080/hello?username=kim에 들어가고 쿼리 파라미터로 받은 값을 출력해보면 정상적으로 쿼리 파라미터 값을 받은 것을 확인할 수 있다.
또한 response 응답 메시지를 보낼 수 있다.
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
response.getWriter().write("hello " + username); // HTTP 메시지 바디에 write
서블릿 컨테이너 동작 방식
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
객체는 임시 저장소, 세션 관리 등 추가적인 여러 부가기능도 제공한다.
src/main/java/hello/servlet/basic/request/RequestHeaderServlet
서블릿 어노테이션을 추가한다.
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
START LINE 정보
request.getMethod() // 메서드
request.getProtocol() // 프로트콜
request.getScheme() // 스키마
request.getRequestURL() // 요청 url
request.getRequestURI() // 요청 uri
request.getQueryString() // 쿼리 파라미터
request.isSecure() // 보안(https)
헤더 정보
HTTP 요청 메시지의 모든 헤더의 내용을 출력하기 위한 메서드를 만들어 내용을 확인한다.
request.getHeaderNames().asIterator()
.forEachRemaining(headerName -> System.out.println(headerName + ": " + request.getHeader(headerName)));
모든 정보말고 원하는 헤더의 내용을 출력하기 위한 메서드도 만들어 내용을 확인할 수 있다.
request.getServerName() // 이름
request.getServerPort() // 포트
request.getLocales().asIterator() // 언어
.forEachRemaining(locale -> System.out.println("locale = " + locale));
request.getLocale()
if (request.getCookies() != null) { // 쿠키
for (Cookie cookie : request.getCookies()) {
System.out.println(cookie.getName() + ": " + cookie.getValue());
}
}
request.getContentType() // content 타입
request.getContentLength() // content 길이
request.getCharacterEncoding() // 인코딩
기타 정보
추가적으로 HTTP 메시지의 정보는 아닌 기타 정보들도 확인할 수 있다.
request.getRemoteHost()
request.getRemoteAddr()
request.getRemotePort()
request.getLocalName()
request.getLocalAddr()
request.getLocalPort()
HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법에는 주로 3가지 방법이 있다.
GET - 쿼리 파라미터
- /url?username=hello&age=20
- URL의 쿼리 파라미터에 데이터를 포함해 전달
- ex) 검색, 필터, 페이징
POST - HTML Form
- 메시지 바디에 쿼리 파리미터 형식으로 전달
- ex) 회원 가입, 상품 주문, HTML Form
HTTP message body
- HTTP API에서 주로 사용, JSON, XML, TEXT
- 데이터 형식은 주로 JSON
- POST, PUT, PATCH
메시지 바디 없이, URL의 쿼리 파라미터를 사용해서 데이터를 전달한다.
쿼리 파라미터는 URL에 ? 를 시작으로 보내고 추가 파라미터는 & 로 구분한다.
src/main/java/hello/servlet/basic/request/RequestParamServlet
서블릿 어노테이션을 추가한다.
@WebServlet(name="requestParamServlet", urlPatterns = "/request-param")
전체 파라미터를 조회하는 메서드를 만들어, 파라미터의 key와 value를 출력하는 코드를 작성한다.
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> System.out.println(paramName + "=" + request.getParameter(paramName)));
단일 파라미터를 조회하는 코드를 작성한다.
String username = request.getParameter("username");
String age = request.getParameter("age");
http://localhost:8080/request-param?username=hello&age=20로 파라미터를 전송하면 정상적으로 전체 파라미터와 단일 파라미터가 조회된다.
이름이 같은 복수 파라미터 조회하는 방법은 아래 코드로 작성한다.
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("username = " + name);
}
http://localhost:8080/request-param?username=hello&age=20&username=hello2 해당 파라미터를 전송하면 복수 파라미터가 조회된다.
HTML의 Form을 사용해서 클라이언트에서 서버로 데이터를 전송한다.
HTML Form
Content-Type: application/x-www-form-urlencoded
- 메시지 바디에 쿼리 파리미터 형식으로 데이터를 전달 ex)
username=hello&age=20
src/main/webapp/basic/hello-form.html
에 html Form을 추가하여 /request-param 로 데이터를 보내도록 코드를 작성한다.
Form에 내용을 입력하고 전송 버튼을 누르면 앞서 만든 RequestParamServlet
의 메서드가 호출되어 아래와 같이 파라미터가 조회된다.
application/x-www-form-urlencoded
형식은 GET 쿼리 파라미터 형식과 같아, 위에서 만든 쿼리 파라미터 조회 메서드를 그대로 사용하면 된다.
따라서 request.getParameter()
는 GET 쿼리 파라미터, POST HTML Form 형식 둘 다 지원한다.
추가적으로 Postman을 사용하면 html을 만들 필요없이 쉽게 Test를 할 수 있다.
API 메시지 바디
- HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에서 주로 사용, 데이터 형식은 주로 JSON
- POST, PUT, PATCH
src/main/java/hello/servlet/basic/request/RequestBodyStringServlet
서블릿 어노테이션을 추가한다.
@WebServlet(name = "requestBodyStringServlet", urlPatterns = "/request-body-string")
그리고 HTTP 요청 메시지의 메시지 body를 가져오는 코드를 작성한다.
// body의 내용을 byte 코드로 가져옴
ServletInputStream inputStream = request.getInputStream();
// byte 코드를 string으로 바꿈
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
작성한 코드를 테스트 하기 위해 content-type: text/plain
형식의 단순 텍스트를 Postman으로 요청하면 정상적으로 동작한다.
HTTP API에서 주로 사용하는 JSON 형식으로 데이터를 전달하기 위해 우선 JSON 형식으로 파싱할 수 있게 HelloData라는 새로운 객체를 하나 생성한다.
src/main/java/hello/servlet/basic/HelloData
// lombok 라이브러리를 통해 getter, setter 코드 추가
@Getter @Setter
public class HelloData {
private String username;
private int age;
}
src/main/java/hello/servlet/basic/request/RequestBodyJsonServlet
서블릿 어노테이션과 앞서 나온 메시지 body를 가져오는 코드를 작성한다.
@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-json")
JSON 결과를 파싱해서 객체로 변환하기 위해 JSON 변환 라이브러리를 추가 한다.
private ObjectMapper objectMapper = new ObjectMapper();
그래서 JSON 변환 라이브러리로 메시지 body를 파싱할 객체를 읽고, 객체의 getter를 사용하여 값들을 출력한다.
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
Postman을 사용해 JSON 형식의 HTTP 요청 메시지를 보내고 출력 값을 보면 정상적으로 작동하는 것을 볼 수 있다.
HttpServletResponse 역할
- HTTP 응답 메시지 생성: HTTP 응답코드 지정, 헤더 생성, 바디 생성
- 편의 기능 제공: Content-Type, 쿠키, Redirect
src/main/java/hello/servlet/basic/response/ResponseHeaderServlet
서블릿 어노테이션을 작성한다.
@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
HTTP 응답 메시지에 넣을 값들을 작성한다.
//[status-line]
response.setStatus(HttpServletResponse.SC_OK); // http 응답코드 200
//[response-headers]
response.setHeader("Content-Type","text/plain;charset=utf-8");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("my-header","hello");
작성 후 위에서 작성한 응답 데이터들이 적상적으로 받은 것을 확인할 수 있다.
http://localhost:8080/response-header
HTTP 응답 메시지 생성에서 넣은 값들을 보다 편리하게 넣는 방법이 있다.
// Content 편의 메서드
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
// 쿠키 편의 메서드
Cookie cookie = new Cookie("myCookie", "good");
cookie.setMaxAge(600); //600초
response.addCookie(cookie);
// redirect 편의 메서드
response.sendRedirect("/basic/hello-form.html");
Content 편의 메서드, 쿠키 편의 메서드, redirect 편의 메서드의 내용이 제대로 들어간 것을 확인할 수 있다.
src/main/java/hello/servlet/basic/response/ResponseHtmlServlet
서블릿 어노테이션을 작성한다.
@WebServlet(name = "responseHtmlServlet", urlPatterns = "/response-html")
응답 메시지의 헤더 값을 설정해 준다.
response.setContentType("text/html");
response.setCharacterEncoding("utf-8")
message body로 HTML 응답을 보내준다.
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println(" <div>안녕?</div>");
writer.println("</body>");
writer.println("</html>");
http://localhost:8080/response-html에 들어가면 다음과 같이 응답 데이터가 정상적으로 보내지는 것을 확인할 수 있다.
src/main/java/hello/servlet/basic/response/ResponseJsonServlet
서블릿 어노테이션을 작성한다.
@WebServlet(name = "responseJsonServlet", urlPatterns = "/response-json")
헤더 값을 설정해 준다.
response.setHeader("content-type", "application/json");
response.setCharacterEncoding("utf-8");
username과 age 값을 넣어 HelloData 객체를 만든다.
HelloData helloData = new HelloData();
helloData.setUsername("kim");
helloData.setAge(20);
객체를 JSON 형식으로 변경하기 위해, JSON 변환 라이브러리인 ObjectMapper를 사용한다.
String result = objectMapper.writeValueAsString(helloData);
response.getWriter().write(result);
http://localhost:8080/response-json에 들어가면 아래와 같이 정상적으로 응답 데이터가 보내지는 것을 확인할 수 있다.
지금까지 김영한 - 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술(유료강의) 강의를 참고하여 서블릿 에 대해 공부하였다.