SSAFY 프로젝트를 진행하며 혹은 다른 Back-end 팀원이 작성한 코드가 에러를 뿜었을 때 어떤 에러인지 파악하기 힘들고 또한 Front-end 팀원들과 협업을 할 때 문제가 발생하거나, Response가 제대로 되었는지 등등.... 문제가 종종 발생하곤 했다.
우리의 멋진 팀원 SJP가 BaseResponse라는 체제를 들여오기 전까진 말이다.
발생할 수 있는 에러를 예측하고 미리 코드, 메시지로 작성해 놓아 Response에 담아 보내면 위 사항들은 쉽게 해결될 수 있을 것이다.

domain엔 기능과 관련된 폴더들이 존재하고
전체적으로 사용하는 부분은 global에 담았다.
BaseResponse를 사용하기 전에는 직접 ResponseDto를 리턴타입으로 보냈다.
이에 따라 Response Type이 일정하지 않았다.
BaseResponse를 적용한 Controller를 보겠다.
@PostMapping("/regist")
public BaseResponse<Object> registClothes(@RequestHeader(value = "accessToken", required = false) String token,
@RequestPart("clothesRegistRequestDto") ClothesRegistRequestDto clothesRegistRequestDto,
@RequestPart("file") MultipartFile file) {
try {
UUID memberId = getMemberIdFromToken(token); // 사용자 체크
// 옷 정보 등록
ClothesRegistResponseDto clothesRegistResponseDto = clothesService.registClothes(clothesRegistRequestDto, memberId, token, file);
return baseResponseService.getSuccessResponse(clothesRegistResponseDto);
} catch (BaseException e) {
return baseResponseService.getFailureResponse(e.status);
}
}
Postman을 통해 이 Controller에 요청을 보내보겠다.

다음과 같은 Response를 반환하였다.
message를 보면 "등록되지 않은 사용자가 요청을 했구나!"
하고 한번에 알 수 있다.
먼저 회원가입을 진행 해주고
다시 요청을 보냈더니,

다음과 같이 성공 코드인 1000번과 메세지
그리고 ResponseDto에 담긴 정보들을 확인할 수 있다.
확실히 좋다!!!
아래는 사용했던 코드이다.
package com.ssafy.moeutto.global.response;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public class BaseResponse<T> {
private boolean isSuccess; // 성공, 실패 여부
private String message; // 메시지
private int code; // 코드
private T data; // 전달 데이터
@Builder
public BaseResponse(boolean isSuccess, String message, int code, T data) {
this.isSuccess = isSuccess;
this.message = message;
this.code = code;
this.data = data;
}
}
package com.ssafy.moeutto.global.response;
public interface BaseResponseService {
/**
* 성공 응답 메서드 - 전달 데이터 O
*
* @param data - 결과 데이터
* @param <T> - 반환 타입 => Generic
* @return BaseResponse - 응답 객체
*/
<T> BaseResponse<Object> getSuccessResponse(T data);
/**
* 성공 응답 메서드 - 전달 데이터 X
*
* @param <T> - 반환 타입 => Generic
* @return BaseResponse - 응답 객체
*/
<T> BaseResponse<Object> getSuccessResponse();
/**
* 실패 응답 메서드
*
* @param status - BaseResponseStatus에서 생성한 status
* @param <T> - 반환 타입 => Generic
* @return BaseResponse - 응답 객체
*/
<T> BaseResponse<Object> getFailureResponse(BaseResponseStatus status);
}
package com.ssafy.moeutto.global.response;
import org.springframework.stereotype.Component;
@Component
public class BaseResponseServiceImpl implements BaseResponseService {
/**
* 성공 응답 메서드 - 전달 데이터 O
*
* @param data - 결과 데이터
* @param <T> - 반환 타입 => Generic
* @return BaseResponse - 응답 객체
*/
public <T> BaseResponse<Object> getSuccessResponse(T data) {
return BaseResponse.builder()
.isSuccess(true)
.code(BaseResponseStatus.SUCCESS.getCode())
.message(BaseResponseStatus.SUCCESS.getMessage())
.data(data)
.build();
}
/**
* 성공 응답 메서드 - 전달 데이터 X
*
* @param <T> - 반환 타입 => Generic
* @return BaseResponse - 응답 객체
*/
public <T> BaseResponse<Object> getSuccessResponse() {
return BaseResponse.builder()
.isSuccess(true)
.code(BaseResponseStatus.SUCCESS.getCode())
.message(BaseResponseStatus.SUCCESS.getMessage())
.build();
}
/**
* 실패 응답 메서드
*
* @param status - BaseResponseStatus에서 생성한 status
* @param <T> - 반환 타입 => Generic
* @return BaseResponse - 응답 객체
*/
public <T> BaseResponse<Object> getFailureResponse(BaseResponseStatus status) {
return BaseResponse.builder()
.isSuccess(status.isSuccess())
.code(status.getCode())
.message(status.getMessage())
.build();
}
}
package com.ssafy.moeutto.global.response;
import lombok.Getter;
@Getter
public enum BaseResponseStatus {
// -------- 성공 코드 시작 -------- //
SUCCESS(true, 1000, "요청에 성공했습니다."),
// -------- 성공 코드 종료 -------- //
// -------- 실패 코드 시작 -------- //
// -------- 필요한 에러 코드 추가 => Code 만들 때 안겹치게 몇번대 사용할 건지 얘기할 것 -------- //
/**
* Member
* Code : 2000번대
*/
NOT_FOUND_MEMBER(false, 2001, "일치하는 사용자가 없습니다."),
....
/**
* Clothes
* Code : 3000번대
*/
NOT_FOUND_CLOTHES(false, 3001, "옷 정보가 존재하지 않습니다),
...
/**
* Calendar
* Code : 4000번대
*/
NOT_FOUND_CALENDAR_INFO(false, 4001, "캘린더가 존재하지 않습니다."),
... 기타 실패 코드
// -------- 실패 코드 종료 -------- //
private boolean isSuccess; // 성공 여부
private String message; // 메시지
private int code; // 코드
/**
* BaseResponseStatus 에서 해당하는 코드를 매핑
*
* @param isSuccess
* @param code
* @param message
*/
BaseResponseStatus(boolean isSuccess, int code, String message) {
this.isSuccess = isSuccess;
this.code = code;
this.message = message;
}
}
package com.ssafy.moeutto.global.response;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseException extends Exception {
public BaseResponseStatus status;
}
작성자 : 박성준 ( https://velog.io/@park98sj )