클라이언트에서 HTTP 요청을 통해 전달한 데이터를 서버에서 매핑하는 방법에 대해 학습한 내용입니다.
개인적인 학습의 대한 정리 내용입니다.
HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법에는 크게 3가지가 있습니다.
1. GET메서드(쿼리 파라미터)
ex) /url?username=hello&age=20
HTTP 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
예) 검색, 필터, 페이징 등, 검색에서 많이 사용한다.
2. POST메서드 : HTML Form
HTML 메시지 바디에 content-type: application/x-www-form-urlencoded 인코딩 타입으로 쿼리 파리미터 형식을 전달
예) 회원 가입, 상품 주문, HTML Form 사용
3. HTTP message body에 데이터를 직접 담아서 요청
HTTP API에서 주로 사용하는 방식으로 JSON, XML, TEXT 등의 데이터 형식을 사용할 수 있으며
주로 JSON 사용한다. 지원 메서드 : POST, PUT, PATCH
HTTP 요청 데이터 매핑
1. HttpServletRequest의 getParameter() 메서드
ex) url/request-param-v1?username=hello&age=20
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
String username = request.getParameter("username");
// String[] usernames = request.getParameterValues("username"); // 이름이 같은 복수 파라미터 조회
int age = Integer.parseInt(request.getParameter("age"));
log.info("username={}, age={}", username, age);
response.getWriter().write("ok");
}
GET 쿼리 파리미터 전송 방식, POST HTML Form 전송 방식 둘 다 구분 없이 조회할 수 있다.
(POST 일 때는 content-type이 application/x-www-form-urlencoded 일 경우만!)
참고) content-type은 HTTP 메시지 바디의 데이터 형식을 지정한다.
GET URL 쿼리 파라미터 형식으로 클라이언트에서 서버로 데이터를 전달할 때는 HTTP 메시지 바디를 사용하지 않기 때문에 content-type이 없다.
POST HTML Form 형식으로 데이터를 전달하면 HTTP 메시지 바디에 해당 데이터를 포함해서 보내기 때문에
바디에 포함된 데이터가 어떤 형식인지 Content-Type을 꼭 지정해야 한다. 이렇게 폼으로 데이터를 전송하는 형식을
application/x-www-form-urlencoded 라 한다.
이것을 간단히 요청 파라미터(request parameter) 조회라 한다.
2. @RequestParam 애노테이션
스프링이 제공하는 @RequestParam 애노테이션을 사용하면 요청 파라미터를 매우 편리하게 사용할 수 있다.
@RequestParam : 파라미터 이름으로 바인딩
@RequestParam의 name(value) 속성이 파라미터 이름으로 사용
- @RequestParam("username") -> request.getParameter("username")와 동일하다.
@RequestMapping("/request-param")
public void requestparam(@RequestParam("username") String username,
@RequestParam("age") int age) throws IOException {
response.getWriter().write("ok");
}
HTTP 파라미터 이름이 변수 이름과 같으면 @RequestParam(name="xx") 생략 가능
@RequestMapping("/request-param-v1")
public void requestparam(@RequestParam String username,
@RequestParam int age) throws IOException {
response.getWriter().write("ok");
}
String , int , Integer 등의 단순 데이터 타입이면 @RequestParam도 생략 가능
@RequestMapping("/request-param-v1")
public void requestparam(String username,
int age) throws IOException {
response.getWriter().write("ok");
}
3. Map타입으로 조회
파라미터를 Map, MultiValueMap으로 조회할 수 있다
@ResponseBody
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap) {
log.info("username={}, age={}", paramMap.get("username"), paramMap.get("age"));
return "ok";
}
Map 자료형에 매핑된다.
다만 같은 이름의 여러 파라미터가 전송될 경우 Map은 중복을 허용하지 않기에 MultiValueMap을 사용해야 한다.
@RequestParam MultiValueMap으로 매핑 시
MultiValueMap(key=[value1, value2, ...]) 형식으로 매핑된다.
파라미터의 값이 1개가 확실하다면 Map을 사용해도 되지만, 그렇지 않다면 MultiValueMap 을 사용하자.
4. HTTP 요청 파라미터 - @ModelAttribute
실제 개발을 하면 요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야 한다.
보통 다음과 같이 코드를 작성할 것이다.
@RequestParam String username;
@RequestParam int age;
HelloData data = new HelloData();
data.setUsername(username);
data.setAge(age);
스프링은 이 과정을 완전히 자동화해주는 @ModelAttribute 애노테이션을 제공한다.
@ResponseBody
@RequestMapping("/request")
public String requestParamV4(@ModelAttribute HelloData helloData) {
return "ok";
}
스프링 MVC는 @ModelAttribute 가 있으면 다음을 실행한다.
[객체 이름은 예시]
- HelloData 객체를 생성한다.
- 요청 파라미터의 이름으로 HelloData 객체의 프로퍼티를 찾는다.
- 그리고 해당 프로퍼티의 setter를 호출해서 파라미터의 값을 입력(바인딩) 한다.
예) 파라미터 이름이 username 이면 setUsername() 메서드를 찾아서 호출하면서 값을 입력한다.
프로퍼티 객체에 getUsername() , setUsername() 메서드가 있으면, 이 객체는 username이라는 프로퍼티를 가지고 있다. username 프로퍼티의 값을 변경하면 setUsername() 이 호출되고, 조회하면 getUsername() 이 호출된다.
참고사항)
@ModelAttribute는 생략할 수 있다. 하지만 @RequestParam 도 생략할 수 있으니 혼란이 발생할 수 있다.
스프링은 해당 생략 시 다음과 같은 규칙을 적용한다.
- String , int , Integer 같은 단순 타입 : @RequestParam
- 나머지 : @ModelAttribute
@RequestParam 애노테이션을 생략하면 스프링 MVC는 내부에서 required=false를 적용한다.
@RequestParam 애노테이션 사용 시 파라미터에 값이 없는 경우 defaultValue를 사용하면 기본 값을 적용할 수 있다.
'SPRING' 카테고리의 다른 글
[SPRING] HTTP 요청 데이터 매핑(JSON) - 3 (0) | 2022.03.13 |
---|---|
[SPRING] HTTP 요청 데이터 매핑(단순 텍스트) - 2 (0) | 2022.03.12 |
[SPRING] HTTP 요청 헤더 다루기 (0) | 2022.02.23 |
[SPRING] 애노테이션 기반의 요청 매핑 (0) | 2022.02.16 |
[SPRING] SLF4j을 사용한 로깅방법 (0) | 2022.02.02 |
댓글