본문 바로가기
Today I Learned 2024. 5. 17.

(24.05.17)[5주차] Spring 입문 마무리(SpringBoot JPA @ExceptionalHandler)

피드백을 알게된 내용을 정리하면서 마무리하며, 알아본 내용을 추가적으로 정리했다.


Spring 입문 강의 추가학습 정리

@ControllerAdvice @ExceptionalHandler 로 예외 출력

더보기
package com.sparta.scheduler.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class SchedulerExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
    }
}
  • Spring Framework에서 Annotation인@ControllerAdvice @ExceptionalHandler 을 사용해서 예외가 던져지면 화면으로 그 예외를 출력할 수 있는 코드
  • index.html 화면단에서 해당 내용을 받아서 alert를 통해서 오류 내용을 사용자에게 출력, 전달 할 수 있게 설계

@ControllerAdvice

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
...
  • Spring MVC 모델에서 @Controller에서 발생하는 예외를 처리하는 클래스임을 표시
  • 몸통안에 예외 처리를 위한 여러 메서드를 포함해서 실행시킬 수 있고, @ExceptionalHandler 를 여기서 활용 가능
    • HTTP를 통해 Clinet에게 보내줄 body작성 @ResponseBody annotation이  @RestController와 다르게 없기 때문에 @ResponseBody를 클래스 안에 써야

@ExceptionHandler(예외 클래스)

  • 특정 예외를 처리하기 위한 메서드를 지정해서 사용할 수 있음을 표시
  • 매개변수로는 처리하려는 예외의 클래스
    • 개인과제인 나만의 일정관리 서버 프로그램을 만드는데 Scheduler 에서 모든 예외를 IllegalArgumentException로 통일하여 메시지를 출력하는 방식을 채택했으므로, 매개변수를 IllegalArgumentException.class로 지정했음
  • 변수로 받은 예외클래스의 예외가 발생하면 해당 메서드가 호출되어 예외를 처리하는 부분

HttpStatus

public enum HttpStatus implements HttpStatusCode {
...
  • HTTP 상태코드를 받아와서 상태코드에 해당하는 상태의 상수를 정의한 enum
  • value : 400 의 reasonPhrase: "Bad Request"일 경우, HttpStatus.BAD_REQUEST를 뜻하게 됨
    • 워냑 양이 방대하고 Deprecated한 부분도 있기 때문에 흔히 알고 있는 상태코드별로 구분만 할 수 있도록

 

 

ExceptionHandler도 RESTful API의 영역일 수가 있을까

더보기
@ControllerAdvice
public class SchedulerExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public ResponseEntity<SchedulerResponseDto> handleIllegalArgumentException(IllegalArgumentException e) {
        SchedulerResponseDto responseDto = new SchedulerResponseDto();
        responseDto.setMessage(e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(responseDto);
    }
}

이슈

  • RESTful한 API를 위해서 DTO타입으로 반환시켜 Client로 오류 메시지를 보내려고 하는데, 그렇다면 HTTP 상태코드를 담을 수 없게 되는 문제

원인

  • DTO로 반환을 할경우에는 HTTP 상태를 맞춰서 반환할 수가 없어서 ResponseEntity<> 감싸서 반환을 시켜야 할 필요가 있음
  • 예외가 발생하는 거에 대해서는 굳이 RESTful하게 만들지 않아도 상관이X API 단에서의 Docker Swagger관련이 전혀 아니기 때문

해결

@ControllerAdvice
public class SchedulerExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ExceptionResponseDto> handleIllegalArgumentException(IllegalArgumentException e) {
        ExceptionResponseDto exceptionResponseDto = new ExceptionResponseDto();
        exceptionResponseDto.setMessage(e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(exceptionResponseDto);
    }
}
  • 따라서 그냥  ResponseEntity<SchedulerResponseDto>를 써도무관.
  • 단, 만약 DTO가 엄청나게 많아질 경우엔, 모든 DTO를 다 감싸서 위처럼  ExceptionHandler로 만들어야 해결할 가능성이 존재
    • 즉, 감싸서 DTO를 내보낼거면 그냥, 새로운 오류메시지 DTO를 만들어서 사용하는 것
    • 일종의 CommonDTO를 만들어 내서 사용할 수 있도록 하면 됨

 


개인 과제도 피드백 받아 계속 진행이 될것!

다음주는 심화과정으로 가니, 계속 복습하면서 잊지말고 가져가야 할 듯.