05.Exception

Exception

์˜ˆ์™ธ ์ฒ˜๋ฆฌ์™€ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€

์„œ๋ธ”๋ฆฟ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

์ˆœ์ˆ˜ ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ง€์› ๋ฐฉ์‹

.

Exception

์ž๋ฐ” ์ง์ ‘ ์‹คํ–‰ ์‹œ ์˜ˆ์™ธ ๋ฐœ์ƒ

  • ์ž๋ฐ” ๋ฉ”์ธ ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•  ๊ฒฝ์šฐ main ์“ฐ๋ ˆ๋“œ ์‹คํ–‰

  • main ์“ฐ๋ ˆ๋“œ ์‹คํ–‰ ๋„์ค‘์— ์˜ˆ์™ธ๋ฅผ ์žก์ง€ ๋ชปํ•˜๊ณ  ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์ง€๋ฉด, ์˜ˆ์™ธ ์ •๋ณด๋ฅผ ๋‚จ๊ธฐ๊ณ  ํ•ด๋‹น ์“ฐ๋ ˆ๋“œ ์ข…๋ฃŒ

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์˜ˆ์™ธ ๋ฐœ์ƒ

@GetMapping("/error-ex")
    public void errorEx() {
    throw new RuntimeException("์˜ˆ์™ธ ๋ฐœ์ƒ!");
}
  • ์‚ฌ์šฉ์ž ์š”์ฒญ๋ณ„๋กœ ๋ณ„๋„์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ํ• ๋‹น๋˜๊ณ , ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ์‹คํ–‰

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ, try~catch ๋กœ ์˜ˆ์™ธ๋ฅผ ์žก์•„์„œ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์—†์Œ.

  • ํ•˜์ง€๋งŒ, ์˜ˆ์™ธ๋ฅผ ์žก์ง€ ๋ชปํ•˜๊ณ , ์„œ๋ธ”๋ฆฟ ๋ฐ–์œผ๋กœ ์˜ˆ์™ธ๊ฐ€ ์ „๋‹ฌ๋  ๊ฒฝ์šฐ WAS(tomcat)๊นŒ์ง€ ์˜ˆ์™ธ ์ „๋‹ฌ

    WAS <- ํ•„ํ„ฐ <- ์„œ๋ธ”๋ฆฟ <- ์ธํ„ฐ์…‰ํ„ฐ <- ์ปจํŠธ๋กค๋Ÿฌ(์˜ˆ์™ธ๋ฐœ์ƒ)
  • WAS ๋Š” Exception ์˜ˆ์™ธ๊ฐ€ ์˜ฌ๋ผ์˜ค๋ฉด ์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์œผ๋กœ ์ธ์ง€ํ•˜๊ณ  HTTP Status 500 โ€“ Internal Server Error ๋ฐ˜ํ™˜

    # ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ์˜ˆ์™ธ ํŽ˜์ด์ง€ OFF
    server.error.whitelabel.enabled=false

.

response.sendError(HTTP ์ƒํƒœ ์ฝ”๋“œ, ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€)

  • ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ HttpServletResponse.sendError ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

    • sendError ํ˜ธ์ถœ ์‹œ ๋ฐ”๋กœ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, response ๋‚ด๋ถ€์— ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์—ฌ WAS(Servlet container) ์—๊ฒŒ ์ „๋‹ฌ

    • WAS(Servlet container) ๋Š” ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต ์ „์— response ์— sendError() ํ˜ธ์ถœ ๊ธฐ๋ก ํ™•์ธ ํ›„, ํ˜ธ์ถœ๋˜์—ˆ๋‹ค๋ฉด ์„ค์ •ํ•œ ์˜ค๋ฅ˜ ์ฝ”๋“œ์— ๋งž๋Š” ๊ธฐ๋ณธ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ์ถœ๋ ฅ

  • sendError ํ๋ฆ„

์„œ๋ธ”๋ฆฟ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€

์„œ๋ธ”๋ฆฟ์€ Exception ์ด ์„œ๋ธ”๋ฆฟ ๋ฐ–์œผ๋กœ ์ „๋‹ฌ๋˜๊ฑฐ๋‚˜ response.sendError() ํ˜ธ์ถœ ์‹œ ๊ฐ ์ƒํ™ฉ์— ๋งž์ถ˜ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ ์ œ๊ณต

