Back-End (Web)/Spring

[Spring] @RequestParam & @ModelAttribute

JABHACK 2024. 12. 17. 13:31

쿼리 파라미터(Query Parameter)

📌 HTTP 요청 URL의 일부로, Key-Value 형태로 데이터를 전달하는 방법

  • 쿼리 파라미터는 URL 경로 끝에 **?**로 시작하며, 여러 개의 파라미터는 **&**로 구분됩니다.
구조
<URL>?<key1>=<value1>&<key2>=<value2>

 

특징

  1. 클라이언트가 서버로 데이터를 전달할 때 사용.
  2. GET 요청에서 주로 사용되며, 요청 URL에 데이터를 포함.
  3. 데이터가 URL에 노출되므로 민감한 정보를 보내는 데 적합하지 않음.
  4. 여러 파라미터를 전달할 수 있음.

 

 

HTML 폼 데이터(Form Data)

📌 HTML 폼(Form)을 통해 서버로 전달되는 Key-Value 형태의 데이터입니다.

  • 폼 데이터는 주로 POST 요청의 HTTP 요청 본문(body)에 포함됩니다.

 

구조

HTML 폼을 통해 데이터를 보낼 때, Key-Value 쌍으로 데이터를 전달합니다. 데이터는 HTTP 요청 본문에 포함되거나, GET 요청의 경우 쿼리 파라미터로 전송됩니다.

 

특징

  1. POST 요청에서 주로 사용되며, 데이터가 HTTP 요청 본문에 포함.
  2. GET 요청에서는 폼 데이터가 쿼리 파라미터로 전달.
  3. 데이터를 숨길 수 있으나, 민감한 데이터는 암호화(HTTPS) 필요.
  4. 주로 사용자 입력 데이터를 서버로 전달할 때 사용.

 

HTML 폼 예제

<form action="/submit" method="POST">
    <label for="name">Name:</label>
    <input type="text" id="name" name="name">
    
    <label for="email">Email:</label>
    <input type="email" id="email" name="email">
    
    <button type="submit">Submit</button>
</form>

 

POST 요청 본문 예시:

name=John&email=john.doe@example.com

 

Spring 컨트롤러에서 처리:

@PostMapping("/submit")
public String handleForm(
    @RequestParam String name,
    @RequestParam String email) {
    return "Name: " + name + ", Email: " + email;
}

 

 

쿼리 파라미터와 폼 데이터의 차이

  쿼리 파라미터 (Query Parameter) HTML 폼 데이터 (Form Data)
데이터 위치 URL 경로 끝 (쿼리 스트링) HTTP 요청 본문(body) 또는 URL 쿼리
주요 HTTP 메서드 GET POST (또는 GET)
노출 여부 데이터가 URL에 노출됨 POST 요청 시 URL에 노출되지 않음
사용 목적 짧고 간단한 데이터 전달 사용자 입력 데이터 전송
데이터 크기 제한 브라우저에 따라 URL 길이 제한 (2,000~8,000자) 요청 본문에 데이터를 보내므로 제한 없음
보안성 민감한 데이터 전달에 부적합 POST로 전달 시 상대적으로 안전 (HTTPS 권장)

 

 

예제 비교

쿼리 파라미터

GET /search?keyword=spring&category=books

 

폼 데이터

POST /submit
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

name=John&email=john.doe@example.com

 

결론

  • 쿼리 파라미터는 주로 GET 요청에서 사용되며, URL에 간단한 데이터를 전달.
  • 폼 데이터는 주로 POST 요청에서 사용되며, 대량의 사용자 입력 데이터를 서버로 보낼 때 적합.

 

 

 

@RequestParam

📌 HTTP 요청의 쿼리 파라미터(Query Parameter)나 HTML 폼 데이터(Form Data)를 컨트롤러 메서드의 매개변수로 매핑하는 데 사용됩니다. 주로 클라이언트가 요청 시 전달하는 Key-Value 형식의 데이터를 처리할 때 사용됩니다.

  • URL에서 파라미터 값과 이름을 함께 전달하는 방식으로 주로 HTTP 통신 Method 중 GET 방식의 통신을 할 때 많이 사용한다. @Requestparam을 사용하면 요청 파라미터 값에 아주 쉽고 간편하게 접근(Parameter Binding)할 수 있습니다.
  • ?뒤에 오는 URL을 Query String, Query Parameter, Request Param이라 합니다.
  • GET 요청에서 쿼리 파라미터를 처리하거나, POST 요청에서 폼 데이터를 처리하는 데 사용됩니다.

 

사용 목적

  • 쿼리 파라미터(Query Parameter):
    • URL에 포함된 Key-Value 형식의 데이터를 매핑.
    • 예: GET /api/search?keyword=spring
  • 폼 데이터(Form Data):
    • HTML 폼을 통해 전송된 데이터를 매핑.
    • 예: POST 요청 본문에 name=John&email=john.doe@example.com 데이터가 포함.

주요 속성

  설명 기본값
name 요청 파라미터의 이름을 명시. 매개변수 이름과 동일
required 요청 파라미터가 필수인지 여부. true
defaultValue 요청 파라미터가 없을 때 사용할 기본값. 없음

@RequestParam과 다른 어노테이션 비교

어노테이션 설명
@RequestParam 요청의 쿼리 파라미터 또는 폼 데이터를 매핑.
@PathVariable URL 경로의 변수 값을 매핑.
@RequestBody HTTP 요청 본문(body)의 데이터를 매핑 (JSON, XML 등).

 

주의 사항

  1. 필수 속성 처리:
    • 기본적으로 @RequestParam은 요청 파라미터가 없으면 에러를 발생시킵니다.
      필요한 경우 required = false를 명시하거나, defaultValue를 설정하세요.
  2. 타입 변환:
    • Spring은 문자열 값을 기본적으로 매핑하며, 필요한 경우 자동으로 타입 변환을 지원합니다.
      단, 변환할 수 없는 타입이 지정되면 예외가 발생합니다.

 

@Slf4j
@Controller
public class RequestParamControllerV2 {

	@ResponseBody
	@GetMapping("/v1/request-param")
	public String requestParamV1 (
					@RequestParam("name") String userName,
					@RequestParam("age") int userAge													
	) {
		// logic
		log.info("name={}", userName);
    log.info("age={}", userAge);
		return "success";
	}

}
  1. @Controller + @ResponseBody
    • View를 찾는 것이 아니라 ResponseBody에 응답을 작성한다(=@RestController)
  2. @RequestParam
    • 파라미터 이름으로 바인딩한다.
  3. @RequestParam(”속성값”)
    • 속성값이 파라미터 이름으로 매핑된다.

Postman
출력 결과

 

“속성값”과 변수명이 같으면 생략이 가능하다.

ex) @RequestParam("name") String name

// GET http://localhost:8080/v2/request-param?name=sparta&age=100
@ResponseBody
@GetMapping("/v2/request-param")
public String requestParamV2 (
				@RequestParam String name,
				@RequestParam int age													
) {
	// logic
	log.info("name={}", name);
  log.info("age={}", age);
	return "success";
}

 

 

 

 

@RequestParam 사용법

1. 어노테이션, 속성값 모두 생략

  • @RequestParam은 생략이 가능하다.
// GET http://localhost:8080/v3/request-param?name=sparta&age=100
@ResponseBody
@GetMapping("/v3/request-param")
public String requestParamV3 (
				String name,
				int age													
) {
	// logic
	log.info("name={}", name);
  log.info("age={}", age);
	return "success";
}
  • 생략하면 @RequestParam(required=false) 필수 여부 속성이 default로 설정된다.
  • 단, 요청 파라미터와 이름이 완전히 같아야 한다.
  • 단순 타입(int, String, Integer 등)이어야 한다.

 

