Notice
Recent Posts
Recent Comments
Link
관리 메뉴

look-forest

스프링 MVC 기본 기능 - 요청 본문

Spring/Spring MVC - 웹 개발 핵심 기술

스프링 MVC 기본 기능 - 요청

studyHub 2023. 5. 7. 22:37

스프링 MVC가 제공하는 기본 기능 중 HTTP 요청 관련 기능을 정리해보자

 

 


요청 매핑

1. 애노테이션 기반의 요청 매핑

    //@RequestMapping 에 method 속성으로 HTTP 메서드를 지정하지 않으면 HTTP 메서드와 무관하게 호출
    @RequestMapping(value = {"/hello-basic", "/hello-go"}, method = RequestMethod.GET)
    public String helloBasic() {
        return "ok";
    }

    /**
     * 편리한 축약 애노테이션
     * @GetMapping
     * @PostMapping
     * @PutMapping
     * @DeleteMapping
     * @PatchMapping
     */
    @PostMapping(value = "/mapping-get")
    public String mappingGet() {
        return "ok";
    }

 

2. PathVariable(경로 변수) 사용

최근 HTTP API는 리소스 경로에 식별자를 넣는 스타일을 선호한다.

  • /mapping/userA
  • URL 경로를 템플릿화 할 수 있는데, @PathVariable 을 사용하면 매칭 되는 부분을 편리하게 조회할 수 있다.
  • @PathVariable 의 이름과 파라미터 이름이 같으면 생략할 수 있다.
    @GetMapping(value = "/mapping/{userId}")
    public String mappingPath(@PathVariable("userId") String data) {
        return "ok";
    }

    /**
     * PathVariable 사용 다중
     */
    @GetMapping("/mapping/users/{userId}/orders/{orderId}")
    public String mappingPath(@PathVariable String userId, @PathVariable Long orderId) {
        log.info("mappingPath userId={}, orderId={}", userId, orderId);
        return "ok";
    }

 

3. 특정 파라미터 조건 매핑

파라미터 조건을 추가로 매핑할 수도 있다.

@GetMapping(value = "/mapping-param", params = "mode=debug")
public String mappingParam() {
	return "ok";
}

 

4. HTTP 헤더 조건 매핑

HTTP 헤더 조건을 추가로 매핑할 수도 있다.

 

4-1. 특정 헤더로 추가 매핑

@GetMapping(value = "/mapping-header", headers = "mode=debug")
public String mappingHeader() {
	return "ok";
}

 

4-2. 미디어 타입 헤더 조건 매핑

   1) Content-Type => consumes

       HTTP 요청 메시지의 콘텐츠 타입을 지정. 서버는 소비하는 입장.

/**
 * consumes="application/json"
 * consumes="!application/json"
 * consumes="application/*"
 * consumes="*\/*"
 * MediaType.APPLICATION_JSON_VALUE
 */
@PostMapping(value = "/mapping-consume", consumes = MediaType.APPLICATION_JSON_VALUE)
public String mappingConsumes() {
	return "ok";
}

   2)  Accept => produces

       응답받을 수 있는 데이터 타입을 지정 => 서버는 생산하는 입장

/**
 * produces = "text/html"
 * produces = "!text/html"
 * produces = "text/*"
 * produces = "*\/*"
 */
@PostMapping(value = "/mapping-produce", produces = MediaType.TEXT_PLAIN_VALUE)
public String mappingProduces() {
	return "ok";
}

 

*활용 예시

더보기
리소스를 계층으로 매핑하면 이렇게 깔끔해지고, 식별하기도 쉽다!

HTTP 헤더 정보 조회

애노테이션 기반의 스프링 컨트롤러는 다양한 파라미터를 지원한다

사용 가능한 파라미터 목록은 아래 공식 메뉴얼 참고
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-annarguments

 

//private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RequestHeaderController.class);
@Slf4j //위 코드를 자동으로 생성해서 로그를 선언해준다. 개발자는 편리하게 log 라고 사용하면 된다.
@RestController
public class RequestHeaderController {

    @RequestMapping("/headers")
    public String headers(HttpServletRequest request,
                          HttpServletResponse response,
                          HttpMethod httpMethod,
                          Locale locale,
                          //MultiValueMap : 하나의 키에 여러 값을 받을 수 있다. HTTP header, HTTP 쿼리 파라미터와 같이 하나의 키에 여러 값을 받을 때 사용
                          @RequestHeader MultiValueMap<String, String> headerMap,
                          @RequestHeader("host") String host,
                          @CookieValue(value = "cookieName", 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("cookie={}", cookie);
        return "ok";
    }
}

 


HTTP 요청 파라미터

클라이언트에서 서버로 요청 데이터를 전달할 때는 주로 다음 3가지 방법을 사용한다.

1. GET - 쿼리 파라미터