์„œ๋ธ”๋ฆฟ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ๋“ฑ๋ก

  • ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋Š” ์˜ˆ์™ธ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ํ•ด๋‹น ์˜ˆ์™ธ์™€ ๊ทธ ์ž์‹ ํƒ€์ž…์˜ ์˜ค๋ฅ˜๋ฅผ ํ•จ๊ป˜ ์ฒ˜๋ฆฌ

์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ์ปจํŠธ๋กค๋Ÿฌ

์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ์š”์ฒญ ํ๋ฆ„

  • WAS ๊นŒ์ง€ ์˜ˆ์™ธ๊ฐ€ ์ „ํŒŒ๋  ๊ฒฝ์šฐ, WAS ๋Š” ํ•ด๋‹น ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ์ •๋ณด ํ™•์ธ ํ›„ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ์š”์ฒญ

  • WAS ๋Š” ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ์š”์ฒญ ์‹œ ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ request.attribute ์— ์ถ”๊ฐ€ํ•ด์„œ ์ „๋‹ฌ

DispatcherType ๐ŸŒž

ํด๋ผ์ด์–ธํŠธ๋กœ ๋ถ€ํ„ฐ ๋ฐœ์ƒํ•œ ์ •์ƒ ์š”์ฒญ์ธ์ง€, ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•œ ๋‚ด๋ถ€ ์š”์ฒญ์ธ์ง€ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ธ”๋ฆฟ์€ DispatcherType ์ •๋ณด ์ œ๊ณต

  • ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ์ถœ๋ ฅ์„ ์œ„ํ•ด WAS ๋‚ด๋ถ€์—์„œ ํ•„ํ„ฐ, ์„œ๋ธ”๋ฆฟ, ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœ

  • ์ด๋ฏธ ์ดˆ๊ธฐ ์š”์ฒญ์—์„œ ๊ฒ€์ฆ์ด ์™„๋ฃŒ๋œ ๋ถ€๋ถ„์€ ์žฌํ˜ธ์ถœ ๋  ๊ฒฝ์šฐ ๋น„ํšจ์œจ์ 

.

DispatcherType

  • ์„œ๋ธ”๋ฆฟ ์ŠคํŽ™์€ ์‹ค์ œ ๊ณ ๊ฐ์ด ์š”์ฒญํ•œ ๊ฒƒ์ธ์ง€, ์„œ๋ฒ„๊ฐ€ ๋‚ด๋ถ€์—์„œ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ธ์ง€ DispatcherType ์œผ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณต

.

ํ•„ํ„ฐ์™€ DispatcherType

  • DispatcherType ๋กœ๊ทธ ํ•„ํ„ฐ

  • ๋กœ๊ทธ ํ•„ํ„ฐ ๋“ฑ๋ก

.

ํ•„ํ„ฐ์™€ Interceptor

  • DispatcherType ๋กœ๊ทธ ์ธํ„ฐ์…‰ํ„ฐ

  • ๋กœ๊ทธ ์ธํ„ฐ์…‰ํ„ฐ ๋“ฑ๋ก

.

DispatcherType ํ๋ฆ„

์Šคํ”„๋ง ๋ถ€ํŠธ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ๐ŸŒž

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ์„œ๋ธ”๋ฆฟ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ํ˜ธ์ถœ์— ํ•„์š”ํ–ˆ๋˜ ์•„๋ž˜ ๋ณต์žกํ•œ ๊ณผ์ •์„ ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณต

  • WebServerCustomizer ๋งŒ๋“ค๊ธฐ

  • ์˜ˆ์™ธ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ErrorPage ์ถ”๊ฐ€ โž” ErrorPage ์ž๋™ ๋“ฑ๋ก

    • /error ๊ฒฝ๋กœ๋ฅผ ๊ธฐ๋ณธ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋กœ ์„ค์ •

    • ์„œ๋ธ”๋ฆฟ ๋ฐ–์œผ๋กœ ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์ง€๊ฑฐ๋‚˜, response.sendError(...) ํ˜ธ์ถœ ์‹œ ๋ชจ๋“  ์˜ค๋ฅ˜๋Š” /error ํ˜ธ์ถœ

    • ErrorMvcAutoConfiguration ํด๋ž˜์Šค๊ฐ€ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋ฅผ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ์—ญํ• 

  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์šฉ ์ปจํŠธ๋กค๋Ÿฌ(ErrorPageController) ์ƒ์„ฑ โž” ์ž๋™ ๋“ฑ๋ก(BasicErrorController)

    • ErrorPage ์—์„œ ๋“ฑ๋กํ•œ /error ๋ฅผ ๋งคํ•‘ํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ

.

BasicErrorController

  • ๊ธฐ๋ณธ์ ์ธ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ๋กœ์ง์ด ๋ชจ๋‘ ๊ตฌํ˜„

  • ๊ฐœ๋ฐœ์ž๋Š” ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ํ™”๋ฉด๋งŒ BasicErrorController ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฃฐ๊ณผ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ์„œ ๋“ฑ๋ก

    • ์ •์  HTML ์ผ ๊ฒฝ์šฐ ์ •์  ๋ฆฌ์†Œ์Šค, ๋ทฐ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•œ ๋™์  ์˜ค๋ฅ˜ ํ™”๋ฉด์ผ ๊ฒฝ์šฐ ๋ทฐ ํ…œํ”Œ๋ฆฟ ๊ฒฝ๋กœ์— ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ํŒŒ์ผ ์ƒ์„ฑ

.

BasicErrorController View ์„ ํƒ ์šฐ์„ ์ˆœ์œ„

.1. ๋ทฐ ํ…œํ”Œ๋ฆฟ

  • resources/templates/error/500.html

  • resources/templates/error/5xx.html

.2. ์ •์  ๋ฆฌ์†Œ์Šค(static, public)

  • resources/static/error/400.html

  • resources/static/error/404.html

  • resources/static/error/4xx.html

.3. ์ ์šฉ ๋Œ€์ƒ์ด ์—†์„ ๋•Œ ๋ทฐ ์ด๋ฆ„(error)

  • resources/templates/error.html

ํ•ด๋‹น ๊ฒฝ๋กœ ์œ„์น˜์— HTTP ์ƒํƒœ ์ฝ”๋“œ ์ด๋ฆ„์˜ ๋ทฐ ํŒŒ์ผ์„ ๋„ฃ์–ด๋‘์ž.

๋ทฐ ํ…œํ”Œ๋ฆฟ์ด ์ •์  ๋ฆฌ์†Œ์Šค๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๊ณ ,

404, 500 ์ฒ˜๋Ÿผ ๊ตฌ์ฒด์ ์ธ ๊ฒƒ์ด 5xx์ฒ˜๋Ÿผ ๋œ ๊ตฌ์ฒด์ ์ธ ๊ฒƒ ๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๋‹ค.

.

BasicErrorController ์ œ๊ณต ๊ธฐ๋ณธ ์ •๋ณด

  • ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ model ์— ๋‹ด์•„ View ์— ์ „๋‹ฌ

  • message, exception, errors, trace ์ •๋ณด๋Š” ๋ณด์•ˆ์ƒ default ๋กœ ํฌํ•จ์ด ๋˜์–ด์žˆ์ง€ ์•Š์Œ

    • properties ์„ค์ •์„ ํ†ตํ•ด ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ model ์— ํฌํ•จํ• ์ง€ ์—ฌ๋ถ€ ์„ ํƒ

    • never: ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

    • always: ํ•ญ์ƒ ์‚ฌ์šฉ

    • on_param: ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ํ•ด๋‹น ์ •๋ณด ๋…ธ์ถœ

      • HTTP ์š”์ฒญ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ(?message=&errorsa=&trace=)๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ํ•ด๋‹น ์ •๋ณด๋“ค์ด model ์— ๋‹ด๊ฒจ ๋ทฐ ํ…œํ”Œ๋ฆฟ์— ์ถœ๋ ฅ

      • ์šด์˜ ์„œ๋ฒ„์—์„œ๋Š” ๋น„๊ถŒ์žฅ

์‹ค๋ฌด์—์„œ๋Š” ์ด ์ •๋ณด๋“ค์„ ๋…ธ์ถœํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ๊น”๋”ํ•œ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€์™€ ๊ณ ๊ฐ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ ,

์˜ค๋ฅ˜๋Š” ์„œ๋ฒ„์— ๋กœ๊ทธ๋กœ ๋‚จ๊ฒจ์„œ ๋กœ๊ทธ๋กœ ํ™•์ธํ•˜์ž.

