달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

JSF의 새로운 얼굴, MyFaces

 

 

지금은 웹 프레임워크의 전성시대라고 해도 과언이 아닐 것이다. MVC(Model -View-Controller) 형태의 모델2가 발표된 이후 수많은 웹 프레임워크가 발표됐고, 이런 웹 프레임워크의 난립(?)은 프로젝트 시작부터 어떤 것을 선택해야 할지에 대한 고민을 안겨주었다. 모든 웹 프레임워크가 나름대로 강조하는 장점들이 있지만, 왠지 ‘2%’ 부족하다는 느낌은 우리로 하여금 섣불리 그것을 선택하기를 주저하게 한다. 하지만 난세에 영웅이 난다고 했던가? JSF(Java Sever Faces)는 자바 표준 스펙(JCP-127)이라는 점에서 태생부터가 다른 웹 프레임워크와는 차별성을 보여주고 있다. 또한 스트럿츠 프로젝트의 리더인 Craig R. McClanahan 이 주도하고 스트럿츠의 커미터들이 대거 참여를 했다는 점에서 스트럿츠 이상의 그 무엇을 기대해도 좋을 것이라는 기대감을 갖게 한다.

JSF의 오픈소스 구현체, MyFaces
MyFaces는 JSF의 오픈소스 구현체이다. 인큐베이터에서 스트럿츠와 같은 위치인 최상위 프로젝트로 격상된 오픈소스 프로젝트인 것을 보면 ASF에서 MyFaces에 거는 기대가 얼마나 큰 것인지를 알 수 있다. MyFaces는 JSF의 구현체임으로 MVC 모델을 기본으로 한 최신의 웹 애플리케이션 프레임워크이며, 무엇보다 UI 단의 풍부한 컴포넌트는 그 어떤 웹 프레임워크와 비교해도 뒤떨어지지 않는다. 이번 기사에서는 JSF에 대한 설명보다 MyFaces에 포함된 쓸만한 컴포넌트들을 중심으로 설명하고자 한다. <표 1>에는 MyFaces의 동작 여부를 테스트한 리스트를 보여주고 있지만, 다른 버전의 WAS 등에서도 JSP 2.0이 지원될 수 있는 환경만 갖추어진다면 적용하기에는 큰 무리가 없다.

MyFaces 설치하기
MyFaces를 동작시켜보기 위해선 다음과 같은 소프트웨어가 필요하다.

◆ JDK 1.5 설치
◆ 톰캣 5.5.7 설치 : 기존의 톰캣을 사용할 경우 JSF 라이브러리가 있다면 삭제한다(jsf-api.jar, jsf-impl.jar).
◆ MyFaces Example 설치
      - <TOMCAT_HOME>/webapps 디렉토리 밑에 war를 설치한다.
      - 톰캣 실행 후  <TOMCAT_HOME>/webapps/myfaces-examples/WEB-INF /lib/commones-el.jar와 jsp-2.0.jar를 삭제한다(톰캣 5.5일 경우만).
      - 톰캣을 재시작한다.



MyFaces의 다양한 컴포넌트
MyFaces는 다양한 컴포넌트들로 무장하고 있다. 기존 웹 기반의 자바 프레임워크가 가지지 않는 이런 여러 가지 UI단 컴포넌트들은 MyFaces가 가는 길을 좀 더 편하게 만들 것이다. 많은 개발자들이 평소 프로젝트를 진행하면서, ‘아 이런 UI 컴포넌트들이 있었으면 좋겠다!’라고 생각했던 것의 대부분을 MyFaces에서 만나볼 수 있다. 또한 MyFaces는 JSF의 구현체로써 기본적인 JSF 관련 태그 선언부의 경우 다음과 같이 JSF를 따르고 있다.

<%@ taglib uri=”http://java.sun.com/jsf/html” prefix=”h”%>
<%@ taglib uri=”http://java.sun.com/jsf/core” prefix=”f”%>

MyFaces의 확장 컴포넌트를 사용하기 위해서는 다음과 같은 선언부를 사용해야 한다.

<%@ taglib uri=”http://myfaces.apache.org/extensions” prefix=”x”%>
<%@ taglib uri=”http://myfaces.apache.org/wap” prefix=”wap”%>

