서버에서 client로 여러개의 data를 넘겨 주기 위해 새로운 방법이 필요했다
ErrorCode
@Getter
@AllArgsConstructor
public enum ErrorCode {
/* 400 BAD_REQUEST : 잘못된 요청 */
INVALID_REFRESH_TOKEN(BAD_REQUEST, "리프레시 토큰이 유효하지 않습니다"),
MISMATCH_REFRESH_TOKEN(BAD_REQUEST, "리프레시 토큰의 유저 정보가 일치하지 않습니다"),
CANNOT_FOLLOW_MYSELF(BAD_REQUEST, "자기 자신은 팔로우 할 수 없습니다"),
/* 401 UNAUTHORIZED : 인증되지 않은 사용자 */
INVALID_AUTH_TOKEN(UNAUTHORIZED, "권한 정보가 없는 토큰입니다"),
UNAUTHORIZED_MEMBER(UNAUTHORIZED, "현재 내 계정 정보가 존재하지 않습니다"),
/* 404 NOT_FOUND : Resource 를 찾을 수 없음 */
MEMBER_NOT_FOUND(NOT_FOUND, "해당 유저 정보를 찾을 수 없습니다"),
REFRESH_TOKEN_NOT_FOUND(NOT_FOUND, "로그아웃 된 사용자입니다"),
NOT_FOLLOW(NOT_FOUND, "팔로우 중이지 않습니다"),
/* 409 CONFLICT : Resource 의 현재 상태와 충돌. 보통 중복된 데이터 존재 */
DUPLICATE_RESOURCE(CONFLICT, "데이터가 이미 존재합니다"),
;
private final HttpStatus httpStatus;
private final String detail;
}
ErrorResponse
@Getter
@Builder
public class ErrorResponse {
private final LocalDateTime timestamp = LocalDateTime.now();
private final int status;
private final String error;
private final String code;
private final String message;
public static ResponseEntity<ErrorResponse> toResponseEntity(ErrorCode errorCode) {
return ResponseEntity
.status(errorCode.getHttpStatus())
.body(ErrorResponse.builder()
.status(errorCode.getHttpStatus().value())
.error(errorCode.getHttpStatus().name())
.code(errorCode.name())
.message(errorCode.getDetail())
.build()
);
}
}
- 실제로 유저에게 보낼 응답 Format 입니다.
- 일부러 500 에러 났을 때랑 형식을 맞췄습니다. status, code 값은 사실 없어도 됩니다.
- ErrorCode 를 받아서 ResponseEntity<ErrorResponse> 로 변환해줍니다.
@ControllerAdvice 는 프로젝트 전역에서 발생하는 모든 예외를 잡아줍니다.
@ExceptionHandler 는 발생한 특정 예외를 잡아서 하나의 메소드에서 공통 처리해줄 수 있게 해줍니다.
따라서 둘을 같이 사용하면 모든 예외를 잡은 후에 Exception 종류별로 메소드를 공통 처리할 수 있습니다.
Exception 사용
@RequiredArgsConstructor
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Transactional
public boolean follow(Long memberId) {
Member currentMember = getCurrentMember();
// 팔로우할 상대방 정보가 없는 경우
Member targetMember = memberRepository.findById(memberId)
.orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND));
// 자기 자신을 팔로우 하려는 경우
if (currentMember.equals(targetMember)) {
throw new CustomException(CANNOT_FOLLOW_MYSELF);
}
// code...
}
}
MEMBER_NOT_FOUND 실제 응답
{
"timestamp": "2021-03-14T03:29:01.878659",
"status": 404,
"error": "NOT_FOUND",
"code": "MEMBER_NOT_FOUND",
"message": "해당 유저 정보를 찾을 수 없습니다"
}
CANNOT_FOLLOW_MYSELF 실제 응답
{
"timestamp": "2021-03-14T03:16:25.98361",
"status": 400,
"error": "BAD_REQUEST",
"code": "CANNOT_FOLLOW_MYSELF",
"message": "자기 자신은 팔로우 할 수 없습니다"
}
결론
Spring 에는 프로젝트 전역에서 발생하는 Exception 을 한 곳에서 처리할 수 있다.
Enum 클래스로 ErrorCode 를 정의하면 Exception 클래스를 매번 생성하지 않아도 된다.
실제 클라에게 날라가는 응답에서 code 부분만 확인하면 어떤 에러가 발생했는지 쉽게 파악 가능하다.
'항해 99(9기) > 항해 일일' 카테고리의 다른 글
항해 99 17일차 (0) | 2022.10.05 |
---|---|
항해 99 16일차 (0) | 2022.10.04 |
항해 99 13일 차 (0) | 2022.10.01 |
항해 12일 차 (0) | 2022.09.30 |
항해 11일 차 (0) | 2022.09.29 |