메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

JSF 2 fu: 복합 컴포넌트의 우수 사례

확장 가능한 사용자 정의 컴포넌트 구현

David Geary, President, Clarity Training, Inc.
http:/Photo of David Geary
저자이자 강사이며 컨설턴트이기도 한 David Geary는 JSF와 GWT(Google Web Toolkit)를 사용하여 웹 애플리케이션을 구현하는 방법을 개발자에게 강의하고 있으며 Clarity Training, Inc.의 사장이다. 그는 JSTL 1.0 및 JSF 1.0/2.0 Expert Groups의 일원이었으며 Sun에서 시행하는 Web Developer Certification Exam의 공동 출제자였고 Apache Struts 및 Apache Shale과 같은 오픈 소스 프로젝트에 기여했다. 그가 집필한 Graphic Java Swing은 꾸준히 베스트셀러로 판매되고 있는 Java 서적 중 하나이며 Core JSF(Cay Horstman과 공동 집필)는 베스트셀러로 판매되고 있는 JSF 서적이다. David는 컨퍼런스와 사용자 그룹에서 정기적으로 연사로 나서고 있고 2003년부터 NFJS tour에서 정회원으로 활동 중이며 Java University에서 세 차례 강의했고 JavaOne Rock Star로 세 차례 선정되었다.

요약:  JSF 2 fu 기사 시리즈 중 이번 회에서는 Java™ Server Faces 복합 컴포넌트를 구현하기 위한 5가지 우수 사례를 학습할 것입니다. 여기서 제시하는 지침에 따라 페이지 작성자가 사용자 정의 컴포넌트를 손쉽게 확장하도록 할 수 있습니다.

이 연재 자세히 보기

원문 게재일:  2011 년 1 월 11 일 번역 게재일:  2011 년 4 월 26 일
난이도: 중급 원문:  보기 PDF:  A4 and Letter (168KB | 16 pages)Get Adobe® Reader®
페이지뷰:  1909 회
의견:  


이 시리즈의 정보

David Geary가 작성했으며 제목이 동일한 세 편의 소개 기사의 후속 기사인 JSF 2 fu 시리즈를 읽으면 JSF 2 프레임워크 스킬을 개발하고 연마하여 쿵푸(kung fu) 마스터처럼 전문가가 될 수 있다. 현재에 작성 중인 시리즈에서는 프레임워크와 주위 환경에 대해 더 자세히 살펴본다. 또한 이 시리즈에서는 CDI(Contexts and Dependency Injection)와 같은 일부 Java EE 기술을 JSF와 통합되는 방법을 살펴보며 기사의 범위를 벗어난 내용도 일부 설명한다.

JSF는 컴포넌트 기반 프레임워크이며, 이는 곧 JSF가 컴포넌트를 자체적으로 구현하는 데 필요한 인프라를 제공한다는 의미이다. JSF 2를 사용하면 사용자 정의 복합 컴포넌트를 간단히 구현할 수 있다.

필자는 전에 작성한 기사들에서 여러 가지 복합 컴포넌트의 구현 방법을 설명했었다("Templating 및 복합 구성 요소", "Ajax 구성 요소" 및 "복합 컴포넌트를 구현한 후 Ajax 추가하기" 참조). 본 기사에서는 JSF 2로 복합 컴포넌트를 구현하기 위한 다음 5가지 우수 사례를 제시하여 그 주제와 JSF 2 fu 시리즈를 요약할 것이다.

  1. DIV에 컴포넌트 랩핑
  2. JavaScript와 Ajax의 통합
  3. JavaScript 클로저를 사용하여 한 페이지에서 여러 컴포넌트 지원
  4. 페이지 작성자가 컴포넌트를 사용자 정의하는 방식
  5. 컴포넌트 국제화

이런 우수 사례들을 설명하기 위해, 간단한 복합 컴포넌트의 구현에 이들이 어떻게 적용되는지 설명하겠다.

편집 가능한 입력 복합 컴포넌트

본 기사의 예제 컴포넌트는 편집 가능한 입력 복합 컴포넌트이다. 그림 1에 표시된 애플리케이션에서는 두 개의 편집 가능한 입력을 사용하는데, 하나는 이름, 하나는 성을 입력하기 위한 것이다.


