API 스펙 변경에 유연하게 대응해야 합니다.
컬렉션 그 자체로 반환하지 말고 커스텀 타입으로 한 번 감싸서 반환합시다. 아래 코드로 살펴봅시다.
@GetMapping()
public ResponseEntity<List<RoomResponseDTO>> getAllRooms() {
List<Room> rooms = roomService.getAllRooms();
List<RoomResponseDTO> collect = rooms.stream()
.filter(m -> !m.isDeleted())
.map(m-> RoomResponseDTO.from(m))
.toList();
return ResponseEntity.ok().body(collect);
}
엔티티 자체를 API Response에 노출하지 않고, Room 엔티티를 RoomResponseDTO로 변환하고 있습니다. 엔티티를 직접 API 스펙에 노출하지 않았기 때문에 엔티티의 변경이 API 스펙의 변경으로 이어지지 않습니다. 또한 프레젠테이션 계층을 위한 로직(@Valid 등)을 엔티티가 아닌 DTO에서 관리할 수 있습니다.
하지만 getAllRooms 메서드는 ResponseEntity<List<RoomResponseDTO>>를 반환하며 API 스펙이 고정됩니다. 이처럼 컬렉션을 직접 반환하면 향후 API 스펙을 변경하기 어렵습니다. 만약 getAllRooms 메서드의 API 스펙에 새로운 필드가 추가된다면, 컬렉션만 반환하는 List<RoomResponseDTO>로 대응하기 어렵습니다.
ResponseEntity로 묶어서 반환하긴 하지만 상태코드(Status), 헤더(headers), 응답데이터(ResponseData) 등을 묶는 역할을 하는 ResponseEntity로는 고정된 API 스펙을 유연하게 만들 수 없습니다.
별도의 Result 클래스를 생성해서 해결해야 합니다.
@Data
@AllArgsConstructor
public class Result<T> {
private T data;
}
@RestController
@RequiredArgsConstructor
public class RoomController {
...
@GetMapping("api/v1/...")
public ResponseEntity<Result> getAllRooms() {
List<Room> rooms = roomService.getAllRooms();
List<RoomResponseDTO> collect = rooms.stream()
.filter(m -> !m.isDeleted())
.map(m-> RoomResponseDTO.from(m))
.toList();
return ResponseEntity.ok().body(new Result(collect));
}
}
컬렉션을 Result 커스텀 타입으로 한 번 감싸서 ResponseData로 보내면 API스펙이 변경되어 count 필드가 추가되었다면 Result 클래스만 수정하면 대응할 수 있습니다.
@Data
@AllArgsConstructor
public class Result<T> {
private T data;
private int count;
}
API 스펙 변경에 유연하게 대응하기 위해서 앞으로 컬렉션을 커스텀 타입으로 한 번 감싸서 반환하도록 합시다.
'실시간 채팅 솔루션 개발 > 문제 해결 사례' 카테고리의 다른 글
Entity 삭제 시 발생하는 Referential integrity constraint violation 에러 (0) | 2024.10.25 |
---|---|
그럼 모든 JPA 에러는 롤백 처리해야 할까? (트랜잭션 롤백 여부) (0) | 2024.10.23 |
JPA가 던지는 체크 에러를 언체크 에러로 변환하면, 트랜잭션이 롤백 될까? (0) | 2024.10.23 |
프록시의 PK만 조회하면, 1+N 쿼리 문제가 터지지 않는다? (1) | 2024.10.21 |