Spring Boot에서 ApiResponse는 REST API 개발 시 클라이언트에게 응답을 보낼 때 사용되는 구조를 정의하는 클래스이다. API 호출이 성공했는지 실패했는지, 그리고 그에 따른 데이터를 포함하여 다양한 정보를 응답으로 보낼 수 있다.
ApiResponse 기본 구조
ApiResponse 객체는 주로 다음과 같은 필드를 가진다:
- status (HttpStatus): 응답의 상태를 나타내며, 성공 또는 실패 여부를 표시한다. HttpStatus는 HTTP 응답 상태 코드를 담고 있다. (예: 200 OK, 404 Not Found)
- message (String): 응답에 대한 설명 메시지를 포함한다. 성공 또는 오류에 대한 메시지를 클라이언트에게 전달한다.
- data (Object): 응답 데이터이다. 요청의 결과에 따라 반환할 실제 데이터가 여기에 포함된다. 데이터는 객체, 배열, 또는 다른 구조일 수 있다.
- timestamp (LocalDateTime): 응답이 발생한 시간을 기록한다.
✏️ 코드
이번 팀 프로젝트 중 튜터님에게 받은 피드백중 Api Response를 사용해 보라는 말씀을 하셨는데 구현을 해 사용해 보니 훨씬 단일화되고 간결한 Response를 볼 수 있었다 코드는 아래와 같았다.
package com.sparta.springnewsfeed.global.dto;
import com.fasterxml.jackson.annotation.JsonInclude; // null 값을 포함하지 않도록 JSON 직렬화 시 설정
import lombok.Getter; // Lombok을 사용하여 getter 메서드를 자동 생성
import org.springframework.validation.BindingResult; // 스프링에서 검증 결과를 처리하는 클래스
import org.springframework.validation.FieldError; // 필드에 대한 오류를 나타내는 클래스
import org.springframework.validation.ObjectError; // 객체 레벨의 오류를 나타내는 클래스
import java.util.HashMap; // Map을 사용하기 위해 HashMap을 import
import java.util.List; // 리스트를 처리하기 위한 import
import java.util.Map; // 키-값 쌍을 관리하기 위한 Map 인터페이스 사용
@JsonInclude(JsonInclude.Include.NON_NULL) // JSON 응답에서 null 값은 포함하지 않도록 설정
@Getter // Lombok을 사용하여 모든 필드의 getter 메서드를 자동으로 생성
public class ApiResponse<T> {
// 응답 상태를 나타내는 enum
public enum Status {
SUCCESS, FAIL, ERROR
}
private final Status status; // 응답의 상태 (성공, 실패, 오류)
private final T data; // 응답 데이터 (제네릭 타입)
private final String message; // 응답 메시지 (성공, 실패 등 관련 설명)
// 생성자: status, data, message를 초기화하는 private 생성자
private ApiResponse(Status status, T data, String message) {
this.status = status;
this.data = data;
this.message = message;
}
// 성공적인 응답을 생성하는 static 메서드 (데이터 포함)
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(Status.SUCCESS, data, "요청이 성공적으로 처리되었습니다");
}
// 성공적인 응답을 생성하지만 내용이 없을 때 사용
public static ApiResponse<?> successWithNoContent() {
return new ApiResponse<>(Status.SUCCESS, null, "요청이 성공적으로 처리되었지만 내용이 없습니다");
}
// 검증 실패 시 BindingResult에서 오류를 추출하여 응답을 생성하는 메서드
public static ApiResponse<?> fail(BindingResult bindingResult) {
Map<String, String> errors = new HashMap<>(); // 오류를 저장할 Map 객체 생성
List<ObjectError> allErrors = bindingResult.getAllErrors(); // 모든 오류를 가져옴
for (ObjectError error : allErrors) { // 오류 리스트를 순회
if (error instanceof FieldError) { // 필드 오류인 경우
errors.put(((FieldError) error).getField(), error.getDefaultMessage()); // 필드 이름과 메시지를 Map에 저장
} else { // 객체 오류인 경우
errors.put(error.getObjectName(), error.getDefaultMessage()); // 객체 이름과 메시지를 Map에 저장
}
}
return new ApiResponse<>(Status.FAIL, errors, "검증에 실패했습니다"); // 오류와 함께 실패 응답 반환
}
// 이미 만들어진 오류 목록을 받아서 실패 응답을 생성하는 메서드
public static ApiResponse<?> fail(Map<String, String> errors) {
return new ApiResponse<>(Status.FAIL, errors, "검증에 실패했습니다");
}
// 오류 발생 시 오류 메시지와 함께 에러 응답을 생성하는 메서드
public static ApiResponse<?> error(String message) {
return new ApiResponse<>(Status.ERROR, null, message);
}
}
- @JsonInclude(JsonInclude.Include.NON_NULL): 이 애노테이션은 응답에서 null 값을 제거하여 반환한다.
- ApiResponse 클래스: 제네릭 타입의 API 응답 객체를 생성한다. 성공, 실패, 오류에 대한 다양한 응답을 처리할 수 있다.
- Status enum: 응답의 상태를 SUCCESS, FAIL, ERROR 세 가지로 구분하여 사용한다.
- success 메서드: 요청이 성공했을 때 응답을 생성하는 메서드로, 데이터가 포함된다.
- fail 메서드: 유효성 검사에서 오류가 발생했을 때 BindingResult를 통해 오류를 수집하고 이를 응답으로 반환한다.
- error 메서드: 서버 오류 또는 기타 처리 중 오류가 발생했을 때, 해당 오류 메시지와 함께 응답을 반환한다.
🔡 사용예시
@PostMapping("/signup")
public ResponseEntity<ApiResponse<?>> signup(@RequestBody UserRequestDto userRequest, HttpServletResponse res) {
try {
return ResponseEntity.ok(ApiResponse.success(userService.signup(userRequest,res)));
}catch (Exception e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.error("회원 가입 중 오류가 발생햇습니다."));
}
}
위와 같이 ResponseEntity에서 ApiResponse로 한번 감싸준뒤 try-catch 문으로 상태에 따라 정해진 dto를 보내주면 된다.
'Spring' 카테고리의 다른 글
[SprinBoot] 스프링 AWS EC2 배포, RDS 연동 후기 (1) | 2024.10.11 |
---|---|
[SpringBoot]MyBatis (2) | 2024.10.01 |
[SpringBoot] ArgumentResolver 사용하여 jwt 정보 가져오기 (0) | 2024.09.04 |
[SpringBoot]Entity 연관관계 방향성 (0) | 2024.08.29 |
[SpringBoot] NaverOpen API 사용 (0) | 2024.08.29 |