위의 방식은 권장하지 않습니다. 명시적으로 표시되어있지 않으면 팀의 협의가 있지 않는 경우 다른 개발자들에게 혼동을 주게 됩니다. 최소 @RequestParam String name 속성 값 생략 형태를 쓰면 됩니다.

 

2. required 속성 설정

  • 파라미터의 필수 값을 설정한다.
  • API 스펙을 규정할 때 사용한다.
@ResponseBody
@GetMapping("/v4/request-param")
public String requestParam (
				@RequestParam(required = true) String name, // 필수
				@RequestParam(required = false) int age	// 필수가 아님										
) {
	// logic
	log.info("name={}", name);
  log.info("age={}", age);
	return "success";
}

 

  • @RequestParam을 사용하면 기본 Default값은 True이다.
    • True로 설정된 파라미터 값이 요청에 존재하지 않으면 400 BadRequest(클라이언트 측 에러)
  • Exception이 발생하지 않는 경우

ex) http://localhost:8080/v4/request-param?name=sparta&age=100

  • Exception이 발생하는 경우

ex) http://localhost:8080/v4/request-param?age=100

 

ex) http://localhost:8080/v4/request-param

  • required = false 설정이 되어있으면 해당 파라미터는 없어도 된다.
    • 주의! http://localhost:8080/v4/request-param?name=sparta 요청한다면?

  • 500 Error가 발생한다.
  • int Type에는 null을 넣을 수 없다. 0이라도 들어가야 한다.

 

따라서 보통 null을 허용하는 Integer로 사용하거나 default 옵션을 사용한다.

@ResponseBody
@GetMapping("/v4/request-param")
public String requestParam (
				@RequestParam(required = true) String name, // 필수
			  @RequestParam(required = false) Integer age										
) {
	// logic
	log.info("name={}", name);
  log.info("age={}", age);
	return "success";
}

 

  • 파라미터 Key값만 있고 Value가 없는 경우 http://localhost:8080/request-param?name=

  • null과 빈 문자열 “”은 다르다!
  • 위 형태는 빈 문자열 “” 로 인식한다, True지만 통과가 되어버린다. 주의해야 한다.

 

 

3. default 속성 적용

  • 파라미터의 기본 값을 설정한다.
@ResponseBody
@GetMapping("/v5/request-param")
public String requestParam (
				@RequestParam(required = true, defaultValue = "sparta") String name,
		    @RequestParam(required = false, defaultValue = "1") int age											
) {
	// logic
	log.info("name={}", name);
  log.info("age={}", age);
	return "success"	
}

 

  • name Parameter 의 값이 없으면 기본적으로 “sparta”으로 설정한다

ex) http://localhost:8080/v5/request-param?age=100

  • age Parameter의 값이 없으면 기본적으로 1 으로 설정한다.

ex) http://localhost:8080/v5/request-param?name=wonuk

ex) http://localhost:8080/v5/request-param

  • 주의! defaultValue 속성을 설정하게 되면 “” 빈 문자열의 경우에도 기본 값이 설정된다.

ex) http://localhost:8080/v5/request-param?name&age

 

4. Map 사용

  • Parameter를 Map형태로 조회가 가능하다.
@ResponseBody
@GetMapping("/v6/request-param")
public String requestParamV6(
        @RequestParam Map<String, String> map
) {
    // logic
    log.info("name={}", map.get("name"));
    log.info("age={}", map.get("age"));

    return "success";
}

 

  • Map 형태(key=value)로 조회가 가능하다

ex) http://localhost:8080/v6/request-param?name=sparta&age=100

  • MultiValueMap 형태(key=[value1, value2])로 조회가 가능하다.
@ResponseBody
@GetMapping("/v6/request-param")
public String requestParamV6(
        @RequestParam MultiValueMap<String, String> map
) {
    // logic
    log.info("name={}", map.get("name"));
    log.info("age={}", map.get("age"));

    return "success";
}
  • ex) http://localhost:8080/v6/request-param?
  • name=sparta&name=wonuk&name=tutor&age=100

