들어가며
웹 애플리케이션 개발에서 클라이언트(프론트엔드)와 서버(백엔드)는 서로 정보를 주고 받는다. 이때 클라이언트는 보통 JSON(Javascript Object Notation) 형태로 데이터를 전송한다. 그러나, 서버 특히 자바 기반의 스프링 서버는 이러한 정보를 JSON 문자열이 아닌, 자바 객체 형태로 처리해야 한다.
클라이언트 JSON 데이터를 서버의 자바 객체로, 또는 그 반대로 변환하는 과정은 웹 API의 핵심이다. 이 복잡하지만 필수적인 '통역' 작업을 스프링에서는 `@RequestBody` 어노테이션과 `ObjectMapper`의 역할이 중요하다.
@RequestBody
클라이언트(프론트)가 HTTP Body에 JSON 형식의 데이터를 담아 서버로 전송할 때, Spring Controlle에서 `@RequestBody` 어노테이션은 이 JSON 형식의 데이터를 원하는 자바 객체 (DTO)로 변환해주는 역할을 한다.
이 어노테이션이 없다면 개발자는 HTTP 요청의 Body에서 직접 JSON 문자열을 꺼내어 파싱하고 필드별로 객체에 값을 설정하는 번거로운 작업을 수동으로 해야 했을 것이다.
✅ 요청 처리 흐름의 핵심 경로
1) `HandlerMethodArgumentResolver` : 요청을 처리할 적절한 핸들러 메서드가 결정된 후, 메서드의 각 인자를 처리할 `ArgumentResolver`가 호출된다. `@RequestBody`가 붙은 인자는 `RequestResponseBodyMethodProcessor`에 의해 처리된다.
2) `RequestResponseBodyMethodProcessor` : 이 프로세서는 HTTP Body를 읽어 들이고, 이 Body의 내용을 자바 객체로 변환하기 위해 `HttpMessageConverter` 인터페이스에게 작업을 위임한다.
HttpMessageConverter
Spring에서는 이 변환 작업을 수행하기 위해 내부적으로 `HttpMessageConverter` 라는 핵심 인터페이스를 사용한다. 이름 그대로 HTTP 메시지(요청 또는 응답)를 자바 객체로 변환하거나 그 반대의 작업을 수행하는 역할을 한다.
✅ 컨버터 선택 및 작동 원리
`RequestResponseBodyMethodProcessor`는 요청 Body의 JSON String을 읽어 들인 후, 등록된 여러 컨버터 중 다음 기준에 따라 적절한 컨버터를 선택한다.
1) 지원 여부 확인 : 현재 컨버터가 해당 미이더 타입과 대상 자바 클래스를 처리할 수 있는지 확인한다.
2) 기본 컨버터 : Spring Boot는 JSON 처리를 위해 `MappingJackson2HttpMessaageConverter`를 기본적으로 사용하도록 자동 구성된다.
Jackson의 ObjectMapper
`MappingJackson2HttpMessageConverter`가 JSON 변환을 담당하는 Spring의 겉모습이라면, 그 내부에서 실제 직렬화와 역직렬화를 수행하는 것은 Jackson 라이브러리의 핵심 클래스인 `ObjectMapper`이다.
✅ ObjectMapper의 역할
`ObjectMapper`는 자바 객체와 JSON 데이터 간의 직렬화 및 역직렬화를 처리하는 Jackson 라이브러리의 핵심 클래스이다.
- 역직렬화 (Deserialization) : JSON -> Java Object
- `@RequestBody`가 작동할 때 발생한다.
- 클라이언트가 보낸 JSON 문자열 ObjectMapper가 읽고, 개발자가 지정한 자바 객체의 필드에 대응하는 값을 찾아 넣어 객체를 생성한다.
- 직렬화 (Serialization) : Java Object -> JSON
- `@RequestBody`나 `@RestController`에서 자바 객체를 리턴할 때 발생한다.
- 서버가 처리한 자바 객체를 ObjectMapper가 읽고, 클라이언트에게 응답하기 위한 JSON 문자열로 변환한다.
'Spring' 카테고리의 다른 글
| [Spring] JDBC(Java Database Connectivity) (0) | 2025.12.20 |
|---|---|
| [Spring] 액츄에이터 (Actuator) (0) | 2025.12.18 |
| [Spring] Spring AI와 LangChain4j 비교 (0) | 2025.11.24 |
| [Spring] 임베디드 타입 (@Embeddable, @Embedded) (0) | 2025.11.10 |
| [Spring] Lombok 이해하기 - @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor (0) | 2025.11.04 |