JSCook 메뉴 컴포넌트
JSCook 메뉴 컴포넌트는 <화면 2>에서 보듯이 웹 페이지의 메뉴를 만들어 낼 수 있는 컴포넌트이다. 커스텀 태그(custom tag)로 제공되고 실제 실행은 자바스크립트에 의해 동작된다. JSCook 메뉴는 Heng Yuan이라는 청년에 의해 개발된 자바스크립트로 작성된 메뉴 스크립트이다. 본래의 JSCook 메뉴의 경우 자바스크립트의 변수로 메뉴들을 정의하고, 이렇게 정의된 변수를 통해 자바스크립트가 메뉴를 표현하게 되어 있었다(변수로 메뉴를 정의하는 것은 상당히 번거로운 작업처럼 보였는데, JSCook의 홈페이지에서는 이런 메뉴 변수를 정의하는 Menu Builder를 제공하고 있다. Menu Builder는 브라우저상에서 메뉴의 이름과 아이콘 위치 등을 입력하면 자동으로 자바스크립트 소스를 만들어준다).

 


 

 

MyFaces에서는 커스텀 태그를 통해 정의된 메뉴의 URL과 레이블, 아이콘들을 정의한다. 실제 브라우저의 요청에 의해 커스텀 태그가 동작하게 되면(자바스크립트로써) 기존의 JSCook 메뉴가 원하는 형태의 소스로 변경된다. 즉 JSCook 메뉴의 경우 MyFaces의 커스텀 태그를 사용할 수도 있고, 자바스크립트 형태로도 사용할 수 있음으로 때에 따라 적절한 방법을 사용하면 된다. JSCook 메뉴를 구성하는 항목은 유일한 아이디와 아이템 레이블 그리고 링크 클릭시의 액션으로 구성되며, 모든 JSCook 메뉴는 <x:jscookMenu/> 태그를 부모 태그로 해야 하며, 각 메뉴 항목은 <x:navigationMenuItem/>으로 추가할 수 있다.

<리스트 1> JSCook 메뉴 예제
<%@ taglib uri="http://myfaces.apache.org/extensions" prefix="x"%>
                               :
<x:jscookMenu layout="hbr" theme="ThemeOffice" >
  <x:navigationMenuItem id="nav_1" itemLabel="#{example_messages['nav_Home']}" action="go_home" />
  <x:navigationMenuItem id="nav_2" itemLabel="#{example_messages['nav_Examples']}" >
    <x:navigationMenuItem id="nav_2_1" itemLabel="#{example_messages['nav_Sample_1']}" action="go_sample1" icon="images/myfaces.gif" />
  </x:navigationMenuItem>
</x:jscookMenu>

트리 컴포넌트
트리 컴포넌트의 경우 <화면 3>처럼 보이는 전형적인 트리의 형태를 갖추고 있으며, <리스트 2>의 예제를 보면 벌써 몇몇 개발자의 입에서는 탄성이 나올 법한 코드로 이뤄져 있다. DefultMutableTree Node 등 기존 Swing에서 사용하던 트리 컴포넌트와 거의 동일한 형태로 제공되며 사용하기도 상당히 편리하다. JSP의 Scriptlet을 통해 트리 컴포넌트를 구성하는 각 노드들에 대해 생성하고, Root 트리 노드를 기준으로 insert 메쏘드를 통하여 추가할 수 있다. 또한 구성된 트리 구조를 pageContext의 Attribute에 넣어 페이지가 다시 리로딩되거나 호출됐을 때 기존에 구성된 트리 구조를 재사용하도록 하고 있다. 트리 컴포넌트는 <x:tree/> 태그를 부모로 하여 구성되며, value 항목에 스크립트릿으로 TreeModel을 구성하여 pageContext에 셋팅된 값이 보여진다.

<리스트 2> 트리 예제
<%@ page import="org.apache.myfaces.custom.tree.DefaultMutableTreeNode,
                 org.apache.myfaces.custom.tree.model.DefaultTreeModel"%>
<%@ page session="true" contentType="text/html;charset=EUC-KR"%>
<%@ taglib uri="
http://myfaces.apache.org/extensions" prefix="x"%>