💡 파라미터 Map의 Value가 1개인 경우에는 Map, 여러 개인 경우 MultiValueMap을 사용한다. 하지만 대부분의 파라미터 값은 한 개만 존재한다.

 

 

 

@ModelAttribute

📌 HTTP 요청 데이터(Form 데이터, 쿼리 파라미터 등)를 객체에 바인딩하거나, 뷰에 데이터를 전달하는 데 사용됩니다.

  • 요청 파라미터를 받아 필요한 Object로 바인딩 해준다. 주로 HTML 폼에서 전송된 데이터를 바인딩하고 HTTP Method POST인 경우 사용된다.
  • 매개변수에 사용: 요청 데이터를 객체로 매핑.
  • 메서드에 사용: 뷰에 공통 데이터를 추가.

 

주요 역할

1. 요청 데이터를 객체로 바인딩

  • 클라이언트에서 전달된 **요청 데이터(쿼리 파라미터, 폼 데이터)**를 자동으로 객체 필드에 바인딩합니다.
  • 주로 POST 요청의 폼 데이터를 처리할 때 사용됩니다.

2. 뷰(View)에 데이터 전달

  • 컨트롤러 메서드에서 반환 값이 아닌, 뷰에 데이터를 추가합니다.
  • 뷰에 공통적으로 전달해야 하는 데이터를 설정할 때 유용합니다.

 

 

특징 및 동작

1. 객체 생성 및 데이터 바인딩

  • Spring은 @ModelAttribute를 사용하면 다음 단계를 수행합니다:
    1. 지정된 클래스의 객체를 생성합니다.
    2. 요청 데이터(쿼리 파라미터, 폼 데이터)를 객체 필드에 매핑합니다.

2. 요청 방식에 따른 동작

  • GET 요청: 객체를 초기화하거나 뷰에 데이터를 전달.
  • POST 요청: 폼 데이터를 객체에 바인딩.

3. 생략 가능

  • @ModelAttribute는 생략 가능하며, 매개변수가 사용자 정의 객체라면 Spring이 자동으로 @ModelAttribute를 적용합니다.

 

주요 속성

  설명
value @ModelAttribute("name") 형식으로 모델 객체의 이름을 지정.
뷰에 데이터 전달 메서드에 사용하면 데이터를 뷰에 전달.
객체 바인딩 매개변수에 사용하면 요청 데이터를 객체에 자동 바인딩.

 

 

주의 사항

  1. 필드 이름 매칭:
    • 요청 데이터의 Key와 객체 필드 이름이 동일해야 바인딩됩니다.
    • Key와 필드 이름이 다르면 바인딩되지 않습니다.
  2. 유효성 검증:
    • @Valid와 함께 사용하여 요청 데이터를 검증할 수 있습니다
  3. 중복 데이터 처리:
    • 동일한 이름의 데이터를 여러 메서드에서 설정하면, 마지막으로 설정된 데이터가 우선합니다.
@PostMapping("/register")
public String registerUser(@Valid @ModelAttribute User user, BindingResult result) {
    if (result.hasErrors()) {
        return "form";
    }
    return "success";
}

 

 

기존 코드

@Data는 @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructer를 자동으로 설정해주는 역할을 한다. 테스트 용도로만 사용하고 실무에서는 잘 사용하지 않는다.

 

  • ex) http://localhost:8080/v1/tutor + x-www-form-urlencoded
@Data
public class Tutor {

	private String name;
	private int age;

}

@Controller
public class ModelAttributeController {

	@ResponseBody
  @PostMapping("/v1/tutor")
  public String requestParamV1(
          @RequestParam String name,
          @RequestParam int age
  ) {
      Tutor tutor = new Tutor();
      tutor.setName(name);
      tutor.setAge(age);

      return "tutor name = " + name + " age = " + age;
  }

}

 

  • @RequestParam 의 Mapping을 사용하게 되면 위와 같은 객체를 생성하는 코드가 포함된다.
    • @ModelAttribute 는 해당 과정을 자동화 한다.
  • Postman
POST /v1/tutor
content-type: application/x-www-form-urlencoded

