관리 메뉴

Rootable의 개발일기

HTTP 요청 파라미터 본문

Spring

HTTP 요청 파라미터

dev-rootable 2023. 7. 15. 20:21

HTTP에서 요청 데이터를 전달할 때 주로 3가지 방식을 사용한다.

 

1. GET 쿼리 파라미터 전송

 

2. POST HTML Form 전송

 

3. HTTP Body에 직접 담아서 전송 - HTTP API

 

요청 데이터를 처리하는 방법을 하나씩 알아보고 각 방식에 맞게 적절하게 선택하자.

 

📌 GET 쿼리 파라미터 및 POST HTML Form - 요청 파라미터 처리

 

🔎 서블릿

 

HttpServletRequest.getParameter를 통해 요청 파라미터를 다룰 수 있다.

 

이 방식은 GET 쿼리 파라미터 전송 방식과 POST HTML Form 전송 방식 둘 다 형식이 같으므로 구분 없이 조회 가능하다.

 

 

🔎 @RequestParam

 

HttpServletRequest와 같은 역할

 

즉, 요청 파라미터 값을 받아올 수 있다.

 

HTTP API처럼 직접 HTTP 바디에 데이터를 담는 경우에는 사용 불가

 

요청 파라미터 이름과 변수 이름이 같으면, @RequestParam의 name 값이 없어도 된다.

 

 

위 경우처럼 이름이 같은 상황에서 String, int, Integer 등 단순 타입이면 @RequestParam 생략 가능

 

@RequestParam 생략하면 Spring MVC 내부에서 required=false를 적용한다. 즉, 빈 값을 허용한다.

 

 

특별히 값을 지정하지 않았을 때, 기본 값을 설정하려면 defaultValue 옵션을 사용하면 된다. (빈 문자를 넣더라도 기본 값으로 바뀜)

 

defaultValue가 있기 때문에 required 옵션은 의미가 없다.

 

 

파라미터 값을  Map 또는 MultiValueMap으로 받을 수 있다.

 

 

동일 키에 값이 2개 이상인 경우 MultiValueMap을 사용해야 한다.

 

요청 : http://localhost:8080/request-param-map?username=hello&age=20&username=kim

 

 

🔎 @ModelAttribute

 

요청 파라미터 값을 객체에 바인딩할 수 있다.

 

HTTP API처럼 직접 HTTP 바디에 데이터를 담는 경우에는 사용 불가

 

 

@ModelAttribute 사용 전

 

@ModelAttribute 사용 후

 

위 코드에서 객체를 생성하고, 각 요청 파라미터 값의 setter를 호출하여 값을 바인딩하는 부분을 @ModelAttribute가 수행한다.

 

타입이 맞지 않는 값을 넣으면 BindException 발생

 

@ModelAttribute는 생략 가능하다. 그런데 @RequestParam도 생략 가능하기 때문에 생략 시 따르는 규칙이 있다.

 

💡 @ModelAttribute 생략시 규칙

1. String, int, Integer 같은 단순 타입 = @RequestParam
2. 나머지 = @ModelAttribute 적용(argument resolver로 지정해 둔 타입 제외)

 

📌 HTTP API - 단순 텍스트 처리

 

HTTP message body에 데이터를 직접 담아서 요청하는 방식이다.

 

데이터 형식은 주로 JSON이고, POST, PUT, PATCH 등의 메서드를 사용한다.

 

요청 파라미터와 다르게, @RequestParam, @ModelAttribute를 사용할 수 없다.

 

🔎 서블릿

 

HttpServletRequest의 getInputStream을 통해 ServletInputStream으로 받을 수 있다.

 

ServletInputStream은 클라이언트로부터 온 binary 데이터를 읽기 위해 제공되는 input stream이다.

 

서블릿을 통해 HTTP body 읽기

 

요청 스펙

 

 

✔ Stream

 

출처 : https://velog.io/@hidaehyunlee/%EB%8D%B0%EC%9D%B4%ED%84%B0%EA%B0%80-%EC%A0%84%EB%8B%AC%EB%90%98%EB%8A%94-%EC%9B%90%EB%A6%AC-OSI-7%EA%B3%84%EC%B8%B5-%EB%AA%A8%EB%8D%B8%EA%B3%BC-TCPIP-%EB%AA%A8%EB%8D%B8

 

클라이언트-서버 구조에서 클라이언트가 전송한 데이터는 응용 계층부터 물리 계층을 타고 전송된다. 이때, 물리 계층까지 간 데이터는 바이너리 데이터 형태이므로, 서버 측(IntelliJ와 같은 프레임워크)은 바이너리를 읽을 수 있는 InputStream과 같은 객체가 필요하다. 반대로 서버에서 데이터를 적어서 클라이언트로 내려줄 때는 OutputStream을 사용할 수 있다.

 

