Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

JSP 템플릿 사용하기

개발을 할 때 어찌됐든 가장 신경써야 하는 것중 하나는 DRY(Don't Repeat Yourself)이다. 실용주의 프로그래밍같은 쪽에서 항상 강조하는거고... 유지보수 해보면 코드를 모듈화해서 재사용성이 얼마나 중요한지 피부로 느낄수 있다.(메뉴 글자 하나 바꾸는거 똑같은거 열몇개씩 계속 해보면... ㅋ 꼭 한번에 말안하고 다 바꾸면 변경사항 또 얘기해주고.. ㅋ )

JSP에서도 forword기능을 사용해서 페이지의 공통부분을 템플릿으로 뽑아내서 공통으로 사용할 수 있다. 예를 들어 모든페이지에 똑같은 로고, 상단메뉴, 사이드메뉴, 푸터 등등 어느 페이지나 공통으로 들어가는 틀을 가지고 있는 템플릿을 사용해서 코드작성을 줄일수 있다. 참고로 말하자면 이건 MVC Model 1정도에서 쓰일 방법이라고 생각한다. 고급으로 갈수록 이런 걸 대체할 수 있는 용도의 것들이 많이 존재하고 있으니까...(나두 Model 2에 JSTL하고 싶다규 ㅠ..ㅠ)


<jsp:forward page="template.jsp">
    <jsp:param name="CONTENT" value="introView.jsp" />
</jsp:forward>


예를 들어 사이트 소개페이지인 intro.jsp를 위처럼 만든다. 아무것도 하는 일이 없다. 페이지를 받자마자 template.jsp로 요청을 포워딩해준다. forward는 요청을 그대로 포워딩하는 것이기 때문에 포워딩된 후에도 주소창에는 그냥 intro.jsp가 있다. 페이지를 템플릿으로 포워딩하면서 introView.jsp라는 파일명을 파라미터로 넘겨준다.

그럼 template.jsp를 보자.


<%
    String content = request.getParameter("CONTENT");
%>
<html>
    <head></head>
    <body>
        <jsp:include page="/template/header.jsp" flush="false" />

        <jsp:include page="/template/mainMenu.jsp" flush="false" />

        <jsp:include page="<%= content %>" flush="false" />

        <jsp:include page="/template/footer.jsp" flush="false" />
    </body>
</html>



html코드는 별로 중요하지 않으니 간략화 했다. 탬플릿페이지를 가지고 있고 템플릿이 각 부분(위에서는 헤더, 메인메뉴, 푸터)의 공통파일을 불러들이고 바뀌어야 하는 부분만 content변수를 이용해서 다른 파일을 불러온다. 이렇게 하면 공통적인 곳의 코드는 한파일에서 관리하고 상황에 따라 어느정도 유연하게 템플릿파일을 구성해서 사용할 수 있다. 그리고 위의 예제에서는 3번째 include에서 파라미터로 받은 introView.jsp를 인클루드 한다. 바뀌는 부분의 파일명만 변수로 설정하여 원하는대로 바꾸어서 출력할 수 있다.

flush는 true일 경우 인클루드 전에 현재 있는 버퍼를 출력한다. 보통 false를 사용하는 듯한대 상황에 따라 선택할 나름이다. 인클루드에도 파라미터를 forwoard사용시와 동일하게 넘겨줄 수 있지만 이런식에 구성에서는 intro.jsp가 받은 파라미터를 템플릿이나 include되는 파일내에서 모두 getParameter로 받을수 있기 때문에 아주 특이한 경우 아니면 템플릿에서 파라미터를 넘겨줄 필요는 없을 듯 하다.(너무 믿지는 마시길.. ㅎㅎ) 이제 introView.jsp에 원하는 내용부분을 작성하면 된다.





여기서 인클루드를 사용할 때 동적으로 할지 정적으로 할지는 약간 생각해 보아야 할 문제이다. 파일 인클루드는 <jsp:include>액션태그(동적)와 include 디렉티브(정적) 2가지 방식이 있다.

<jsp:include page="introView.jsp" flush="false" />
<%@ include file="introView.jsp" %>

위 두 코드는 보이는 면 동일하게 동작을 한다. 하지만 동작방식 자체는 완전히 다른데 동적과 정적이라는 말에서도 느낄 수 있듯이 액션태그로 사용하면 페이지가 요청할 때마다 인클루드 페이지를 실행하고 결과를 가져와서 인클루드 하는 방식이고 디렉티브 방식으로 하면 jsp를 처음 컴파일 할 때부터 인클루드 할 페이지의 소스를 가져와서 해당위치에 넣은 후에 컴파일을 한다. 컴파일된 입장에서 본다면 디렉티브를 사용하면 하나의 파일이나 마찬가지란 얘기다.

이 방식을 이해하면 몇가지 더 생각해야 할 부분이 있다. 액션태그로 하면 모든 jsp가 다른 파일이나 마찬가지기 때문에 모든 변수를 새로 정의해 주어야 한다. 파라미터도 파일마다 따로 받고.... 보여주고자 하는 intro.jsp의 입장에서는 같은 변수나 파라미터를 여러번 정의하고 받아오는 것이다. 반면 디렉티브 방식은 결국은 하나의 파일이 된다고 했다. 그래서 template이나 다른 인클루드 파일에서 정의한 변수를 또다른 인클루드에서 정의할 경우는 변수가 중복되기 때문에 에러가 난다.

또한 디렉티브 방식은 소스가 바뀔때 반드시 재컴파일 되는것을 보장해주지 않는다고 한다. 그리고 완전히까지는 분석되지 않았는데 액션태그 방식을 사용하던 중 특정 인클루드된 파일이 갱신되지 않고 계속해서 임시인터넷 파일에서 나와서 캐시사용을 막아주어야 했었다.. ㅜ..ㅜ  물론 속도면에서는 디렉티브 방식이 당연히 빠르다. 그리고 또한유지보수 할 때 자신이 만든 소스가 아니면 변수추적을 해야 되는데 이렇게 파일이 쪼개져 있을 경우 상당히 쉽지 않다. 액션태그 방식은 그나마 괜찮지만 디렉티브 방식을 사용하면 변수선언이나 할당등이 다른 파일에 있을 경우가 많기 때문에 추적하기가 만만치 않다. 어느쪽이 좋을지는 자신이 상황에 맞게 선택할 일이다.
2008/09/23 00:06 2008/09/23 00:06