반응형

@RestControllerAdvice 

스프링부트에서 @RestController를 이용해서 api를 개발하는경우에 예외처리시 이용한다.

예외를 처리하고 응답객체를 리턴해줄수있다. api응답으로 에러객체를만들어서 보내줄수있다.

@Transactional(readOnly = true)
public CommuteTotalResponse checkTime(CommuteGetDto request) {
    Employee employee = memberRepository.findById(request.getEmployeeId())
            .orElseThrow(IllegalArgumentException::new);
    CommuteTimeResponseList commuteTimeResponseList = new CommuteTimeResponseList(request, employee);

    return new CommuteTotalResponse(commuteTimeResponseList.getCommuteTimeResponseList());
}

 

기존에는 이렇게 서비스계층에서 예외를 처리해서 에러를 내게되면 500에러가 나면서 

이런 모양의 에러객체를 리턴해주게된다.

{
    "timestamp": "2024-03-15T09:31:41.095+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/commute/worktime"
}

 

이 에러는 지금 내가요청하는 직원아이디를 없는아이디로 넣어서 나오는 에러인데

만약 이 API를 지금처럼 내가 직접만들고 해결한다면 백엔드코드를 보고 수정할수있을 것이다.

그러나 협업을 하게되고 클라이언트에서 요청했는데 이런 에러가나온다면

클라이언트측에서는 어떤 문제로 이런에러가 발생했는지 알기어려울 것이다.

이걸 해결하기 위해서 @RestControllerAdvice를 사용할수있다.

 

CommuteServiceExceptionHandler(에러 처리 객체)

@RestControllerAdvice
public class CommuteServiceExceptionHandler {
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> illegalArgumentExceptionHandle(IllegalArgumentException e) {
        return ResponseEntity.badRequest().body("error : " + e.getMessage());
    }
}

 

이렇게 에러를 처리하는 객체를 만들고 @RestControllerAdvice를 달아주면

@RestController에서 에러가 발생하면 이 객체에서 전역적으로 처리해줄수있게된다. 

 

@ExceptionHandler(처리할예외.class)

여기에는 처리해줄 예외객체를 명시해주면 해당예외가발생시 해당하는 메서드를 실행시켜준다.

 

위의 코드는 IllegalArgumentException을 처리하는 메서드이다. 

service에서 아이디로검색한 직원이 없는경우에 IllegalArgumentException을 발생시키고

해당 예외가 이곳으로 와서 처리된다.

응답코드를 세팅하기위해서 리턴타입을 ResponseEntity로 해주었다.

ResponseEntity를 리턴해야 응답코드를 변경해서 보내줄수있으며

그냥 객체를 내보내게되면 해당 객체를 Json으로 보내주지만 응답객체는 200으로 나오게된다.

 

String으로 에러메시지를 리턴하는경우


 

ResponseEntity로 응답코드를 세팅해서 리턴하는경우

 

 

ResponseEntity<>로 특정객체를 감싸서 리턴해줄수도있다.

이번에는 api의 응답객체로 사용할 wrapper객체를 만들고 ResponseEntity로 이 객체를 감싸서 응답을 보내보자.

 

Api

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class Api<T> {

    private String resultCode;
    private String resultMessage;
    @Valid
    private T data;
    private Error error;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    @JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
    public static class Error{
        private List<String> errorMessage;
    }
}

 

이 객체는 응답 결과데이터와 ,응답코드, 응답메시지,에러정보를 가지고있게된다 

만약 정상적인 요청을 보낸다면 

{
    "result_code": "200",
    "result_message": "OK",
    "data": {
        "name": "홍길동",
        "nick_name": "닉",
        "password": "1234",
        "email": "kim@gmail.com",
        "phone_number": "010-5491-2645",
        "register_at": "2024-03-16T09:58:14",
        "age": 26,
        "name_check": true
    },
    "error": null
}
 
이렇게 데이터에 응답객체를 가지고있고 응답코드,응답메시지도 표시해줄수있다. 
이 경우에 에러가 발생한다면.
 
 
{
    "result_code": "400",
    "result_message": "Bad Request",
    "data": null,
    "error": {
        "error_message": [
            "error :직원 정보가없습니다."
        ]
    }
}
 
이렇게 데이터는 빈값으로 주고 에러객체에 에러메시지값을 세팅해서 내보내줄수도있다. 
 

에러핸들러

@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<Api<? extends Objects>> illegalArgumentExceptionHandle(IllegalArgumentException e) {
    String message = "error :" + e.getMessage();
    Error error = Error.builder()
            .errorMessage(Collections.singletonList(message))
            .build();

    Api errorResponse = Api.builder()
            .resultCode(String.valueOf(HttpStatus.BAD_REQUEST.value()))
            .resultMessage(HttpStatus.BAD_REQUEST.getReasonPhrase())
            .error(error)
            .build();

    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
}

 

이 경우에 Error객체를 만들어주고 Api객체에 세팅해주어야해서 코드는 약간 길어지지만

정리해서 따로 메서드로 분리한다면 더 깔끔하게 정리할수있을것같다. 

 

일반 사용자의 입장에서는 에러가 기분나쁘고 고장난것처럼 느껴지지만

개발하는 입장에서는 에러가 명확하고 어떤부분에서 에러가 발생하는지 확실하게 알려주는편이 더 좋다고 생각한다.

그래야 클라이언트측에서 실수를 한건지 백엔드에서 예외처리를 못해준건지 명확해지고

요청정보가 잘못되었다면 빠르게 수정할수있다. 

반응형

+ Recent posts