name=wonuk&age=100

 

 

@ModelAttribute 적용

  • ex) http://localhost:8080/v2/tutor+ x-www-form-urlencoded
@ResponseBody
@PostMapping("/v2/tutor")
public String modelAttributeV2(
				@ModelAttribute Tutor tutor													
) {
		
	String name = tutor.getName();
	int age = tutor.getAge();

	return "tutor name = " + name + " age = " + age;
}
  • Postman
POST /v2/tutor
content-type: application/x-www-form-urlencoded

name=wonuk&age=100

 

  • @ModelAttirubte 동작 순서
    1. 파라미터에 @ModelAttribute가 있으면 파라미터인 Tutor 객체를 생성한다.
    2. 요청 파라미터 이름으로 객체 필드의 Setter를 호출해서 바인딩한다.
      1. 파라미터 이름이 name 이면 setName(value); 메서드를 호출한다.
      2. 파라미터 이름과 필드 이름이 반드시 같아야 한다!
  • @Data의 Setter가 없다면?
@Getter
public class Tutor {

	private String name;
	private int age;

}

  • 객체 필드에 값이 set되지 않는다.

 

  • 파라미터의 타입이 다른 경우
    • 만약 요청 파라미터 age 에 int가 아닌 String 이 전달된다면?
    ex) http://localhost:8080/v2/tutor+ x-www-form-urlencoded
POST /v2/tutor
content-type: application/x-www-form-urlencoded

name=wonuk&age=nbcamp

  • BindException 발생
  • 이런 경우 때문에 **Validation(검증)**이 필요하다.

 

@ModelAttirubte 생략

  • @ModelAttribute와 지난 시간에 배운 @RequestParam은 모두 생략이 가능하다.

ex) http://localhost:8080/v3/tutor+ x-www-form-urlencoded

POST /v3/tutor
content-type: application/x-www-form-urlencoded

name=wonuk&age=100
@ResponseBody
@PostMapping("/v3/tutor")
public String modelAttributeV3(Tutor tutor) {

	String name = tutor.getName();
	int age = tutor.getAge();

	return "tutor name = " + name + " age = " + age;
}
  • Spring에서는 @RequestParam이나 @ModelAttribute가 생략되면
    • String, int, Integer 와 같은 기본 타입은 @RequestParam과 Mapping한다. V4
@ResponseBody
@PostMapping("/v4/tutor")
public String requestParamV2(
        String name,
        int age
) {
    return "tutor name = " + name + " age = " + age;
}

 

  • 나머지 경우들(객체)은 모두 @ModelAttribute 와 Mapping한다. V3

 

 

@RequestParam vs @ModelAttribute 차이

 

주요 차이점

  @RequestParam @ModelAttribute
목적 특정 **단일 파라미터(쿼리 파라미터, 폼 데이터)**를 매핑. 요청 데이터를 객체 형태로 매핑.
대상 데이터 단일 Key-Value 쌍 (예: ?key=value) 여러 Key-Value 쌍을 객체의 필드에 매핑.
적용 대상 개별 매개변수. 객체.
데이터 출처 쿼리 파라미터, 폼 데이터. 폼 데이터, 쿼리 파라미터, 경로 변수 등.
기본값 설정 defaultValue 속성을 통해 가능. 객체 필드에 기본값을 설정하거나, 빈 객체 생성.
뷰 데이터 전달 뷰 데이터 전달 기능 없음. 뷰에 데이터를 전달할 수 있음 (메서드 레벨 사용).
생략 가능 여부 생략 불가능 (명시적으로 사용해야 함). 매개변수에서 생략 가능 (Spring이 자동으로 객체를 매핑).
주요 사용 사례 단순 쿼리 파라미터 또는 단일 데이터 처리. 폼 데이터나 복잡한 데이터 구조(객체) 처리.

 

사용 목적에 따른 선택

@RequestParam

  • 요청 데이터가 단순한 Key-Value 쌍이고, 각각 개별적으로 처리할 경우.
  • 쿼리 파라미터나 단일 폼 데이터 값에 적합.

