티스토리 뷰
[Spring]Spring MVC - Custom Exception을 이용한 클라이언트 출력
Vagabund.Gni 2022. 8. 26. 00:03Spring MVC - Controller + Service
[Spring]Spring MVC - Controller 클래스 구조 생성 및 설계
[Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현
[Spring]Spring MVC - Controller 클래스에 ResponseEntity 적용
[Spring]Spring MVC - Controller 클래스에 DTO 적용
[Spring]Spring MVC - DTO 유효성 검증(Validation)
[Spring]Spring MVC - DI를 통한 API 계층 ↔ 서비스 계층 연동
[Spring]Spring MVC - 매퍼(Mapper)를 이용한 DTO 클래스 ↔ 엔티티(Entity) 클래스 매핑
[Spring]Spring MVC - @ExceptionHandler를 이용한 예외처리
[Spring]Spring MVC - @RestControllerAdvice를 이용한 예외처리
Spring Data JDBC
[Spring]JDBC(Java DataBase Connectivity)
[Spring]Spring Data JDBC, Spring Data JDBC 사용법
[Spring]Spring Data JDBC - 도메인 엔티티&테이블 설계
Spring Data JPA
[Spring]JPA(Java Persistence API)
[Spring]JPA - Entity ↔ DB Table Mapping
[Spring]JPA - Entity ↔ Entity Mapping
[Spring]Spring Data JPA - 데이터 액세스 계층 구현
대망의 API - 서비스 계층의 연동 마지막 글이다.
아직은 에러 메시지가 클라이언트가 아닌 콘솔에만 출력되고 있다.
지난 글에서 사용자 정의 예외(Custom Exception) 클래스를 전부 구축했으니
이번 글에선 GlobalExceptionAdvice 클래스와 ErrorResponse 클래스를 수정하고,
포스트맨을 이용해 다양한 에러 메시지를 출력해 본다.
2022.08.25 - [개발/Spring] - [Spring]Spring MVC - 비즈니스로직 예외 던지기(throw) 및 처리
getMember()에 요청 전송 시 에러 메시지 출력
가장 먼저 지난 글 마지막에 구현했던 handleBusinessLogicException()에서 처리된 예외를 출력해보자.
위 사진에서 올린 바와 같이 현재는 콘솔에만 메시지가 출력되는 상황이다.
먼저 핸들러 메서드가 받은 에러메세지를 기반으로 필요한 정보만 전달하는 ErrorResponse 클래스를 수정한다.
package com.gnidinger.response;
import com.codestates.exception.ExceptionCode;
import lombok.Getter;
import org.springframework.validation.BindingResult;
import javax.validation.ConstraintViolation;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Getter
public class ErrorResponse {
private int status;
private String message;
public ErrorResponse(int status, String message) {
this.status = status;
this.message = message;
}
...
public static ErrorResponse of(ExceptionCode exceptionCode) {
return new ErrorResponse(exceptionCode.getStatus(), exceptionCode.getMessage());
}
...
}
먼저 에러 메시지를 담을 변수와 생성자를 추가하고,
Static Factory Method(정적 메서드) of()를 생성해준다.
이는 enum으로 작성했던 ExceptionCode를 매개변수로 받아 Status와 Message를 전달하는 역할을 한다.
계속해서 에러를 처리할 GlobalExceptionAdvice 클래스를 수정하자.
package com.gnidinger.advice;
import com.codestates.exception.BusinessLogicException;
import com.codestates.response.ErrorResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolationException;
@RestControllerAdvice
public class GlobalExceptionAdvice {
...
@ExceptionHandler
public ResponseEntity handleBusinessLogicException(BusinessLogicException e) {
System.out.println(e.getExceptionCode().getStatus());
System.out.println(e.getMessage());
final ErrorResponse response = ErrorResponse.of(e.getExceptionCode());
// return new ResponseEntity<>(HttpStatus.valueOf(e.getExceptionCode().getStatus())); // 기존 코드
return new ResponseEntity<>(response, HttpStatus.valueOf(e.getExceptionCode().getStatus()));
}
}
먼저 Static Factory Method(정적 메서드) of()를 사용해 객체를 생성한다.
Custom Exception인 BusinessLogicException 클래스에서 ExceptionCode(Status, Message)를 읽어온다.
리턴하는 ResponseEntity<>에 HttpStatus만 바로 담던 부분에 response를 추가해
response(Status, Message)와 HttpStatus(404 NOT_FOUND)를 담아 유연하게 만들어주고 있다.
콘솔에 출력하던 부분은 삭제하지 않고 그대로 두었다.
클라이언트를 통해 요청을 보내면 의도했던 메시지가 출력되는 것을 확인할 수 있다.
ExceptionHandler 구현 - METHOD_NOT_ALLOWED
이어서 핸들러 메서드에 맞지 않는 요청을 보낼 때의 에러 메시지를 출력해 보자.
예를 들자면 POST로 보내야 할 요청을 PATCH로 잘못 보냈을 때의 에러 메시지이다.
먼저 HttpStatus를 전달해줄 메서드를 ErrorResponse에 추가한다.
package com.gnidinger.response;
...
import org.springframework.http.HttpStatus;
...
@Getter
public class ErrorResponse {
...
public static ErrorResponse of(HttpStatus httpStatus) {
return new ErrorResponse(httpStatus.value(), httpStatus.getReasonPhrase());
}
...
}
이번엔 HttpStatus를 입력받아 value()(405), getReasonPhrase()(Method Not Allowed)를 읽어온다.
계속해서 GlobalExceptionAdvice 클래스에 해당 에러를 처리할 핸들러 메서드를 작성해 보자.
package com.gnidinger.advice;
...
import org.springframework.web.HttpRequestMethodNotSupportedException;
...
@RestControllerAdvice
public class GlobalExceptionAdvice {
@ExceptionHandler
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public ErrorResponse handleHttpRequestMethodNotSupportedException
(HttpRequestMethodNotSupportedException e) {
System.out.println(HttpStatus.METHOD_NOT_ALLOWED.value());
System.out.println(HttpStatus.METHOD_NOT_ALLOWED.getReasonPhrase());
final ErrorResponse response = ErrorResponse.of(HttpStatus.METHOD_NOT_ALLOWED);
return response;
}
}
이번엔 고정된 HttpStatus를 사용할 것이기 때문에 @ResponseStatus를 붙여주었다.
value()와 getReasonPhrase()를 콘솔에도 출력하는 것을 확인할 수 있다.
결과는 아래와 같다.
ExceptionHandler 구현 - INTERNAL_SERVER_ERROR
마지막으로 개발자의 구현 실수로 발생하는 예외를 처리하기 위한 코드를 구현해보자.
먼저 NullPointerException을 유도하기 위해 MemberService 클래스의 deleteMember()를 수정하자.
public void deleteMember(long memberId) {
String logResult = null;
System.out.println(logResult.toUpperCase());
}
ErrorResponse는 위에서 작성했으니 GlobalExceptionAdvice 클래스에 핸들러 메서드만 추가하면 끝이다.
@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleException(Exception e) {
System.out.println(HttpStatus.INTERNAL_SERVER_ERROR.value());
System.out.println(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
final ErrorResponse response = ErrorResponse.of(HttpStatus.INTERNAL_SERVER_ERROR);
return response;
}
위의 두 케이스와 동일한 방식으로 정의했으며, 결과는 아래와 같다.
이렇게 에러 메시지를 클라이언트에 출력하는 것까지 구현해 보았다.
API ↔ 서비스 계층의 연동이라는 게 아직까지도 막연하고 코끼리 다리를 만지는 기분이 들지만,
계속 열심히 정리하고 복습해야겠다.
'Java+Spring > Spring' 카테고리의 다른 글
[Spring]Spring Data JDBC, Spring Data JDBC 사용법 (0) | 2022.08.26 |
---|---|
[Spring]SQL Mapper vs. ORM (0) | 2022.08.26 |
[Spring]JDBC(Java DataBase Connectivity) (0) | 2022.08.26 |
[Spring]Spring MVC - 비즈니스로직 예외 던지기(throw) 및 처리 (0) | 2022.08.25 |
[Spring]Spring MVC - @RestControllerAdvice를 이용한 예외처리 (0) | 2022.08.24 |
[Spring]Spring MVC - @ExceptionHandler를 이용한 예외처리 (1) | 2022.08.24 |
- Total
- Today
- Yesterday
- 스프링
- 칼이사
- 남미
- Algorithm
- 기술면접
- 자바
- 동적계획법
- 유럽여행
- 맛집
- a6000
- 야경
- 세계일주
- 세모
- 면접 준비
- 지지
- 유럽
- RX100M5
- 스트림
- 중남미
- 세계여행
- 파이썬
- Backjoon
- BOJ
- 알고리즘
- java
- 백준
- spring
- Python
- 여행
- 리스트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |