본문 바로가기
프로그래밍/스프링프레임워크

스프링프레임워크 에러페이지 만들기

by pentode 2018. 4. 21.

프로그램 수행중에 예기치 못한 예외가 발생하면 에러페이지를 보여주게 됩니다. WAS 의 기본 에러페이지는 대부분 코드중의 예외 라인과 상세한 스택 추적 정보를 보여주게 되므로 운영 환경에서는 보안상 문제가 됩니다. 그러므로 대부분 자체적인 에러 페이지를 제작하여 보여주게 됩니다. 여기서는 서블릿에서 기본적으로 제공하는 에러페이지 설정과 스프링 프레임워크에서 지원하는 에러페이지 설정부분을 알아 봅니다.



I. web.xml 에서 에러페이지 설정하기


소스파일명과 Exception 이 발생한 라인번호, 예외 메세지, 스택 추적 정보가 보여집니다. 개발시에는 유용하지만 운영시에는 보안상 문제가 됩니다.


1. Tomcat에서 에러페이지 설정이 없을 경우





2. web.xml 파일에 에러페이지 설정하기


예외 타입별로, HTTP Status 코드 별로 에러 페이지를 지정할 수 있습니다. IE의 경우 응답코드가 404, 500 일 경우 브라우저의 자체 에러페이지가 보여집니다.


<error-page>

    <exception-type>java.lang.Throwable</exception-type>

    <location>/WEB-INF/views/common/error.jsp</location>

</error-page>


<error-page>

    <error-code>404</error-code>

    <location>/WEB-INF/views/common/error404.jsp</location>

</error-page>


<error-page>

    <error-code>500</error-code>

    <location>/WEB-INF/views/common/error500.jsp</location>

</error-page>


- 크롬의 경우 지정된 에러페이지가 보입니다.





- IE 의 경우 브라우저 자체의 페이지가 보입니다.(Edge는 지정된 에러페이지가 보입니다.) 브라우저 설정에서 바꿀 수 있지만, 사용자에게 바꾸라고 할 수는 없습니다.




3. HTTP Status 코드를 지정한다.


- 에러페이지에서 응답코드를 직접 지정하여 변경합니다.


<% response.setStatus(200); %>


- 에러 페이지에서 HTTP 응답코드를 200으로 지정하면 IE 에서도 지정된 에러페이지가 보입니다.





4. 웹 방화벽을 사용하고 있을 경우


- HTTP Status 코드가 404, 500 등 에러 상태이면 웹방화벽 자체의 오류 페이지를 보여줄 것입니다.

- HTTP Status 코드를 200으로 변경하면 역시 지정된 페이지를 보여줄 수 있습니다.



II.  스프링 프레임워크에서 에러페이지


1. Exception Resolver 설정하기


- root-context.xml 에서 설정합니다.

- 예외 별로 예외 페이지를 지정할 수 있습니다.

- 예외 별로 HTTP Status 코드를 지정할 수 있습니다.


<beans:bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

    <beans:property name="defaultErrorView" value="common/err/error" />

    <beans:property name="defaultStatusCode" value="200" />

    <beans:property name="exceptionAttribute" value="exception" />

    <beans:property name="excludedExceptions" value="com.tistory.pentode.exception.UncheckException" />

    <beans:property name="exceptionMappings">

        <beans:props>

            <beans:prop key="com.tistory.pentode.exception.DatabaseException">common/err/error_database</beans:prop>

            <beans:prop key="com.tistory.pentode.exception.SecurityException">common/err/error_security</beans:prop>

            <beans:prop key="com.tistory.pentode.exception.BusinessException">common/err/error_business</beans:prop>

            <beans:prop key="com.tistory.pentode.exception.AjaxException">common/err/error_ajax</beans:prop>

        </beans:props>

    </beans:property>

    <beans:property name="statusCodes">

        <beans:props>

            <beans:prop key="common/err/error_database">500</beans:prop>

            <beans:prop key="common/err/error_security">403</beans:prop>

            <beans:prop key="common/err/error_business">500</beans:prop>

            <beans:prop key="common/err/error_ajax">200</beans:prop>

        </beans:props>

    </beans:property>

