์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ธ(Exception)๊ฐ ๋ฐ์ํ์ ๋, ๋ด๋ถ์ ์ผ๋ก Spring์์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ์ฌ ํด๋ผ์ด์ธํธ์ ์๋ต์ผ๋ก ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด์ฃผ๋๋ฐ, ์ด ๋ ํด๋ผ์ด์ธํธ๋ ์ด๋์์ ์์ธ๊ฐ ๋ฐ์ํ๋์ง ์ฝ๊ฒ ์ ์ ์์
โ @ExceptionHandler ์ฌ์ฉํ์ฌ ์๋ฌ ์๋ต ๋ฉ์ธ์ง๋ฅผ ์ง์ ์์ฑํ์ฌ ์๋ต์ผ๋ก ๋ณด๋ด์ค ์ ์์ !
Controller ๋ ๋ฒจ์์๋ง ์ฌ์ฉ
์์ธ์ฒ๋ฆฌ๋ฅผ ํ ํธ๋ค๋ฌ ๋ฉ์๋๋ฅผ ์์ฑํ๊ณ , ๊ทธ ์์ @Exception
์ ๋ํ
์ด์
์ ๋ถ์ฌ ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ์ ์ก ๊ฐ๋ฅ
( But, ์์ ๊ฒฝ์ฐ ์๋ฌ ์ ๋ณด ๋ฟ๋ง ์๋๋ผ Response Body ์ ์ฒด ์ ๋ณด๊น์ง ์ ๋ฌ๋จ ! )
โ ๊ณตํต๋๋ ์๋ฌ๋ ErrorResponse ํด๋์ค
๋ฅผ ๋ฐ๋ก ๋ง๋ค์ด DTO ํด๋์ค์ ์ ํจ์ฑ ๊ฒ์ฆ ์คํจ ์, ์คํจํ ํ๋(๋ฉค๋ฒ ๋ณ์)์ ๋ํ Error ์ ๋ณด๋ง ๋ด์์ ๊ทธ ํด๋์ค ๋ด์ FieldError
ํด๋์ค๋ก ์๋ต์ผ๋ก ์ ์ก ๊ฐ๋ฅ
โ ์ด ๊ฒฝ์ฐ, ์๋ฌ๊ฐ ์ฌ๋ฌ๊ฐ๊ฐ ๋ ์ ์๊ธฐ ๋๋ฌธ์, ํธ๋ค๋ฌ ๋ฉ์๋ ๋ด์์ FieldError
ํด๋์ค๋ List ๊ฐ์ฒด
๋ฅผ ์ด์ฉํ์ฌ ์๋ฌ ์ ๋ณด๋ฅผ ๋ด๊ณ ๋๊ฒจ์ค ์ ์์
โ๏ธ
ErrorResponse ํด๋์ค
โ ์๋ฌ ๊ฒ์ฌํ ํญ๋ชฉ ์ ๋ฆฌํ๋ ํด๋์ค
๊ฐ ํด๋์ค๋ง๋ค @Exception ์ ๋ํ
์ด์
์ ์ฌ์ฉํ์ฌ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ํด์ผํ๋ฏ๋ก
๊ฐ Controller ํด๋์ค๋ง๋ค ์ฝ๋์ ์ค๋ณต์ด ๋ฐ์
ํ๋์ Controller ํด๋์ค ๋ด์ ์ฒ๋ฆฌํด์ผํ ์์ธ๊ฐ ์ ํจ์ฑ ๊ฒ์ฆ ์คํจ์ ๋ํ ์์ธ(MethodArgumentNotValidException)๋ง ์๋๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์,
ํ๋์ Controller ํด๋์ค ๋ด์ @ExceptionHandler
๋ฅผ ์ถ๊ฐํ ์๋ฌ ์ฒ๋ฆฌ ํธ๋ค๋ฌ ๋ฉ์๋๊ฐ ๋์ด๋จ
Ex.
patchMember()
ํธ๋ค๋ฌ ๋ฉ์๋์ URI ๋ณ์์ธ โ/{member-id}โ์ 0์ด ๋์ด์ฌ ๊ฒฝ์ฐ,
ConstraintViolationException
์ด ๋ฐ์
โ ๊ทธ Controller ํด๋์ค ์์๋ ์ ํจ์ฑ ๊ฒ์ฌ ํธ๋ค๋ฌ ๋ฉ์๋ + ์ด ์์ธ๋ฅผ ์ฒ๋ฆฌํ ํธ๋ค๋ฌ ๋ฉ์๋ ์ด๋ ๊ฒ ๋๊ฐ๊ฐ ์๊น
Controller ํด๋์ค ๋ด์์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋์ @RestControllerAdvice
์ ๋ํ
์ด์
์ฌ์ฉํ์ฌ ์๋ก ํด๋์ค ๋ง๋ค๋ฉด,
๊ทธ ํด๋์ค์์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ๊ณตํตํํ์ฌ ์ฌ๋ฌ Controller ํด๋์ค์์@ExceptionHandler
/@InitBinder
/@ModelAttribute
๊ฐ ๋ถ์ ๋ฉ์๋ ๊ณต์ ํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅ
๐ก
@InitBinder
/@ModelAttribute
์ ๋ํ ์ด์ ์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR, Server Side Rendering) ๋ฐฉ์์์ ์ฃผ๋ก ์ฌ์ฉ๋๋ ๋ฐฉ์
Ex. JSP, Thymeleaf
@RestControllerAdvice
๊ฐ ๋ถ์ ํด๋์ค์๋ @ExceptionHandler ์ ๋ํ
์ด์
์ด ๋ถ์๋ ์๋ฌ ์ฒ๋ฆฌ ํธ๋ค๋ฌ ๋ฉ์๋๋ค์ ๋ฃ์ผ๋ฉด ๋จ
๊ฐ ์ปจํธ๋กค๋ฌ๋ง๋ค ๋ฐ๊ฒฌ๋๋ ์๋ฌ๋ฅผ @RestControllerAdvice
๊ฐ ์ฒ๋ฆฌ
โ๏ธ
@RestControllerAdvice
์ ๋ํ ์ด์ ์ด ๋ถ์ ํด๋์ค
โ ๊ฐ ํธ๋ค๋ฌ ๋ฉ์ธ์ง์ ์๋ฌ ์๋ต ์ ๋ฌํ๋ ํด๋์ค
โ๏ธ
@ResponseStatus
์ ๋ํ ์ด์
โ HTTP Status๋ฅผ ๋์ ํํ
Ex.@ResponseStatus(HttpStatus.BAD_REQUEST)
๐ก
@RestControllerAdvice
vs@ControllerAdvice
@RestControllerAdvice
=@ControllerAdvice
+@ResponseBody
โ
โ@RestControllerAdvice
์ ๋ํ ์ด์ ์ JSON ํ์์ ๋ฐ์ดํฐ๋ฅผ Response Body๋ก ์ ์กํ๊ธฐ ์ํด์ ResponseEntity๋ก ๋ฐ์ดํฐ๋ฅผ ๋ํํ ํ์๊ฐ ์์
๋ค์ด๋ฐ ์ปจ๋ฒค์ (Naming Convention)
๊ฐ์ฒด ์์ฑ์ ์ด๋ค ๊ฐ๋ค์(of~) ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค๋ ์๋ฏธ
์์ฑ์์ private ์ ๊ทผ ์ ์ด์๊ฐ ๋ถ์์ ๊ฒฝ์ฐ, ๊ฐ ์ญํ ๊ตฌ๋ถ์ ์ํด
์์ฑ์์ ๊ฐ์ ์ญํ ์ ํ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ
โ
Ex. ErrorResponse of(BindingResult bindingResult)
โ An ErrorResponse instance is made of BindingResult object
โ๏ธ ์ฒดํฌ ์์ธ (Checked Exception)
โ๏ธ ์ธ์ฒดํฌ ์์ธ (Unchecked Exception)
โ Java๋ Spring์์ ์๋ง์ RuntimeException์ ์ง์ํด์ฃผ์ง๋ง, ๊ฐ๋ฐ์๊ฐ ์ง์ ์์ธ(Exception)๋ฅผ ๋ง๋ค์ด์ผ ํ ๊ฒฝ์ฐ๋ ์์ !
โ ์์ธ๋ฅผ ๋์ง๋ค๊ณ ํจ
๋ฐฑ์๋ ์๋ฒ์ ์ธ๋ถ ์์คํ
๊ณผ์ ์ฐ๋์์ ๋ฐ์ํ๋ ์๋ฌ ์ฒ๋ฆฌ
โ ๋ฐฑ์๋ ์๋ฒ ์ชฝ์์ ์์ธ๋ฅผ ์๋์ ์ผ๋ก ๋์ ธ์ ํด๋ผ์ด์ธํธ ์ชฝ์ ์๋ฌ๊ฐ ๋ฐ์ํ ์ ๋ณด๋ฅผ ์๋ ค์ค ์ ์์
์์คํ
๋ด๋ถ์์ ์กฐํํ๋ ค๋ ๋ฆฌ์์ค(์์, Resource)๊ฐ ์๋ ๊ฒฝ์ฐ
โ ์๋น์ค ๊ณ์ธต์์ ํด๋น ํ์ ์ ๋ณด๊ฐ ์๋ค๋ ์์ธ๋ฅผ ์๋์ ์ผ๋ก ์ ์กํด์ ํด๋ผ์ด์ธํธ ์ชฝ์ ์๋ ค์ค ์ ์์
ํด๋ผ์ด์ธํธ๊ฐ Controller์ ํด๋น ํธ๋ค๋ฌ ๋ฉ์๋๋ก ์์ฒญ ๋ณด๋
์์ธ๊ฐ ๋ฐ์ํ๋ค๋ฉด, Service ํด๋์ค์์ RuntimeException์ ๋์ง
Service ํด๋์ค ๋ด์ ํด๋น ํธ๋ค๋ฌ ๋ฉ์๋์๋
throw
ํค์๋ ์ฌ์ฉํ์ฌ RuntimeException ๊ฐ์ฒด์ ์ ์ ํ์์ธ ๋ฉ์์ง
๋ฅผ ํฌํจ
โ
Ex. throw new RuntimeException("Not found member");
throw new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND);
@RestControllerAdvice
์ ๋ํ
์ด์
์ด ๋ถ์ ํด๋์ค์ ํด๋น ์์ธ์ ์๋ต์ ๊ตฌํํ๊ณ ์๋ ๋ฉ์๋์์ ๊ทธ throwํ ์์ธ๋ฅผ catchํ์ฌ ๊ฐ์ด ๋ ๋ผ์จ ์์ธ ๋ฉ์ธ์ง๋ฅผ ์ถ๋ ฅํด์ค
class๊ฐ ์๋ enum์ผ๋ก ์๋น์ค ๊ณ์ธต์์ ๋์ง Custom Exception์ ์ฌ์ฉํ ExceptionCode
๋ฅผ ์ ์
โ ๋น์ฆ๋์ค ๋ก์ง์์ ๋ฐ์ํ๋ ๋ค์ํ ์ ํ์ ์์ธ๋ฅผ enum์ ์ถ๊ฐํด์ ์ฌ์ฉํ ์ ์์
์์ธ๋ค์ ์ ๋ฆฌํ ExceptionCode
๋ฅผ ๋ฉค๋ฒ ๋ณ์๋ก ๋ฐ๊ณ RuntimeException
์ ์์๋ฐ๋ BusinessLogicException
ํด๋์ค๋ฅผ ์ ์
( ์ด ๋, ์์ฑ์์์ exceptionCode.getMessage()
์ ๊ฒฝ์ฐ์๋ ์์ ํด๋์ค์ ์์ฑ์๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ supuer()
ํค์๋ ์ฌ์ฉ )
โ @RestControllerAdvice
์ ๋ํ
์ด์
์ ๊ฐ์ง๊ณ ์๋ ํด๋์ค์๋ ResponseEntity
์ ์ฐ๋ฆฌ๊ฐ ์ ์ํ ErrorResponse
์ฌ์ฉ ๊ฐ๋ฅ
โ๏ธ
ResponseEntity
โ ๋ฆฌํด๊ฐ์ผ๋ก HttpStatus๋ฅผ ๋์ ์ผ๋ก ์ง์ ๊ฐ๋ฅ
โ
โ๏ธErrorResponse
โ ๊ณ ์ ๋ HttpStatus๋ฅผ ์ง์ ํ๊ธฐ ๋๋ฌธ์ @ResponseStatus ์ ๋ํ ์ด์ ์ผ๋ก HttpStatus๋ฅผ ์ง์ ํด์ค์ผํจ
projects ๋ด์ be-template-exception-handle ํ์ผ
git ๋ด์ be-homework-exception ํ์ผ
์ ๋ฒ ํ์ต๊น์ง๋ ๋ฐ๋ผ๊ฐ๊ธฐ ๊ด์ฐฎ์๋๋ฐ ์ค๋์ ๊ฐ์๊ธฐ ์ฝ๋ ์๋ ๋ง์์ง๋ฉด์ ์ดํด๊ฐ ์ด๋ ค์ด ๋ถ๋ถ์ด ๊ฝค ์์๋ค !!
๊ทธ๋๋ ํ์ด ํ์ต ํ๋ฉด์ ํ์ด๋์ด ๋ง์ด ์๋ ค์ฃผ์
์ ์ดํด๊ฐ ๋ง์ด ๋์๋ค! ๐
๊ทผ๋ฐ ํ๋ฃจํ๋ฃจ ์ค์ตํด๋ณด๋ ์ฝ๋์ ์์ด ๋ง๋ค๋ณด๋ ๋ณต์ต์ ์์ฃผ ํด์ค์ผ ์์ง ์์ ๊ฒ ๊ฐ๋ค ใ