개발/Spring

Spring MVC / Controller에서 요청 데이터를 받는 방법

highright96 2021. 5. 28.

Controller에서 요청 데이터를 받는 방법

클라이언트가 보낸 데이터를 받을 수 있게 해주는 어노테이션을 소개하려고 한다.

 

1. HTTP 헤더 조회

스프링 컨트롤러는 HTTP 헤더 정보를 갖는 다양한 어노테이션과 파라미터를 제공한다.

아래의 예제로 하나씩 알아보자.

@RestController
public class RequestHeaderController {
  @RequestMapping("/headers")
  public String headers(
    HttpServletRequest request,
    HttpServletResponse response,
    HttpMethod httpMethod,
    Locale locale,
    @RequestHeader MultiValueMap<String, String> headerMap,
    @RequestHeader(value = "host") String host,
    @CookieValue(value = "myCookie") String cookie) {
      return "ok";
  }
}
  • HttpServletRequest, HttpServletResponse
    • 클라이언트의 요청과 반환할 응답 객체이다.
  • HttpMethod
    • Http Method를 조회한다.(Get, Post, Patch, Put, Delete)
  • Locale
    • Accept Language
  • @RequestHeader MultiValueMap<String, String> headerMap
    • 모든 HTTP 헤더를 MultiValueMap 형식으로 조회한다.
  • @RequestHeader("xxx") String host
    • 특정 헤더를 조회한다.
    • 필수 값 여부, 기본 값을 설정할 수 있다.
       @RequestHeader(value = "host", required = true, defaultValue = "defalutValue") String host​
  • @CookieValue(value = “myCookie”) String cookie
    • 특정 쿠키를 조회한다.
    • 필수 값 여부, 기본 값을 설정할 수 있다.
      @CookieValue(value = "myCookie", required = true, defaultValue = "defalutValue") String cookie
참고
MultiValueMap
Map과 유사한데, 하나의 키에 여러 값을 받을 수 있다.
ex) KeyA=value1&KeyA=value2

 

2. HTTP 요청 파라미터 조회

@RequestParam

요청 URL : /requestParam?username=userA

@RequestMapping("/requestParam")
public String requestParamMap(@RequestParam("username") String name) {
  return "ok";
}

만약 파라미터 이름이 변수 이름과 같으면 ("xxx")를 생략할 수 있다.

@RequestMapping("/requestParam")
public String requestParamMap(@RequestParam String username) {
  return "ok";
}

@RequestParam도 생략해 더 간단히 표현할 수 있다.

개인적인 생각으로 “너무 축약한 게 아닌가?”라는 생각이 든다.

팀과 따로 정한 게 아니라면 @RequestParam 정도는 적어주는 것이 좋을 듯하다.

 

@RequestParam 필수 여부

@RequestParam에 required 속성을 추가해 필수 여부를 정할 수 있다. 기본값은 true이다.

@RequestMapping("/requestParam")
public String requestParamMap(@RequestParam(required = false) String username) {
  return "ok";
}
  • 요청 : /requestParam?username=userA 정상
  • 요청 : /requestParam?username= 정상
    • 참고로? username=으로 요청이 오면 빈 공백("")이 전달된다.(String일 경우)
  • 요청 : /requestParam 예외 발생

 

@ModelAttribute

개발을 하면 보통 아래와 같이 요청 파라미터를 받아서 객체로 만들어준다.

@RequestMapping("/modelAttribute")
public String modelAttributeV0(@RequestParam String username, @RequestParam int age) {
  UserRequest userRequest = new UserRequest();
  userRequest.setUsername(username);
  userRequest.setAge(age);
  return "ok";
}

스프링은 이 과정을 자동화해주는 @ModelAttribute 어노테이션을 제공한다.

위의 코드는 아래와 같이 바꿀 수 있다.

@RequestMapping("/modelAttribute")
public String modelAttributeV0(@ModelAttribute UserRequest userRequest) {
  return "ok";
}

@ModelAttribute도 생략할 수 있으나, 적어주는 게 좋을 듯하다.

 

몇 가지 주의할 점이 있다.

  • 바인딩할 UserRequest 클래스에 Setter와 Getter를 반드시 만들어줘야 한다.
  • BindException이 발생하지 않도록 적절한 Validation 처리를 해야 한다.

 

3. HTTP 메시지 조회

@RequestBody

요청 파라미터와 다르게, HTTP 메시지 바디를 통해 데이터가 넘어오는 경우는 @RequestParam과 @ModelAttribute를 사용할 수 없다.

이를 위해 스프링은 @RequestBody 어노테이션을 제공한다.

@RestController
public class RequestBodyJsonController {
  @PostMapping("/request-body-json-v2")
  public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
    UserRequest userRequest = objectMapper.readValue(messageBody, UserRequest.class);
    return "ok";
  }
}

@RequestBody는 HTTP 메시지 바디에서 데이터를 꺼내고 JSON 형태의 문자열로 변환하는 역할을 해준다.

따라서 우리는 변환된 문자열을 Jackson 라이브러리인 objectMapper를 사용해서 자바 객체로 변환해주면 된다.

사실 개발자 입장에서 일일이 자바 객체로 변환하는 것도 매우 번거롭다.

@RequestBody는 아래와 같이 변환할 객체를 적어주면 위의 과정도 축약할 수 있다.

@Controller
public class RequestBodyJsonController {
  @ResponseBody
  @PostMapping("/requestBody")
  public String requestBodyJsonV3(@RequestBody UserRequest userRequest) {
    return "ok";
  }
}

몇 가지 주의할 점이 있다.

  • @RequestBody는 생략 불가능하다.
  • HTTP 요청 시에 content-type이 application/json인지 확인해야 한다.

 

4. 참고

댓글