์คํ๋ง๋ถํธ ์น MVC ํ๋ก์ ํธ์์ ์ํ ์ฝ๋์ ๋ฐ๋ผ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๊ณ ๋ทฐ์ ๊ฐ๊ฐ์ ์๋ฌ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ์น ์ฌ์ดํธ๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
๋ง์ฝ Github์์ ์กด์ฌํ์ง ์๋ ํ์ด์ง๋ก ์ ์ํ ๊ฒฝ์ฐ ์ฅํ ๋น-์์ด ์ฌ๋ฌ๋ถ์ ๋ง์์ค๋๋ค. ์คํ๋ง ๋ถํธ์์๋ ๊ฐ๋จํ ํน์ ์์น์ htmlํ์ด์ง๋ง ์ถ๊ฐํด ์ฃผ๋ฉด ์ด๋ฐ ์๋ฌ ํ์ด์ง๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
์คํ๋ง๋ถํธ์์ ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง๊ฐ ์์ต๋๋ค.
Spring Initializr์ ์ ์ํ์ฌ ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ณ .zip ํ์ผ๋ก ๋ค์ด๋ฐ์ ์ ์์ต๋๋ค. ํ๋ก์ ํธ ๋ฉํ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ณ web ์์กด์ฑ์ ๊ฒ์ํ์ฌ Spring MVC and Tomcat์ ์ถ๊ฐํด์ค ๋ค์ Generate Project ๋ฒํผ์ ํด๋ฆญํ์ฌ ํ๋ก์ ํธ๋ฅผ ๋ค์ด๋ฐ์ต๋๋ค.
์ ๋ ๋ ๋ฒ์งธ ๋ฐฉ๋ฒ์ธ Spring Initializr๋ฅผ ์ฌ์ฉํ์ฌ ErrorHandle ์ด๋ผ๋ ์ด๋ฆ์ ํ๋ก์ ํธ๋ฅผ ์์ฑํ์ต๋๋ค.
์์ฑํ ์คํ๋ง ํ๋ก์ ํธ๋ฅผ ์ด๊ณ ๊ธฐ๋ณธ ํ๋ก์ ํธ๊ฐ ์ ํ ๋ ๊ทธ๋๋ก ์๋ฒ๋ฅผ ์คํํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ์์http://localhost:8080 ์ฃผ์๋ก ์ ์ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋ฌ ํ์ด์ง๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์ด ์๋ฌ ํ์ด์ง๋ Tomcat์์ ๋ง๋ค์ด์ง๋ ๊ฒ์ด ์๋๋ผ ์คํ๋ง๋ถํธ์ ์ํด ๋ง๋ค์ด์ง ํ์ด์ง์ ๋๋ค. ์คํ๋ง์์ ์ด๋ฐ ๊ธฐ๋ณธ์ ์ธ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๊ณณ์ BasicErrorController์ ๋๋ค.
BasicErrorController
// ...
// text/html๊ฐ ํฌํจ๋ ํค๋๊ฐ ์๋ ์์ฒญ์๋ ๋ทฐ๋ฅผ ๋ฐํ
@RequestMapping(produces = {"text/html"})
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = this.getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
return modelAndView != null ? modelAndView : new ModelAndView("error", model);
}
// ๊ทธ ์ธ์๋ json ๊ฐ์ฒด๋ฅผ ๋ฐํ
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = this.getStatus(request);
return new ResponseEntity(body, status);
}
// ...
BasicErrorController ์ฝ๋์ ํด๋น ๋ถ๋ถ์ HTTP ์์ฒญ์ Accept ํค๋์ text/html
๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ์ html ๋ทฐ๋ฅผ ๋ฐํํ๊ณ , ๊ทธ ์ธ์๋ json ๊ฐ์ฒด๋ฅผ ๊ฒฐ๊ณผ๋ก ๋ฐํํฉ๋๋ค. ์์ Whitelabel Error Page๋ ์ ์์ ๊ฒฝ์ฐ๊ฐ ๋ฉ๋๋ค.
๋ฐ๋๋ก, ์น ๋ธ๋ผ์ฐ์ ๊ฐ ์๋๋ผ ์ฝ์์์ curl๋ก ํค๋ ์์ด ํ์ด์ง๋ฅผ ์์ฒญํ๋ฉด json ํํ์ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ ๋ฌ๋ฐ์ต๋๋ค.
curl http://localhost:8080/
{"timestamp":"2019-04-19T00:32:38.982+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}
ํค๋์ Accept: text/html
์ ์ถ๊ฐํ๋ฉด ์น ๋ธ๋ผ์ฐ์ ์ ๋์ผํ๊ฒ html ๋ทฐ๋ฅผ ๋ฐํํฉ๋๋ค.
curl -H "Accept: text/html" http://localhost:8080
<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Fri Apr 19 17:01:20 KST 2019</div><div>There was an unexpected error (type=Not Found, status=404).</div><div>No message available</div></body></html>
http://localhost:8080 ์ฃผ์๋ก ์ ๊ทผํ๋ฉด ํ์ฌ๋ ์คํ๋ง์ด BasicErrorController๋ฅผ ํตํด ์์ฑํ Whitelabel Error Page๋ง ๋ณผ ์ ์์ต๋๋ค. ์ด ์๋ฌ ํ์ด์ง๋ ์ค์ ํ์ผ์ server.error.path๋ error.path๊ฐ ์์ ๊ฒฝ์ฐ ๋ง์ง๋ง์ผ๋ก ์คํ๋ง์ด ๋ง๋ค์ด์ฃผ๋ ์๋ฌ ํ์ด์ง์ ๋๋ค.
Whitelabel Error Page๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ํด, ๋จผ์ ๋ฃจํธ ์ฃผ์("/")์ ๋ํด์๋ index.html์ ์ถ๊ฐํ์ฌ ์ ์์ ์ผ๋ก ์ ๊ทผ๋๋ ํ์ด์ง๋ฅผ ๋ง๋ค๊ฒ ์ต๋๋ค.
index.html์ ์ ์ ๋ฆฌ์์ค ๋งตํ ์ ์ฌ์ฉํ๋ ๋ฆฌ์์ค ๊ธฐ๋ณธ ๊ฒฝ๋ก ์ค ์๋ฌด๊ณณ์๋ ์์น์์ผ๋ ๋ฉ๋๋ค.
์ ๋ src/main/resources/static ์์น์ index.html๊ณผ ์ด๋ฏธ์ง ํ์ผ์ ํ๋ ์ถ๊ฐํ์ต๋๋ค.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img src="toto.jpeg" width="300" height="400" alt="index cat">
<h1>Hello, Godori!</h1>
</body>
</html>
์๋ฒ๋ฅผ ์คํํ์ฌ ๋ฃจํธ๋ก ์ ์ํ๋ฉด ์ ์์ ์ผ๋ก index.html์ด ๋ณด์ ๋๋ค.
https://http.cat ์ ์ํ ์ฝ๋๋ฅผ ๊ณ ์์ด ์ฌ์ง์ผ๋ก ํํํ ์ฌ๋ฐ๋ ์ฌ์ดํธ์ ๋๋ค.
Github์ 404 ์๋ฌ ํ์ด์ง์ฒ๋ผ, ํน์ ์ํ ์ฝ๋์ ๋ฐ๋ผ ์๋ก ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํด์ฃผ๋ ์ปค์คํ ์๋ฌ ํ์ด์ง๋ฅผ ๋ค์ HTTP Cats์ ์ด๋ฏธ์ง๋ฅผ ์ด์ฉํด ๋ง๋ค์ด ๋ณผ๊ฒ์.
resources์ static ๋๋ ํ ๋ฆฌ ์์ error ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ 404.html๊ณผ 5xx.html ํ์ผ ๋ ๊ฐ๋ฅผ ์์ฑํฉ๋๋ค. ํ์ด์ง ์ด๋ฆ์ ์ํ ์ฝ๋์ ๋์ผํ๊ฒ 404 ๋ฑ์ผ๋ก ์ ๊ฑฐ๋, 500๋ฒ๋ ์ํ์ ๋ํด ์ฒ๋ฆฌํ๋ค๋ ์๋ฏธ๋ก 5xx.html๋ฑ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค.
(๋ง์ฝ static ๋๋ ํ ๋ฆฌ ์์ ๋๋ ํ ๋ฆฌ๊ฐ error ํ๋ ๋ฟ์ด๋ผ๋ฉด ๋๋ ํ ๋ฆฌ ์ด๋ฆ์ด static.error ๋ผ๋ ํํ๋ก ๋ณด์ผ ์๋ ์์ต๋๋ค)
404์ 500 ์๋ฌ์ ๋ํด ๊ฐ๊ฐ์ html ํ์ด์ง๋ฅผ ๊ตฌ์ฑํ๊ณ , SampleController ๋ผ๋ ์ด๋ฆ์ Controller๋ฅผ ์์ฑํ์ฌ localhost:8080/error ๋ก ์ ์ํ๋ฉด ์๋ฌ๋ฅผ ๋์ง๋ ํ์ด์ง๋ฅผ ๋ง๋ญ๋๋ค.
package com.godori.ErrorHandle;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SampleController {
@GetMapping("/error")
public String errorpage(){
throw new IllegalStateException("Error");
}
}
์ด์ / ํน์ /error ์ฃผ์ ์ธ์ ํ์ด์ง๋ก ์ ๊ทผํ๋ฉด 404 Not Found ์๋ฌ ํ์ด์ง๋ฅผ, /error๋ก ์ ๊ทผํ๋ฉด 500 Internal Server Error ํ์ด์ง๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์๋ฌ ํ์ด์ง๋ ๋ณ๋ก ๋ณด๊ณ ์ถ์ง ์์ ํ์ด์ง์ง๋ง ๋ง๋ค์ด ๋๋ฉด ์ฌ์ดํธ์ ์์ฑ๋๋ฅผ ์ฌ๋ฆด ์ ์์ผ๋ ๋ณธ์ธ๋ง์ ์๋ฌ ํ์ด์ง๋ฅผ ๋ง๋ค์ด ์ฒ๋ฆฌํด ๋ณด์์.
๊ธ์ ๊ณ ์์ด๊ฐ ์๋ค ๐๐ป ์ข์ ๊ธ