그림 1. 편집 가능한 텍스트 컴포넌트
맨 위에서 맨 아래까지, 이름에 대한 편집 순서를 보여주는 3개의 스크린샷

맨 위에서 맨 아래까지, 그림 1에 있는 3개의 스크린샷은 이름에 대한 편집 순서를 보여준다.

  • 맨 위의 스크린샷은 애플리케이션의 최초 모양을 나타낸 것으로, First name:Last name: 레이블 오른쪽에 edit... 단추가 있다.
  • 중간의 스크린샷은 사용자가 First name: 옆에 있는 edit... 단추를 클릭하고 텍스트 입력 영역에 Roger를 입력한 직후에 애플리케이션의 모양을 나타낸 것이다. 텍스트 입력 영역 오른쪽에 done 단추가 표시된다.
  • 맨 아래의 스크린샷은 사용자가 done 단추를 클릭한 후의 애플리케이션 모양을 나타낸 것이다. 이때는 First name: Roger가 표시되고 그 오른쪽에 edit... 단추가 있다.

다음으로, 편집 가능한 입력 컴포넌트를 사용하는 방법을 설명한 후 그 컴포넌트가 어떻게 구현되는지 보여주겠다. 그 후, 컴포넌트의 구현이라는 관점에서 5가지 우수 사례를 각각 설명하겠다.

컴포넌트 사용

JSF 복합 컴포넌트를 사용할 때는 편집 가능한 입력 컴포넌트를 사용하고, 적당한 네임스페이스를 선언하고, JSF가 복합 컴포넌트에 대해 생성하는 태그를 사용한다. 리스트 1은 그림 1에 표시된 페이지에 대한 마크업과 함께 그 두 단계를 나타낸 것이다.


리스트 1. <util:inputEditable> 사용
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:util="http://java.sun.com/jsf/composite/util">
   <h:head>
      <title>Implementing custom components</title>
   </h:head>
   <h:body>
      <h:form>   
         <h:panelGrid columns="2">
            First name: 
            <util:inputEditable id="firstName" 
                             value="#{user.firstName}"/>
               
            Last name:
            <util:inputEditable id="lastName" 
                             value="#{user.lastName}"/>
        </h:panelGrid>
      </h:form>
   </h:body>  
</html>

완전성을 기하기 위해, 리스트 2에서는 리스트 1에서 참조된 user bean의 구현을 보여준다.


리스트 2. User bean

package com.corejsf;

import java.io.Serializable;
import javax.inject.Named; 
import javax.enterprise.context.SessionScoped; 

@Named("user") 
@SessionScoped
public class UserBean implements Serializable {
   private String firstName;
   private String lastName;

   public String getFirstName() { return firstName; }   
   public void setFirstName(String newValue) { firstName = newValue; }

   public String getLastName() { return lastName; }
   public void setLastName(String newValue) { lastName = newValue; }   
}

이제 편집 가능한 입력 컴포넌트의 사용법을 알았으니, 어떻게 구현되는지를 설명하겠다.

컴포넌트의 구현

편집 가능한 입력 컴포넌트는 그림 2의 파일 시스템 계층 구조에서 보는 바와 같이, resources/util 디렉토리의 inputEditable.js, inputEditable.properties 및 inputEditable.xhtml 파일에서 구현된다.


그림 2. 컴포넌트의 파일
inputEditable 컴포넌트에 대한 폴더 및 파일 계층 구조를 보여주는 스크린샷

리스트 3 은 inputEditable.xhtml을 나타낸 것이다.


