[ Spring ]/SpringMVC 1편

[Spring] HttpServletRequest / HTTP 요청 데이터를 얻는 3가지 방법

쿠릉쿠릉 쾅쾅 2022. 2. 15. 11:41
728x90

 

HTTP 요청 데이터

  • HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법이 3가지가 있다.
    • GET - 쿼리 파라미터
    • POST - HTML Form
    • HTTP message body

 


 

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

  • 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달한다.
  • 검색, 필터, 페이징 등에서 많이 사용하는 방식이다.
  • 쿼리 파라미터는 URL에 ? 를 시작으로 보낼 수 있다. 추가 파라미터는 & 로 구분하면 된다.
    • ex) http://localhost:8080/request-param?username=hello&age=20
    • 전달 데이터 : username=hello / age=20
  • 서버에서 HttpServletRequest 객체를 통해 쿼리 파라미터를 편하게 조회할 수 있다.
  • GET (URL 쿼리 파라미터) 형식으로는 클라이언트에서 서버로 데이터를 전달할 때 HTTP 메시지 바디를 사용하지 않기 때문에 content-type이 없다.

 

📌 ReqeustParamServlet 클래스

package hello.servlet.basic.request;

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;
import java.util.Enumeration;
import java.util.Map;

/**
 * 1. 파라미터 전소 기능
 * http://localhost:8080/request-param?username=hello&age=20
 *
 * 2. 동일한 파라미터 전송 가능
 * http://localhost:8080/request-param?username=hello&username=kim&age=20
 * */

@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("[전체 파라미터 조회] - start");

        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");
        System.out.println("request.getParameter(username) = " + username);

        String age = request.getParameter("age");
        System.out.println("request.getParameter(age) = " + age);
        System.out.println();

        System.out.println("[이름이 같은 복수 파라미터 조회]");
        System.out.println("request.getParameter(username)");

        String[] usernames = request.getParameterValues("username");

        for (String name : usernames) {
            System.out.println("username = " + name);
        }

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

    }
}
  • 실무에서는 파라미터를 전부 조회할 일이 많이 없다.
  • 대부분 단일 파라미터 조회를 많이 쓴다.
    • request.getParameter()
  • 쿼리 파라미터가 username=hello&username=kim 처럼 파라미터 이름은 하나인데, 값이 중복된 경우 request.getParameter() 메서드를 사용한다.

 

 

🔍 쿼리 파라미터 조회 메서드

// 단일 파라미터 조회
String uesername = request.getParameter("uesername");

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

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

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

 


 

HTTP 요청 데이터 - POST (HTML Form)

  • HTML Form을 사용해서 클라이언트에서 서버로 데이터를 전송할 수 있다.
  • 주로 회원가입, 상품 주문 등에서 사용한다.
  • POST로 요청하기 때문에 데이터를 Http request message body에 쿼리 파라미터 형식으로 전달한다.
    • ex) username=hello&age=20
  • 메세지 바디의 데이터 형식이 쿼리 파라미터와 동일한 형식이라서 GET 방식과 같은 방법으로 조회할 수 있다.
  • 즉, request.getParameter() 메서드는 GET 방식과 POST 방식을 둘 다 지원한다.
  • POST HTML Form 형식으로 데이터를 전달하면 HTTP 메시지 바디에 해당 데이터를 포함해서 보내기 때문에 바디에 포함된 데이터가 어떤 형식인지 Content-Type을 반드시 지정해야 한다.
    • 예시
      • content-type: application/x-www-form-urlencoded
        • HTML Form으로 데이터를 전달하는 형식을 application/x-www-form-urlencoded 라고 한다.
        • content-type을 pplication/x-www-form-urlencoded으로 적으면 메시지 바디의 데이터 형식이 GET 방식의 쿼리 파라미터 형식과 같아진다.
        • 그래서 쿼리 파라미터 조회 메서드( rqeust.getParameter() )를 그대로 사용하면 된다.
      • message body : username=hello&age=20
    • Content-Type이란, HTTP 통신에서 전송되는 데이터 타입을 나타내는 header 정보 중 하나다.
    • Content-Type은 HTTP 메시지 바디의 데이터 형식을 지정한다.
    • 데이터를 받은 쪽에서 Content-Type에 따라 데이터를 어떻게 처리할지 결정한다.
    • 데이터를 Content-Type 없이 보내면 데이터를 받는 쪽에서 단순히 텍스트 데이터로 인식한다.
    • HTTP 메서드에서 GET 방식은 URL에 쿼리파라미터 형식으로 key=value 형식으로 보내기 때문에 Context-Type이 필요가 없다.
    • POST 또는 PUT 방식처럼 메시지 바디에 데이터를 전달할 때 Content-Type이 필요하다.

 

