Home HttpServletRequest 객체 - 요청 데이터
Post
Cancel

HttpServletRequest 객체 - 요청 데이터

이 게시글은 인프런의 유료 강의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 수강하며 공부한 내용을 담고있습니다.
저작권에 의해 강의내용에 해당하는 전체 코드는 공개할 수 없습니다.
저작권에 의해 모든 내용을 담을 수 없습니다. 중복 및 반복되는 내용은 생략했습니다.

개요

HttpServletRequest 객체를 이용해 Client 에서 전송한 데이터를 받는 방법에 대해 공부한다.

전송 방식

  • GET - 쿼리 파라미터
    • 쿼리 파라미터에 값을 포함시켜 전달하는 방식
    • http://url.com/path?username=kim&age=20
  • POST - Form
    • Form 을 이용해 데이터를 전달하는 방식
    • Form 데이터는 body 에 보관되지만 형식은 쿼리 파라미터와 동일하다.
    • username=kim&age=20 값이 그대로 body 에 보관되기 때문에 쿼리 파라미터와 동일한 방법으로 데이터를 꺼낼 수 있다.
    • content-type 이 application/x-www-form-urlencoded 이다.
  • HTTP message body
    • JSON, XML, TEXT 같은 데이터를 전송할 때 사용한다.
    • POST, PUT, PATCH 방식을 사용하며 데이터는 body 에 보관하여 전송한다.

GET - 쿼리 파라미터

  • username = kim
  • age = 20

위 값을 전송하려면 url 에 ?username=kim&age=20 을 붙여서 보낸다.
해당 요청을 받는 서블릿을 작성하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Step 1
        System.out.println("--- 파라미터 전체 출력 ---");

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

        System.out.println("--- 파라미터 전체 출력 끝 ---");
        System.out.println();

        // Step 2
        System.out.println("--- 파라미터 하나씩 출력 ---");
        String age = request.getParameter("age");
        System.out.println("username = " + request.getParameter("username"));
        System.out.println("age = " + request.getParameter("age"));
        System.out.println("--- 파라미터 하나씩 출력 끝 ---");
        System.out.println();

        // Step 3
        System.out.println("--- 중복되는 파라미터 출력 ---");
        String[] usernames = request.getParameterValues("username");
        for(String username : usernames) {
            System.out.println("username = " + username);
        }
        System.out.println("--- 중복되는 파라미터 출력 끝 ---");
        System.out.println();

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

우선 http://localhost:8080/request-param 으로 보낸 요청을 받을 수 있게 서블릿의 urlpatterns="request-param" 으로 작성한다.
이후 Step 1 부분을 작성 후 http://localhost:8080/request-param?username=kim&age=20 를 주소창에 입력한다.

1
2
3
4
--- 파라미터 전체 출력 ---
username = kim
age = 20
--- 파라미터 전체 출력 끝 ---

그럼 위와 같은 결과를 콘솔창에서 확인할 수 있다.
코드를 읽어보면 유추할 수 있듯이 request.getParameterNames() 는 모든 parameter 이름을 가져온다. 여기서는 username, age 가 되겠다.
가져온 username 과 age 를 request.getParameter() 에 넣어 값을 꺼낸다.

Step 2 도 동일한 방식이다.
전체 파라미터를 가져올 필요가 없고, GET 요청에 포함된 parameter 이름을 직접 request.getParameter() 에 입력하여 출력하는 방식이다.

Step 3 이 조금 다르다.
Step 3 에서는 요청이 http://localhost:8080/request-param?username=kim&age=20&username=hong 라고 가정한다.

  • username = kim
  • username = hong

그럼 username 이 두 개가 된다.
이 때 request.getParameter("username") 을 사용하면 앞에 있는 kim 만 출력되기 때문에 request.getParameterValues("username") 을 사용해야 한다.

Post - From 데이터

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/request-param" method="post">
    username: <input type="text" name="username" />
    age: <input type="text" name="age" />
    <button type="submit">전송</button>
</form>
</body>
</html>

우선 form 데이터를 전송할 수 있게 위 html 파일을 추가한다.
경로 : webapp > basic (디렉토리 생성) > hello-form.html (생성)
귀찮으면 Postman 을 사용해도 된다.

사진1
사진2

그리고 localhost:8080/basic/hello-form.html 로 들어가서 값을 넣어 전송하면 개발자 도구에서 전송한 값을 확인할 수 있다.
Header 에서 content-type 이 application/x-www-form-urlencoded 인 것을 확인할 수 있고, Payload 에서 내가 보낸 값을 확인할 수 있다.
Payload 를 확인하면 내가 전송한 값의 형식이 쿼리 파라미터와 동일한 형식인 것을 확인할 수 있다.
따라서 서버에서 request.getParameter("username") 을 사용하여 값을 꺼낼 수 있고, 콘솔에서도 제대로 출력되는 모습을 확인할 수 있다.
쉽게말해 GET - 쿼리 파라미터 방식과 Form 방식은 동일한 메서드를 사용해 값을 가져올 수 있어 간편하다.

body 에 단순 텍스트 담아서 전송

사진3
위 이미지와 같이 Body 에 단순한 텍스트만 담아서 전달하려고 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
@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();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        System.out.println("message body : " + messageBody);

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

    }
}

실습을 위한 Servlet 을 작성한다.
body 에 담겨있는 값을 그대로 가져오려면 request.getInputStream() 을 사용한다.
가져온 값은 ServletInputStream 형태이므로 String 으로 형변환 한다.

사진4

Postman 을 사용해 테스트 한다.
콘솔창에 Hello, World! 가 출력되는 것을 확인할 수 있다.

request.getInputStream() 은 body 에 담겨있는 값을 그대로 가져오기 때문에 form 으로 전송한 값도 읽을 수 있다.
Postman 을 사용해 form 데이터를 전송하면 콘솔창에 출력되는 것을 확인할 수 있다.

body 에 JSON 형식을 담아서 전송

JSON 도 단순 문자열이기 때문에 기본적인 방법은 텍스트와 동일하다.
차이점은 Content-type 을 자동으로 application/json 으로 잡아주고, 서블릿에 따라 JSON 을 자동으로 인식해 파싱까지 해줄 수 있다.
여기서는 JSON 문자열을 그대로 가져와서 직접 파싱한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {
    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);

        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");
    }
}
1
2
3
4
5
6
@Getter
@Setter
public class HelloData {
    String username;
    int age;
}

스프링 MVC 에 JSON 라이브러리인 Jackson 이 포함되어 있어 바로 가져다 쓰면된다.
Jackson 라이브러리로 변환시킬 때 JSON 이랑 동일한 형식을 가진 Class 를 만들자.

사진5

1
2
3
4
5
6
7
// 콘솔창에 출력되는 결과
{
    "username": "kim",
    "age": 20
}
helloData.getUsername() = kim
helloData.getAge() = 20

어차피 스프링 사용하면 JSON 을 자동으로 파싱해주는데 굳이 공부해야 싶을 수도 있지만, 서블릿에 대한 학습을 통해 스프링의 내부 동작에 대해 더 쉽게 이해할 수 있도록 한다.
그리고 서블릿의 불편한 점을 좀 더 개선해서 지금의 스프링이 JSON 을 파싱해준다고 생각하면 된다.

This post is licensed under CC BY 4.0 by the author.

HttpServletRequest 객체 기초

HttpServletResponse 객체 기초적인 사용방법