우리는 개발을 하다보면 이런 에러를 보게 된다. 너무 좋다.
개발하는 입장에서는 이런 에러를 보고 어디를 수정해야 하는지 알게된다.
하지만 사용자는 이런화면을 보게된다면 해당사이트에 대한 신뢰를 잃을 것이다.
또 코드의 일부가 노출 될 수 있다.
애초에 모든 화면에서 이런 에러가 나오지않게 개발하는 것이 좋지만
예상치 못한 곳에서(개발자코드, 네트워크 에러,DB 문제 등) 문제는 항상 발생한다.
이럴 때 에러화면을 그대로 보여주기보단 에러가 났을 때
특정 페이지 화면을 보여줘 이런 문제들을 방지할 수 있다.
다음도 에러가났을 때 서버에서 기본적으로 만들어주는 화면 대신 보여주는 화면이 있다.
그럼 우리는 에러가 났을 때 어떻게 해야 '파란'에러화면 대신 우리가 원하는 페이지를 보여줄 수 있을까?
※에러가 났을 때 기본적으로 제공하는 화면은 어떤 서버(node.js, 톰캣 등)에 따라 다르다.
저 파란화면은 톰캣에서 기본적으로 제공하는 화면이다.
에러페이지 지정
01errorMain.jsp
다음과 같이 jsp를 작성해보자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%=request.getParameter("aa").substring(0)%>
</body>
</html>
실행결과 :
url에 'aa'라는 파라미터를 붙이지않으면 request.getParameter("aa")는
null이기 때문에 nullPointerException이 발생한다.
이 때 대신 보여줄 에러페이지를 만들어보자.
01errorPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
에러타입 <%=exception.getClass().getTypeName() %><br>
에러메시지 <%=exception.getMessage() %>
</body>
</html>
에러페이지는 page디렉티브의 isErrorPage속성을 'true'로 명시해
에러가 발생했을 때 보여지는 페이지라는걸 명시한다.
isErrorPage를 true로 했으면 에러페이지에서만 사용할 수 있는 exception객체를 사용할 수 있다.
이 exception객체는 어떤 에러가 발생했는지, 해당에러에 관한 정보를 담고있는 객체이다.
이제 에러가 발생할 01errorMain.jsp의 page디렉티브에 errorPage속성을 지정해주자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" errorPage="01errorPage.jsp" %>
이는 01errorMain.jsp에서 에러발생 시 01errorPage.jsp를 대신 보여주겠다는 의미다.
다시 01errorMain.jsp를 실행해보자.
파란 에러화면 대신 01errorPage.jsp 화면이 나오는걸 확인할 수 있다.
(※ exception.getMessage() 는 에러에 따라 에러메세지를
리턴하는게 있고 그냥 null을 리턴하는게 있다)
에러페이지 만들기
/WEB-INF/err 폴더에 위치시키자.
error404.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" isErrorPage="true"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
400에러가 발생했습니다.
해당 url을 처리할 수 없어서 나는 에러입니다
</body>
</html>
error500.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" isErrorPage="true"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
500에러가 발생했습니다.
<%=exception.getClass().getTypeName()%>
</body>
</html>
에러 타입별 페이지 지정하기
에러가 날 페이지마다 에러페이지 지정을 해도되지만,웹 애플리케이션 설정에서
exception이 발생할 때마다 exception type별로 특정 에러페이지를 보여주게 할 수도 있다.
web.xml 다음과 같은 태그를 추가해보자.
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/WEB-INF/err/error500.jsp</location>
</error-page>
<exception-type>은 패키지까지 다 써야하고,
<location>은 해당 Exception이 발생했을 시 보여줄 jsp위치를 지정한다.
NullPointerException이 발생하는 jsp를 만들고 실행시켜보자.
02main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>02/main.jsp</title>
</head>
<body>
<%
//nullPointerException발생
int age=0;
if(age==0){
throw new NullPointerException();
}
%>
<%=age %>
</body>
</html>
02main.jsp실행 중 에러가 발생해서 /WEB-INF/err/err500.jsp 화면이 대신 보여진다
결과화면
응답 상태코드 별 에러페이지 지정
응답 상태코드 종류는
https://developer.mozilla.org/ko/docs/Web/HTTP/Status 를 참고하자.
200은 정상, 301은 redirect, 404 not found, 500 서버에러만 기억하자.
이 중 404,500은 에러화면을 보여주자.
이게 우리가 가장 많이 보이는 에러화면이다
실습 전 web.xml에 위에서 작성한
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/WEB-INF/err/error500.jsp</location>
</error-page>
를 지워주도록 하자.
대신
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/err/error404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/err/error500.jsp</location>
</error-page>
를 추가해주자. 아까는 <exception-type>이었지만 지금은 <error-code>이다.
404는 not found이기 때문에 서버에 없는 jsp를 요청해보자.
localhost:8080/study/jsfkdltghjfkghjsfkdlghjsfkdlghfghjsfkdlgh.jsp를 요청해보니
404에 해당하는 error404.jsp화면을 보여준다.
500은 서버에러인데 서버측에러이다. 보통 개발자 코드가 잘못된 경우이다.
위에서 작성한 02main.jspe도 NullPointerException이 발생하고
이 때의 상태코드는 500이기때문에 error500.jsp가 보여야한다.
이렇게 에러가 났을 때
사용자가 볼만한 에러페이지를 대신 보여주는 실습을 해봤지만
우리는 개발하는동안 실제로 발생한 파란색 에러화면을 보고
에러를 수정해야하니까 web.xml에 있는 <error-page> 태그를 전부 삭제해주자.
에러페이지 우선순위
1. jsp에서 page디렉티브 errorPage 지정
2. Exception Type별
3. 응답 상태코드별
errorPage를 1개만 지정하는 page디렉티브가 우선순위는 당연히 높을것이고
exception type별에 해당하는 에러들은 모두 상태코드 500이다.
그러므로 상태코드가 가장 광범위하고, 그 다음이 exception type, page디렉티브 순이고
범위가 적을수록 우선순위가 높다.
에러와 버퍼와의 관계
4번처럼 버퍼를 비우고 에러페이지 내용을 저장하는데
버퍼크기가 작아서 에러가 발생전 flush()되거나
임의로 에러코드 만나기전 flsuh()한다면 에러화면전에 flush()된 내용이 출력된다.
위의 01errorMain.jsp을 다음과 같이 수정해보자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" errorPage="01errorPage.jsp"
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
이거슨 에러가 나기 전 발생한 코드여 <br>
<%
out.flush();
%>
<%=request.getParameter("aa").substring(0)%>
</body>
</html>
실행하면 01errorPage.jsp내용이 담기지만 그 전에 '이거슨 에러가 나기전 발생한 코드여'
부분도 출력되는 걸 볼수있다.
근데 담기는 데이터가 버퍼를 초과하는 경우는 거의 없기 때문에 크게 신경쓰지 않아도 된다.