์คํ๋ง์ ์ฌ์ฉํ์ง ์๋ ์์ํ ์๋ธ๋ฆฟ ์ปจํ ์ด๋๋ ์์ธ๋ฅผ ๋ค์ ๋ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ค.
- Exception - ์ฐ๋ฆฌ๊ฐ ์๊ณ ์๋ ๊ทธ ์ผ๋ฐ์ ์ธ ์์ธ
- response.sendError(HTTP ์ํ ์ฝ๋, ์ค๋ฅ ๋ฉ์์ง)
1. Exception์ ์ฒ๋ฆฌ ๋ฐฉ์
์๋ฐ์ ๋ฉ์ธ ๋ฉ์๋๋ฅผ ์ง์ ์คํํ๋ ๊ฒฝ์ฐ, main์ด๋ผ๋ ์ด๋ฆ์ ์ฐ๋ ๋๊ฐ ์คํ๋๋ค.
๋ง์ฝ ์คํ ๋์ค์ ์์ธ๋ฅผ ์ก์ง ๋ชปํ๊ณ ์ฒ์ ์คํํ main() ๋ฉ์๋๋ฅผ ๋์ด์ ์์ธ๊ฐ ๋์ ธ์ง๋ฉด, ์์ธ ์ ๋ณด๋ฅผ ๋จ๊ธฐ๊ณ ํด๋น ์ฐ๋ ๋๋ ์ข ๋ฃ๋๋ค. ์ด๊ฑด ๋ง์ด๋ค ๊ฒฝํํด ๋ณด์์ ๊ฒ์ด๋ค.
์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ ์ฌ์ฉ์ ์์ฒญ๋ณ๋ก ๋ณ๋์ ์ฐ๋ ๋๊ฐ ํ ๋น๋๊ณ , ์ด๋ ์๋ธ๋ฆฟ ์ปจํ ์ด๋ ์์์ ์คํ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, try catch๋ก ์ก์ง ๋ชปํ๊ณ ์๋ธ๋ฆฟ ์ปจํ ์ด๋ ๋ฐ์ผ๋ก ์์ธ๊ฐ ์ ๋ฌ๋๋ฉด ์ด๋ป๊ฒ ๋์ํ ๊น?
WAS (์ฌ๊ธฐ๊น์ง ์ ํ) <- ํํฐ <- ์๋ธ๋ฆฟ <- ์ธํฐ์ ํฐ <- ์ปจํธ๋กค๋ฌ (์์ธ ๋ฐ์)
ํด๋น ๊ฒฝ์ฐ์๋, Tomcat์ด ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ HTTP ์ํ์ฝ๋ 500๋ฒ์ ์ค๋ฅ ํ๋ฉด์ ๋์ฐ๊ฒ ๋๋ค.
(๋ง์ฝ ์คํ๋ง ๋ถํธ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์คํ๋ง ๋ถํธ๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ์ค๋ฅ ํ์ด์ง๊ฐ ๋์์ง๋ค.)
Exception์ ๊ฒฝ์ฐ์๋, ์๋ฒ ๋ด๋ถ์์ ์ฒ๋ฆฌํ ์ ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ์ผ๋ก ์๊ฐํด์ HTTP ์ํ์ฝ๋ 500์ ๋ฐํํ๋ ๊ฒ์ด๋ค.
2. SendError
WAS (sendError ํธ์ถ ๊ธฐ๋ก ํ์ธ) <- ํํฐ <- ์๋ธ๋ฆฟ <- ์ธํฐ์ ํฐ <- ์ปจํธ๋กค๋ฌ (response.sendError())
response.sendError()๋ฅผ ํธ์ถํ๋ฉด, response ๋ด๋ถ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค๋ ์ํ๋ฅผ ์ ์ฅํด๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋ธ๋ฆฟ ์ปจํ ์ด๋๋ client์๊ฒ ์๋ตํ๊ธฐ ์ ์ response์ sendError()๊ฐ ํธ์ถ๋์๋์ง ํ์ธํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ํธ์ถ๋์๋ค๋ฉด, ์ค์ ํ ์ค๋ฅ ์ฝ๋์ ๋ง์ถ์ด ํฐ์บฃ์ ๊ธฐ๋ณธ ์ค๋ฅ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ค๋ค
์๋ฌ ํ์ด์ง ์ปค์คํ ํ๊ธฐ
ํฐ์ผ์ด๋ ์คํ๋ง์ด ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ ์๋ฌ ํ์ด์ง ๋์ , ์กฐ๊ธ ๋ ์ด์๊ฒ ์์ธ ํ์ด์ง๋ฅผ ๊พธ๋ฏธ๊ณ ์ถ๋ค๋ฉด, ์ปค์คํ ์๋ฌ ํ์ด์ง๋ฅผ ๋ฑ๋กํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
WebServerFactoryCustomizer<ConfigurableWebServerFactory> ๋ฅผ ์์๋ฐ์ customize ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉ ํ์ฌ ๊ตฌํํ๋ฉด ๋๋ค.
@Component
public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Override
public void customize(ConfigurableWebServerFactory factory) {
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/errorpage/404");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500");
ErrorPage errorPageEx = new ErrorPage(RuntimeException.class, "/errorpage/500");
factory.addErrorPages(errorPage404, errorPage500, errorPageEx);
}
}
๊ทธ๋ฆฌ๊ณ ํด๋น ์์ฒญ์ ์ฒ๋ฆฌํ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ฑ๋กํด์ผ ํ๋ค.
@Slf4j
@Controller
public class ErrorPageController {
//RequestDispatcher ์์๋ก ์ ์๋์ด ์์
public static final String ERROR_EXCEPTION = "javax.servlet.error.exception";
public static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
public static final String ERROR_MESSAGE = "javax.servlet.error.message";
public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";
@RequestMapping("/error-page/404")
public String errorPage404(HttpServletRequest request, HttpServletResponse
response) {
log.info("errorPage 404");
printErrorInfo(request);
return "error-page/404";
}
@RequestMapping("/error-page/500")
public String errorPage500(HttpServletRequest request, HttpServletResponse
response) {
log.info("errorPage 500");
printErrorInfo(request);
return "error-page/500";
}
private void printErrorInfo(HttpServletRequest request) {
log.info("ERROR_EXCEPTION: ex=",request.getAttribute(ERROR_EXCEPTION));
log.info("ERROR_EXCEPTION_TYPE: {}",request.getAttribute(ERROR_EXCEPTION_TYPE));
log.info("ERROR_MESSAGE: {}", request.getAttribute(ERROR_MESSAGE)); //ex์ ๊ฒฝ์ฐ NestedServletException ์คํ๋ง์ด ํ๋ฒ ๊ฐ์ธ์ ๋ฐํ
log.info("ERROR_REQUEST_URI: {}",request.getAttribute(ERROR_REQUEST_URI));
log.info("ERROR_SERVLET_NAME: {}",request.getAttribute(ERROR_SERVLET_NAME));
log.info("ERROR_STATUS_CODE: {}",request.getAttribute(ERROR_STATUS_CODE));
log.info("dispatchType={}", request.getDispatcherType());
}
}
์์ธ ํ์ด์ง ์๋ ์๋ฆฌ
์์์ ๋ฑ๋กํ ์์ธ ํ์ด์ง๋ ์ด๋ป๊ฒ ์๋ํ ๊ฒ์ผ๊น?
์๋ธ๋ฆฟ์ Exceptionํน์ response.sendError()๊ฐ ํธ์ถ ๋์์ ๋, WAS๊น์ง ์ ํ๋๋ค๋ฉด WAS๋ ํด๋น ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ ์ค๋ฅ ํ์ด์ง ์ ๋ณด๋ฅผ ์ฐพ๋๋ค.
์๋ฅผ ๋ค์ด ์์ ๊ฒฝ์ฐ์๋ RuntimeException ์์ธ๊ฐ WAS๊น์ง ์ ๋ฌ๋๋ฉด, WAS๋ ์ค๋ฅ ํ์ด์ง ์ ๋ณด๋ฅผ ํ์ธํ๋ค.
RuntimeException์ ์ค๋ฅ ํ์ด์ง๋ก "/error/500"์ด ์ง์ ๋์ด ์์ผ๋ฉฐ, WAS๋ ์ค๋ฅ ํ์ด์ง๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด "/error-page/500"์ ๋ค์ ์์ฒญํ๋ค.
๋ค์ ์์ฒญํ๋ค๋ ๊ฒ์ด ์ค์ํ๋ค.
์ ์ฒด์ ์ธ ์์ธ ๋ฐ์์ ์์ฒญ ํ๋ฆ์ ๋ค์๊ณผ ๊ฐ๋ค.
1. WAS -> ํํฐ -> ์๋ธ๋ฆฟ -> ์ธํฐ์ ํฐ -> ์ปจํธ๋กค๋ฌ //์์ฒญ์ด ๋ค์ด์จ ๊ฒฝ์ฐ
2. WAS(์ฌ๊ธฐ๊น์ง ์ ํ) <- ํํฐ <- ์๋ธ๋ฆฟ <- ์ธํฐ์ ํฐ <- ์ปจํธ๋กค๋ฌ (์์ธ ๋ฐ์) //์ปจํธ๋กค๋ฌ์์ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ
3. WAS "/error-page/500" -> ํํฐ -> ์๋ธ๋ฆฟ -> ์ธํฐ์ ํฐ -> ์ปจํธ๋กค๋ฌ ("/error-page/500")์ฒ๋ฆฌ
DispatcherType
์๋ฌ ํ์ด์ง์ ๋์ ์๋ฆฌ์ ๋ํด ์ค๋ช ํ ๋ถ๋ถ์ ๋ค์ ์ดํด๋ณด์.
1. WAS -> ํํฐ -> ์๋ธ๋ฆฟ -> ์ธํฐ์ ํฐ -> ์ปจํธ๋กค๋ฌ //์์ฒญ์ด ๋ค์ด์จ ๊ฒฝ์ฐ
2. WAS(์ฌ๊ธฐ๊น์ง ์ ํ) <- ํํฐ <- ์๋ธ๋ฆฟ <- ์ธํฐ์ ํฐ <- ์ปจํธ๋กค๋ฌ (์์ธ ๋ฐ์) //์ปจํธ๋กค๋ฌ์์ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ
3. WAS "/error-page/500" -> ํํฐ -> ์๋ธ๋ฆฟ -> ์ธํฐ์ ํฐ -> ์ปจํธ๋กค๋ฌ ("/error-page/500")์ฒ๋ฆฌ
์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ค๋ฅ ํ์ด์ง๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด WAS ๋ด๋ถ์์ ๋ค์ ํ๋ฒ ํธ์ถ์ด ๋ฐ์ํ๋ค.
์ด๋ ํํฐ์ ์ธํฐ์ ํฐ๋ ๋ชจ๋ ๋ค์ ํธ์ถ๋๋๋ฐ, ์๋ฌ ํ์ด์ง๋ฅผ ๋์ฐ๊ธฐ ์ํด ๋ด๋ถ์์ ์ผ์ด๋๋ ํธ์ถ์ ๋ํด ํํฐ์ ์ธํฐ์ ํฐ๋ฅผ ์๋์ํค์ง ์๊ณ ์ถ์ ๊ฒฝ์ฐ๊ฐ ๋ง์ ๊ฒ์ด๋ค.
๊ฒฐ๊ตญ ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด์๋ ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฐ์ํ ์ ์ ์์ฒญ์ธ์ง, ์๋๋ฉด ์ค๋ฅ ํ์ด์ง๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํ ๋ด๋ถ ์์ฒญ์ธ์ง ๊ตฌ๋ถํ ์ ์์ด์ผ ํ๋ค.
์๋ธ๋ฆฟ์ ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด DispatcherType์ด๋ผ๋ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค.
๊ณ ๊ฐ์ด ์ฒ์ ์์ฒญํ์ ๊ฒฝ์ฐ DispatcherType์ REQUEST์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ค๋ฅ ํ์ด์ง๋ฅผ ๋ถ๋ฌ์ค๊ธฐ ์ํ ์์ฒญ์์ DispatcherType์ ERROR์ด๋ค.
์ด๋ ๋ฏ DispatcherType์ ํตํด ์์ฒญ์ ๊ตฌ๋ถํ ์ ์์ผ๋ฉฐ, ์ด ์ธ์๋ ์๋์ ๊ฐ์ ์ฌ๋ฌ DispatcherType์ด ์กด์ฌํ๋ค.
REQUEST : ํด๋ผ์ด์ธํธ ์์ฒญ
ERROR : ์ค๋ฅ ์์ฒญ
FORWARD : ์๋ธ๋ฆฟ์์ ๋ค๋ฅธ ์๋ธ๋ฆฟ์ด๋ JSP๋ฅผ ํธ์ถํ ๋
INCLUDE : ์๋ธ๋ฆฟ์์ ๋ค๋ฅธ ์๋ธ๋ฆฟ์ด๋ JSP์ ๊ฒฐ๊ณผ๋ฅผ ํฌํจํ ๋
ASYNC : ์๋ธ๋ฆฟ ๋น๋๊ธฐ ํธ์ถ
๊ทธ๋ฆฌ๊ณ ํํฐ์ ๋ํด DispatcherType์ ์ ์ฉํ๊ณ ์ถ์ ๊ฒจ์ฐ, FilterRegistrationBean.setDispatcherTypes๋ฅผ ์ง์ ํด์ฃผ๋ฉด ๋๋ค.
๊ธฐ๋ณธ๊ฐ์ DispatcherType.REQUEST์ด๋ฏ๋ก, ํด๋ผ์ด์ธํธ์ ์์ฒญ์ด ์๋ ๊ฒฝ์ฐ์๋ง ํํฐ๊ฐ ์ ์ฉ๋๋ค.
์ธํฐ์ ํฐ์ ๊ฒฝ์ฐ์๋ excludePathPatterns๋ฅผ ์ฌ์ฉํ์ฌ, ์ค๋ฅ ํ์ด์ง ๊ฒฝ๋ก์ ๋ํด ์ธํฐ์ ํฐ๊ฐ ํธ์ถ๋์ง ์๋๋ก ํ๋ ๋ฐฉ๋ฒ๋ฐ์ ์๋ค.
๐ Reference
'๐๏ธ Spring > Web MVC' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[MVC] ์์ธ ์ฒ๋ฆฌ - API ์์ธ ์ฒ๋ฆฌ (@ExceptionHandler, @ControllerAdvice) (0) | 2022.02.19 |
---|---|
[MVC] ์์ธ ์ฒ๋ฆฌ - ์คํ๋ง ๋ถํธ์์์ ์ค๋ฅ ํ์ด์ง (0) | 2022.01.18 |
[MVC] ํํฐ, ์ธํฐ์ ํฐ (0) | 2022.01.15 |
[MVC] Bean Validation - ๊ฒ์ฆ (0) | 2022.01.08 |
[MVC] ๊ตญ์ ํ, ๋ฉ์์ง ๊ธฐ๋ฅ (+ LocaleResolver) (0) | 2022.01.08 |