참고글


errorPage 설정시 출력 버퍼 동작
서블릿 웹 컨테이너는 서블릿이나 JSP 페이지에서 처리한 내용을 클라이언트에 출력할 때 출력 버퍼를 사용하게 됩니다. 이때 JSP 페이지에서 page 디렉티브의 errorPage 설정을 통해 에러 처리를 하는 경우 버퍼 사이즈에 주의가 필요합니다.

예를들어 NullPointerException이 발생하는 nullEx.jsp 페이지가 있고, nullEx.jsp 페이지에서 오류가 발생할 때 처리할 페이지를 errorPage 속성을 통해 internalEx.jsp로 지정했다면 다음 그림과 같은 동작을 하게됩니다.

1. nullEx.jsp에서 처리 결과를 출력 버퍼에 담습니다. 버퍼가 가득차면 브라우저로 버퍼에 담은 내용을 출력하지만 아직 버퍼는 가득 차지 않았기 때문에 브라우저로 처리내용을 출력하지 않고 버퍼로 출력합니다.

2. JSP 페이지를 처리하던 중 NullPointerException이 발생하게 됩니다. 이전에 쌓아둔 출력 버퍼의 내용을 모두 비우고 제어를 errorPage 속성에 명시한 에러페이지 internalEx.jsp 페이지로 넘깁니다.

4. 에러페이지의 내용을 깨끗이 비워진 출력 버퍼에 담고 결국 브라우저에 출력하여 사용자는 서버에 오류가 발생했다는 오류 페이지를 보게 됩니다.




errorPage 설정시 출력 버퍼 설정 주의사항
만약 출력 버퍼 사이즈가 작을 경우에 오류가 발생한다면 어떻게 될까요? 출력 버퍼사이즈를 지정하지 않는 경우 기본적으로 JSP는 8kb 크기의 출력 버퍼를 가지게 됩니다. 그러나 다음의 nullEx.jsp 페이지에서는 이를 1kb로 지정해 주었습니다.

보다시피 안녕하세요를 150번 출력한 후 NullPointerException이 발생하도록 되어 있습니다.

nullEx.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
      pageEncoding="UTF-8" buffer="1kb" errorPage="/internalEx.jsp"%>                            
 
 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
      <%
            for (int i = 0; i < 150; i++) {
                  out.println("안녕하세요");
            }
 
 
            String nullStr = null;
            System.out.println(nullStr.toString());
      %>
</body>
</html>
cs

 

 



다음은 에러가 발생했을때 처리하여 보여주게 될 internalEx.jsp 페이지입니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>            
      
<!DOCTYPE html>
<html>
<head>
      <meta charset="UTF-8">
</head>
<body>
죄송합니다.
내부 오류가 발생하였습니다.
</body>
</html>
cs

 

 


nullEx.jsp 페이지를 요청했을때의 결과는 아이러니하게도 안녕하세요가 모두 출력된 후 에러 처리 페이지의 내용이 출력되었습니다.



심지어는 HTTP 응답 메시지를 보니 아래처럼 상태코드가 500이 아닌 200 OK인 것을 알 수 있습니다. 어떻게 된 것일까요?
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8                                                        
Date: Wed, 01 Aug 2018 16:03:47 GMT
Content-Length: 2533
 
 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
       안녕하세요
안녕하세요
안녕하세요
안녕하세요
안녕하세요
...생략...
       
<!DOCTYPE html>
<html>
<head>
       <meta charset="UTF-8">
</head>
<body>
죄송합니다.
 
 
내부 오류가 발생하였습니다.
</body>
</html>
cs

 

 




원인 분석
원인은 앞의 과정을 이해했다면 매우 간단히 생각해볼 수 있습니다. 

1. 버퍼는 기본 크기인 8kb보다 8배 줄어든 1kb로 설정했습니다.

2. 안녕하세요를 반복해서 출력하다보면 1kb의 버퍼를 채우게 됩니다. 최초 첫번째 꽉찬 버퍼를 브라우저측에 비울 때 HTTP 응답 코드와 헤더등을 포함하여 출력하게 됩니다.

3. 몇십번의 안녕하세요를 더 출력하고 버퍼가 꽉 찰때마다 브라우저로 버퍼의 내용을 출력합니다.

4. 브라우저로 내용을 출력한 이후 비워진 버퍼에 어김없이 안녕하세요를 출력한 중 NullPointerException이 발생하고 버퍼를 비웁니다. 그러나 이미 버퍼의 내용을 몇번이나 브라우저로 전송해버리고 난 이후입니다.

5. 에러페이지인 internalEx.jsp 페이지의 내용을 버퍼로 보내고 브라우저로 출력합니다. 브라우저는 1 ~ 4번 과정을 통해 받은 HTTP 응답 헤더 및 안녕하세요 그리고 에러처리 페이지의 내용까지 몽땅 사용자에게 보여줍니다.




해결 방법
해결 방법은 특별한 것이 아닌 errorPage 속성을 통해 에러페이지를 지정하는 경우 충분한 크기의 버퍼 사이즈를 지정해주는 것입니다.
블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

,