본문 바로가기

Advance I/Spring MVC

22.08.01

서블릿

프로젝트 생성

서블릿 자체는 스프링, 스프링 부트가 필요하지 않다.

그러나 스프링 부트가 환경설정이 편리하고 WAS를 내장하고 있기 때문에 사용한다.

 

JSP 사용을 위해서는 Packaging에서 War 선택

project dependencies

Hello 서블릿

서블릿은 톰캣 같은 웹 애플리케이션 서버를 직접 설치하고, 그 위에 서블릿 코드를 클래스 파일로 빌드해서 올린 다음, 톰캣 서버를 실행하면 된다. 하지만 이 과정은 매우 번거롭다.

스프링 부트는 톰캣 서버를 내장하고 있으므로, 톰캣 서버 설치 없이 편리하게 서블릿 코드를 실행할 수 있다.

 

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

@ServletComponentScan

스프링 부트는 서블릿을 직접 등록해서 사용할 수 있도록 @ServletComponentScan 을 지원한다. 

 

in SpringApplication.class

@ServletComponentScan //서블릿 자동 등록

@SpringBootApplication

 

서블릿 등록하기

1. HttpServlet.class를 상속

2. 클래스 레벨로 @WebServlet(name = "helloServlet", urlPatterns = "/hello") //name: 서블릿 이름, urlPatterns: URL 매핑

3. protected void service(HttpServletRequest request, HttpServletResponse response) 메서드 구현 (ctrl+O)

  -해당 서블릿 호출 시 실행되는 메서드

 

쿼리 파라미터 받아오기

> localhost:8080/hello?username=kim

in 서블릿, request.getParameter("username") //kim

 

Response 객체 초기화

response.setContentType("text/plain"); //HTTP response message header

response.setCharacterEncoding("utf-8");

response.getWriter().write("hello " + username); //HTTP response message body

 

*F12: 개발자 도구. HTTP 정보 확인

 

HTTP 요청 메시지 로그로 확인하기 (개발 단계)

in application.properties

logging.level.org.apache.coyote.http11=debug

서블릿 컨테이너 동작 방식

스프링 부트에 내장된 톰캣 서버(WAS)는 서블릿 컨테이너 기능을 포함

HTTP 요청이 오면 WAS가 HTTP 요청 메세지를 기반으로 HttpServletRequest, HttpServletResponse 구현체를 생성하고 url로 매핑된 서블릿에 주입

요청에 따른 로직을 실행하고 response 객체 정보로 HTTP 응답을 생헝하여 웹브라우저에 반환

 

참고: HTTP 응답에서 Content-Length는 웹 애플리케이션 서버가 자동으로 생성해준다.

HttpServletRequest

HTTP 요청 메시지를 개발자가 직접 파싱 가능 -> 매우 불편

서블릿은 HTTP 요청 메시지를 파싱하여 결과를 HttpServletRequest 객체에 담아서 제공

HTTP 요청 메세지

POST /save HTTP/1.1    /* start line */
Host: localhost:8080   /* header */
Content-Type: application/x-www-form-urlencoded

username=kim&age=20    /* body */
...
  • START LINE: HTTP 메소드, URL, 쿼리 스트링, 스키마, 프로토콜
  • 헤더: 헤더 조회
  • 바디: form 파라미터 형식 조회, message body 데이터 직접 조회

임시 저장소 기능

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

-저장: request.setAttribute(name, value)

-조회: request.getAttribute(name)

 

세션 관리 기능 (ex.login)

request.getSession(create: true)

 

etc... 바디에 json이 와도 통으로 읽어와서 라이브러리를 통해 파싱

HTTP 요청 데이터

HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법

주로 다음 3가지 방법을 사용한다.

 

GET - 쿼리 파라미터

  • /url?username=hello&age=20
  • 메세지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
  • 예) 검색, 필터, 페이징등에서 많이 사용하는 방식

 

POST - HTML Form

  • content-type: application/x-www-form-urlencoded
  • 메세지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20
  • 예) 회원 가입, 상품 주문, HTML Form 사용

 

