"body" :{...} 부분에 제네릭을 이용해 데이터를 보내주고
"result" 부분에 -> http 에러코드, 메시지, 설명 이렇게 3가지 정보를 준다"body" 부분에는, 제네릭을 이용해 원하는 데이터를 보낸다
Api즉 밖을 감싸주는 클래스와result부분을 만들어준다@Data
@NoArgsConstructor
@AllArgsConstructor
public class Api<T> {
private Result result;
@Valid
private T body;
}
Api<T> 형태를 갖는다T 제네릭 타입을 이용해 실직적으로 성공하여, 요청한 데이터를 body에 담아서 보낸다@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Result {
private Integer resultCode;
private String resultMessage;
private String resultDescription;
}
ErrorCode는 코드 실수 + 오타 방지를 위해서
- Enum 클래스로 만들것이다
- Common 공통 영역의 패키지에 둘 것이다.
@AllArgsConstructor
@Getter
public enum ErrorCode implements ErrorCodeIfs{
OK(200,200,"성공"),
BAD_REQUEST(HttpStatus.BAD_REQUEST.value(), 400,"잘못된 요청"),
SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), 500,"서버에러"),
NULL_POINT(HttpStatus.INTERNAL_SERVER_ERROR.value(),512,"Null Point");
private final Integer httpStatusCode; // 상응하는 http status 코드
private final Integer errorCode; // 인터널 에러 코드
private final String description; //설명
}
@AllArgsConstructor을 이용해 몇가지의 ErrorCode를 정의하였다.httpStatusCode는 실제 http status 코드이고errorCode는 앞서 말했듯이 http status 코드가 모든 오류를 설명할 수 없기 때문에, 우리 서비스만의 에러 코드가 된다그런데.. 서비스가 확장됨에 따라
- 에러 코드는 더 늘어날 것이고...
- 수십,수백개가 될 수 있다
- 그런데 🤔 이를 우리가 다 기억하기도 어렵고 이 클래스 안에 많은 수의 에러 코드를 두면 찾기 어려울 것이다
- 그래서
✅ 인터페이스를 만들고 -> 각 기능에 맞게 에러 코드들을 나누어서 개발을 진행하도록 하자!!!
public interface ErrorCodeIfs {
Integer getHttpStatusCode();
Integer getErrorCode();
String getDescription();
}
SOLID의 SRP와 기능확장인 OCP부분 그리고 LSP를 잘 지키는 방법이라고 할 수 있다/**
* User의 경우 1000번대 에러 코드 사용
*/
@AllArgsConstructor
@Getter
public enum UserErrorCode implements ErrorCodeIfs {
USER_NOT_FOUND(400,1404,"사용자를 찾을 수 없습니다");
private final Integer httpStatusCode; // 상응하는 http status 코드
private final Integer errorCode; // 인터널 에러 코드
private final String description; //설명
}

ErrorCodeIfs를 상속받는 에러 클래스를 만들어 분할해서 코드를 사용하자!@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Result {
private Integer resultCode;
private String resultMessage;
private String resultDescription;
public static Result OK(){
return Result.builder()
.resultCode(ErrorCode.OK.getErrorCode())
.resultMessage(ErrorCode.OK.getDescription())
.resultDescription("성공")
.build();
}
public static Result ERROR(ErrorCodeIfs errorCodeIfs){
return Result.builder()
.resultCode(errorCodeIfs.getErrorCode())
.resultMessage(errorCodeIfs.getDescription())
.resultDescription("에러 발생")
.build();
}
public static Result ERROR(ErrorCodeIfs errorCodeIfs, Throwable tx){
return Result.builder()
.resultCode(errorCodeIfs.getErrorCode())
.resultMessage(errorCodeIfs.getDescription())
.resultDescription(tx.getLocalizedMessage())
.build();
}
public static Result ERROR(ErrorCodeIfs errorCodeIfs, String description){
return Result.builder()
.resultCode(errorCodeIfs.getErrorCode())
.resultMessage(errorCodeIfs.getDescription())
.resultDescription(description)
.build();
}
}
static 메서드로 만들어서 쉽게 사용하게 한다Api<T>에도 적용@Data
@NoArgsConstructor
@AllArgsConstructor
public class Api<T> {
private Result result;
@Valid
private T body;
public static <T> Api<T> OK(T data){
Api<T> api = new Api<>();
api.body=data;
api.result=Result.OK();
return api;
}
public static Api<Object> ERROR(Result result){
Api api = new Api<Object>();
api.body=result;
api.result=result;
return api;
}
public static Api<Object> ERROR(ErrorCodeIfs errorCodeIfs){
Api api = new Api<Object>();
api.result=Result.ERROR(errorCodeIfs);
return api;
}
public static Api<Object> ERROR(ErrorCodeIfs errorCodeIfs,Throwable tx){
Api api = new Api<Object>();
api.result=Result.ERROR(errorCodeIfs,tx);
return api;
}
public static Api<Object> ERROR(ErrorCodeIfs errorCodeIfs,String description){
Api api = new Api<Object>();
api.result=Result.ERROR(errorCodeIfs,description);
return api;
}
}
<T> 제네릭 타입으로 정의해준다<T> 제네릭타입이 아니다Api.Error는 Result.Error에 따라 오버로딩해줘야 한다