<%
   if (pageContext.getAttribute("treeModel", PageContext.SESSION_SCOPE) == null) {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("XY");
      DefaultMutableTreeNode a = new DefaultMutableTreeNode("A");
      root.insert(a);
      DefaultMutableTreeNode b = new DefaultMutableTreeNode("B");
      root.insert(b);
      DefaultMutableTreeNode c = new DefaultMutableTreeNode("C");
      root.insert(c);

      DefaultMutableTreeNode node = new DefaultMutableTreeNode("a1");
      a.insert(node);
      node = new DefaultMutableTreeNode("a2 ");
      a.insert(node);
      node = new DefaultMutableTreeNode("b ");
      b.insert(node);

      a = node;
      node = new DefaultMutableTreeNode("x1");
      a.insert(node);
      node = new DefaultMutableTreeNode("x2");
      a.insert(node);

      pageContext.setAttribute("treeModel", new DefaultTreeModel(root), PageContext.SESSION_SCOPE);
   }
%>

<x:tree id="tree" value="#{treeModel}"
        styleClass="tree"
        nodeClass="treenode"
        selectedNodeClass="treenodeSelected"
        expandRoot="true">
</x:tree>

정렬 가능한 테이블 컴포넌트
<x:dataTable/>은 HTML의 Table 형태로 데이터를 표현하는 수단으로 상당히 유용하게 사용할 수 있는 태그이다. 정렬 가능한 테이블은 dataTable이라는 CustomTag에 sortColumn과 sortAscending이라는 속성을 부여해 줌으로써 정렬 가능한 테이블 형태로 보여주는 것이다. <화면 4>에서 Car Type과 Car Color 부분을 클릭하면 순방향 정렬과 역방향 정렬로 토글(toggle)되며 내용이 표시된다. dataTable의 Header 영역에 sort를 할 수 있는 링크를 주기 위해 command SortHeader를 사용하고 있고 화살표의 사용여부를 arrow=”true”로 설정하고 있다. <x:dataTable/>을 부모 태그로 사용하며 각 컬럼마다 <h:column/>을 사용하여 테이블 구조를 나타나게 된다.

<리스트 3> 정렬 가능한 테이블 예제
<x:dataTable styleClass="standardTable"
        headerClass="standardTable_SortHeader"
        footerClass="standardTable_Footer"
        rowClasses="standardTable_Row1,standardTable_Row2"
        var="car"
        value="#{list.cars}"
        sortColumn="#{list.sort}"
        sortAscending="#{list.ascending}"
        preserveDataModel="true"
        preserveSort="true">

    <f:facet name="header">
        <h:outputText value="(header table)"  />
    </f:facet>
    <f:facet name="footer">
        <h:outputText value="(footer table)"  />
    </f:facet>

    <h:column>
        <f:facet name="header">
            <x:commandSortHeader columnName="type" arrow="true">
                <h:outputText value="#{example_messages['sort_cartype']}" />
            </x:commandSortHeader>
        </f:facet>
        <h:outputText value="#{car.type}" />
        <f:facet name="footer">
            <h:outputText id="ftr1" value="(footer col1)"  />
        </f:facet>
    </h:column>

    <h:column>
        <f:facet name="header">
            <x:commandSortHeader columnName="color" arrow="true">
                <h:outputText value="#{example_messages['sort_carcolor']}" />
            </x:commandSortHeader>
        </f:facet>
        <h:outputText value="#{car.color}" />
        <f:facet name="footer">
            <h:outputText id="ftr2" value="(footer col2)"  />
        </f:facet>
    </h:column>

</x:dataTable>

HTML 에디터 컴포넌트
HTML 에디터 컴포넌트의 경우 Kupu라는 이름으로 존재하던 WYSIWYG XHTML 에디터를 MyFaces의 컴포넌트로 포함시킨 것이다. HTML 에디터의 경우 상당히 많은 사이트에서 사용되고 있지만 웹 프레임워크 단에서의 UI 컴포넌트로 제공되는 것은 처음이 아닌가 싶다. HTML 에디터의 경우 글자체, Bold, Underline 등의 폰트를 꾸밀 수 있는 버튼과 색상, 정렬 등 다른 상용 HTML 에디터와 비교해도 뒤떨어지지 않는 기능성을 보여주고 있다. HTML 에디터 커스텀 태그의 경우 필수 속성은 없다.