@ModelAttribute

  • 요청 데이터가 객체로 표현 가능한 경우.
  • 복잡한 폼 데이터(여러 필드가 있는 객체)를 처리하거나, 뷰와 데이터를 쉽게 연동할 때 유리.

 

요약

상황 선택
단일 쿼리 파라미터 처리. @RequestParam
복잡한 폼 데이터를 객체로 매핑. @ModelAttribute
기본값 설정이 필요한 경우. @RequestParam
뷰에 데이터를 전달해야 하는 경우. @ModelAttribute
객체 기반 데이터 처리가 필요한 경우. @ModelAttribute

 

결론

  • **@RequestParam**은 단일 데이터(Key-Value) 처리에 적합하며, 간단한 요청에 사용됩니다.
  • **@ModelAttribute**는 폼 데이터나 요청 데이터를 객체 형태로 처리하거나, 뷰와 연동된 데이터를 전달할 때 유용합니다.
  • @RequestParam, @ModelAttribute는 GET + Query Parameter와, POST HTML Form Data를 바인딩하는 방법이다.

 

HTTP Message Body (요청)

📌 HTTP 요청(Request) 또는 응답(Response)에서 실제 데이터를 담는 부분입니다.

  • 주로 클라이언트와 서버 간에 전송되는 JSON, XML, HTML, 바이너리 파일, 텍스트 등 다양한 콘텐츠를 포함합니다.

 

특징

  • 이제부터 배울 내용은 HTTP Message Body에 직접적으로 Data가 전달되는 경우이다.
    • Request Body의 Data를 바인딩하는 방법이다.
  • REST API에서 주로 사용하는 방식이다.
  • HTTP Method POST, PUT, PATCH에서 주로 사용한다.
    • GET은 Request Body가 존재할 수는 있지만 권장하지 않는다.
  • JSON, XML, TEXT 등을 데이터 형식으로 사용한다.

 

 

HTTP Message 구조

 

 

HTTP Request, Response 예시

  • Server에서 Request로 전달받은 Data를 처리하기 위해서 바인딩 해야 한다.

ex) JSON → Object

 

 

 

TEXT

📌  HTTP Request Body에 Data가 전송되는 경우 HttpMessageConverter를 통해 바인딩된다.

  • 현대에는 Restful API를 주로 사용하고 있어서 대부분의 경우 JSON 형식으로 통신한다.

 

HttpServletRequest 예시

  • request.getInputStream();
@Slf4j
@Controller
public class RequestBodyStringController {
	
	@PostMapping("/v1/request-body-text")
  public void requestBodyTextV1(
          HttpServletRequest request,
          HttpServletResponse response
  ) throws IOException {

      ServletInputStream inputStream = request.getInputStream();
      String bodyText = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
      
      response.getWriter().write("response = " + bodyText);

  }

}
  • Request → Body → raw → Text

  • Request Header Content-Type : text/plain

 

I/O 예시

  • InputStream(읽기) 파라미터 지원
    • HTTP Request Body Data 직접 조회
  • OutputStream(쓰기) 파라미터 지원
    • HTTP Response Body 직접 결과 출력
@PostMapping("/v2/request-body-text")
public void requestBodyTextV2(
				InputStream inputStream,
				Writer responseWriter
) throws IOException { 
		
	String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
	
	responseWriter.write("response = " + bodyText);
}

Postman

HttpEntity 예시

  • HttpMessageConverter 사용
  • HttpEntity를 사용하면 HttpMessageConverter를 사용한다.
@PostMapping("/v3/request-body-text")
public HttpEntity<String> requestBodyTextV3(HttpEntity<String> httpEntity) { 
		
	// HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
	String body = httpEntity.getBody();
		
	return new HttpEntity<>("response = " + body); // 매개변수 = Body Message
	
}

 

