Spring Boot로 REST API를 개발하면 ResponseDto부분에서 필요한 부분을 리스트 형식으로 가져오는지
어떻게 가져올지 고민을 하는데 이번에는 중첩 DTO를 사용해보았다.
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TrainerReservationResponseDto {
private Long reservationId;
private LocalDate reservationDate;
private LocalTime reservationTime;
private ReservationStatus status;
private GymInfo gym;
private UserInfo user;
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class GymInfo {
private Long gymId;
private String name;
private String address;
private String number;
}
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class UserInfo {
private Long userId;
private String name;
private String email;
private String phone;
}
}
{
"reservationId": 1,
"reservationDate": "2025-06-01",
"reservationTime": "15:00",
"status": "CONFIRMED",
"gym": {
"gymId": 1,
"name": "피트니스센터",
"address": "서울시 강남구",
"number": "02-1234-5678"
},
"user": {
"userId": 1,
"name": "홍길동",
"email": "hong@example.com",
"phone": "010-1234-5678"
}
}
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TrainerReservationFlatDto {
private Long reservationId;
private LocalDate reservationDate;
private LocalTime reservationTime;
private ReservationStatus status;
// Gym 정보
private Long gymId;
private String gymName;
private String gymAddress;
private String gymNumber;
// User 정보
private Long userId;
private String userName;
private String userEmail;
private String userPhone;
}
{
"reservationId": 1,
"reservationDate": "2025-06-01",
"reservationTime": "15:00",
"status": "CONFIRMED",
"gymId": 1,
"gymName": "피트니스센터",
"gymAddress": "서울시 강남구",
"gymNumber": "02-1234-5678",
"userId": 1,
"userName": "홍길동",
"userEmail": "hong@example.com",
"userPhone": "010-1234-5678"
}
구분 | 중첩 DTO | Flat DTO |
---|---|---|
가독성 | 논리적 구조 명확 | 필드가 많아지면 복잡 |
타입 안전성 | 강함 (내부 클래스) | 약함 (필드명 혼재) |
재사용성 | 높음 (GymInfo 재사용 가능) | 낮음 |
JSON 크기 | 약간 큼 (중첩 구조) | 작음 |
파싱 복잡도 | 중간 | 낮음 |
확장성 | 좋음 | 나쁨 |
// 체육관 정보만 필요할 때
GymInfo gymInfo = reservation.getGym();
String gymName = gymInfo.getName();
// 다른 DTO에서도 동일한 구조 재사용
public class GymDetailResponseDto {
private GymInfo gym; // 재사용!
private List<TrainerInfo> trainers;
}
// 컴파일 타임에 오류 검출
reservation.getGym().getName(); // ✅ 안전
reservation.getGymName(); // ❌ 오타 가능성
4.쉬운 확장성
public static class GymInfo {
private Long gymId;
private String name;
private String address;
private String number;
// 새 필드 추가 시 여기만 수정하면 됨
private String description;
private List<String> facilities;
}
// 중첩: 더 많은 브래킷과 키
{"gym": {"gymId": 1, "name": "..."}}
// 평면: 더 간결
{"gymId": 1, "gymName": "..."}
// 중첩: 한 단계 더 접근
const gymName = reservation.gym.name;
// 평면: 직접 접근
const gymName = reservation.gymName;
✅ 관련 필드가 많고 논리적 그룹핑이 가능할 때
✅ 코드 재사용성이 중요할 때
✅ 도메인 구조가 복잡할 때
✅ 장기적 확장 가능성이 높을 때
✅ 타입 안정성이 중요한 프로젝트
✅ 필드 수가 적을 때
✅ 성능이 매우 중요할 때 (모바일 앱)
✅ 단순한 CRUD 작업
✅ 레거시 시스템과의 호환성이 필요할 때