.

์Šคํ”„๋ง ๋ถ€ํŠธ ์˜ค๋ฅ˜ ๊ด€๋ จ ์˜ต์…˜

ํ™•์žฅ ํฌ์ธํŠธ

  • ์—๋Ÿฌ ๊ณตํ†ต ์ฒ˜๋ฆฌ ์ปจํŠธ๋กค๋Ÿฌ์˜ ๊ธฐ๋Šฅ์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ ErrorController ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„์„œ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜, BasicErrorController ๋ฅผ ์ƒ์† ๋ฐ›์•„์„œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

์Šคํ”„๋ง ๋ถ€ํŠธ ๊ธฐ๋ณธ ์ œ๊ณต ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์˜ค๋ฅ˜ ํŽ˜์ด์ง€ ๊ด€๋ จ ๋Œ€๋ถ€๋ถ„์˜ ๋ฌธ์ œ๋Š” ์†์‰ฝ๊ฒŒ ํ•ด๊ฒฐ ๊ฐ€๋Šฅํ•˜๋‹ค.

API ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋Š” ๋‹จ์ˆœํžˆ ๊ณ ๊ฐ์—๊ฒŒ ์˜ค๋ฅ˜ ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๋ฉด ๋˜์ง€๋งŒ, API ๋Š” ๊ฐ ์˜ค๋ฅ˜ ์ƒํ™ฉ์— ๋งž๋Š” ์˜ค๋ฅ˜ ์‘๋‹ต ์ŠคํŽ™์„ ์ •ํ•˜๊ณ , JSON์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ตํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

produces ์„ค์ •

  • produces = MediaType.APPLICATION_JSON_VALUE

    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญํ•˜๋Š” HTTP Header Accept ๊ฐ’์ด application/json ์ผ ๋•Œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

  • ResponseEntity ๋Š” ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๊ฐ€ ๋™์ž‘ํ•˜๋ฉด์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ JSON ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜

Spring Boot ๊ธฐ๋ณธ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ

API ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋„ ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ์˜ค๋ฅ˜ ๋ฐฉ์‹์„ ์‚ฌ์šฉ