Postman

  • Spring의 HttpMessageConverter 덕분에 간편하게 Request Data에 접근할 수 있다.
    1. HttpEntity를 사용하면 HttpMessageConverter가 동작하여 자동으로 매핑된다.
    2. 요청 뿐만이 아닌 응답까지 HttpEntity 하나만으로 사용이 가능해진다.

 

 

HttpEntity

📌 HTTP 요청(Request)와 응답(Response)의 헤더(Header)와 본문(Body)을 캡슐화하는 데 사용됩니다.

  • HttpEntity는 HTTP Header, Body 정보를 편리하게 조회할 수 있도록 만들어준다.

 

주요 특징

  • 헤더(Header)와 바디(Body) 모두를 포함:
    • HTTP 요청 또는 응답의 헤더와 바디를 관리.
  • Immutable 객체:
    • HTTP 메시지를 불변(Immutable) 상태로 다룸.
  • Spring의 HTTP 클라이언트와 서버 모두에서 사용 가능:
    • REST API 호출에서 요청을 보낼 때, 응답 데이터를 받을 때 활용.

 

HttpEntity 역할

  1. Http Request Body Message를 직접 조회한다
  2. Request 뿐만 아니라 Response도 사용할 수 있도록 만들어준다.
  3. Response Header 또한 사용할 수 있다.
  4. Request Parameter를 조회하는 기능들과는 아무 관계가 없다.
  5. View를 반환하지 않는다.

 

주요 클래스

HttpEntity는 Spring에서 두 가지 주요 클래스의 기반이 됩니다:

  1. RequestEntity:
    • HTTP 요청을 표현.
    • 요청의 헤더, URL, HTTP 메서드 등을 캡슐화.
    • HTTP Request Method, URL 정보가 추가 되어있다.
  2. ResponseEntity:
    • HTTP 응답을 표현.
    • 응답의 상태 코드, 헤더, 바디를 관리.
    • HTTP Response 상태 코드 설정이 가능하다.
@Controller
public class RequestBodyStringController {
	
	@PostMapping("/v4/request-body-text")
  public HttpEntity<String> requestBodyTextV4(RequestEntity<String> httpEntity) {

      // HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
      String body = httpEntity.getBody();
      // url, method 사용 가능

      return new ResponseEntity<>("response = " + body, HttpStatus.CREATED); // Body Data, 상태코드
  }

}

 

Postman

  • 위 방법을 적용해도 불편하다.
    • Data를 httpEntity에서 꺼내어 사용해야 한다.
Spring은 Http RequestBody Message를 읽어서 String이나 Object로 자동으로 변환해준다. 이때 HttpMessageConverter가 사용된다. 

 

 

@RequestBody, @ResponseBody

📌 Spring에서 @RequestBody, @ResponseBody 어노테이션을 사용하면 각각 Request, Response 객체의 Body에 편하게 접근하여 사용할 수 있다.

@Controller // @RestController = @Controller + @ResponseBody
public class RequestBodyStringController {
	
  @ResponseBody
  @PostMapping("/v5/request-body-text")
  public String requestBodyTextV5(
          @RequestBody String body,
          @RequestHeader HttpHeaders headers
  ) {
      // HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
      String bodyMessage = body;

      return "request header = " + headers + " response body = " + bodyMessage;
  }
}

Postman

  • @RequestBody
    • 요청 메세지 Body Data를 쉽게 조회할 수 있다.
  • @RequestHeader
    • 요청 헤더 정보 조회
  • @ResponseBody
    • 응답 메세지 바디에 값을 쉽게 담아서 전달할 수 있도록 해준다.
    • View가 아닌 데이터를 반환한다.

 

요약

  1. 요청 파라미터, HTML Form Data에 접근하는 경우
    • @RequestParam, @ModelAttribute 를 사용한다.
  2. Http Message Body에 접근하는 경우
    • @RequestBody를 사용한다. (JSON, XML, TEXT)

 

 

HTTPMessageConverter

