- 공통 응답 DTO 사용하기
- 컨트롤러에서의 기존 응답 형식
- 공통 응답 DTO 적용
공통 응답 DTO를 사용해 일관된 응답을 할 수 있도록 구성하는 방법을 알아보았다.
기존 컨트롤러에서는 예를 들어 특정 사용자의 정보를 반환한다면(여기서는 nickname만 반환한다.) 다음과 같은 코드로 작성되었을 것이다.
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/{userId}")
public ResponseEntity getUser(@PathVariable UUID userId) {
UserResponseDto responseDto = userService.getUser(userID)
return ResponseEntity.ok(responseDto);
}
}
@Getter
@Builder
public class UserResponseDto {
private String nickname;
}
응답을 확인해 보면 다음과 같은 형식이 될 것이다.
{
"nickname": "Test"
}
만약 여기서 사용자의 email을 응답에 추가한다면, 형식은 아래와 같이 달라질 것이다.
{
"nickname": "Test"
"email": "Test@email.com"
}
모든 API에서 공통된 형식으로 응답을 보내줄 수 있도록, 공통 응답 DTO를 구현하고 사용하도록 해 보자.
@Getter
@Builder
public class ResponseDTO<T> {
private Integer status;
private String message;
private T data;
public static <T> ResponseDTO<T> of(Integer status, String message, T data) {
return ResponseDTO.<T>builder()
.status(status)
.message(message)
.data(data)
.build();
}
}
위와 같이 공통 응답 DTO 클래스를 만들었다.
필드로는 message, data를 포함시켰다.
Object 타입을 사용하지 않고 제네릭 T로 선언한 이유는, 컴파일 시 에러를 감지해서 런타임 에러가 발생하는 것을 방지하기 위해서이다.
정적 팩토리 메서드를 추가해 직접 생성자를 호출하지 않고 객체를 생성할 수 있도록 했다.
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/{userId}")
public ResponseEntity<ResponseDTO<UserResponseDto>> getUserNickname(@PathVariable UUID userId) {
UserResponseDto responseDto = userService.getUser(userId);
ResponseDTO<UserResponseDto> response = ResponseDTO.of("사용자 조회 성공", responseDto);
return ResponseEntity.ok(response);
}
}
예시를 위해 작성된 코드이므로 message는 하드코딩으로 처리했다.
이렇게 ResponseDTO에 T data에 기존에 반환하던 dto를 넣어 주면, 아래와 같이 응답 형식이 생성될 것이다.
{
"message": "사용자 조회 성공",
"data": {
"nickname": "Test"
}
}
공통 응답 DTO를 사용한다면 어떤 API를 작성하던 간에 응답 형식은 같아질 것이다.