❗️ 에러 화면은 톰캣이 생성한 것
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파라미터 출력</title>
</head>
<body>
<!--name 파라미터의 값을 읽어와 대문자로 변환해서 출력-->
name 파라미터 값:<% request.getParameter("name").toUpperCase(); %>
</body>
</html>
만약 name
파라미터가 없으면 request.getParameter("name")
은 null
을 리턴하므로 NullPointerException 을 발생시킨다.
개발 과정에서는 에러 화면에 표시된 에러 내용을 보고 어떤 에러가 발생했는지 알 수 있어서 에러 화면을 보는 것이 도움이된다. 하지만 사용자 입장에서 보면, 이런 에러 화면을 봤을 때 더이상 해당 사이트를 신뢰하지 않게 된다. 또한, 코드의 일부가 노출되기 때문에 보안 측면에서도 좋지 않다.
try-catch
로 직접 익셉션을 처리하면 응답 결과 중 일부만 선택해서 변경할 수 있다.
이런 에러 화면을 노출하고 싶지 않으면 try-catch
를 이용하여 익셉션이 발생할 때 알맞은 응답을 생성할 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파라미터 출력</title>
</head>
<body>
name 파라미터 값:
<% try { %>
<%= request.getParameter("name").toUpperCase() %>
<%
} catch(Exception e) {
%>
name 파라미터가 올바르지 않습니다.
<% } %>
</body>
</html>
Exception이 발생했을 때 이렇게 일부만 응답을 바꾸는 대신 완전히 다른 응답 결과를 보여주고 싶다면 이 방법이 아닌 에러페이지를 사용해야 한다.
❗️ JSP 페이지 Exception
Java에서는FileInputStream
을 쓰면 익셉션표시가 뜬다. 하지만 JSP 페이지에서는 익셉션표시가 뜨지 않는다. 이는 Servlet 내부의 service 메서드가throws
하고 있기 때문이다. 스크립트릿으로 일어난 일들은 service 메서드 안에 들어가게되는데 다throws
되어진다. (모든 예외가 적용되는 것은 아니다.)
✔️ <%@ page errorPage = "..." %>
JSP는 실행 도중 익셉션이 발생할 때 에러 화면 대신 지정한 JSP 페이지를 보여줄 수 있는 기능을 제공하고 있다. 익셉션이 발생하면 보여줄 JSP 페이지는 page 디렉티브의 errorPage 속성을 이용해서 지정한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
// Exception이 발생하면 에러 페이지를 실행하도록 지정한다.
<%@ page errorPage="/error/viewErrorMessage.jsp" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파라미터 출력</title>
</head>
<body>
name 파라미터 값: <%= request.getParameter("name").toUpperCase() %>
</body>
</html>
✔️ <%@ page isErrorPage = "true"%>
에러 페이지에 해당하는 JSP 페이지는 page 디렉티브의 isErrorPage
속성의 값을 true
로 지정해야 한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page isErrorPage="true" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>에러 발생</title>
</head>
<body>
<h1>요청 처리 과정에서 에러 발생!</h1>
<h2>빠른 시간내에 문제를 해결하도록 하겠습니다.</h2><br>
// 익셉션 기본 객체의 클래스 이름을 출력
에러 타입: <%= exception.getClass().getName() %><br>
에러 메세지: <%= exception.getMessage() %>
</body>
</html>
✔️ isErrorPage = "true"와 "false"의 차이
❗️ Excpetion 기본 객체
: JSP 실행 과정에서 발생한 exception 객체
viewErrorMessage.jsp는 true
로 지정되었으므로 exception 기본 객체가 된다.
인터넷 익스플로러에서 실행하면 지정한 에러 페이지가 아닌 익스플로러가 자체적으로 제공하는 HTTP 오류 메시지가 화면에 출력된다.
- 응답의 상태 코드가 400, 404, 500 등 에러코드
- 전체 응답 결과 데이터의 길이가 512바이트보다 작을 때
직접 만든 JSP 에러 페이지의 데이터 길이는 288바이트이기 때문에, 인터넷 익스플로러는 자신의 화면을 출력하게 된다.
따라서, 익스플로러에서도 에러 페이지의 내용이 올바르게 출력되기 원한다면, 에러 페이지가 생성하는 응답 데이터가 512바이트보다 커야 한다. 그 부분은 주석으로 처리해 주면 된다.
✔️ JSP / Servlet은 에러 코드별로 사용할 에러 페이지를 web.xml 파일에 지정 가능하다.
<error-page> <error-code>에러코드</error-code> <location>에러페이지의 URI</location> </error-page>
자주 발생하는 에러 코드에 대해서는 별도의 에러 페이지를 지정해 주는 것이 좋다.
<error- page>
<location>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<display-name>study</display-name>
// 404 에러 응답 화면 지정
<error-page>
<error-code>404</error-code>
<location>/error/error404</location>
</error-page>
// 500 에러 응답 화면 지정
<error-page>
<error-code>500</error-code>
<location>/error/error500</location>
</error-page>
</web-app>
<error-page> <exception-type>익셉션 타입</exception-type> <location>에러페이지 URI</location> </error-page>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<display-name>study</display-name>
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error/errorNullPointer.jsp</location>
</error-page>
</web-app>
버퍼가 다 차면 버퍼의 내용을 웹 브라우저에 전달하는데, 처음 버퍼를 flush
할 때 응답 헤더를 전송한다. (버퍼의 동작 방식) 이때, 버퍼를 최초로 flush
할 때까지 에러가 발생하지 않으면 웹 브라우저에 200번의 응답 상태 코드가 전송된다.
이런 이유로 에러 응답 코드와 에러 페이지의 내용을 웹 브라우저에 완전하게 전송하려면 버퍼가 flush
되면 안된다.
😵 버퍼가
flush
된 이후에 에러가 발생하면?
- 웹 브라우저에 이미 200번의 응답 상태 코드와 일부 응답 결과 화면이 전송되기 때문에, 일부 페이지의 내용이 웹 브라우저에 출력되고 그 뒤에 에러 페이지의 내용이 붙게 된다. 그리고 이미 200번을 받았기 때문에 웹 브라우저는 정상적으로 응답이 도착했다고 판단한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
// 버퍼 크기를 1KB로 설정
<%@ page buffer="1kb" %>
// 에러 페이지 지정
<%@ page errorPage="/error/viewErrorMessage.jsp" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>버퍼 플러시 이후 에러 발생 결과</title>
</head>
<body>
<%
// 1KB를 초과하는 데이터를 출력해서 버퍼가 플러시 되도록 한다.
// 이 과정에서 200번의 응답 코드가 전송된다.
for(int i = 0; i < 300; i++) {
out.println(i);
}
%>
// ArithmeticException
<%= 1 / 0 %>
</body>
</html>
위 예시를 보듯이, 버퍼가 flush
된 이후에 익셉션이 발생하면 에러 페이지가 원하는 형태로 출력되지 않는다.