[JSP 리팩토링] 태그 파일로 중복 코드 제거하기

<%@ page language=”java” contentType=”text/html; charset=UTF-8″ pageEncoding=”UTF-8″%>
<%@ taglib prefix=”page” tagdir=”/WEB-INF/tags/page”%>
<%@ taglib prefix=”form” uri=”http://www.springframework.org/tags/form”%>
<%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core”%>
<%@ taglib prefix=”s” tagdir=”/WEB-INF/tags/study”%>

<page:studypage>
<s:defaultpage>
    <h1>스터디 추가</h1>
    <form:form commandName=”study” method=”post”>
    <p>
        <label>스터디명</label>
        <form:input path=”studyName” cssClass=”text” />
        <form:errors path=”studyName” />
    </p>
    <p>
        <label>최대인원수</label>
        <form:input path=”maximum” cssClass=”text” />
        <form:errors path=”maximum” />
    </p>
    <p>
        <label>시작일</label>
        <form:input path=”startDay” cssClass=”text”/>
        <form:errors path=”startDay” />
    </p>
    <p>
        <label>종료일</label>
        <form:input path=”endDay” cssClass=”text”/>
        <form:errors path=”endDay” />
    </p>
    <p>
        <label>설명</label>
        <form:textarea path=”descr” rows=”4″ cols=”60″ cssClass=”text”/>
        <form:errors path=”descr” />
    </p>
    <br/><hr/><br/>
    <a href=”<c:url value=”/study/list.do”/>”>취소</a>
    <input type=”submit” value=”저장” class=”s_waitblock” />
    </form:form>