  • /url?username=hello&age=20
  • 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
  • 예) 검색, 필터, 페이징등에서 많이 사용하는 방식

2. POST - HTML Form

  • content-type: application/x-www-form-urlencoded
  • 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20
  • 예) 회원 가입, 상품 주문, HTML Form 사용

3. HTTP message body에 데이터를 직접 담아서 요청

  • HTTP API에서 주로 사용, JSON, XML, TEXT
  • 데이터 형식은 주로 JSON 사용
  • POST, PUT, PATCH

 

 

요청 파라미터 vs HTTP 메시지 바디 요청

  • 파라미터를 조회하는 기능: @RequestParam , @ModelAttribute
  • HTTP 메시지 바디를 직접 조회하는 기능: @RequestBody

 


[요청 파라미터 조회]  쿼리 파라미터, HTML Form

GET, POST HTML Form 둘다 형식이 같으므로 구분없이 조회할 수 있다.

@RequestParam

 

@ModelAttribute

실제 개발을 하면 요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야 한다.
보통 다음과 같이 코드를 작성할 것이다.

 

스프링은 이 과정을 완전히 자동화해주는 @ModelAttribute 기능을 제공한다.
그러려면 요청 파라미터를 바인딩(연결, 입력) 받을 클래스를 정의해야 한다.

 

스프링MVC는 @ModelAttribute 가 있으면 다음을 실행

  1. HelloData 객체를 생성
  2. 요청 파라미터의 이름으로 HelloData 객체의 프로퍼티를 찾는다.
  3. 해당 프로퍼티의 setter를 호출해서 파라미터의 값을 입력(바인딩)
타입이 안맞으면 바인딩 오류를 발생시키는데, 이를 처리하는 방법은 검증 부분에서 다룬다

 

참고로 @ModelAttribute는 생략 가능하다.

객체를 파라미터로 받고, 이를 처리하는 어떠한 애노테이션도 없다면,

Spring MVC에서 우선적으로 ModelAttributeMethodProcessor를 통해서 바인딩 할 수 있는지 체크하고,
@Primary가 적용된 생성자 > 파라미터를 많이 받는 생성자 순으로 생성자를 리턴해 바인딩할 객체를 생성한다.
그 후 resolveArgument()를 호출해서 파라미터를 객체에 바인딩하고, 그 외 바이딩되지 않은 값은 setter로 바인딩한다.

즉, setter가 없어도 파라미터를 받는 생성자가 있다면 바인딩 받을 수 있다.

 

@ModelAttribute에는 한 가지 기능이 더 있는데,
바로 모델(Model)에 @ModelAttribute 로 지정한 객체를 자동으로 넣어주는 것이다.
- key 값은 @ModelAttribute 에 지정한 name(value) 속성, 없으면 클래스명 첫자 소문자

[HTTP 메세지 바디 조회] - 단순 텍스트, JSON

HTTP BODY의 단순 텍스트 조회 - @RequestBody

 

헤더의 정보도 필요할 경우 - @HttpEntity 

  • HttpEntity(개체, 객체): HTTP header, body 정보를 편리하게 조회
  • 스프링MVC 내부에서 HTTP 메시지 바디를 읽어서 문자나 객체로 변환해서 전달해주는데, 이때 HTTP 메시지 컨버터( HttpMessageConverter )라는 기능을 사용
  • 응답에서도 HttpEntity 사용 가능 - 메시지 바디 정보 직접 반환
  • HttpEntity 를 상속받은 다음 객체들도 같은 기능을 제공 : RequestEntity, ResponseEntity

 

HTTP BODY의 JSON 조회 - @RequestBody

JSON 데이터는 주로 객체로 변환해서 쓴다.

@RequestBody로 조회한 JSON 데이터를 ObjectMapper 라이브러리를 이용해 객체로 변환하는 과정이 필요하다.

 

Spring은 이 귀찮은 과정을 지원해준다.

@RequestBody에 직접 만든 객체를 지정할 수 있다. by 메세지컨버터

HttpEntity, @RequestBody를 사용하면 HTTP 메시지 컨버터가 HTTP 메시지 바디의 내용을 문자나 객체 등으로 변환

참고로 @RequestBody는 생략 불가하다. 생략 시 @ModelAttribute로 동작하기 때문이다.
-> body에 setter로 넣을 파라미터가 없어 기본값으로 객체 생성됨.

 

응답 시에는 @ResponseBody를 사용하면 객체를 HTTP 메시지 바디에 직접 넣어줄 수 있다. by 메세지컨버터

 

 

 

 


 

참고 자료 & 이미지 출처
스프링 MVC 1편(김영한 님)