</beans:bean>


- defaultErrorView : 지정되지 않은 예외에 대한 기본 에러페이지 입니다.

- defaultStatusCode : 상태 코드 맵핑이 없는 예외를 위한 기본 상태 값.

- exceptionAttribute : 기본값이 "exception" 이다. 예외의 모델 속성 키값 ${exception.message}

- excludedExceptions : 하나 또는 그 이상의 예외를 리졸버에서 제외합니다. 제외된 예외에 대해서는 web.xml 에서 지정된 값이 적용됩니다.

- exceptionMappings : 예외 클래스에 대해 에러 페이지를 지정합니다.

- statusCodes : 에러 페이지에 상태 코드를 지정할 수 있습니다. 모든 예외에 대해 동일한 응답코드를 발생하려면 이것을 사용하지 않고, defaultStatusCode를 지정하면 됩니다.




2. Ajax호출시 예외 처리하기


- Ajax 호출하기


<script type="text/javascript">

//<![CDATA[

function AjaxNormalCall() {

    var sendData = JSON.stringify({date:"날짜", time:"시간", week:"요일"});

    AjaxCall("<c:url value='/ajaxNormal.do'/>", sendData);

}


function AjaxExceptionCall() {

    var sendData = JSON.stringify({date:"날짜", time:"시간", week:"요일"});

    AjaxCall("<c:url value='/ajaxException.do'/>", sendData);

}


function AjaxCall(url, sendData) {

    $.ajax({

        type: "POST",

        url : url,

        data: sendData,

        dataType: "json",

        contentType:"application/json;charset=UTF-8",

        async: true,

        beforeSend: function(xhr) {

            xhr.setRequestHeader("AjaxCall", "true");

        },

        success : function(data, status, xhr) {

            console.log(data);

            alert(data.code);

        },

        error: function(xhr, textStatus, errorThrown) {

            alert(xhr.responseText);

        }

    });

}

//]]>

</script>


- Ajax 호출시 beforeSend 이벤트에서 xhr.setRequestHeader("AjaxCall", "true"); 로 헤더 정보에 AjaxCall 임을 표시합니다.


@AfterThrowing(pointcut="execution(* com.tistory.pentode.*Controller.*(..))", throwing="exception")

public void afterThrowingMethod(JoinPoint jp, Exception exception) throws Exception {


    ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();

    HttpServletRequest request =  attr.getRequest();


    if("true".equals(request.getHeader("AjaxCall"))) {

        throw new AjaxException("AjaxException 발생", exception);

    }

}


- AfterThrowing 어드바이스를 만들어서 Ajax 요청이면 발생한 예외를 AjaxException 으로 랩핑해서 다시 던집니다.


<beans:bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

    ...

    <beans:property name="exceptionMappings">

        <beans:props>

            ...

            <beans:prop key="com.tistory.pentode.exception.AjaxException">common/err/error_ajax</beans:prop>

        </beans:props>

    </beans:property>

    <beans:property name="statusCodes">

        <beans:props>

            ...

            <beans:prop key="common/err/error_ajax">200</beans:prop>

        </beans:props>

    </beans:property>

</beans:bean>


- Exception Resolver에서 에러페이지를 지정하고 HTTP 응답코드를 200으로 지정합니다.

- 응답코드가 200이면 Ajax 호출 스크립트의 success 이벤트에서 처리가 되고, 500 이면 error 이벤트에서 처리가 됩니다.


<%@ page contentType="text/json; charset=utf-8" pageEncoding="utf-8"%>

{"code":"error"}


- error_ajax.jsp 파일에서는 에러코드를 json 데이터로 보냅니다. 응답코드가 200으로 지정되었으므로 success 에서 처리가 됩니다.

- success에서는 필요에  따라 실제 에러페이지로 리다이렉트 등의 처리를 하면 되겠습니다.




이것으로 스프링 프레임워크에서 에러 페이지를 지정하는 방법에 대해 알아 보았습니다.


※ 전체 예제소스

srping_error.zip


반응형