본문 바로가기
Backend, Server/Spring MVC

[Spring MVC] 스프링 MVC 기본 기능 - (2) HTTP 요청

by ggyongi 2022. 1. 18.
반응형

HTTP 헤더 정보 조회 방법

@RequestMapping("/headers")
public String headers(HttpServletRequest request,
                      HttpServletResponse response,
                      HttpMethod httpMethod,
                      Locale locale,
                      @RequestHeader MultiValueMap<String, String> headerMap,
                      @RequestHeader("host") String host,
                      @CookieValue(value = "myCookie", required = false) String cookie
                      ) {

    log.info("request={}", request);
    log.info("response={}", response);
    log.info("httpMethod={}", httpMethod);
    log.info("locale={}", locale);
    log.info("headerMap={}", headerMap);
    log.info("header host={}", host);
    log.info("myCookie={}", cookie);
    return "ok";

}

주요 파라미터

@RequestHeader MultiValueMap<String, String> headerMap : 모든 HTTP 헤더를 MultiValueMap 형식으로 조회

MultiValueMap이란?

- Map과 유사하지만, 하나의 키에 여러 Value를 받을 수 있음

- HTTP 헤더, HTTP 쿼리 파라미터와 같이 하나의 키에 여러 값을 받을 때 사용

(ex) keyA=value1&keyA=value2)

 

 

요청 데이터 조회

다음과 같이 크게 3가지

1. GET - 쿼리 파라미터 : ?username=hello&age=20

2. POST - HTML Form : 메세지 바디에 쿼리 파라미터 형식으로 전달 username=hello&age=20

 - content-type : application/x-www-form-urlencoded

3. HTTP message body에 직접 데이터를 담아서 요청 - API에서 주로 사용하며 주로 JSON

 - POST, PUT, PATCH

 

요청 파라미터 조회법

1. request.getParameter() - HttpServletRequest가 제공하는 방식

2. @RequestParam("username") - 좀 더 편리하게 값을 꺼내올 수 있음, 파라미터 이름이 같으면 생략 가능

더보기
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String username = request.getParameter("username");
    int age = Integer.parseInt(request.getParameter("age"));
    log.info("username={}, age={}", username, age);

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

@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
        @RequestParam("username") String memberName,
        @RequestParam("age") int memberAge){

    log.info("username={}, age={}", memberName, memberAge);
    return "ok";
}

@ResponseBody
@RequestMapping("/request-param-v3")
public String requestParamV3(
        @RequestParam String username,
        @RequestParam int age){

    log.info("username={}, age={}", username, age);
    return "ok";
}

@ResponseBody
@RequestMapping("/request-param-v4")
public String requestParamV4(String username, int age){
    log.info("username={}, age={}", username, age);
    return "ok";
}

- @RequestParam(required = false)

required는 파라미터 필수 여부이다. 기본값은 true이다. 

주의점은 기본형에 null 입력이 안되므로 @RequestParam(required = false) int age 같은 경우에는 예외 발생할 수 있음

더보기
@ResponseBody
 @RequestMapping("/request-param-required")
 public String requestParamRequired(
         @RequestParam(required = true) String username,
         @RequestParam(required = false) Integer age){

     log.info("username={}, age={}", username, age);
     return "ok";
 }


 @ResponseBody
 @RequestMapping("/request-param-default")
 public String requestParamDefault(
         @RequestParam(required = true, defaultValue = "guest") String username,
         @RequestParam(required = false, defaultValue = "-1") int age){

     log.info("username={}, age={}", username, age);
     return "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";
}

4. @ModelAttribute

객체를 받는 방법도 가능하다. @ModelAttribute는 다음 두가지 기능을 가진다.

1. 요청 파라미터 처리 : 객체를 생성하고 요청 파라미터값을 프로퍼티 접근법(setXX)로 입력해줌

2. Model 추가 : @ModelAtrribute 어노테이션이 달린 객체를 자동으로 모델에 넣어줌. 이때 이름을 바꿀 수도 있는 데 다음과 같이 하면 된다. 

@ModelAttribute("hello") Item item : 이름을 hello로 지정하면
model.addAttribute("hello", item); 모델에 hello 이름으로 저장(이 코드가 자동으로 실행됨)

*이름을 생략하면 클래스이름의 제일 앞글자를 소문자로만 바꿔서 저장 ex) Item -> item

더보기
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
    return "ok";
}


//@ModelAttribute도 생략이 가능하나 명확성을 위해 권장하진 않는다고 한다.
@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV2(HelloData helloData) {
    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
    return "ok";
}

스프링은 해당 생략시 다음과 같은 규칙을 적용한다.

String , int , Integer 같은 단순 타입 = @RequestParam

나머지 = @ModelAttribute (argument resolver 로 지정해둔 타입 외)

 

 

메세지 바디 조회 - 단순 텍스트

v1. InputSream 사용을 통해 읽기 가능

더보기
@PostMapping("/request-body-string-v1")
public void requestBodyStringV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
    ServletInputStream inputStream = request.getInputStream();
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

    log.info("messageBody={}", messageBody);

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

v2. InputStream을 파라미터로 바로 받아올 수 있음

더보기
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {

    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    log.info("messageBody={}", messageBody);

    responseWriter.write("ok");
}

v3. HttpEntity 사용

- httpEntity.getBody(), httpEntity.getHeaders()로 바디, 헤더 정보를 편리하게 조회할 수 있음

- 응답에도 사용 가능 : 응답으로 HttpEntity를 바로 반환하면 됨

더보기
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException {
    
    String messageBody = httpEntity.getBody();
    log.info("messageBody={}", messageBody);

    return new HttpEntity<>("ok");
}

v4. @RequestBody 사용

주의: 요청 파라미터를 조회하는 @RequestParam, @ModelAttribute와는 관련없음

더보기
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) throws IOException {
    log.info("messageBody={}", messageBody);
    return "ok";
}

* @ResponseBody : 이걸 달아주면 String으로 바로 응답 결과를 HTTP 메시지 바디에 담아서 전달할 수 있다.

 

 

메세지 바디 조회 - JSON

v1. ObjectMapper 사용 : objectMapper를 사용하여 객체로 변환 가능

더보기
private ObjectMapper objectMapper = new ObjectMapper();

@PostMapping("/request-body-json-v1")
public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
    ServletInputStream inputStream = request.getInputStream();
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

    log.info("messageBody={}", messageBody);
    HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());

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

v2. @RequestBody 사용(사실상 단순 텍스트 복습)

더보기
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {

    log.info("messageBody={}", messageBody);
    HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());

    return "ok";
}

3. @RequestBody에 객체 파라미터를 바로 지정해줄 수 있다. 

**@RequestBody는 생략불가: @ModelAttribute와 혼동될 수 있음

더보기
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData helloData) {

    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
    return "ok";
}

4. HttpEntity도 당연히 사용 가능

더보기
@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
    HelloData data = httpEntity.getBody();
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    return "ok";
}

5. @ResponseBody를 달아주면 해당 객체를 바로 HTTP 메시지 바디에 넣어서 전달해줄 수 있음

더보기
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData helloData) {
    log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
    return helloData;
}

 

작동 방식 정리

@RequestBody : JSON 요청 - (HTTP메시지 컨버터) -> 객체

@ResponseBody : 객체 - (HTTP메시지 컨버터) -> JSON 응답

 


---------------
참고: 인프런 김영한님 강의(스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술)

 

비전공자 네카라 신입 취업 노하우

시행착오 끝에 얻어낸 취업 노하우가 모두 담긴 전자책!

kmong.com

댓글