<리스트 4> HTML 에디터 컴포넌트 예제
<x:htmlEditor value="#{editor.text}"
 style="height: 60ex;"
 formularMode="#{editor.formularMode}"
 allowEditSource="#{editor.allowEditSource}"
 showPropertiesToolBox="#{editor.showPropertiesToolBox}"
 showLinksToolBox="#{editor.showLinksToolBox}"
 showImagesToolBox="#{editor.showImagesToolBox}"
 showTablesToolBox="#{editor.showTablesToolBox}"
 showDebugToolBox="#{editor.showDebugToolBox}"/>

DataScroller 컴포넌트
DataScroller 컴포넌트의 경우 리스트를 표현하는 JSP 단에서 페이지 이동을 할 때 사용하는 컴포넌트이다. 페이지 이동의 경우 몇몇 사이트에서 커스텀 태그를 만들어 사용하는 경우를 보았으나, 거의 대부분은 특별한 표준이 없이 개발되고 있는 것 중에 하나이다. 하지만 리스트의 경우 페이지 이동은 필수적인 컴포넌트인 것을 보면, My Faces에 DataScroller가 있다는 것은 참으로 다행스러운 일이다. 또한 <x:dataScroller/>를 부모 태그로 하여 현재 페이지를 나타낼 pageCountVal 속성이 존재하며, 각 페이지의 navigation의 여부를 paginator 속성의 boolean 타입을 정의하고 보여질 총 페이지 수를 paginatorMaxPages로 정의할 수 있다.

<리스트 5> DataScroller 예제
<x:dataScroller id="scroll_1"
        for="data"
        fastStep="10"
        pageCountVar="pageCount"
        pageIndexVar="pageIndex"
        styleClass="scroller"
        paginator="true"
        paginatorMaxPages="9"
        paginatorTableClass="paginator"
        paginatorActiveColumnStyle="font-weight:bold;"
        >
    <f:facet name="first" >
        <h:graphicImage url="images/arrow-first.gif" border="1" />
    </f:facet>
    <f:facet name="last">
        <h:graphicImage url="images/arrow-last.gif" border="1" />
    </f:facet>
    <f:facet name="previous">
        <h:graphicImage url="images/arrow-previous.gif" border="1" />
    </f:facet>
    <f:facet name="next">
        <h:graphicImage url="images/arrow-next.gif" border="1" />
    </f:facet>
    <f:facet name="fastforward">
        <h:graphicImage url="images/arrow-ff.gif" border="1" />
    </f:facet>
    <f:facet name="fastrewind">
        <h:graphicImage url="images/arrow-fr.gif" border="1" />
    </f:facet>
</x:dataScroller>
<x:dataScroller id="scroll_2"
        for="data"
        rowsCountVar="rowsCount"
        displayedRowsCountVar="displayedRowsCountVar"
        firstRowIndexVar="firstRowIndex"
        lastRowIndexVar="lastRowIndex"
        pageCountVar="pageCount"
        pageIndexVar="pageIndex"
        >
    <h:outputFormat value="#{example_messages['dataScroller_pages']}" styleClass="standard" >
        <f:param value="#{rowsCount}" />
        <f:param value="#{displayedRowsCountVar}" />
        <f:param value="#{firstRowIndex}" />
        <f:param value="#{lastRowIndex}" />
        <f:param value="#{pageIndex}" />
        <f:param value="#{pageCount}" />
    </h:outputFormat>
</x:dataScroller>

여러 Validation 컴포넌트
MyFaces의 Validation의 경우 썬 JSF RI가 세 가지 정도의 기본적인 Validation을 제공하는 것에 추가적으로 이메일, 신용카드 , ISBN, Equal 같은 상당히 유용한 Validation을 제공한다. Valication을 넣는 방법으로는 <f:validator/> 태그에 validatorId로써 사용하고자 하는 Validator 클래스를 지정하는 방법과 <x:validateXXX/>와 같은 MyFaces의 확장 태그 형태로 사용할 수 있다.