BasicErrorController ์ฝ”๋“œ ์ผ๋ถ€

  • ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ๊ธฐ๋ณธ ์„ค์ •์€ ์˜ค๋ฅ˜ ๋ฐœ์ƒ์‹œ /error ๋ฅผ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋กœ ์š”์ฒญ

  • BasicErrorController ๋Š” /error ๊ฒฝ๋กœ๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ๋ฐ›์Œ.(server.error.path ๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅ

BasicErrorController ๋Š” HTML ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ ๋งค์šฐ ํŽธ๋ฆฌ

๋‹จ, API ๋Š” ๊ฐ ์ปจํŠธ๋กค๋Ÿฌ๋‚˜ ์˜ˆ์™ธ๋งˆ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ด์•ผ ํ•˜๋ฏ€๋กœ @ExceptionHandler ์‚ฌ์šฉ ๊ถŒ์žฅ

ExceptionResolver

HandlerExceptionResolver

  • ์Šคํ”„๋ง MVC ๋Š” ์ปจํŠธ๋กค๋Ÿฌ(ํ•ธ๋“ค๋Ÿฌ) ๋ฐ–์œผ๋กœ ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์ง„ ๊ฒฝ์šฐ ์˜ˆ์™ธ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , ๋™์ž‘์„ ์ƒˆ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” HandlerExceptionResolver ์ œ๊ณต

    • ExceptionResolver ์ ์šฉ ์ „ ์˜ˆ์™ธ์ฒ˜๋ฆฌ

      Result
    • ExceptionResolver ์ ์šฉ ํ›„ ์˜ˆ์™ธ์ฒ˜๋ฆฌ

      Result
  • ์ฐธ๊ณ . ExceptionResolver ๋กœ ์˜ˆ์™ธ๋ฅผ ํ•ด๊ฒฐํ•ด๋„ postHandle() ํ˜ธ์ถœ X

HandlerExceptionResolver Interface ๊ตฌํ˜„

.

HandlerExceptionResolver ๋ฐ˜ํ™˜ ๊ฐ’์— ๋”ฐ๋ฅธ DispatcherServlet ๋™์ž‘ ๋ฐฉ์‹

  • ๋นˆ ModelAndView

    • new ModelAndView() ์ฒ˜๋Ÿผ ๋นˆ ModelAndView ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ทฐ๋ฅผ ๋ Œ๋”๋ง ํ•˜์ง€์•Š๊ณ , ์ •์ƒ ํ๋ฆ„์œผ๋กœ ์„œ๋ธ”๋ฆฟ์ด ๋ฆฌํ„ด

  • ModelAndView ์ง€์ •

    • ModelAndView ์— View, Model ๋“ฑ์˜ ์ •๋ณด๋ฅผ ์ง€์ •ํ•ด์„œ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ทฐ๋ฅผ ๋ Œ๋”๋ง

  • nul

    • null ์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ๋‹ค์Œ ExceptionResolver ๋ฅผ ์ฐพ์•„์„œ ์‹คํ–‰

    • ๋งŒ์•ฝ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ExceptionResolver ๊ฐ€ ์—†์œผ๋ฉด ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ฐ€ ์•ˆ๋˜๊ณ , ๊ธฐ์กด์— ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ์„œ๋ธ”๋ฆฟ ๋ฐ–์œผ๋กœ ๋˜์ง

.

ExceptionResolver ํ™œ์šฉ

  • ์˜ˆ์™ธ ์ƒํƒœ ์ฝ”๋“œ ๋ณ€ํ™˜

    • ์˜ˆ์™ธ๋ฅผ response.sendError(..) ํ˜ธ์ถœ๋กœ ๋ณ€๊ฒฝํ•ด์„œ ์„œ๋ธ”๋ฆฟ์—์„œ ์ƒํƒœ ์ฝ”๋“œ์— ๋”ฐ๋ฅธ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์œ„์ž„

    • ์ดํ›„ WAS ๋Š” ์„œ๋ธ”๋ฆฟ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๋ฅผ ์ฐพ์•„์„œ ๋‚ด๋ถ€ ํ˜ธ์ถœ(default. /error)

    • ex. ์‹ค์ œ ์„œ๋ฒ„์—์„œ๋Š” 500 ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์ง€๋งŒ Client ์—๊ฒŒ๋Š” 4xx ์ฝ”๋“œ ์ „๋‹ฌ

  • ๋ทฐ ํ…œํ”Œ๋ฆฟ ์ฒ˜๋ฆฌ

    • ModelAndView ์— ๊ฐ’์„ ์ฑ„์›Œ์„œ ์˜ˆ์™ธ์— ๋”ฐ๋ฅธ ์ƒˆ๋กœ์šด ์˜ค๋ฅ˜ ํ™”๋ฉด์„ ๋ทฐ ๋ Œ๋”๋ง์„ ํ†ตํ•ด ๊ณ ๊ฐ์—๊ฒŒ ์ œ๊ณต

    • return new ModelAndView("error/400");

  • API ์‘๋‹ต ์ฒ˜๋ฆฌ

    • response.getWriter().println("hello"); ์ฒ˜๋Ÿผ HTTP ์‘๋‹ต ๋ฐ”๋””์— ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ์ „๋‹ฌ

    • ์—ฌ๊ธฐ์— JSON ์œผ๋กœ ์‘๋‹ตํ•˜๋ฉด API ์‘๋‹ต ์ฒ˜๋ฆฌ

.

WebMvcConfigurer ์— ๋“ฑ๋ก

  • configureHandlerExceptionResolvers ์‚ฌ์šฉ ์‹œ ์Šคํ”„๋ง์ด ๊ธฐ๋ณธ์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ExceptionResolver ๊ฐ€ ์ œ๊ฑฐ๋˜๋ฏ€๋กœ extendHandlerExceptionResolvers ๋ฅผ ์‚ฌ์šฉ

ExceptionResolver ์ ์šฉ

Exception

HandlerExceptionResolver ๊ตฌํ˜„

WebConfig ์— HandlerExceptionResolver ๋“ฑ๋ก

์ •๋ฆฌ.

์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ExceptionResolver ์—์„œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌ

์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๊นŒ์ง€ ์˜ˆ์™ธ๊ฐ€ ์ „๋‹ฌ๋˜์ง€ ์•Š๊ณ (๊ฒฐ๊ณผ์ ์œผ๋กœ WAS ์ž…์žฅ์—์„œ๋Š” ์ •์ƒ ์ฒ˜๋ฆฌ)

์Šคํ”„๋ง MVC ์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” ์ข…๋ฃŒ

Spring ExceptionResolver

Spring Boot ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ExceptionResolver

HandlerExceptionResolverComposite ์— ์•„๋ž˜ ์ˆœ์„œ๋กœ ๋“ฑ๋ก

  • ExceptionHandlerExceptionResolver

    • @ExceptionHandler ์ฒ˜๋ฆฌ

    • API ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” ๋Œ€๋ถ€๋ถ„ ์ด ๊ธฐ๋Šฅ์œผ๋กœ ํ•ด๊ฒฐ

  • ResponseStatusExceptionResolver

    • HTTP ์ƒํƒœ ์ฝ”๋“œ ๋ณ€๊ฒฝ

  • DefaultHandlerExceptionResolver

    • ์Šคํ”„๋ง ๋‚ด๋ถ€ ๊ธฐ๋ณธ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

ExceptionHandler ๐ŸŒž

ExceptionHandlerExceptionResolver

์Šคํ”„๋ง์€ API ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด @ExceptionHandler ๋ฅผ ์‚ฌ์šฉํ•œ ํŽธ๋ฆฌํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ ์ œ๊ณต

  • ๊ฐ ์‹œ์Šคํ…œ๋งˆ๋‹ค ๋‹ค๋ฅธ ์‘๋‹ต ๋ชจ์–‘๊ณผ ์ŠคํŽ™

  • ์˜ˆ์™ธ์— ๋”ฐ๋ฅธ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์‘๋‹ต

  • ์ปจํŠธ๋กค๋Ÿฌ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์˜ˆ์™ธ ์‘๋‹ต

  • ModelAndView ๊ฐ€ ์•„๋‹Œ Json ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜

  • ๋“ฑ.. ์„ธ๋ฐ€ํ•œ ์ œ์–ด ํ•„์š”

.

@ExceptionHandler ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

  • @ExceptionHandler ์„ ์–ธ ํ›„ ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ์€ ์˜ˆ์™ธ ์ง€์ •

  • ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ

  • ์ง€์ •ํ•œ ์˜ˆ์™ธ ๋˜๋Š” ํ•˜์œ„ ์ž์‹ ํด๋ž˜์Šค ๋ชจ๋‘ ์ฒ˜๋ฆฌ

  • ๋‹ค์–‘ํ•œ ์˜ˆ์™ธ๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

  • ์˜ˆ์™ธ ์ƒ๋žต

  • ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์‘๋‹ต

.

@ExceptionHandler ์‹คํ–‰ ํ๋ฆ„

  • ์ปจํŠธ๋กค๋Ÿฌ ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋กœ ์˜ˆ์™ธ(IllegalArgumentException)๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ ๋ฐ–์œผ๋กœ ๋˜์ ธ์ง

  • DispatcherServlet ์„ ๊ฑฐ์ณ ์˜ˆ์™ธ ๋ฐœ์ƒ์œผ๋กœ ExceptionResolver ์ž‘๋™

    • ๊ฐ€์žฅ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ ExceptionHandlerExceptionResolver ์‹คํ–‰

  • ExceptionHandlerExceptionResolver ๋Š” ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ์— IllegalArgumentException ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” @ExceptionHandler ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ

  • @ExceptionHandler ์„ ์–ธ ๋ฉ”์„œ๋“œ ์‹คํ–‰

    • @RestController ์ด๋ฏ€๋กœ @ResponseBody ์ ์šฉ โž” HTTP ์ปจ๋ฒ„ํ„ฐ๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  JSON ์‘๋‹ต

  • @ResponseStatus(HttpStatus.BAD_REQUEST) ๋ฅผ ์ง€์ •ํ–ˆ์œผ๋ฏ€๋กœ HTTP ์ƒํƒœ ์ฝ”๋“œ 400 ์‘๋‹ต

    • ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๊นŒ์ง€ ๋‚ด๋ ค๊ฐ€์ง€ ์•Š๊ณ  ์ •์ƒ ํ๋ฆ„์œผ๋กœ ๋ฐ˜ํ™˜

.

์ƒํ™ฉ์— ๋”ฐ๋ฅธ @ExceptionHandler ํ™œ์šฉ

@ControllerAdvice ๐ŸŒž

์—ฌ๋Ÿฌ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ชจ์•„์„œ ์ฒ˜๋ฆฌ

  • @ExceptionHandler ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์˜ˆ์™ธ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์ •์ƒ ์ฝ”๋“œ์™€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ฝ”๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ์ปจํŠธ๋กค๋Ÿฌ์— ์„ž์—ฌ ์žˆ๋Š” ๋‹จ์ ์ด ์กด์žฌ

  • @ControllerAdvice ๋˜๋Š” @RestControllerAdvice ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ถ„๋ฆฌํ•ด ๋ณด์ž.

@ControllerAdvice

  • ๋Œ€์ƒ์œผ๋กœ ์ง€์ •ํ•œ ์—ฌ๋Ÿฌ ์ปจํŠธ๋กค๋Ÿฌ์— @ExceptionHandler, @InitBinder ๊ธฐ๋Šฅ์„ ๋ถ€์—ฌ

  • @ControllerAdvice ์— ๋Œ€์ƒ์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์— ์ ์šฉ(๊ธ€๋กœ๋ฒŒ ์ ์šฉ)

  • @RestControllerAdvice ๋Š” @ControllerAdvice ์™€ ๋™์ผํ•˜๊ณ , @ResponseBody ๊ฐ€ ์ถ”๊ฐ€

    • @Controller, @RestController ์ฐจ์ด์™€ ๋™์ผ

@ExceptionHandler ์™€ @ControllerAdvice ๋ฅผ ์กฐํ•ฉํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ

ResponseStatusExceptionResolver

์˜ˆ์™ธ์— ๋”ฐ๋ผ HTTP ์ƒํƒœ ์ฝ”๋“œ ์ง€์ •

  • @ResponseStatus ๊ฐ€ ๋‹ฌ๋ ค์žˆ๋Š” ์˜ˆ์™ธ

  • ResponseStatusException ์˜ˆ์™ธ

.

@ResponseStatus ์˜ˆ์™ธ

  • ํ•ด๋‹น ์˜ˆ์™ธ๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ ๋ฐ–์œผ๋กœ ๋„˜์–ด๊ฐ€๋ฉด ResponseStatusExceptionResolver ์˜ˆ์™ธ๊ฐ€ ํ•ด๋‹น ์• ๋…ธํ…Œ์ด์…˜์„ ํ™•์ธํ•ด์„œ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝ(HttpStatus.BAD_REQUEST(400))ํ•˜๊ณ , ๋ฉ”์‹œ์ง€ ํฌํ•จ

    • ResponseStatusExceptionResolver ์—์„œ response.sendError(statusCode, resolvedReason) ํ˜ธ์ถœ

  • sendError(400) ํ˜ธ์ถœ๋กœ WAS ์—์„œ ๋‹ค์‹œ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€(/error) ๋‚ด๋ถ€ ์š”์ฒญ

  • reason ์„ MessageSource ์—์„œ ์ฐพ๋Š” ๋ฉ”์„ธ์ง€ ๊ธฐ๋Šฅ ์ œ๊ณต โž” reason = "error.bad"

`

ResponseStatusException ์˜ˆ์™ธ

  • ์ง์ ‘ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ์˜ˆ์™ธ์— ResponseStatusException ์ ์šฉ

    • @ResponseStatus ๋Š” ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ง์ ‘ (์กฐ๊ฑด์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ)๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ์˜ˆ์™ธ์—๋Š” ์ ์šฉ ๋ถˆ๊ฐ€

DefaultHandlerExceptionResolver

  • ์Šคํ”„๋ง ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์Šคํ”„๋ง ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

    • ์Šคํ”„๋ง ๋‚ด๋ถ€ ์˜ค๋ฅ˜๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€์— ๋Œ€ํ•œ ๋งŽ์€ ๋‚ด์šฉ์ด ์ •์˜

  • TypeMismatchException ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” 500 ์˜ค๋ฅ˜๋ฅผ DefaultHandlerExceptionResolver ๊ฐ€ 400 ์˜ค๋ฅ˜๋กœ ๋ณ€๊ฒฝ

DefaultHandlerExceptionResolver.handleTypeMismatch

Last updated