출처: http://www.tcpschool.com/java/java_io_stream

 

 

🔎 InputStream

 

서블릿 없이 직접 InputStream으로 HTTP body 데이터를 읽을 수 있다.

 

InputStream을 통해 HTTP body 읽기

 

요청 스펙

 

 

💡 InputStream과 OutputStream

Spring MVC가 지원하는 파라미터

InputStream(Reader): HTTP 요청 메시지 바디의 내용을 직접 조회
OutputStream(Writer): HTTP 응답 메시지의 바디에 직접 결과 출력

 

🔎 HttpEntity

 

HttpEntity를 통해 HTTP header, body 정보를 편리하게 조회할 수 있다.

 

HttpEntity를 통해 HTTP body 읽기

 

응답에도 사용 가능하며 헤더 정보도 포함할 수 있다. 응답에 사용할 경우, 뷰를 조회하지 않고 데이터 그대로 클라이언트로 내려간다.

 

참고로, 요청 파라미터를 조회하는 기능과 관계없다.

 

💡 Stream 없이 바로 변환이 가능한 이유

Spring MVC 내부에서 HTTP 메시지 바디를 읽어서 문자나 객체로 변환해서 전달해 주기 때문이다. 이때 HTTP 메시지 컨버터(HttpMessageConverter)라는 기능을 사용한다.

 

💡 RequestEntity, ResponseEntity

RequestEntity : HttpMethod, url 정보를 추가할 수 있으며, 요청에서 사용한다.
ResponseEntity : HTTP 상태 코드를 설정할 수 있고, 응답에서 사용한다.

 

🔎 @RequestBody

 

HTTP 메시지 바디 정보를 편리하게 조회할 수 있다.

 

뷰 리졸버를 통해 뷰를 조회하지 않으며, HttpMessageConverter가 동작하여 요청 바디의 내용을 그대로 가져온다.

 

바디를 조회하는 기능은 요청 파라미터를 조회하는 @RequestParam, @ModelAttribute와 관계없다.

 

@RequestBody를 통해 HTTP body 읽기

 

HttpEntity, @RequestBody, @ResponseBody는 HTTP 메시지 컨버터가 동작한다.

 

📌 HTTP API - JSON 처리

 

🔎 서블릿

 

HttpServletRequest를 사용해서 직접 HTTP body에서 데이터를 읽어올 수 있다.

 

이때, 요청 데이터가 JSON이므로 객체에 파싱 하길 원한다면 ObjectMapper를 사용해야 한다.

 

서블릿을 통해 HTTP body 읽기

 

 

🔎 @RequestBody

 

@RequestBody는 서블릿 사용 없이 단순 텍스트뿐만 아니라 JSON 데이터도 처리할 수 있다.

 

마찬가지로 JSON 데이터이지만 HTTP 메시지 컨버터는 HTTP body의 JSON 데이터도 문자나 객체로 변환해 준다.

 

따라서, ObjectMapper 사용 없이 body를 읽어 와서 HelloData라는 객체에 파싱 할 수 있다.

 

주의할 점은 @RequestBody를 생략할 수 없다는 것이다. 왜냐하면 HelloData는 클래스 타입이므로 생략할 경우, @ModelAttribute가 붙을 수 있기 때문이다.

 

@RequestBody를 통해 HTTP body 읽기

 

@ResponseBody가 붙었으므로 ViewResolver가 동작하지 않고 HTTP 메시지 컨버터가 동작하여 클라이언트로 내려줄 데이터를 HTTP body에 직접 지정할 수 있다.
리턴 값으로 이 데이터가 결정되는데, 아래처럼 HelloData의 data라는 객체를 그대로 내리면 해당 정보가 JSON으로 보인다.

 

 

요청/응답(Postman)

 

🔎 HttpEntity

 

단순 텍스트를 읽었을 때처럼 JSON도 HttpEntity를 통해 HTTP body를 읽을 수 있다.

 

Reference:

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

 

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

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

www.inflearn.com

 

 

'Spring' 카테고리의 다른 글

요청 매핑 핸들러 어뎁터 구조  (0) 2023.07.18
HTTP 메시지 컨버터(HTTP Message Converter)  (0) 2023.07.17
HTTP 요청 매핑  (0) 2023.07.15
@RequestParam vs @ModelAttribute vs @RequestBody  (0) 2023.07.14
서블릿(Servlet) 활용  (0) 2023.07.12