프로젝트

[Kotlin 토이프로젝트] Handling Exceptions

sian han 2022. 11. 18. 14:19

https://github.com/HAN-SEOHYUN/movie-api

 

Handling Exceptions

Exception 을 각각 설명하는 것이 아닌, 

프로젝트를 진행하면서 어떤 과정에서 예외처리가 필요한 상황이 발생했는지,

어떻게 예외를 처리했는지, 또 예외 처리 과정을 어떻게 develop 했는지 흐름에 따라 정리했다.

따라서 위부터 읽어 내려가는 것을 추천한다. 

 

 

 

Expected Exception : How will we know that if the id is there or not ?

( id 값을 넣어서 DTO 를 보내면 Create 가 아니라 Update 가 된다 )

 

1. Define a default value to DTO

이제 id 에 값을 지정하지 않고 send 하면 default value -1 이 들어갈거다.

 

 

2. ServiceIml 에서 id 에 값을 지정( id !=1 ) 하고 send 되었을 시

IllegalArgumentException 이 발생하도록 한다.

 

 

▷ Handle IllegalArgumentException

 

When you are sending a request a receiving a request, it's not just the body. You send a status the body and headers.

Request 를 주거나 받을 때, body 만 있는 것이 아니라, Status 와 Header 가 포함된다. 

 

So for that we can use that ResponseEntity Class.

 

ResponseEntity Class : Instead of directly returning a value, we will be using a wrapper class (ResponseEntity) and pass the value through that. => Refactoring is very simple. 

값을 바로 리턴하는 것 대신, wrapper 클래스를 통해 값을 전달할 것이다. => 리팩토링이 훨씬 쉬워짐

 

위 코드로 id 값을 넣고 POST 로 보내졌을 때 에러는 해결되었지만,

GET 으로 보내지면 또 다른 Exception 이 발생한다.

 

흠.. 이 모든 예외들을 모두 처리할 수 있도록 ExceptionHandler 를 만들어봤다. 

이 방법을 사용하면 try-catch 블럭은 사용할 필요가 없다.

But if you do this it will just violate single responsibility principle. (Because this is a resource class)

하지만 이건 단일책임원칙을 위반한다. 

 

For this, we can create a simple class just for handling Exceptions.

그래서 Exception 만 관리하는 클래스를 만들기로 한다. 

 

Then move the particular function from Resource to ExceptionHandler class.

For let Spring know that this class is responsible for handling Exceptions, annotate @RestControllerAdvice. 

Resource 에 작성한 exceptonHandler 메서드를 ExceptionHandler 클래스로 옮겨주고

ExceptionHandler 가 예외들을 관리하는 것을 Spring 이 알 수 있도록  @RestControllerAdvice 어노테이션을 추가한다. 

 

ExceptionHandler

위 코드의 문제는 잘못된 요청을 보냈을 때 null 을 응답받는다. 

For good API, we need to send proper entity which has timestamps, status, error message.

For a client knows what is going on. 

클라이언트측에서 이해할 수 있는

좋은 API 를 만들기 위해서는 timestamp, status, error message 가 포함된 응답을 하도록 만들어야한다. 

 

So create ApiError data class. 

 

This ApiError will have one thing. We need to have all the attributes like timestamps, status, error message.

So we can do that here. Ideally, we can give default values that is HttpStauts.BAD_REQUEST

ApiError 클래스는 내가 timestamps, status, error message 를 포함한

HttpStauts.BAD_REQUEST 를 응답해주는 것을 돕는다. 

ApiError

So now we can return it in an ApiError

 

Also you can return ApiError with message.

 

Problem is the value is nullable but we pass not null.

For solve this, you can give a default value in ApiError.

 

 

 

▶ 다른 exception 들도 모두 처리하도록 만들고 싶다면

IllegalArgumentException 을 Exception 으로 바꿔라.

그러면 모든 Exception 을 handle 할 수 있게 되기때문에 메서드이름도 generalExceptionHandler 로 바꾸겠음

 

Before : IllegalArgumentException

 

After : Exception

 

 

 

▶ CustomException

You should make your own Exception.

So for a custom Exception , you can make create MovieException class.

어떤 프로젝트를 진행하던 자체 Exception 을 만들어야한다. CustomException 을 만들기 위해, MovieException 클래스를 만들겠다.

 

그런 다음 ExceptionHandler 클래스에서 MovieException 을 handle 해주는 메서드를 생성하면 된다.