📌 HTTP 요청과 응답의 본문(Body)을 Java 객체와 직렬화 가능한 데이터(JSON, XML, 텍스트 등)로 변환하는 역할을 합니다.

  • Spring MVC는 클라이언트와 서버 간 데이터를 효율적으로 교환하기 위해 HTTPMessageConverter를 사용합니다.
  • MappingJackson2HttpMessageConverter는 JSON을 처리하는 대표적인 HTTPMessageConverter의 구현체이다.

 

HttpMessageConverter의 역할

  • 데이터를 Obejct로 변환한다. 대표적으로 JSON을 변환한다.

 

  1. 요청 본문 → Java 객체 변환 (@RequestBody 사용 시):
    • HTTP 요청의 JSON, XML, 텍스트 데이터를 Java 객체로 변환합니다.
  2. Java 객체 → 응답 본문 변환 (@ResponseBody 사용 시):
    • Java 객체를 JSON, XML, 텍스트 등으로 직렬화하여 클라이언트로 전송합니다.

 

 

  • @RequestBody
    • 요청 데이터 + Request Header를 참고하여 Object로 변환한다.
      • HTTP Request Body(JSON Data) → Converter(Jackson) → Object
      • Reqeust Header → Content-Type : application/json(전달할 데이터 형식)
  • @ResponseBody
    • 응답 데이터 + Accept Header를 참고하여 원하는 데이터 형식으로 변환한다.
      • Object → Converter(Jackson) → HTTP Response Body(JSON Data)
      • Request Header → Accept : application/json(허용할 데이터 형식)

 

동작 원리

Spring MVC는 요청과 응답 처리 시 다음 과정을 수행합니다:

  1. 요청 처리:
    • 클라이언트가 HTTP 요청 본문에 데이터를 포함시켜 보냅니다.
    • Spring은 HttpMessageConverter를 사용하여 요청 데이터를 Java 객체로 변환.
  2. 응답 처리:
    • 컨트롤러에서 반환한 Java 객체를 HttpMessageConverter가 JSON, XML 등으로 직렬화하여 응답 본문에 포함.

 

주요 HTTPMessageConverter 구현체

Spring은 다양한 데이터 형식에 따라 여러 HttpMessageConverter 구현체를 제공합니다:

구현체 데이터 형식 설명
MappingJackson2HttpMessageConverter JSON Jackson 라이브러리를 사용하여 JSON 변환 처리.
GsonHttpMessageConverter JSON Gson 라이브러리를 사용하여 JSON 변환 처리.
Jaxb2RootElementHttpMessageConverter XML JAXB를 사용하여 XML 변환 처리.
StringHttpMessageConverter Plain Text 문자열 데이터를 처리.
FormHttpMessageConverter Form Data (application/x-www-form-urlencoded) HTML 폼 데이터를 처리.
ByteArrayHttpMessageConverter Binary Data (byte[]) 바이너리 데이터를 처리.

 

장점

  1. 자동화:
    • 요청과 응답 데이터를 자동으로 변환하여 개발자의 부담을 줄임.
  2. 유연성:
    • JSON, XML, Plain Text 등 다양한 데이터 형식을 지원.
  3. 확장 가능성:
    • 사용자 정의 HttpMessageConverter로 맞춤형 데이터 처리 가능

 

요약

  • **HttpMessageConverter**는 HTTP 요청 및 응답의 본문 데이터를 처리하는 Spring의 핵심 컴포넌트입니다.
  • 요청 데이터를 Java 객체로 변환하거나, Java 객체를 JSON, XML 등으로 변환하여 클라이언트에 전달합니다.
  • Spring은 JSON 변환을 기본적으로 지원하며, 필요에 따라 사용자 정의 구현체를 추가할 수 있습니다.

'Back-End (Web) > Spring' 카테고리의 다른 글

[Spring] Server에서 Client로 Data를 전달하는 방법  (0) 2024.12.19
[Spring] HTTP Message Body & TEXT  (0) 2024.12.18
[Spring] Request Mapping  (1) 2024.12.16
[Spring] Spring Annotation  (1) 2024.12.15
[Spring] Spring MVC 패턴  (1) 2024.12.14