[CS 지식] Spring HTTP 응답 직렬화
HTTP Response에 객체를 넣었을 때 JSON으로 직렬화 하는 방법
Controller를 구현할 때 HTTP Response Body를 채우는 과정에 궁금증이 생겨서 포스트를 작성하게 되었다.
API를 구현하면 보통 JSON 형식으로 HTTP 응답을 보낸다.
이때, ResponseEntity<>를 주로 사용하는데 <> 제너릭에 객체를 집어넣으면 자동으로 JSON으로 직렬화해서 HTTP 응답을 보내준다.
근데 가끔 JSON으로 직렬화가 안될 때가 있다.
이유가 무엇일까? 우선 HTTP Response를 보낼 때 주로 사용하는 방법을 알아보자.
■ HTTP 응답 방식
1. @ResponseBody 또는 @RestController
@ResponseBody를 메서드 레벨에 사용하거나, 클래스 레벨에@RestController를 붙이면 메서드의 반환값이 자동으로 JSON으로 직렬화됨.- Spring은 Jackson(ObjectMapper)을 사용하여 Java 객체를 JSON으로 변환함.
예제:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
public class MyController {
@GetMapping("/example")
public MyResponse getExample() {
return new MyResponse("example", 123);
}
}
class MyResponse {
private String name;
private int value;
// 생성자, getter, setter
}
2. ResponseEntity
- 응답의 HTTP 상태 코드, 헤더, 바디를 명시적으로 제어하고 싶을 때 사용.
ResponseEntity<T>를 사용하면 T가 JSON으로 직렬화됨.
예제:
1
2
3
4
5
@GetMapping("/response-entity")
public ResponseEntity<MyResponse> getResponseEntity() {
MyResponse response = new MyResponse("response", 456);
return ResponseEntity.ok(response);
}
ResponseEntity<?>를 사용하면 다양한 응답 타입을 처리할 수 있음. 상황에 따라 객체, 문자열, 리스트 등을 반환 가능.
예제:
1
2
3
4
5
6
7
8
@GetMapping("/generic-response")
public ResponseEntity<?> getGenericResponse(@RequestParam boolean returnObject) {
if (returnObject) {
return ResponseEntity.ok(new MyResponse("generic", 789));
} else {
return ResponseEntity.ok("This is a plain text response");
}
}
■ 직렬화 실패의 원인
직렬화가 실패하는 일반적인 원인은 다음과 같다.
-
Getter가 없음: Jackson은 기본적으로 getter 메서드를 통해 필드에 접근함. 필요한 getter가 없으면 해당 필드가 JSON에 포함되지 않음.
-
필드가
transient또는static: Jackson은 기본적으로transient또는static필드를 직렬화하지 않음. -
순환 참조: 객체 간의 순환 참조가 존재하면
StackOverflowError가 발생할 수 있음. -
Jackson이 지원하지 않는 타입: 특정 타입(Java 객체)이 기본적으로 JSON으로 변환될 수 없는 경우. (예:
Optional,Object타입)
■ 정리
| 사용법 | 직렬화 동작 | 사용 목적 |
|——————-|———————–|——————————–|
| @ResponseBody | 자동 JSON 직렬화 | 간단한 응답 생성 |
| @RestController | 자동 JSON 직렬화 | API 개발 시 주로 사용 |
| ResponseEntity | 자동 JSON 직렬화 (직접 제어 가능) | 상태 코드, 헤더 제어 필요할 때 |
| ResponseEntity<?> | 동적 응답 처리 가능 | 응답 타입이 상황에 따라 달라질 때 |