Spring 예외처리를 자동으로 해보자!!

Aiden Shin·2022년 8월 5일
0

try/catch 블록은 원래 추하다. 코드 구조에 혼란을 일으키며, 정상 동작과 오류 처리 동작을 뒤섞는다. (클린코드)

@GetMapping("/api/v1/members")
public ResponseEntity getAllMember(Pageable pageable) {

    Page<Member> memberPage;
    
    // 반복적으로 발생하는 Try-Catch
    try {
          memberPage = memberFindService.getAllMemberPage(pageable);
    } catch (RuntimeException re) {
        return ResponseEntity.badRequest().build();
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

    return ResponseEntity.ok().body(MemberAdminDto.Info.of(memberPage));
}

위와 같이 try-catch를 반복적으로 사용하는 경우 내 손가락도 아프고.. 가독성도 떨어진다.. 스프링의 @ControllerAdvise 를 이용해서 손가락을 지켜보자!!


@ExceptionHandler

@ExceptionHandler@Controller, @RestController가 적용된 Bean내에서 발생하는 예외를 잡아서 하나의 메서드에서 처리해주는 기능을 한다.
({ }) 안에 처리할 예외 클래스를 넣은 후 매서드로 처리 내용을 구현하면 된다.

@ControllerAdvise

@Controller@RestController에서 발생한 예외를 한 곳에서 관리하고 처리할 수 있게 도와주는 어노테이션이다.

@ControllerAdvice
@Slf4j
public class ExceptionController {

    // 400
    @ExceptionHandler({
            MemberJoinException.class,
            RuntimeException.class
    })
    public ResponseEntity<Object> BadRequestException(final RuntimeException ex) {
        log.warn("error", ex);
        return ResponseEntity.badRequest().body(ex.getMessage());
    }

    // 401
    @ExceptionHandler({ AccessDeniedException.class })
    public ResponseEntity handleAccessDeniedException(final AccessDeniedException ex) {
        log.warn("error", ex);
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ex.getMessage());
    }

...

    // 500
    @ExceptionHandler({ Exception.class })
    public ResponseEntity<Object> handleAll(final Exception ex) {
        log.info(ex.getClass().getName());
        log.error("error", ex);
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }

}

@ControllerAdvice 를 통해 모든 컨트롤러에서 발생하는 예외를 잡고 @ExceptionHandler 를 통해 발생하는 예외의 종류마다 처리할 매서드를 정의한다.


// Exception Controller 설정 전 코드
@GetMapping("/api/v1/members")
public ResponseEntity getAllMember(Pageable pageable) {

    Page<Member> memberPage;
    
    // 반복적으로 발생하는 Try-Catch
    try {
          memberPage = memberFindService.getAllMemberPage(pageable);
    } catch (RuntimeException re) {
        return ResponseEntity.badRequest().build();
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

    return ResponseEntity.ok().body(MemberAdminDto.Info.of(memberPage));
}
// Exception Controller 설정 후 코드
@GetMapping("/api/v1/admin/members") public ResponseEntity getAllMember(Pageable pageable) {

// RuntimeException 발생 시 알아서 400에러 리턴, Exception 발생 시 500 리턴
    Page<Member> memberPage = memberFindService.getAllMemberPage(pageable);

    return ResponseEntity.ok().body(MemberAdminDto.Info.of(memberPage));
}

설정이 완료되면 Controller에 예외를 처리하는 코드를 작성하지 않아도 알아서 설정해놓은 대로 예외를 처리해준다.
물론 직접 try/catch를 통해 예외를 처리하면 직접 처리한 것이 우선순위로 작동하게 된다.


블로그 이전으로 인해 이전 글을 옮겨왔습니다. - 원본: [Spring]컨트롤러 예외처리를 자동으로

profile
개발하는 서아아빠

0개의 댓글