<리스트 6> Validation 예제
<h:outputLabel for="form1:email" value="#{example_messages['validate_email']}" />
<h:inputText id="email" value="#{validateForm.email}" required="true">
    <f:validator validatorId="org.apache.myfaces.validator.Email"/>
</h:inputText>
<h:message id="emailError" for="form1:email" styleClass="error" />

<h:outputLabel for="form1:email2" value="#{example_messages['validate_email']}2" />
<h:inputText id="email2" value="#{validateForm.email2}" required="true">
    <x:validateEmail />
</h:inputText>
<h:message id="emailError2" for="form1:email2" styleClass="error" />

<h:outputLabel for="form1:creditCardNumber" value="#{example_messages['validate_credit']}" />
<h:inputText id="creditCardNumber" value="#{validateForm.creditCardNumber}" required="true">
    <x:validateCreditCard />
</h:inputText>
<h:message id="creditCardNumberError" for="form1:creditCardNumber" styleClass="error" />

     <h:outputLabel for="form1:regExprValue" value="#{example_messages['validate_regexp']}" />
<h:inputText id="regExprValue" value="#{validateForm.regExpr}" required="true">
    <x:validateRegExpr pattern='d{5}' />
</h:inputText>
     <h:message id="regExprValueError" for="form1:regExprValue" styleClass="error" />

     <h:outputLabel for="form1:isbn" value="#{example_messages['validate_isbn']}" />
<h:inputText id="isbn" value="#{validateForm.isbn}" required="true">
    <x:validateISBN />
</h:inputText>
     <h:message id="isbnError" for="form1:isbn" styleClass="error" />

<h:outputLabel for="form1:equal" value="#{example_messages['validate_equal']}" />
<h:inputText id="equal" value="#{validateForm.equal}" required="true"/>
<h:message id="equalError" for="form1:equal" styleClass="error" />

<h:outputLabel for="form1:equal2" value="#{example_messages['validate_equal']}2" />
<h:inputText id="equal2" value="#{validateForm.equal2}" required="true">
    <x:validateEqual for="form1:equal" />
</h:inputText>
<h:message id="equal2Error" for="form1:equal2" styleClass="error" />

<h:panelGroup/>
<h:commandButton id="validateButton" value="#{example_messages['button_submit']}" action="#{validateForm.submit}"/>
<h:panelGroup/>

MyFaces의 장밋빛 미래
JSF가 자바 표준 스펙으로써 향후 J2EE의 웹 프레임워크의 중심이 될 것이라는 생각은 그리 어렵지 않게 할 수 있다. 또한 MyFaces가 JSF의 오픈소스 구현체로써 상당히 중요하게 대접(?)받을 것도 쉽게 알 수 있다. MyFaces는 충실한 JSF의 구현체이면서 유용한 컴포넌트들로 무장하고 있다. 다만 조금 걱정이 되는 부분은 UI가 상당히 다이나믹한 국내의 실정에서 얼마나 적용 가능성이 있을지에 대한 우려와 개발자 입장에서 커스텀 태그에 대한 사용이 얼마나 쉽게 받아들일 수 있는가가 문제가 될 수 있을 것으로 보인다. MyFaces는 이클립스와 같은 IDE와의 연계성, J2EE 진영의 주요 벤더에서 JSF를 제대로 지원하는 순간부터 MyFaces의 활용도는 그 어떤 JSF의 구현체보다 활발할 것이다. 아직 제한된 오픈소스만을 사용하는 국내 실정에서 좀 더 많은 오픈소스를 사용하게 되는 계기가 MyFaces를 통해 시작되기를 간절히 바랄뿐이다. [maso]

 

 

출처 : http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=6094

 

'JAVA > JSP_Servlet' 카테고리의 다른 글

[펌] 자바툴(솔루션) 정리  (0) 2005.11.16
sitemesh ..  (0) 2005.11.09
[link] XMLC Site....  (0) 2005.10.25
[link] 자바 어플로 만든 쇼핑몰  (0) 2005.10.25
[펌] JSP 2.0에서 Custom Tag활용  (0) 2005.10.25
Posted by tornado
|