리스트 3. inputEditable 컴포넌트의 마크업(inputEditable.xhtml)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:composite="http://java.sun.com/jsf/composite">
    
    <composite:interface>
       <composite:attribute name="text"/>
       <composite:editableValueHolder name="text" targets="editableText" />
       <composite:actionSource name="editButton" targets="editButton" />
       <composite:actionSource name="doneButton" targets="doneButton" />
       <composite:clientBehavior name="edit" event="action" targets="editButton"/>
       <composite:clientBehavior name="done" event="action" targets="doneButton"/>
       <composite:facet name="textMessage"/>
    </composite:interface>

    <composite:implementation>
      <h:outputScript library="javascript" name="prototype.js" target="head"/>
      <h:outputScript library="javascript" name="scriptaculous.js" target="head"/>
      <h:outputScript library="javascript" name="effects.js" target="head"/>   
      <h:outputScript library="util" name="inputEditable.js" target="head"/>
          
      <div id="#{cc.clientId}">
         <h:outputText id="text" value="#{cc.attrs.text}"/>          
         <h:commandButton id="editButton" type="button" 
            value="#{cc.resourceBundleMap.editButtonText}"
            onclick="this.startEditing()"/>

         <h:inputText id="editableText" value="#{cc.attrs.text}" style="display: none"/>
        
         <h:commandButton id="doneButton" 
            value="#{cc.resourceBundleMap.doneButtonText}" style="display: none">
          
             <f:ajax render="text textMessage" execute="editableText" 
               onevent="ajaxExecuting"/>
            
         </h:commandButton>
       
         <h:panelGroup id="textMessage">
            <composite:renderFacet name="textMessage"/>
         </h:panelGroup>
      </div>
      
      <script> com.clarity.init('#{cc.clientId}'); </script>
    
    </composite:implementation>    
</html>

마크업에서는 4개의 컴포넌트를 작성하는데, 처음에는 그 중 2개(텍스트 및 편집 단추)만 보인다. 사용자가 편집 단추를 클릭하면 애플리케이션은 리스트 4에서 구현된 com.clarity.startEditing() JavaScript 함수를 호출한다.


리스트 4. inputEditable 컴포넌트의 JavaScript(inputEditable.js)
package com.corejsf;
   var com = {};

if (!com.clarity) {
   com.clarity = {
      init: function (ccid) {
         var mydiv = document.getElementById(ccid);
         mydiv.editButton = $(mydiv.id + ':editButton');
         mydiv.text = $(mydiv.id + ':text');
         mydiv.editableText = $(mydiv.id + ':editableText');
         mydiv.doneButton = $(mydiv.id + ':doneButton');
         mydiv.doneButton.offsetLeft = mydiv.editButton.offsetLeft;
           
         mydiv.editButton.startEditing = function() {
           mydiv.text.fade( { duration: 0.25 } );
           mydiv.editButton.fade( { duration: 0.25 } );
      
           window.setTimeout( function() {
              mydiv.editableText.appear( { duration: 0.25 } );
              mydiv.doneButton.appear( { duration: 0.25 } );
      
               window.setTimeout( function() { 
                  mydiv.editableText.focus(); 
               }, 300); 
            }, 300); 
         };
      },
   
      toggleDisplay: function(element) {
         element.style.display = element.style.display == "none" ? "" : "none"; 
      },
           
      ajaxExecuting: function(data) {
         var mydiv = $(data.source.parentNode);
      
         if (data.status == 'complete') {
            toggleDisplay(mydiv.editableText);
            toggleDisplay(mydiv.doneButton);
            toggleDisplay(mydiv.text);
            toggleDisplay(mydiv.editButton);
         }
      }
   }
}

startEditing() 함수에서는 Scriptaculous 프레임워크의 fade()appear() 메소드를 사용한다(참고자료 참조). 또한, 이 함수는 두 개의 타이머를 사용하여 페이드와 모양이 올바른 순서로 발행하도록 한다. startEditing() 함수는 결국 텍스트 입력에 포커스를 준다는 점에도 주목하자.

리스트 5 는 inputEditable.properties를 나타낸 것이다.


리스트 5. inputEditable 컴포넌트의 특성 파일(inputEditable.properties)
editButtonText=edit...
doneButtonText=done

다음으로, 5가지 우수 사례의 관점에서 편집 가능한 입력의 구현에 대해 설명하겠다.


DIV에 컴포넌트 랩핑