HTTP message body에 데이터를 직접 담아서 요청

  • HTTP API에서 주로 사용, JSON, XML, TEXT
  • 데이터 형식은 주로 JSON 사용
  • POST, PUT, PATCH

GET 쿼리 파라미터

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

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

 

content-type: null

 

쿼리 파라미터 조회 메서드

String username = request.getParameter("username"); //단일 파라미터 조회
Enumeration<String> parameterNames = request.getParameterNames(); //파라미터 이름들 모두 조회
Map<String, String[]> parameterMap = request.getParameterMap(); //파라미터를 Map으로 조회
String[] usernames = request.getParameterValues("username"); //복수 파라미터 조회

parameterName = key 를 통해 parameter = value 를 출력하는 코드

request.getParameterNames().asIterator()
      .forEachRemaining(paramName -> System.out.println(paramName +
      "=" + request.getParameter(paramName)));

 

복수 파라미터에서 단일 파라미터 조회

username=hello&username=kim 과 같이 파라미터 이름은 하나인데, 값이 중복이면 어떻게 될까?

request.getParameter() 는 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 한다.

지금처럼 중복일 때는 request.getParameterValues() 를 사용해야 한다.

참고로 이렇게 중복일 때 request.getParameter() 를 사용하면 request.getParameterValues() 의 첫 번째 값을 반환한다.

POST HTML Form

메세지 바디에 데이터가 들어가기 때문에 content-type이 있다. application/x-www-form-urlencoded

메세지 바디에 쿼리 파라미터 형식으로 데이터를 전달한다.

(웹 브라우저 개발자 모드에서 확인)

 

참고: content-type은 HTTP 메세지 바디의 데이터 형식을 지정한다.

 

application/x-www-form-urlencoded 형식은 앞서 GET에서 살펴본 쿼리 파라미터 형식과 같다.

클라이언트(웹 브라우저) 입장에서는 두 방식에 차이가 있지만, 서버 입장에서는 둘의 형식이 동일하므로, request.getParameter() 로 구분없이 조회할 수 있다.

 

html 없이 테스트 (postman)

 

HTTP 요청 데이터 - API 메세지 바디

서버 간 통신, 앱에서 요청, 웹 클라이언트(react, vue.js )가 자바 스크립트로 요청할 때 주로 사용

POST, PUT, PATCH

 

단순 텍스트 전송

HTTP 메세지 바디의 데이터를 InputStream을 사용해서 직접 읽을 수 있다.

inputStream은 byte 코드를 반환한다. byte 코드를 우리가 읽을 수 있는 문자(String)로 보려면 문자표(Charset)를 지정해주어야 한다.

>StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

 

POST http://localhost:8080/request-body-string

content-type: text/plain

message body: hello

 

JSON 전송

HTTP API에서 주로 사용하는 JSON 형식

 

POST http://localhost:8080/request-body-json

content-type: application/json

message body: {"username": "hello", "age": 20}

 

전송받은 JSON은 보통 객체로 파싱하여 사용한다.

 

1. InputStream으로 HTTP 메세지 바디의 데이터를 읽는다.

2. Jackson, Gson 같은 JSON 변환 라이브러리를 통해 JSON을 자바 객체로 변환한다.

  -스프링 부트로 Spring MVC를 선택하면 기본으로 Jackson 라이브러리( ObjectMapper )를 함께 제공

 

참고: HTML form 데이터도 메시지 바디를 통해 전송되므로 직접 읽을 수 있다. 하지만 편리한 파리미터 조회 기능( request.getParameter(...) )을 이미 제공하기 때문에 파라미터 조회 기능을 사용하는 것을 권장한다.

 

'Advance I > Spring MVC' 카테고리의 다른 글

22.08.09  (0) 2022.08.09
22.08.06  (0) 2022.08.06
22.08.04  (0) 2022.08.04
22.08.03  (0) 2022.08.03
22.07.26 :: 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술  (0) 2022.07.26