Model 1 방식에서 효과적인 JSP 구현법
개요
프로젝트에 따라 Model 1 방식을 사용하는 경우가 생기는데 이 때, Controller의 역할이나 유지 보수성을 향상하기 위한 방법을 생각해본다.
JSP에 많은 기능을 담기 때문에 이를 정리하는 것이 중요하다. 이를 위해 부분적으로 Model 2 방식을 흉내내는 방법을 사용하기로 한다.
Model 1 방식은 View 와 Bean으로 구분되지만 Presentation 영역과 비지니스 로직이 혼재되어 다음과 같은 문제를 나타내기 쉽다.
서버 작업과 클라이언트 작업이 혼재되는 경우가 많다.
JSP to JSP 이동이 빈번히 발생한다. 이 때, form을 통해 parameter를 전달하는 과정에서 정보의 누락이 생길 수 있다.
한 화면에서 여러 기능이 존재하는 경우, 필요한 parameter가 상이하여 이를 페이지 이동으로 표현하는 경우 정보가 단절될 수 있다.
공통 기능을 위한 동일한 코드들이 반복적으로 여러 JSP에 사용될 가능성이 높다.
이런 부분들은 개발 스타일이나 프로젝트 표준에 따라 발생하지 않을 수도 있다. 하지만 기존 시스템(AS-IS)에서 정리되지 않은 형태로 존재할 수도 있고 규모가 작아 Model 1 방식을 채택한 경우 개발 편의성을 위해 표준을 두지 않고 개발자 역량에 맡기는 경우가 있다.
기존 Code를 리팩토링 하는 경우나 신규 개발에 앞서 개인이 맡은 모듈 단위의 표준을 정하는 것은 효율성을 올리는데 도움이 될 것이라 믿는다.
Model 1 방식에서 작은 규모의 Model 2 방식의 모방은 규모가 크지 않은 상황에 개발 편의성과 유지 보수성 사이의 조율을 하는 방법 중 하나이다.
1. Page Structure
Page 구성에는 Presentation 측면에서 Layout과 코드 구현 측면에서 Document Structure로 나눌 수 있다. (도움 이미지 첨부하자)
Model 1 방식에서 자칫 두 경우 모두 중복된 코드를 만들기 쉬운데 이를 제거하는 것 만으로도 구조적인 모습을 갖추기가 용이하다.
Model 1 방식에서 중복성 제거는 "include" 를 사용하여 이룰 수 있다. 이 때, JSP는 하나의 코드 블럭으로 생각할 수 있다.
JSP에서 사용하는 "include" 에는 다음과 같은 2가지 방법이 있다.
* JSP Action - <jsp:include page="URI" flush="true" />
1) body 구문이 없는 경우
<jsp:include page="URI" flush="true" />
2) body 구문이 있는 경우
<jsp:include page="URI" flush="true">
<jsp:param name="..." value="..." />
</jsp:include>
위와 같이 두가지 사용 용법이 있으며, 두번째 방법을 사용하면 해당 jsp파일에 파라메터 값도 넘겨 줄 수가 있다.
JSP Action 구문의 include는 각각 파일을 컴파일 한 후 두 파일의 실행 결과를 한 곳에 합쳐서 출력을 한다. 즉, 완전히 "별도로" 동작하게 된다.
# flush="true" 는 include를 실행하기 전에 out.flush()를 실행할지 여부로 JSP 스펙 1.1 까지는 반드시 true로 설정이 되어 있어야만 했지만 1.2 부터는 true/false중 원하는것을 선택할 수 있다. (사실 flush 가 false일 경우가 발생하는 이유를 저로서는 잘 이해가 되지 않습니다. 이 부분에 대해서 아시는 분 께서는 꼭 저에게도 한번 설명을 부탁드립니다.)
* include 지시어 - <%@ include file="URI" %>
include 지시어는 컴파일 되기전에 파일이 내용이 합쳐진다. 즉, 내용을 자신의 문서 내에 포함하여 하나의 파일로 인식한다.
* Action 구문과 include 지시어의 중요한 차이점
JSP는 먼저 servlet 으로 변환되고, 그 다음 servlet 이 컴파일 되어 그 결과를 화면에 출력해 주게 된다.
그런데, Action 구문을 사용 하였을 때에는 두개의 파일 각각 다른 파일처리 되어 두개의 servlet 파일 생성된다. 따라서 어느 한 파일이 수정되면 곧바로 적용되어 화면에 출력이 된다.
하지만 include 지시어 문을 사용하게 되면 하나의 servlet 파일이 생성된다. 이로 인해, JSP파일이 수정이 될 때 servlet 으로 재 변경되어 다시 컴파일이 이루어 지지만 include를 수행하는 파일에서는 수정 전의 내용이 출력된다.
해당 파일의 내용이 수정된다 하더라도 JSP엔진에서는 include를 수행한 파일은 수정사항이 없으므로 JSP 엔진에서는 같은 파일로 인식하여, servlet 파일을 다시 생성하지 않기 때문이다.
따라서, include 지시어 문을 사용하셨을 경우에는 두개의 파일 모두 수정해 주어야한다.
또, include 지시어를 사용할 경우에는 최종 결과가 온전한 JSP 문서 구성을 따르면 된다. 이는 각 부분은 꼭 온전한 JSP 문법을 완성한 형태일 필요는 없다는 뜻이다.
반대로, Action 구분을 사용할 경우에는 각 JSP 페이지 마다 Life scope를 갖게 되므로 다른 JSP와 영향도를 효과적으로 낮출 수 있다.
위와 같은 특성을 잘 활용하여 중복을 처리하려는 단위로 기능이 기준이 된 경우에는 Action 구문으로, 단순 코드의 반복이 기준인 경우에는 include 지시어로 활용하는 것이 좋다.
예를들어, 화면 구성을 하는 경우 Layout에 따라 기능 단위로 나눌 수 있으므로 이를 Action 구문을 활용하여 나눌 수 있다.
또한 Model 1 에서 각 JSP에서 URL이나 세션 정보를 통해 현재 접근이 유효한지 검사하는 모듈처럼 기계적으로 반복되는 코드의 일련은 include 지시어를 활용하여 나눌 수 있다.
2. Page Navigate
Mini-Dispatcher 선언 <jsp:forward page="URI"> (= PageContext.forward( "URI"); )를 통한 Dispatcher 구성
<%@ include file="URI">를 통한 일률적인 Form 구성
3. Ajax 처리
응답 대기시 입력 컨트롤 방지
4. Tag Library 활용