JSF에서 복합 컴포넌트를 작성할 때는 프레임워크에서 이름 지정 컨테이너라고 하는 것도 작성하는데, 이 컨테이너에는 복합 컴포넌트에 있는 모든 컴포넌트가 포함된다. 하지만, 이름 지정 컨테이너에서 마크업을 생성하지는 않으며, 그 대신 JSF에서 복합 컴포넌트 내에 있는 각각의 컴포넌트에 대한 마크업을 생성한다. 결국, 기본적으로 그 ID를 가진 컴포넌트가 없기 때문에 페이지 마크업이 컴포넌트를 컴포넌트 ID를 기준으로 전체로서 참조할 수 없다.

복합 컴포넌트를 구현할 때 DIV에 컴포넌트를 랩핑하여 페이지 작성자에게 복합 컴포넌트를 참조할 수 있는 능력을 부여할 수 있다. 예를 들어, 페이지 마크업이 편집 가능한 입력 컴포넌트를 Ajax 호출의 일부로서 참조하도록 하려는 경우를 생각해보자. 다음 마크업에서 이름 입력을 처리하는 Ajax 단추를 추가한다. 이 단추를 클릭하면 서버에 대해 Ajax 호출이 이루어지고, 여기서 이름 입력이 처리된다. Ajax 호출 리턴 시, JSF가 그 입력을 렌더링한다.

<h:form>   
   <h:panelGrid columns="2">
      First name: 
      <util:inputEditable id="firstName" 
                       value="#{user.firstName}"/>
               
      Last name:
      <util:inputEditable id="lastName" 
                       value="#{user.lastName}"/>

      <h:commandButton value="Update first name">
         <f:ajax execute="firstName" render="firstName">
      </h:commandButton>
  </h:panelGrid>
</h:form>

리스트 3에서 DIV에 컴포넌트를 랩핑했기 때문에 위의 마크업에 있는 Ajax 단추가 작동하는 것이다.

<div id="#{cc.clientId}">

   ...

</div>

DIV에 사용되는 ID는 복합 컴포넌트 자체의 클라이언트 ID이다. 따라서 페이지 작성자는 방금 설명한 Ajax 단추와 마찬가지로 복합 컴포넌트를 전체로서 참조할 수 있다.


JavaScript와 Ajax의 통합

본 기사에 게재된 정적인 스크린샷에서 볼 수 없는 한 가지는 사용자가 edit... 단추를 클릭할 때 편집 가능한 입력 컴포넌트가 수행하는 페이드 애니메이션이다. 페이드는 최종적으로 Scriptaculous 프레임워크에 의해 완료된다. 리스트 3에서는 <h:outputScript> 태그를 사용하여 Scriptaculous의 필수 JavaScript를 출력하고, 리스트 4에서는 프레임워크의 fade()appear() 메소드를 사용하여 원하는 애니메이션을 표현한다.

mydiv.editButton.startEditing = function() {
  mydiv.text.fade( { duration: 0.25 } );
  mydiv.editButton.fade( { duration: 0.25 } );
      
  window.setTimeout( function() {
     mydiv.editableText.appear( { duration: 0.25 } );
     mydiv.doneButton.appear( { duration: 0.25 } );
      
      window.setTimeout( function() { 
         mydiv.editableText.focus(); 
      }, 300); 
   }, 300); 
};

위의 JavaScript에서 중첩된 타이머는 애니메이션에서 모든 것이 때맞춰 발생하도록 하는 역할을 한다. 예를 들어, 필자는 입력한 정보가 화면에 나타난 것을 확인할 때까지는 입력 텍스트에 포커스를 주지 않고 기다린다. 그렇지 않으면, 입력 정보가 나타나기 전에 focus()를 호출하는 경우 호출이 충실히 실행되지 않는다.

JSF와 함께 Scriptaculous 또는 JQuery와 같은 타사 JavaScript 프레임워크를 사용하는 방법은 간단하다. 페이지에 적당한 JavaScript를 출력한 다음, JavaScript 코드에 프레임워크를 사용하면 된다.

사용자가 done 단추를 클릭하면 편집 가능한 입력 컴포넌트에서 Ajax를 사용하여 서버를 호출할 수도 있다.

<h:commandButton id="doneButton" 
   value="#{cc.resourceBundleMap.doneButtonText}" style="display: none">
          
   <f:ajax render="text textMessage" execute="editableText" 
      onevent="ajaxExecuting"/>
            
</h:commandButton>

