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이나 다른 인클루드 파일에서 정의한 변수를 또다른 인클루드에서 정의할 경우는 변수가 중복되기 때문에 에러가 난다.
또한 디렉티브 방식은 소스가 바뀔때 반드시 재컴파일 되는것을 보장해주지 않는다고 한다. 그리고 완전히까지는 분석되지 않았는데 액션태그 방식을 사용하던 중 특정 인클루드된 파일이 갱신되지 않고 계속해서 임시인터넷 파일에서 나와서 캐시사용을 막아주어야 했었다.. ㅜ..ㅜ 물론 속도면에서는 디렉티브 방식이 당연히 빠르다. 그리고 또한유지보수 할 때 자신이 만든 소스가 아니면 변수추적을 해야 되는데 이렇게 파일이 쪼개져 있을 경우 상당히 쉽지 않다. 액션태그 방식은 그나마 괜찮지만 디렉티브 방식을 사용하면 변수선언이나 할당등이 다른 파일에 있을 경우가 많기 때문에 추적하기가 만만치 않다. 어느쪽이 좋을지는 자신이 상황에 맞게 선택할 일이다.
홈페이지를 하나 만들고 있는데
야금야금 시작한게 점점 일이 커져서 이제서야 템플릿을 써볼까 생각을 하네요..^^;
지금 머리속으로 생각만 해보고는 있지만 템플릿을 써서 포워딩을 해줄때
만약 실제 보여지는 페이지(introView.jsp)가 어떤 폴더안에 들어가 있다면..
그리고 그 폴더안에서 js 파일이 있어서 introView.jsp에서 상대경로로 external로 js파일을 사용한다면 js파일 보호도 가능할 것 같은데.. 맞는건가요?
어차피 익스플로러에서는 intro.jsp에 대한 정보만 보일테니..
그리고 소스를 보아도 js파일이 상대경로로 되어 있으면 폴더명을 모르면 접근도 불가능할테고요.
그렇지 않습니다.
JS파일은 was가 파싱하는 것이 아닌 웹브라우저가 파싱하기 때문에 클라이언트쪽으로 무조건 내려주게 됩니다. 만약 클라이언트에서 접근할 수 없는 JS라면 사용할 수가 없습니다.(물론 서버쪽 JS도 있긴 하지만 용도가 다르고 말씀하시는 부분이 서버쪽 JS는 아닌것 같아서요..)
암호화등의 꼼수들이 있긴 하지만 JS는 보호할 수 없습니다.
그리고 학습목적이시라면 jsp템플릿은 이해정도로만 보시고 jstl쪽으로 넘어가시는게 더 좋다고 생각됩니다.
저는 js파일의 경로를 모르게 할 수 있지 않을까 했는데..
해보니 이미 파싱한 후에 js파일을 참조하기 때문에 결국에는 intro.jsp파일을 기준으로 경로를 잡게 되더라구요.
그리고 액션태그로 해보니 introView.jsp에서도 request를 통해 값을 가져올 수 있었습니다.
하지만... 다시 한번 형변환을 해줘야 하는 불편함이...
오늘은 집에가서 디렉티브 방식으로 해봐야 되겠네요.
이클립스로 작업하고 있는데 디렉티브 방식으로 인클루드 된 것도 알아서 에러처리 안하고 인식하더라구요.
그리고 jstl은.. 우선 다 만들고 나서 스프링 적용할 때 수정해볼려고요~
지금은.. 내용 구현이 우선이라서..^^;
덕분에 좋은정보 얻고 갑니다~
ㅎㅎㅎ 이미 다 테스트해보고 해결하셨군요.
include디렉티브에서도 동일하게 request를 가져올 수 있을듯 합니다. 파일안에 내장되는 소스라서요...
즐거운 코딩 되시길.. ㅎㅎ