이번 글은 데브코스 Spring Boot REST API 실습 8강 내용을 정리한 글이다.
8강에서는 엔티티를 그대로 API 응답으로 반환하지 않고,
DTO(PostDto)를 도입하는 과정을 3단계 실습으로 나누어 진행했다.
이 강의의 핵심은
DTO를 “만드는 것”보다, DTO를 잘못 설계했을 때 어떤 문제가 발생하는지를
직접 경험하도록 하는 데 있다.
이전 강의(7강)까지는 컨트롤러에서 Post 엔티티를 그대로 반환했다.
return post;
이 방식의 문제점은 다음과 같다.
그래서 8강에서는
엔티티와 API 응답을 분리하기 위해 DTO를 도입한다.
PostDto 클래스 도입, JSON 응답 실패
먼저 PostDto 클래스를 만들고,
컨트롤러의 반환 타입을 Post → PostDto로 변경한다.
public class PostDto {
private int id;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
private String subject;
private String body;
public PostDto(Post post) {
this.id = post.getId();
this.createdDate = post.getCreateDate();
this.modifiedDate = post.getModifyDate();
this.subject = post.getTitle();
this.body = post.getContent();
}
}
@GetMapping("/{id}")
public PostDto getItem(@PathVariable int id) {
Post post = postService.findById(id).get();
return new PostDto(post);
}
하지만 조회 요청을 보내면
JSON 응답이 실패하거나 비어 있는 문제가 발생한다.
Jackson은 객체를 JSON으로 변환할 때
Java Bean 규약을 따른다.
즉, 기본적으로 다음 요소만 JSON 필드로 인식한다.
public getter 메서드public 필드하지만 첫 번째 PostDto는
private👉 Jackson 입장에서는
“외부로 노출 가능한 데이터가 하나도 없는 객체”로 보인다.
결과적으로 Jackson은 이 객체를
Empty Bean(빈 객체) 로 판단한다.
빈 객체라도 오류를 발생시키지 않도록 설정
spring:
jackson:
serialization:
fail-on-empty-beans: false
이 설정의 의미는 다음과 같다.
{}로 응답👉 에러는 사라지지만
👉 데이터는 여전히 내려오지 않는다
즉, 이는 근본적인 해결이 아니라 임시 회피에 불과하다.
PostDto에 @Getter 적용하여 JSON 정상 출력
@Getter
public class PostDto {
private int id;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
private String subject;
private String body;
public PostDto(Post post) {
this.id = post.getId();
this.createdDate = post.getCreateDate();
this.modifiedDate = post.getModifyDate();
this.subject = post.getTitle();
this.body = post.getContent();
}
}
@Getter를 적용하면 Lombok이 다음 메서드를 자동 생성한다.
getId()
getCreatedDate()
getModifiedDate()
getSubject()
getBody()
이제 Jackson은 getter를 통해 값을 읽을 수 있고,
JSON 응답도 정상적으로 생성된다.
실제 JSON 응답은 다음과 같이 출력된다.
{
"body": "내용 1",
"createdDate": "2025-12-21T01:47:02.82079",
"id": 1,
"modifiedDate": "2025-12-21T01:47:02.82079",
"subject": "제목 1"
}
하지만 PostDto의 필드 선언 순서는 다음과 같다.
private int id;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
private String subject;
private String body;
id가 맨 앞에 나오지 않는 이유는 무엇일까?
Jackson은 JSON을 생성할 때
자바 필드 선언 순서를 기준으로 하지 않는다.
기본적으로 Jackson은:
즉, 다음 이름들이
body
createdDate
id
modifiedDate
subject
사전순으로 정렬되어
현재와 같은 JSON 출력 결과가 나온다.
필요하다면 @JsonPropertyOrder를 사용해
명시적으로 순서를 지정할 수 있다.
@JsonPropertyOrder({
"id",
"subject",
"body",
"createdDate",
"modifiedDate"
})
@Getter
public class PostDto {
...
}
다만 실무에서는
JSON은 키 기반 접근이므로 순서를 크게 신경 쓰지 않는 경우가 많다.
fail-on-empty-beans=false는 임시 대응일 뿐이다8강은 DTO를 도입하는 과정에서
Jackson 직렬화 규칙과 DTO 설계의 중요성을 단계적으로 체험하는 강의였다.