Spring ExceptionResolver

Springboot๊ฐ€ ์ œ๊ณตํ•˜๋Š” ExceptionResolver๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ HandlerExceptionResolverComosite์— ๋‹ค์Œ ์ˆœ์„œ๋กœ ๋“ฑ๋ก๋œ๋‹ค. (์šฐ์„ ์ˆœ์œ„)

  1. ExceptionHandlerExceptionResolver

  2. ResponseStatusExceptionResolver โ†’ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‘๋‹ต ์ฝ”๋“œ ๋ณ€๊ฒฝ

  3. DefaultHandlerExceptionResolover โ†’ ์Šคํ”„๋ง ๋‚ด๋ถ€์—์„œ ์ž์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌ

์˜ˆ์™ธ๊ฐ€ ExceptionHandlerExceptionResolver์—์„œ ์ฒ˜๋ฆฌ๋˜๋ฉด ์ดํ›„์˜ resolver๋Š” ์ง„ํ–‰๋˜์ง€ ์•Š๊ณ  null์ด ๋ฐ˜ํ™˜๋  ๊ฒฝ์šฐ ๋‹ค์Œ resolver๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

ResponseStatusExceptionResolver

์˜ˆ์™ธ์— ๋”ฐ๋ผ์„œ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ง€์ •ํ•˜๋Š” resolver์ด๋‹ค.

  • @ResponseStatus ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ๋Š” ์˜ˆ์™ธ

  • ResponseStatusException ์˜ˆ์™ธ

@ResponseStatus

@ResponseStatus(code = HttpStatus.XXX, reasone = "error message")
public class CustomExcpeiton extends RuntimeException {
   ...
}

์ •์˜ํ•œ ํด๋ž˜์Šค๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด, ์ƒํƒœ ์ฝ”๋“œ์™€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ response.sendError()์— ๋„ฃ์–ด์ฃผ๊ณ  ModelAndView()๋ฅผ return ํ•œ๋‹ค.

ResponseStatusException

@ResponseStatus ์–ด๋…ธํ…Œ์ด์…˜์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ณณ์—๋Š” ์ ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์–ด๋…ธํ…Œ์ด์…˜์„ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์˜ˆ์™ธ ์ฝ”๋“œ ๊ฐ™์€ ๊ณณ์— ์ ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

์ด๋•Œ๋Š” ResponseStatusException ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์œ„์˜ ๋‘ ๊ฒฝ์šฐ ์ „๋ถ€ ResponseStatusExceptionResolver๊ฐ€ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.

  • ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋‚ด๋ถ€์˜ doResolveException()์ด ํ˜ธ์ถœ๋จ.

DefaultHandlerExceptionResolover

์Šคํ”„๋ง ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์Šคํ”„๋ง ์˜ˆ์™ธ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” resolver์ด๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ ์‹œ์ ์— ํƒ€์ž…์ด ๋งž์ง€ ์•Š์œผ๋ฉด ๋‚ด๋ถ€์—์„œ TypeMismatchException์ด ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๊นŒ์ง€ ์ „๋‹ฌ๋˜๊ณ  500 ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์€ ๋Œ€๋ถ€๋ถ„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ HTTP ์š”์ฒญ ์ •๋ณด๋ฅผ ์ž˜๋ชป ํ˜ธ์ถœํ•ด์„œ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์ด๋Ÿฐ ๊ฒฝ์šฐ HTTP ์ƒํƒœ ์ฝ”๋“œ 400์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์–ด์žˆ๋‹ค.

์ด resolver๋Š” ์ด๊ฒƒ์„ 500์ด ์•„๋‹ˆ๋ผ 400์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•œ๋‹ค.

handleTypeMismatch()์˜ ๋‚ด๋ถ€์—์„œ๋Š” send.Error(SC_BAD_REQUEST)๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

์œ„์™€ ๊ฐ™์€ HandlerExceptionResolver๋“ค์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ธฐ ๋ณต์žกํ•˜๋‹ค. API ์˜ค๋ฅ˜์—๋Š” response.sendError()๋ฅผ ํ†ตํ•ด ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์•ผ ํ•˜๊ณ , ModelAndView๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ๋„ ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค.

์Šคํ”„๋ง์€ ์ด๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด @ExceptionHandler๋ผ๋Š” ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

์ด๊ฒƒ์„ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์ด ExceptionHandlerExceptionResolver์ด๋‹ค.

@ExceptionHandler

์˜ˆ์™ธ์— ๋Œ€ํ•œ ๋ณ„๋„์˜ ์„ค์ •์ด ์—†์œผ๋ฉด BasicErrorController๋กœ ์ „๋‹ฌ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ BasicErrorController๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ HandlerExceptioResolver๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์€ ๋ชจ๋“  API ์—๋Ÿฌ๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์‰ฝ์ง€ ์•Š๋‹ค.

  • resolver๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด json ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , HttpServletResponse์— ์ง์ ‘ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ฃผ๊ณ , ModelAndView๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ๋‹ค.

  • ์œ„ ๋ฐฉ์‹์€ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฐ™์€ Exception(RuntimeException ๊ฐ™์€)์„ ๋‹ค๋ฅธ ํ˜•ํƒœ๋กœ ๋‹ค๋ฃจ๊ธฐ ์–ด๋ ต๋‹ค.

์Šคํ”„๋ง์€ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ @ExceptionHandler๋ฅผ ์‚ฌ์šฉํ•ด์„œExceptionHandlerExceptionResolver๋ฅผ ๋™์ž‘ํ•œ๋‹ค.

์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ExceptionHandlerResolver๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @ExceptionHandler๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํƒ์ƒ‰ํ•œ๋‹ค.

์กด์žฌํ•œ๋‹ค๋ฉด ์‹คํ–‰ํ•˜๊ณ  ์ •์ƒ์ ์ธ ํ๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ”์„œ returnํ•œ๋‹ค. ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์ง€๋งŒ, ์ •์ƒ ํ๋ฆ„์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ƒํƒœ ์ฝ”๋“œ๋ฅผ 200์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค. (์˜ˆ์™ธ๋Š” ์ฒ˜๋ฆฌํ•จ.)

  • ์ •์ƒ ํ๋ฆ„์œผ๋กœ ๋ฐ”๋€Œ๋ฉด, ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์— ์˜ˆ์™ธ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋‹ค์‹œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ๊ทธ๋Ÿฌ์ง€ ์•Š๋Š”๋‹ค.

๋”ฐ๋ผ์„œ ์ƒํƒœ ์ฝ”๋“œ๋„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์œผ๋ฉด @ResponseStatus()๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

Last updated