[스프링 MVC 1편]HTTP 요청 데이터

이민우·2023년 7월 23일
1

Spring Boot

목록 보기
8/20

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

HTTP 요청 메세지 종류

주로 3가지 방법을 사용합니다.

  • Get 요청 파라미터
    • /url?username=hello&age=20 (url에 파라미터 넣을땐 ? 삽입)
    • 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
    • 예) 검색, 필터, 페이징등에서 많이 사용하는 방식
  • POST - Html Form
    • content-type: application/x-www-form-urlencoded
    • 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20
    • 예) 회원 가입, 상품 주문, HTML Form 사용
  • HTML message body에 데이터를 직접 담아서 요청
    • HTTP API에서 주로 사용, JSON, XML, TEXT
    • 데이터 형식은 주로 JSON 사용

POST-HTML FORM 예시

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


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

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

앞서 말씀드렸듯이, 쿼리 파라미터는 URL에 다음과 같이 ?를 시작으로 보낼 수있습니다 .추가 파라미터는 &로 구분하면 됩니다.

@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("[전체 파라미터 조회]");
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName-> System.out.println("paramName = " + request.getParameter(paramName)));
        System.out.println("[전체 파라미터 조회] - end");
        System.out.println();

        System.out.println("[단일 파라미터 조회]");
        String username = request.getParameter("username");
        String age = request.getParameter("age");
        System.out.println("age = " + age);
        System.out.println("username = " + username);
        System.out.println();

        System.out.println("[이름이 같은 복수 파라미터 조회]");
        String[] usernames = request.getParameterValues("username");
        for (String name : usernames) {
            System.out.println("username = " + name);

        }
        response.getWriter().write("ok");
    }

코드설명

@WebServlet(name = "requestParamServlet", urlPatterns="/request-param") - name :서블릿의 이름을 설정하는 속성, 기본값은 빈 문자열("")이다. - urlPatterns : 서블릿의 URL 목록을 설정하는 속성. 속성값으로 String 배열을 지정한다.(/request-param 호출하면 해당 클래스 호출)기본값은 빈 배열({})이다.

getParameterNames().asIterator().forEachRemaining

request.getParameter("username") : 단일 파라미터 조회
request.getParameterNames() : 파라미터 이름들 모두 조회
request.getParameterValues("username") : 복수 파라미터 조회

결과
[전체 파라미터 조회] - start
username=hello
age=20
[전체 파라미터 조회] - end
[단일 파라미터 조회] request.getParameter(username) = hello request.getParameter(age) = 20
[이름이 같은 복수 파라미터 조회] request.getParameterValues(username) username=hello

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

username=hello&username=kim 과 같이 파라미터 이름은 하나인데, 값이 중복이면 어떻게 될까?
request.getParameter() 는 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 한다. 지금처럼 중복일 때는 request.getParameterValues() 를 사용해야 한다. 참고로 이렇게 중복일 때 request.getParameter() 를 사용하면 request.getParameterValues() 의 첫 번째 값을 반환한다.

HTTP 요청 데이터 - POST HTML Form

주로 회원가입, 상품 주문에서 사용하는 방식이다.
특징

  • content-type: application/x-www-form-urlencoded
  • 메시지 바디에 쿼리 파리미터 형식으로 데이터를 전달한다.username=hello&age=20

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

  • 요청URL : ~
  • 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 형식도 둘 다 지원한다.

참고
content-type은 HTTP 메시지 바디의 데이터 형식을 지정한다.
GET URL 쿼리 파라미터 형식으로 클라이언트에서 서버로 데이터를 전달할 때는 HTTP 메시지 바디를 사용하지 않기 때문에 content-type이 없다.
POST HTML Form 형식으로 데이터를 전달하면 HTTP 메시지 바디에 해당 데이터를 포함해서 보내기때문에 바디에 포함된 데이터가 어떤 형식인지 content-type을 꼭 지정해야 한다. 이렇게 폼으로 데이터를 전송하는 형식을 application/x-www-form-urlencoded 라 한다.

테스트는 POSTMAN을 사용해서 각자 해봅시다!
Postman 테스트 주의사항

  • POST 전송시
    • Body x-www-form-urlencoded 선택
    • Headers에서 content-type: application/x-www-form-urlencoded 로 지정된 부분 꼭 확인

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

단순 텍스트 형식

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

먼저 가장 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고, 읽어보자. HTTP 메시지 바디의 데이터를 InputStream을 사용해서 직접 읽을 수 있다.

RequestBodyStringServlet

@WebServlet(name="requestBodyStringServlet", urlPatterns = "/request-body-string")
public class RequestBodyStringServlet extends HttpServlet{
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletInputStream inputStream = request.getInputStream(); //메세지 body의 내용을 바이트 코드로 바로 얻을수 있다.
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
        System.out.println("messageBody = " + messageBody);

        response.getWriter().write("ok");
    }
}

코드설명

  • ServletInputStream inputStream = request.getInputStream();
    • 메세지 body의 내용을 바이트 코드로 바로 얻을수 있다.
  • String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    • stream은 bytecode이니 string으로 바꿀때는 어떤 인코딩으로 바꿀건지 설정해주어야 한다. 지정 안할경우 default값이 설정된다.

문자 전송

  • content-type: text/plain
  • message body: hello
  • 결과: messageBody = hello

JSON 형식

JSON형식의 데이터는 주로 HTTP API에서 사용한다.
코드를 통해 알아봅시다.

JSON 형식 전송

  • POST : ~
  • content-type : application/json
  • message body : {"username" : "Lee", "age" : 25}
  • 결과 : messageBody = {"username": "Lee", "age": 25}

HelloData : JSON 형식으로 파싱할 객체

@Getter @Setter
public class HelloData {
    private String username;
    private int age;

}

RequestBodyJsonServlet

@WebServlet(name="requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletInputStream inputStream = request.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        System.out.println("messageBody = " + messageBody);

        //json data 객체로 변환
        HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);

        System.out.println("helloData.getUsername() = " + helloData.getUsername());
        System.out.println("helloData.getAge() = " + helloData.getAge());

        response.getWriter().write("ok");
    }
}

코드설명

  • private ObjectMapper objectMapper = new ObjectMapper();
    • JSON 결과를 파싱해서 사용할 수 있는 자바 객체로 반환시켜주는 Jackson 라이브러리
  • HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
    • JSON DATA를 객체로 변환 시켜준다 !
profile
백엔드 공부중입니다!

0개의 댓글