</s:defaultpage>
<script type=”text/javascript”>
  $(document).ready(function(){
    $(“#startDay”).datepicker({ dateFormat: ‘yy/mm/dd’ });
    $(“#endDay”).datepicker({ dateFormat: ‘yy/mm/dd’ });
  });
</script>
</page:studypage>

이미 태그 파일로 <html> </html>과 js, css 임포트 하는 부분을 제거 해 두었습니다. 태그 파일을 여러 추상화 계층으로 세분화 해서 로우 레벨 태그파일과 하이 레벨 태그파일로 나눌 수도 있겠습니다. 저 위에 보이는 page 태그는 하이 레벨 태그 파일로 볼 수 있고, s 태그는 로우 레벨로 볼 수 있습니다. 하이 레벨이라고 해서 뭔가 더 여러운 태그라는게 아니라, 로우 레벨 태그를 조합하여 한 단계 더 추상화시킨 태그파일 입니다. 이런 구분이 원래 있는 것이 아니라 제가 생각하는 걸 정리한 것 뿐이오니,,, 괜히 “하이 레벨 태그 파일” 이런식으로 구글링을 하는 사태가 없기를 바랍니다.

사설을 좀 길었네요, 일단락하기로 하고, 위 코드를 태그파일로 리팩토링하면 다음과 같이 됩니다.

<page:studypage>
<s:defaultpage>
    <h1>스터디 추가</h1>
    <form:form commandName=”study” method=”post”>
    <s:ftext title=”스터디명” path=”studyName” />
    <s:ftext title=”최대인원수” path=”maximum” />
    <s:fdate title=”시작일” path=”startDay” />
    <s:fdate title=”종료일” path=”endDay” />
    <s:ftextarea title=”설명” path=”descr” rows=”4″ cols=”60″ />
    <hr/>
    <s:back-button url=”/study/list.do” />
    <input type=”submit” value=”저장” class=”s_waitblock” />
    </form:form>
</s:defaultpage>
<script type=”text/javascript”>
  $(document).ready(function(){
    $(“.fdate”).datepicker({ dateFormat: ‘yy/mm/dd’ });
  });
</script>
</page:studypage>

이렇게 했을 때 좋은 점은 소스 코드에서 중복을 제거 했을 때 얻을 수 있는 장점과 같습니다.

그러나,,, 단점도 있는데 태그 파일에 정의해준 속성만 받아서 사용하기 때문에 그만큼 사용할 수 있는 기능이 제한 될달까.. 그런게 좀 있습니다. 해결책은 있습니다. 태그 파일에 거의 모든 속성을 다 정의해 놓고 정말 필요한 것만 required로 하고 사용해도 될테지만.. 태그 파일을 만드는 비용이 꽤 많이 들겠지요. 결국 선택의 기로에 서게 되는데, 저는 귀찮아서;; 그냥 최소한의 속성만 정의해서 쓰는 편입니다.

OSAF 검색 폼 태그 파일 완성

사용자 삽입 이미지
태그 파일을 활요한 JSP 코드는 다음과 같습니다.

<o:searchpage title=”사원관리”>
    <o:searchbuttons popupheight=”400″ popupwidth=”700″ />

    <o:searchform action=”grid.do”>
        <o:searchrow>
            <o:stext path=”name” label=”이름” size=”20″ maxlength=”30″ />
            <o:sselect path=”location” label=”국적” items=”${ref.locations}” isCOV=”yes” />
            <o:sdate path=”birthday” label=”생일” />
        </o:searchrow>
        <o:searchrow>
            <o:sradiobuttons path=”sex” label=”성별” items=”${ref.sexType}” />
        </o:searchrow>
        <o:searchrow>
            <o:scheckboxes path=”hobbies” label=”취미” items=”${ref.hobbyType}” />
        </o:searchrow>
    </o:searchform>
</o:searchpage>

뭔가 많아 보여도, <o:searchrow>를 사용해서 세 줄로 표시했을 뿐, <o:searchrow>를 빼면 별거 없습니다. 이젠 정말 폼 태그 파일 만들차례.. ㅎㄷㄷㄷ.. 어려울텐데.. ㄷㄷㄷㄷ DisplayTag로 만들어봐야지

JavaScript Calendar

참조: http://www.dynarch.com/projects/calendar/
사용자 삽입 이미지
저렇게 달력을 뿌려주는 자바스크립트 라이브러리입니다. Date 정보를 입력받을 때 사용하면 유용하겠죠. 여러 가지 스타일 시트도 제공해주고, 여러 포맷으로 데이터를 조작할 수도 있고, 좋습니다.

jscalander가 제공하는 예제 소스 코드를 보면 어떻게 이용할 수 있을지 대충 알 수 있습니다.

<form action=”#” method=”get”>
<input type=”text” name=”date” id=”f_date_b” /><button type=”reset” id=”f_trigger_b”>…</button>
</form>

<script type=”text/javascript”>
    Calendar.setup({
        inputField     :    “f_date_b”,      // id of the input field
        ifFormat       :    “%m/%d/%Y %I:%M %p”,       // format of the input field
        showsTime      :    true,            // will display a time selector
        button         :    “f_trigger_b”,   // trigger for the calendar (button ID)
        singleClick    :    false,           // double-click mode
        step           :    1                // show all years in drop-down boxes (instead of every other year as default)
    });
</script>

친절하게 주석도 있기 때문에, 금방 적용하실 수 있겠죠. 하지만, 약간의 번거로움은 감수를 하셔야 하며, 저런 컴포넌트가 여럿 필요할 때는 복사 붙여넣기 코드가 JSP 페이지 사방에 나타날 수 있을 겁니다. 그럴 땐 태그 파일을 만들어서 컴포넌트화 해 두면 매우 편합니다.

언젠가 공개할 OSAF를 사용하신다면, 간단한 태그 파일 sdata.tag로 쉽게 저런 UI 컴포넌트를 만들 수 있습니다.

<o:sdate path=”birthday” label=”생일” />

이렇게 한 줄이면 끝이죠. 캬오~ 태그 파일 만쉐이! OSAF 만쉐이!!

휴.. 폼 태그 파일 완성.

<o:popuppage title=”사원등록”>
    <o:buttons>
        <o:savebtn />
        <o:cancelbtn />
    </o:buttons>
    
    <o:form>
        <o:ftext label=”이름” path=”name” size=”10″ maxlength=”20″ />
        <o:ftext label=”아이디” path=”loginId” size=”15″ maxlength=”20″ desc=”최대 20자리까지 입력 할 수 있습니다.” />
        <o:fpassword label=”패스워드” path=”password” size=”10″ maxlength=”16″ desc=”최대 16자리까지 입력 할 수 있습니다.” />
        <o:fradiobuttons label=”성별” path=”sex” items=”${ref.sexType}” />
        <o:fcheckboxes label=”취미” path=”hobbies” items=”${ref.hobbyType}” />
        <o:fselect label=”국적” path=”location” items=”${ref.locations}” isCOV=”yes” />
        <o:ftextarea label=”메모” path=”memo” rows=”3″ cols=”50″ />
    </o:form>
</o:popuppage>

이게 추가와 수정시에 사용할 JSP 페이지 코드입니다. JSP를 몰라도 금방 태그 파일 몇개만 익히면 쉽게 페이지를 찍어낼 수 있습니다. 이 페이지에서 사용하고 있는 태그 파일들은 다음과 같습니다.

사용자 삽입 이미지
흠냐~ 이 녀석들로 만들어 낸 화면입니다.
사용자 삽입 이미지
물론 CSS도 가미가 되어 있습니다. CSS는 잘 몰라서 사부님이 만들어 둔 걸 그대로 쓰고 있습니다. 저기 items 뿌리는 부분의 label 스타일을 좀 변경하고 싶은데;; 일단 스타일은 나중에 변경하기로.. ㅋㅋ

사용자 삽입 이미지
업데이트 뷰에서도 위와 동일한 태그를 사용하면 됩니다. 흠.. 버튼을 하나 추가해서 삭제버튼을 달아야겠군요.

이것으로 폼 태그 파일들은 다 준비가 됐습니다. 이제 그리드 태그 파일만 완성하면… 드디어 OSAF를 출시할 수 있게 됩니다. 캬오~~

1년 반 만에 다시 찾은, EL 안에 EL 사용하는 방법

커스텀 태그에서 Expression Language를 사용하다보면, 언젠간 아래처럼 쓰고 싶은 경우가 발생할 수도 있습니다. 전 예전에 한 번 이 벽에 부딪혀서 결국 못 넘고 좌절한 적이 있는데, 해당 글에 물개선생님이 남겨주신 댓글과 사부님이 만든 태그를 보니.. 이해가 됩니다.

먼저 상황부터 설명을 하자면,..

일단 EL 안에 EL을 사용하고 싶은 경우가 어떤 경우냐면.. 보통 ${member.name} 이렇게 쓰는데, 만약 이 때 이 name라는 값도 변수화 해서 property라는 태그 파일 속성으로 받도록 할 수 있겠습니다. 그리고 이 속성에는 name 뿐만 아니라, age, height 등등 여러 가지 member 객체가 가지고 있는 속성 값을 넣을 수 있다고 했을 때.. EL로 그 속성값을 뿌리려면..

<%@ attribute name=”property” required=”false” %>

${member.${property}}

이렇게 하고 싶습니다. 그쵸? 하지만, 해보시면 아시겠지만 안 됩니다. 저런 문법을 EL이 지원하질 않습니다.

심각: Servlet.service() for servlet sample threw exception
org.apache.el.parser.ParseException: Encountered “{” at line 1, column 4.
Was expecting one of:
    “}” …
    “.” …
    “[” …
    “>” …
    “gt” …
    “<” …
    “lt” …
    “>=” …
    “ge” …
    “<=” …
    “le” …
    “==” …
    “eq” …
    “!=” …
    “ne” …
    “&&” …
    “and” …
    “||” …
    “or” …
    “*” …
    “+” …
    “-” …
    “?” …
    “/” …
    “div” …
    “%” …
    “mod” …
    “(” …
   
    at org.apache.el.parser.ELParser.generateParseException(ELParser.java:1874)
    at org.apache.el.parser.ELParser.jj_consume_token(ELParser.java:1754)
    at org.apache.el.parser.ELParser.DynamicExpression(ELParser.java:156)

자.. 이런 에러가 발생합니다. 괄호를 안쪽부터 처리해주면 좋겠지만, 희망사항이었던 것 같습니다. ${property}의 값이 name이면 ${member.name} 이 되고.. 이건 내부적으로 member.getName()을 호출해서 가져다주면 좋을텐데 말이죠. 흠… 복잡해 질까봐 이렇게 구현하지 않았을지도 모르겠습니다.

어쨋든, 저 윗 글에 물개선생님이 알려주신 코드대로 하면 EL안에 EL을 사용하는 효과를 얻을 수 있습니다.

<%@ attribute name=”property” required=”false” %>

<%
property = (property != null) ? property : “name”;
Object memberPropertyValue = PageContextImpl.proprietaryEvaluate(“${member.” + property + “}“, Object.class, (PageContext)this.getJspContext(), null, false);
out.print(memberPropertyValue.toString());
%>

이렇게 PageContextImpl를 이용해서 가져오면 됩니다. 위에서 제가 원하던 방법대로 자바 코드를 사용해서 처리한 겁니다. “${member.” + property + “} 이렇게 하는 순간, 이미 안 쪽의 변수 값을 가져오기 때문에 이후에는 ${member.name}를 쓰는 것과 같은 것이 됩니다.

흠.. 이상합니다. 저 때도 분명 물개 선생님이 댓글로 코드까지 주셨는데, 저걸 못 써먹고 포기했었습니다. 거의 1년 반이 지난 이제와서 그때 포기했던걸 다시 하게 되네요. ㅋㅋ 1년 반이라…