💡 정리

  • 클라이언트 입장에서 데이터를 보낼 때 GET 방식으로 URL에 쿼리파라미터로 데이터를 보내느냐 / POST 방식으로 HTML Form으로 데이터를 보내느냐에 따라 데이터를 보내는 방법이 서로 다르다.
  • 데이터를 받는 서버 입장에서는 둘 다 형식이 동일하므로 GET, POST 구분 없이 request.getParameter() 메서드로 데이터를 조회하면 된다.

 

💡 Postman을 이용해서 POST 방식 테스트하기

  • Postman 애플리케이션을 이용하여 HTML파일 없이 데이터를 전송할 수 있다. 
  • POST 전송시 Body 카테고리에서 x-www-form-urlencoded를 체크 해줘야한다.

 

  • Header 카테고리에서 application/x-www-form-urlencoded 인지 확인할 것

 


 

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

 

🔍 API 메시지 바디 - 단순 텍스트

  • HTTP message body에 데이터를 직접 담아서 요청한다.
    • HTTP API에서 주로 사용한다.
      • 데이터를 JSON 형식으로 사용한다.
    • POST, PUT, PATCH 방식이다.

 

📌 RequestBodyStringServlet 클래스

package hello.servlet.basic.request;

import org.springframework.util.StreamUtils;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet(name="requestBodyStringServlet", urlPatterns = "/request-body-string")
public class RequestBodyStringServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // HTTP 메시지 바디의 데이터를 바이트 코드로 변환
        ServletInputStream inputStream = request.getInputStream();

        // 바이트 코드를 String 타입으로 변환
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); // 타입 변환시 문자표(Charset)를 UTF-8로 지정할 것
        System.out.println("messageBody = " + messageBody);
        response.getWriter().write("ok");

    }
}
  • 단순 텍스트로 받으려면 HTTP 메시지 바디의 데이터를 바이트 코드로 변환하고 String 타입으로 변환했다. String 타입으로 변환시, UFT-8 지정을 꼭 해줘야 한다. 
    • HTTP 메시지 바디 데이터 → 바이트 코드 → String 타입 (UTF-8 지정)

 

💡 Postman으로 테스트하기

 

🔍 API 메시지 바디 - JSON

  • 요새는 json 형식을 자주 사용한다.

 

📌 HelloData

package hello.servlet.basic;

import lombok.Getter;
import lombok.Setter;

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

}

 

 

📌 RequestBodyJsonServlet 클래스

package hello.servlet.basic.request;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet(name="requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {

    // Jackson 라이브러리
    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);

        // Jackson 라이브러리를 사용해서 JSON 결과를 파싱해서 자바 객체로 변환
        HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);

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

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

    }
}
  • JSON 결과를 파싱해서 사용할 수 있는 자바 객체로 변환하려면 Jackson, Gson 같은 JSON 변환 라이브러리를 사용해야 한다.
  • 스프링 부트로 Spring MVC를 선택하면 기본으로 Jackson 라이브러리(ObjectMapper 클래스)를 함께 제공한다.
  • HelloData 클래스는 JSON 객체를 클래스로 변환할 때 변환된 정보를 받기 위한 임시 데이터 객체다.
  • 지금은 이렇게 Stream을 JSON으로 바꾸고 직접 변환을 해줘야하지만 나중에 Spring MVC를 사용하면 편리하게 사용할 수 있다. 

 

 

 

 

 

 

 


👀 참고 자료

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

 

https://yunzema.tistory.com/186

 

[개념 정리] http content-type 관한 정리

http 통신으로 api와 연동 혹은 api를 구현할 때, 보편적으로 자주 쓰는 Content-Type, Mime-Type이 있지만, 종류에 대해 한번 정리할 필요가 있어 일단 종류와 개념에 대한 내용 정리한다. content-type이란

yunzema.tistory.com

 

https://pygmalion0220.tistory.com/entry/HTTP-Content-Type

 

[HTTP] Content-Type

Spring boot로 파일 다운로드를 구현 하던 중 Content-Type을 보게 되었다. Content-Type? Content-Type?? Content-Type???????????? 컨텐트 타입???????????? HTTP Header에 Conent-Type을 이래저래 지정하고 Fi..

pygmalion0220.tistory.com

 

 

 

 

 

728x90