[Spring || SpringBoot] Rest API 공통 Response 포맷 구현

반응형
SMALL

클라이언트 <-> 서버

ps) 필자는 현재 스프링부트와 리액트를 이용해 프로젝트를 진행 중이어서 위와 같이 리액트와 스프링부트 이미지를 사용했다.

 

클라이언트는 요청을 보내고, 서버는 응답 요청이 들어오면 요청한 데이터를 서버 단 로직을 통해 수행 후, 클라이언트에게 응답 값을 보낸다.

 


참고

2024.03.26 - [Backend/Web] - [Web] REST API란 무엇인가?


ResponseEntity vs. ApiResponse

Spring에서 API Response를 구현하는 데에는 ResponseEntity와 ApiResponse 두 가지 접근 방식이 있다.

 

ResponseEntity

  • Spring의 HTTP응답을 나타내는 클래스
    • HTTP 응답 코드, Header와 Body를 포함할 수 있다.
  • HTTP 응답의 모든 부분을 세밀하게 제어할 수 있다.
    • 상태 코드, Header, Body 등 명시적으로 응답 값을 나타낼 수 있다.
  • 다양한 유형의 응답을 효과적으로 처리할 수 있다.
    • JSON, XML, HTML 등 다양한 형식의 데이터를 반환할 수 있다.

 

ApiResponse

  • API의 응답을 간단하게 나타내기 위한 사용자 지정 클래스
    • JSON 형식의 응답을 표현하는데 사용
  • 응답의 상태(성공 여부), 메시지, 데이터 등을 포함
    • 사용자에게 응답을 보내기 위한 간단한 데이터 구조를 표현
  • HTTP 응답 전체를 다루는 것이 아니라, 응답 내용에 중점보다 간결한 코드로 구성

 

이번 글에서 사용할 API 응답 방식은 ResponseEntity<ApiResponse> 를 사용하려고 한다.

 

ResponseEntity <ApiResponse> 사용하는 이유

  • HTTP 상태 코드 및 헤더 제어
    • HTTP 응답의 상태 코드와 헤더를 명시적으로 설정할 수 있다.
    • ResponseEntity.ok() 대신에 ResponseEntity.status(HttpStatus.OK)) 를 사용하여 상태 코드를 설정할 수 있다. 응답의 성공 여부를 더 명확하게 전달 가능
  • 다양한 응답 처리
    • 아래 코드를 예시로 ResponseEntity.ok와 ApiResponse에서 선언한 OK 메서드를 통해
    • HTTP 상태 코드인 200 값과 응답 값을 반환한다.
ResponseEntity.ok(ApiResponse.OK(mailSenderService.sendEmailForCertification(request.getEmail())))

 

ResponseEntity<ApiResponse> 단점(?)

아무래도 기존에 일반적으로 ApiResponse만 사용할 때보다 절차가 추가된 것이라, 코드를 더 많이 작성해야하며 코드 양이 많아질수록 응답 처리가 복잡해질 수 있다.

 

API 작성하기

ErrorCode

@Getter
@RequiredArgsConstructor
public enum ErrorCode {

    INVALID_TOKEN(401, "Token이 유효하지 않습니다."),
    ACCESS_DENIED(403, "접근 권한이 없습니다."),

    MEMBER_NOT_FOUND(404, "존재하지 않는 회원입니다."),
    AUTHENTICATION_FAILED(400, "아이디 또는 비밀번호가 옳지 않습니다.");

    private final int code;
    private final String msg;
}

 

ErrorCode는 Enum 타입으로 형성되어 있다. 팀원 혹은 타 팀과 협업 시 에러 코드를 직접 정의할 수 있다.

 

ApiBody

@AllArgsConstructor
@Getter
public class ApiBody<T> {
    private T data;
    private T msg;
}

위 사진과 같이 HTTP Response의 body 값을 나타낸다. 

 

ApiHeader

@Getter
@AllArgsConstructor
public class ApiHeader {
    private int resultCode;
    private String codeName;
}

Header에서는 성공 혹은 실패 코드를 나타낸다.

 

ApiResponse<T>

@Getter
public class ApiResponse<T> {
    private static final int SUCCESS = 200;
    private final ApiHeader header;
    private ApiBody body;

    public ApiResponse(ApiHeader header, ApiBody body) {
        this.header = header;
        this.body = body;
    }

    public ApiResponse(ApiHeader header) {
        this.header = header;
    }

    public static <T> ApiResponse<T> OK(T data) {
        return new ApiResponse<T>(new ApiHeader(SUCCESS, "SUCCESS"), new ApiBody(data, null));
    }

    public static <T> ApiResponse<T> fail(ErrorCode errorCode) {
        return new ApiResponse(new ApiHeader(errorCode.getCode(), errorCode.name()), new ApiBody(null, errorCode.getMsg()));
    }
}

 

API 사용하기

@PostMapping("/send-certification")
    public ResponseEntity<ApiResponse<EmailCertificationResponse>> sendCertificationNumber(@Validated @RequestBody EmailCertificationRequestDto request) throws MessagingException, NoSuchAlgorithmException {
        return ResponseEntity.ok(ApiResponse.OK(mailSenderService.sendEmailForCertification(request.getEmail())));
    }

 

 

예시로 이메일 인증 코드를 발급받는 API를 구성하였다.

 

위 사진과 같이 JSON 형태로 이메일 값을 입력하면 아래와 같이 header와 body로 응답 값을 보여주며, header에는 응답 코드를 보여주며 body에는 통신으로 주고받은 값들을 보여준다.

 

좀 어설프게 코드를 작성하였지만, API Response 부분은 개발자들 간에도 어떤 방식으로 전달하는지 말이 많다고 한다. 프로젝트를 마친 후에는 해당 부분에 대해서 좀 더 공부하고 리팩토링을 진행할 예정이다.

 

위 블로그에서 작성된 내용에 틀린 점이나 보완할 점을 발견하시고 댓글로 알려주신다면 너무너무 감사합니다.

반응형
LIST