Spring Boot Web의 여러가지 기능-(4)

개발세발·2024년 1월 23일

예외 처리의 필요성

  • 특정 서버에 요청하면 서버는 응답을 내려주고, 그 응답은 각각의 API마다 규격이 정해져 있다. 예외 상황에 따라서 응답이 달라지면 통일성이 깨지게 된다. 그래서 예외 처리를 통해서 서버가 동일한 응답(규격에 맞는 응답)을 내려줄 수 있도록 예외 처리를 해야 한다.
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class API<T> {
    private T data;
    private String resultCode;
    private String resultMessage;

}
  • 서버에서 응답을 줄 때 지키고자 하는 규격을 가진 클래스.
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder //객체 생성 시 빌더 패턴을 사용하기 위해
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserResponse {
    private String userId;
    private String userName;
    private Integer userAge;
}
  • 응답에 담길 데이터 클래스.
@RestController
@RequestMapping(("/api/user") )
public class UserAPIController {
    private static List<UserResponse> userList = List.of(
            UserResponse.builder() //빌더를 통해 체이닝된 방식으로 사용
                    .userId("1")
                    .userName("홍길동")
                    .userAge(20)
                    .build(),
            UserResponse.builder()
                    .userId("2")
                    .userName("유관순")
                    .userAge(24)
                    .build()
    );
    @GetMapping("/id/{userId}")
    public API<UserResponse> getUser(
            @PathVariable String userId
    ){
        if(true){
            throw new RuntimeException("message");
        }

        var user = userList.stream().
                filter(it -> it.getUserId().equals(userId))
                .findFirst()
                .get();

        API<UserResponse> userResponse = API.<UserResponse>builder()
                .resultCode(String.valueOf(HttpStatus.OK.value()))
                .resultMessage(HttpStatus.OK.name())
                .data(user)
                .build();
        return userResponse;
    }
}
  • user에서 특정 id를 가진 사용자를 get매핑으로 데이터를 받겠다.
  • 별도의 데이터 베이스가 없기 때문에 builder를 통해 생성해준다.
    @ExceptionHandler(value = {NoSuchElementException.class})
    public ResponseEntity<API> noSuchElement(
            NoSuchElementException exception
    ){
        log.info("", exception);
        var reponse =  API.builder()
                .resultCode(String.valueOf(HttpStatus.NOT_FOUND.value()))
                .resultMessage(HttpStatus.NOT_FOUND.getReasonPhrase())
                .build();
        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(reponse);
    }
  • resultCode와 Message를 지정해 놓지 않으면 200으로 OK가 전송되기 때문에 오류는 오류라고 전송해주도록 설정해 주어야 한다.
@Slf4j
@RestControllerAdvice

public class GlobalExceptionHandler {
    //예측하지 못한 모든 예외를 야기서 처리하겠다.

    @ExceptionHandler(value = {Exception.class})
    public ResponseEntity<API> exception(
            Exception e
    ){
        log.error("", e);
        var response = API.builder()
                .resultCode(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()))
                .resultMessage(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase())
                .build();
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(response);
    }
}
  • @ExceptionHandler(value = {Exception.class}) value를 가장 최상위 클래스로 지정해 주면서 RestApiExceptionHandler에서 처리하지 못한 에러를 처리해 주도록 지정.
  • 서버 내부 에러로 규정하기 위해 500에러에 대한 code와 message를 설정.

0개의 댓글