Request Data Mapping

이강현·2025년 9월 24일

HTTP 요청으로 데이터를 전달하는 방식과,
그에 맞는 Spring Framework 의 애너테이션을 정리합니다

HTTP 요청 전달 방식

1. Path Variable(경로 변수)

URI 에 데이터를 담아 요청을 보낼 때, 그 데이터를 Path Variable(경로 변수) 라고 합니다.
주로 리소스의 식별자 성격의 데이터를 경로 변수로 사용합니다.
REST 의 리소스 중심적 설계 특성에 잘 어울리는 방식입니다.
Statelessness 와 URL 이 직관적이라는 장점 또한 얻을 수 있습니다.

2. Query Parameter

URI 뒤에 ? 이후에 key=value 형식으로 데이터를 담아 요청을 보낼 때, 그 데이터를 Query Parameter 라고 합니다.
주로 리소스에 접근할 때 적용할 정렬 조건이나 필터링 조건을 Query parameter 로 사용합니다.
& 를 구분자로 사용하여 여러개의 Query Parameter 를 전달할 수 있으며, 같은 key 를 사용하면 리스트로 데이터를 전달할 수도 있습니다.

3. Request Body(요청 본문)

요청의 구성요소 3가지 라인, 헤더, 본문 중에 본문에 데이터를 담아 요청을 보내는 방식입니다.
주로 URL 에 노출하면 안되는 민감한 정보들이나 복잡한 구조를 가지는 데이터를 한번에 전송하기 위해 사용합니다.
HTML 의 form 테그를 사용하는 웹 폼 데이터나 XML 은 더이상 잘 사용하지 않고, JSON 형식이 가장 널리 사용됩니다.
특수하게 파일같이 다른 형태의 데이터를 요청에서 함께 다루어야 할 때 Multipart 형식을 사용합니다.

Spring Framework 애너테이션

1. @PathVariable

org.springframework.web.bind.annotation 의 @PathVariable 애너테이션은 @RequestMapping 애너테이션에서 명시한 경로 변수가 메서드의 어느 매개변수로 매핑되어야 하는지 지정해줍니다.
기본적으로 변수명을 통해 매핑하며, 애너테이션의 name 요소에 이름을 직접 지정할 수도 있습니다.
특정 조건에서 생략 가능하나, 명시해 주는 것이 좋습니다.

2. @RequestParam

org.springframework.web.bind.annotation 의 @RequestParam 애너테이션은 단 하나의 Query Parameter 가 메서드의 어느 매개변수로 매핑되어야 하는지 지정해줍니다.
다음과 같은 요소로 추가 설정을 해줄 수 있습니다:
defaultValue: 해당 key 로 Query Parameter 를 전달 받지 않았다면 사용할 기본값
name: 매핑의 기준이 되는 key 값
required: 필수 요소인지 여부(기본값 true, false 라면 NPE 위험이 있음, defaultValue 가 있다면 그것을 사용)
매개변수가 Java 의 String 클래스나 primitive 타입과 그에 해당하는 wrapper 클래스라면 애너테이션이 생략되었을 때 @RequestParam 으로 간주합니다.
그외의 사용자 정의 클래스라면 @ModelAttribute 로 간주합니다.

3. @ModelAttribute

org.springframework.web.bind.annotation 의@ModelAttribute 애너테이션은 Query Parameter, 경로변수, 요청 헤더 등을 하나의 객체로 바인딩 해준다고 설명하고 있습니다.
그러나 다른 방식들에서 명확한 역할을 하는 애너테이션이 있기 때문에 @ModelAtrribute 는 여러개의 Query Parameter 를 하나의 객체로 묶어서 다루는 용도로 주로 사용합니다.
앞서 설명했듯이 매개변수가 사용자 정의 클래스라면 생략되었을 때 @ModelAttribute 로 간주합니다.
이렇게 Query Parameter 를 하나의 객체로 묶어서 다루게 되면, @RequestParam 과는 다른 방식으로 기본값이나 필수여부를 설정해야 합니다:
기본값: Java 의 필드변수 초기화 방식을 사용(생성자 호출 시점에 초기화 됨)
필수 여부: @Valid 애너테이션과 함께 사용하여 적절한 애너테이션을 멤버 변수에 적용

4. @RequestBody

Annotation Interface RequestBody 의 @RequestBody 애너테이션은 요청 본문의 데이터를 객체로 매핑해줍니다.
앞서 설명했듯이 애너테이션을 생략한다면 사용자 정의 클래스인 DTO 는 @ModelAttribute 로 간주됩니다.
따라서 @RequestBody 는 생략될 수 없습니다.

⚠️ @RequestBody 의 데이터 바인딩 방식은 @ModelAttribute 와 다릅니다.
@RequestBody 는 요청 본문의 데이터 형식(JSON, XML ...)에 맞는 데이터 바인더를 찾아 사용합니다.
많이 사용하는 JSON 의 경우 Spring 은 기본적으로 jackson-databind 를 사용합니다.
여기서 차이가 발생하는데, Spring 에서 제공하는 @ModelAttribute 매개변수를 하나 이상 가지고있는 생성자 혹은, 기본생성자와 setter 조합으로 데이터를 바인딩합니다.
그러나 jackson-databind 는 Java 의 Reflection API 를 사용하여 데이터를 바인딩합니다.
따라서 요청 본문이 매핑될 객체는 기본 생성자만 public(이마저도 선언하지 않아도 Java 가 자동 생성) 이라면 데이터 바인딩에 성공합니다.
그러나 Query Parameter 의 묶음이 될 객체는 Reflection 없이 객체를 초기화할 방법이 없다면 Spring 역시 데이터 바인딩에 실패합니다.

⚠️ @ParameterObject

io.swagger.v3.oas.annotations 의 @ParameterObject 는 swagger API 문서를 보기좋게 만들어 주는 기능을 합니다.
사용자 정의 클래스인 매개변수에 이 애너테이션을 붙인다 한들 매핑해주는 기능은 없습니다.
그러나 매핑이 되는 이유는 앞서 설명했듯이 @ModelAttribute 가 생략되었다고 간주하기 때문입니다.
만일 @RequestBody 로 지정해야 한다면 두 애너테이션을 함께 사용해야 합니다.
@ParameterObject 는 문서에서 JSON 형식의 입력이 아니라 객체 내의 매핑될 필드를 풀어서 문서를 작성합니다.

정리

데이터 전달 방식

방식데이터 성격목적예시
Path Variable리소스 식별자특정 리소스 하나를 조회, 수정, 삭제/posts/{postId}
Query Parameter정렬/필터링 옵션리소스 목록을 검색하거나 정렬/posts?status=published
Request Body리소스의 내용리소스를 생성하거나 수정할 때의 데이터POST /posts

Spring 애너테이션

애너테이션전달 방식상황
@PathVariablePath Variable경로변수를 매개변수로 매핑
@ReqeustParamQuery Parameter단일 Query Parameter 를 매개변수로 매핑
@ModelAttributeQuery Parameter여러개의 Query Parameter 를 묶어서 하나의 객체로 매핑
@RequestBodyRequest Body요청 본문의 데이터를 객체로 매핑

참고자료:
https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/requestbody.html#page-title
https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.html#page-title
https://docs.spring.io/spring-framework/reference/core/validation/beans-beans.html#beans-binding
https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/requestparam.html#page-title
https://docs.spring.io/spring-framework/docs/current/javadoc-api/index.html

profile
백엔드 개발자 지망생입니다.

0개의 댓글