이전의 마크업에서는 사용자가 done 단추를 클릭할 때 JSF의 <f:ajax> 태그를 사용하여 Ajax를 호출했다. 그 Ajax 호출에서는 서버에서 텍스트 입력을 실행하고 Ajax 호출 리턴 시 텍스트와 텍스트 메시지를 업데이트한다.


JavaScript 클로저 사용

복합 컴포넌트를 구현할 때는 한 페이지에 있는 여러 컴포넌트에 대해 설명해야 한다. 한 컴포넌트의 모든 인스턴스가 같은 JavaScript를 공유할 때, 사용자가 현재 상호 작용 중인 컴포넌트만 조작하도록 주의해야 한다.

여러 가지 방법으로 한 페이지에서 다수의 컴포넌트를 지원할 수 있다. Oracle의 엔지니어인 Jim Driscoll이 유사한 편집 가능 입력 컴포넌트에 대해 쓴 한 블로그 게시글에서 설명한 한 가지 방법은 컴포넌트 ID의 네임스페이스를 유지하는 방법이다(참고자료 참조). 또 한 가지 방법은 다음과 같이 JavaScript 클로저를 사용하는 방법이다.

   com.clarity = {
      init: function (ccid) {
         var mydiv = document.getElementById(ccid);
         mydiv.editButton = $(mydiv.id + ':editButton');
         mydiv.text = $(mydiv.id + ':text');
         mydiv.editableText = $(mydiv.id + ':editableText');
         mydiv.doneButton = $(mydiv.id + ':doneButton');
         mydiv.doneButton.offsetLeft = mydiv.editButton.offsetLeft;
           
         mydiv.editButton.startEditing = function() {
           mydiv.text.fade( { duration: 0.25 } );
           mydiv.editButton.fade( { duration: 0.25 } );
      
           window.setTimeout( function() {
              mydiv.editableText.appear( { duration: 0.25 } );
              mydiv.doneButton.appear( { duration: 0.25 } );
      
               window.setTimeout( function() { 
                  mydiv.editableText.focus(); 
               }, 300); 
            }, 300); 
         };
      },

이것은 리스트 4에 전체가 표시되어 있는 편집 가능한 입력 컴포넌트에 대한 JavaScript이다. 리스트 3의 맨 아래에서 볼 수 있는 바와 같이, 편집 가능한 모든 입력 컴포넌트에 대해 init() 함수가 호출된다. 컴포넌트의 바깥쪽 DIV의 클라이언트 ID를 알고 있는 상태에서, 그 특정 DIV에 대한 참조를 얻는다. 그리고 JavaScript는 런타임에서 오브젝트에 특성과 메소드를 추가할 수 있게 해주는 동적 언어이기 때문에, DIV 자체에 대한 콜백 함수에서 나중에 필요한 모든 요소에 대한 참조를 추가한다.

또한, 컴포넌트의 편집 단추에 startEditing() 메소드를 추가한다. 사용자가 edit...를 클릭할 때 다음과 같이 그 메소드를 호출한다.

<h:commandButton id="editButton" type="button" 
   value="#{cc.resourceBundleMap.editButtonText}"
   onclick="this.startEditing()"/>

startEditing() 함수가 호출될 때, mydiv 변수는 init() 메소드가 호출되었을 때에 가지고 있던 원래 값을 유지한다. 이런 점은 JavaScript 클로저 그리고 어느 정도까지는 Java 내부 클래스의 멋진 특징이다. init()startEditing() 사이에 얼마나 많은 시간이 경과하는지는 중요하지 않으며, 그 사이에 init()가 여러 차례 호출되었는지 여부도 중요하지 않다. 즉, startEditing()이 호출될 때, 이 함수의 mydiv 값은 그 특정 컴포넌트에 대해 init() 메소드가 호출되었을 때 그대로 복사된 값이다.

JavaScript 클로저는 주변 함수의 변수 값을 그대로 유지하기 때문에, 각각의 startEditing() 함수가 자신의 컴포넌트에 대해 알맞은 DIV에 액세스한다고 확신할 수 있다.


페이지 작성자가 사용자 정의하는 방식

컴포넌트 정의가 일반적으로 단 한 행이나 두 행의 XML로 되어 있으므로, 페이지 작성자가 컴포넌트를 사용자 정의하도록 할 수 있다. 복합 컴포넌트를 사용자 정의하는 세 가지 기본적인 방법은 다음과 같다.

  • 유효성 검증기, 변환기 및 리스너 추가
  • 패싯
  • Ajax

유효성 검증기, 변환기 및 리스너

복합 컴포넌트의 내부 컴포넌트를 노출하는 한, 페이지 작성자가 복합 컴포넌트 내부의 컴포넌트에 유효성 검증기, 변환기 및 리스너를 연결하도록 할 수 있다. 예를 들어, 그림 3은 편집 가능한 입력 컴포넌트에 추가된 유효성 검증 기능을 나타낸 것이다.


그림 3. 이름 필드 유효성 검증

그림 3 에는 해당 필드에 최소 10자 이상을 입력해야 한다는 오류 메시지가 표시되어 있다. 페이지 작성자가 다음과 같이 편집 가능한 이름 입력 컴포넌트의 텍스트에 유효성 검증기를 추가했다.

<util:inputEditable id="firstname" text="#{user.firstName}">
   <f:validateLength minimum="10" for="text"/>
</util:inputEditable>

<f:validateLength> 태그의 for 속성에 주목하자. 그 속성은 유효성 검증기가 편집 가능한 입력 컴포넌트 내부의 텍스트를 위한 것임을 JSF에 알려주는 역할을 한다. 컴포넌트의 구현 시 그 텍스트를 노출했기 때문에, JSF에서도 그것을 인식하고 있다.

<composite:interface>
   ...
   <composite:editableValueHolder name="text" targets="editableText" />
   ...
</composite:interface>

<composite:implementation>
   ...
   <h:inputText id="editableText" value="#{cc.attrs.text}" style="display: none"/>
   ...
</composite:implementation>    

패싯

그림 3에서 페이지 맨 아래에 오류 메시지가 표시되어 있다. 그 이유는 필자가 Development 프로젝트 단계를 사용하고 있어, JSF에서 맨 아래에 유효성 검증 오류를 자동으로 추가하기 때문이다. 그 오류가 어떤 편집 가능한 입력과 연관되어 있는지 알 수 없으므로, 그림 4에서처럼 문제가 발생한 컴포넌트 옆에 오류 메시지를 표시하는 것이 더 나을 것이다.


그림 4. 패싯 사용

페이지 작성자가 그렇게 하려면 컴포넌트에 패싯을 추가하면 된다.

<util:inputEditable id="firstname" text="#{user.firstName}">
   <f:validateLength minimum="10" for="text"/>
   <f:facet name="textMessage">
      <h:message for="editableText" style="color: red"/>
   </f:facet>
</util:inputEditable>

컴포넌트에서 그 패싯을 지원한다.

<composite:interface>
   <composite:facet name="textMessage"/>
</composite:interface>
   
<div id="#{cc.clientId}">
   <h:panelGroup id="textMessage">
      <composite:renderFacet name="textMessage"/>
   </h:panelGroup>
   ...
</div>

Ajax

"복합 컴포넌트를 구현한 후 Ajax 추가하기"에서 설명한 것처럼, <composite:clientBehavior> 태그를 사용하여 페이지 작성자로 하여금 복합 컴포넌트에 Ajax 기능을 추가하게끔 할 수 있다. 그림 5는 사용자가 edit... 단추를 클릭할 때 수행되는 Ajax 호출을 모니터하는 대화 상자를 나타낸 것이다.


그림 5. Ajax 요청 모니터링

페이지 작성자는 단지 컴포넌트에 <f:ajax> 태그를 추가하고 Ajax 호출이 처리 중일 때 onevent 속성이 JavaScript 함수(대화 상자를 표시하는 함수)인 Ajax 함수를 호출하도록 지정한다.

<util:inputEditable id="firstname" text="#{user.firstName}">
   <f:validateLength minimum="10" for="text"/>
   <f:facet name="textMessage">
      <h:message for="editableText" style="color: red"/>
   </f:facet>

   <f:ajax event="edit" onevent="monitorAjax"/>
</util:inputEditable>

필자가 해당 컴포넌트의 구현 시 클라이언트 작동을 노출했기 때문에, 페이지 작성자는 그 컴포넌트에 <f:ajax> 태그를 추가할 수 있다.

<composite:interface>
   <composite:clientBehavior name="edit" event="action" targets="editButton"/>
</composite:interface>


국제화

편집 가능한 입력 컴포넌트는 두 개의 단추에 텍스트(edit...done)를 표시한다. 컴포넌트를 다수의 로케일에서 사용할 수 있도록, 그 텍스트를 국제화 및 현지화해야 한다.

어떤 컴포넌트의 텍스트를 현지화하려면, 단순히 해당 컴포넌트와 같은 디렉토리에 특성 파일을 추가한 다음 #{cc.resourceBundleMap.KEY} 표현식(여기서, KEY는 특성 파일의 키임)을 통해 특성 파일에 있는 키에 액세스하면 된다. 리스트 3리스트 5에서 볼 수 있듯이, 그것이 바로 필자가 편집 가능한 입력 컴포넌트의 단추에 대한 텍스트를 현지화하는 방법이다.


결론

JSF 1에서는 컴포넌트를 구현하기 어려웠으므로, 대부분의 JSF 개발자들은 JSF 1에서의 컴포넌트 구현을 꺼렸던 게 사실이다. 하지만, JSF 2에서는 사용자 정의 컴포넌트가 더 이상 사용자 정의 컴포넌트 프레임워크 개발자들만의 배타적 영역이 아니다. 본 기사에서는 복합 컴포넌트를 구현하기 위한 몇 가지 우수 사례를 설명했다. 약간의 작업만으로 페이지 작성자를 위해 손쉽게 확장할 수 있는 자신만의 컴포넌트를 만들 수 있다.


참고자료

교육

  • JSF 웹 사이트: JSF를 이용한 개발에 대한 자세한 정보를 찾아보자.

  • Scriptaculous: 이 JavaScript 프레임워크와 타사의 다른 JavaScript 프레임워크를 JSF와 통합할 수 있다.

  • "Another JSF 2.0 Ajax Component: Editable Text"(Jim Driscoll, java.net, 2008년 11월): Driscoll이 편집 가능한 입력 복합 컴포넌트를 구현하는 다른 접근 방식을 제시한다.

  • developerWorks Java 기술 영역: Java 프로그래밍과 관련된 모든 주제를 다루는 여러 편의 기사를 찾아보자.

제품 및 기술 얻기

  • JSF: JSF 2.0을 다운로드할 수 있다.

토론

  • My developerWorks 커뮤니티에 참여하자. 개발자가 이끌고 있는 블로그, 포럼, 그룹 및 Wiki를 살펴보면서 다른 developerWorks 사용자와 의견을 나눌 수 있다.

필자소개

http:/Photo of David Geary

저자이자 강사이며 컨설턴트이기도 한 David Geary는 JSF와 GWT(Google Web Toolkit)를 사용하여 웹 애플리케이션을 구현하는 방법을 개발자에게 강의하고 있으며 Clarity Training, Inc.의 사장이다. 그는 JSTL 1.0 및 JSF 1.0/2.0 Expert Groups의 일원이었으며 Sun에서 시행하는 Web Developer Certification Exam의 공동 출제자였고 Apache Struts 및 Apache Shale과 같은 오픈 소스 프로젝트에 기여했다. 그가 집필한 Graphic Java Swing은 꾸준히 베스트셀러로 판매되고 있는 Java 서적 중 하나이며 Core JSF(Cay Horstman과 공동 집필)는 베스트셀러로 판매되고 있는 JSF 서적이다. David는 컨퍼런스와 사용자 그룹에서 정기적으로 연사로 나서고 있고 2003년부터 NFJS tour에서 정회원으로 활동 중이며 Java University에서 세 차례 강의했고 JavaOne Rock Star로 세 차례 선정되었다.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=자바, 웹 개발
ArticleID=650655
ArticleTitle=JSF 2 fu: 복합 컴포넌트의 우수 사례
publish-date=01112011
author1-email=david.mark.geary@gmail.com
author1-email-cc=jaloi@us.ibm.com

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.