Java

[펌]JSF(JavaServer Faces) 활용하기 [1/3]

_침묵_ 2005. 10. 6. 20:23
  제   목 :JSF(JavaServer Faces) 활용하기 [1/3]
사용자 삽입 이미지
  작성자 :theclub (theclub@jspgeek.com)작성일 : 2003-10-22 00:44:53    조회 :664

서비스를 재빨리 제공하면서 개발비용을 조금이라도 경감하고 싶어 하는 기업 및 조직의 요구가 높아지는 가운데 , 개발 효율의 향상을 목적으로 한 수 많은J2EE어플리케이션 프레임워크가 제공되고 있다. 100% J2EE 어플리케이션 프레임워크라고 해도, 비지니스 로직를 구축하기 위해서, Web 어플리케이션의 화면 처리를 정의하는 것, 유저 인터페이스를 구축하는 것 등 , 수 많은 종류가 존재한다. 따라서 , 개발자는 구축하려는 어플리케이션에 적절한 프레임워크를 선택할 필요가 있으며, 그와 동시에, 프레임워크의 특성을 충분히 이해한 상태에서 활용할 필요가 있다.

그런데 , 이번에 소개하는 「JavaServer Faces」(이하JSF) 는, 향후 J2EE의 세계에서 표준이 될 Web 어플리케이션의 인터페이스를 구축하기 위한 프레임워크다. JSF는 , 현재Java Community Process(JSR-127) 에 스팩 결정이 진행되고 있다. JSF는 현재 EA4가 제공되고 있어 썬마이크로시스템이 제공하고 있는 「Java Web Services Developer Pack 1.2」(이하JWSDP) 에 포함되어 있다. 이번은 이 JWSDP를 사용해, JSF의 구조와 사용 방법에 대해 설명할 것이다. 덧붙여 JWSDP에는 JSF이외에도 JAXB, XWS-Security, SAAJ 등의 최신의 Web Services, XML관련 기술이 포함되어 있다. 그리고, 어플리케이션 서버로는Tomcat 5가 포함되어 있다.

그리고 JSF는 금년(2003년) 개최된 「JavaOne 2003」에서 썬마이크로시스템이 발표한 「Project RAVE」의 핵심이 되는 기술이다. Project Rave는 GUI와 Web 어플리케이션을 개발할 수 있는 툴로써, 마이크로소프트의 Visual Studio .NET과 같이 Web 어플리케이션을 구성하는 부분을 드래그&드롭으로 배치하고 이벤트 핸들러를 기술하는 개발 스타일을 제공한다. JSF는 IBM, 볼랜드 , 오라클 등 자사의 툴에 채용하는 것을 표명하고 있어, Java에 의한 Web 어플리케이션의 개발이 비약적으로 편리해 질 것이라는 것은 자명한 사실이다.

본 글에서는 2회에 걸쳐 JSF를 설명해 갈 것이다. 전편에서는, JSF 아키텍쳐의 설명과 실제로 코드를 보면서 JSF를 이해해 나갈 것이다. 후편에서는 JSF 어플리케이션의 구축 순서에 대해 자세하게 설명할 예정이다.

JavaServer Faces의 장점

이미 앞에서 언급하였지만 JSF는 Web 어플리케이션의 인터페이스를 구축하기 위한 프레임워크다. JSF를 사용하게 되면 Web 어플리케이션의 비지니스 로직과 프레젠테이션 디자인을 완전히 분리할 수가 있다. 이렇게 되면 비지니스 로직를 개발하는 개발자와 프레젠테이션 디자이너의 역할 분담을 명확하게 할 수가 있어서 Web 어플리케이션의 개발 효율을 올릴 수가 있다. 그러나, 이런 점은 JSP를 사용하는 경우와 큰 차이가 없다고 말할 수 있겠다. 그러나, JSF의 최대 특징은 , 프레젠테이션 컴퍼넌트(텍스트 필드나 버튼 , 셀렉트 박스등 )를 JSP 커스텀 태그 라이브러리를 사용해 표현할 수가 있기 때문에, 컴퍼넌트에 대해서 상태 정보의 보관 및 유지나 input 값의 체크, 타입 변환, 이벤트 제어(이벤트 핸들러), 데이터 모델 매핑 등의 기능을 구현할 수 있다.

예를 들면 , 「상태 정보의 보관 유지」기능은 각 컴퍼넌트에 보존된 attribute를 투명하게 보관 유지한다. 실례를 들자면, 어느 어플리케이션으로 회원 가입 폼에 입력한 후, 등록 버튼을 클릭했을 때에 에러가 발생해서, 폼으로 리턴될 때에도 동일 세션이라면 폼에 입력한 값들이 지워지지 않는다.

그 외에 다른 기능에 대해서는 이 후 의 「JSF 샘플 어플리케이션」에서 설명하기 때문에 여기에서는 생략 한다. 즉, 인터페이스를 구축하는데 필요한 기능을 더욱 간단하게 구현할 수 있는 것이 JSF를 이용하는 장점인 것이다. 그리고, 컴퍼넌트를 독자적으로 작성하기 위한 프레임워크도 준비되어 있어 자유롭게 UI컴퍼넌트를 작성하는 일도 가능하다.

그런데, JSF의 기술 형식은 특별한 스크립트나 마크업 언어를 이용하는 것은 아니다. 전술한 것처럼 JSP 커스텀 태그 라이브러리가 준비되어 있기 때문에, 지금까지 JSP를 구현한 디자이너라면 편리하게 페이지를 작성할 수 있다.

다른 프레젠테이션 테크놀러지를 병용 하는 일도 가능하다.

JSF를 구성하는 컴퍼넌트와 JSF 어플리케이션

JSF는 다음의 기능을 구현하기 위해서 API 및 RI로 구성된다.

  • UI 컴퍼넌트
  • 상태 관리
  • 이벤트 관리
  • 베리데이션
  • 데이터 전환
  • 페이지 네비게이션 정의
  • 국제화

그리고 RI에는 JSP에서 이러한 기능을 간단하게 이용하기 위해서 JSP 커스텀 태그 라이브러리(컴퍼넌트 태그 라이브러리 , 코어 태그 라이브러리)가 준비되어 있다.

JSF 어플리케이션은 일반적인 Web 어플리케이션과 마찬가지로 Web 컨테이너에서 동작한다. 그리고, 다음의 컴퍼넌트로 구성되어 있다.

  • 컴퍼넌트 태그 라이브러리(UI 컴퍼넌트를 표현하기 위한 JSP커스텀 태그 라이브러리)
  • 코어 태그 라이브러리(이벤트 핸들러 및 validator , 컨버터등을 표현하기 위한 JSP 커스텀 태그 라이브러리)
  • 서버 사이드에서 스테이트 풀 오브젝트로서 표현되는 UI 컴퍼넌트
  • validator , 컨버터 , 이벤트 핸들러 , 네비게이션 핸들러
  • JavaBean(데이터 모델:JSF에서는 모델 오브젝트로 불린다 )
  • 서버 사이드 헬퍼 클래스(데이타베이스 액세스 빈 등 )
  • JSF 페이지

JSF 어플리케이션은 컴퍼넌트 태그 라이브러리와 코어 태그 라이브러리를 이용해서 UI 컴퍼넌트를 표현한다. 그렇기 때문에 UI 컴퍼넌트를 표현하기 위해서 HTML 등의 마크 업 언어를 사용해서 직접 코딩할 필요가 없다. 그리고 코어 태그 라이브러리를 사용하면 JSF의 기능을 편리하게 사용할 수 있다.

JSF 페이지의 라이프 사이클

JSF 페이지의 라이프 사이클은 JSP 페이지와 거의 같다. 클라이언트는 HTTP request를 작성하고, 서버는 HTML에 변환된 response를 돌려준다. 다만, JSF에는 전술한 것같은 다양한 기능이 있기 때문에, JSP의 라이프 사이클과는 다른 것이 있다.

사용자 삽입 이미지


·Reconstitute Request Tree
JSF 페이지가 호출되면, 우선 처음에는 컴퍼넌트 트리가 작성된다. 그 페이지에 있는 컴퍼넌트는, 그림2와 같이 트리 구조로 나타내지고 FacesContext에 등록된다.

사용자 삽입 이미지
도2 1개의 폼에 텍스트 필드와 submit 버튼이 존재하는 트리

·Apply Request Values
컴퍼넌트 트리가 작성된 후, 각 컴퍼넌트는 request 파라미터에서 값을 얻어서, 그 값을 보관 유지한다. 에러가 포함된 request가 있을 경우,「Render Response」에 넘어 간다. 만약 값의 변환(정의된 타입으로 변환)이 실패하면, 컴퍼넌트에 에러 메세지가 생성되고 FacesContext에 쌓이게 된다. 이 메세지는 「Process Validator」단계를 거처「Render Response」단계로 넘어간다.

·Process Validations
이 단계에서는 트리에 등록되어 있는 컴퍼넌트 마다 attribute의 값을 검증한다. 무효이면 FacesContext에 에러 메세지를 더해「Render Response」단계로 넘어간다. 「Apply Request Values」단계로 전환 에러가 있었을 경우에도「Render Response」단계에 넘어간다.

·Update Model Values
「Process Validations」단계에서 attribute가 유효하다고 판단 되었을 경우, 그 값을 해당하는 모델 오브젝트 값으로 세팅한다. 모델 오브젝트 property에 지정되어 있는 타입으로 변환할 수 없는 경우는,「Render Response」단계로 넘어가 에러 메세지를 표시한다.

·Invoke Application
이 단계에서는 폼의 submit나 다른 페이지로의 링크 등 어플리케이션 레벨의 이벤트를 핸들링한다. 디폴트인 ActionListner는 컴퍼넌트의 액션을 NavigationHandler에 의해서, 어플리케이션의 configuration file에 정의한 네비게이션 룰에 따라 페이지를 표시한다.

·Render Response
이 단계에서는, FacesContext에 유지하고 있는 컴퍼넌트를 표시합니다. 「Apply Request Values」「Process Validations」단계에서 에러가 발생했을 경우 에러 메세지를 표시한다.

그러면 이제 JSF 어플리케이션을 만들어 보자. 첫머리에서 말했던대로 , 현재 JSF(EA4)는 JWSDP에 수록되어 있다. 따라서, 우선 JWSDP를 인스톨한다.

JWSDP의 인스톨

본글에서는 Windows 2000에서 인스톨하는 순서에 대해서 설명한다. Windows용 바이너리(약46Mbytes)를 아래 URL에서 다운로드한다. 그리고, JWSDP 1.2는 JDK 1.4.1 이후의 JDK가 필요하기 때문에, 사전에 인스톨 해 주어야한다.

「Java Technology & Web Services Downloads」
http://java.sun.com/webservices/downloads/webservicespack.html

다운로드한 파일 「jwsdp-1_2-windows-i586.exe」을 더블 클릭 해, 인스톨러를 통해 인스톨을 실시한다. 설정 항목은, JDK의 인스톨 디렉토리, JWSDP의 인스톨 디렉토리, Web Proxy 서버, Tomcat의 관리자 ID,Password 등으로 매우 간단하게 인스톨 할 수 있다. 인스톨 순서, 인스톨 후의 패스의 설정 방법 등 자세한 것은 위 URL를 참조하기 바란다.

사용자 삽입 이미지
인스톨러 시작 후의 화면

인스톨에 성공하면, Windows의 프로그램 메뉴에, 「Java(TM) Web Service Developer Pack1.2」이 추가된다. 이 메뉴에서 [Start Tomcat]를 선택해 Tomcat을 기동한다.

샘플 어플리케이션을 만들어 보자

Tomcat 기동 후, http://localhost:8080/에 액세스 해 보면 screen shot과 같은 화면이 표시된다. 이 페이지는, JWSDP의 탑 페이지로, 샘플 어플리케이션이나 문서의 링크가 포함되어 있다.

사용자 삽입 이미지
WSDP의 index 페이지

JSF의 샘플 어플리케이션은 4종류가 제공되고 있다. 여기서는,「Guess Number Sample」이라고 하는 간단한 어플리케이션을 예로 들어, JSF의 기본에 대해 설명하기로 하겠다.

사용자 삽입 이미지
JWSDP에 포함되는 샘플 어플리케이션. 이 중에서 「Guess Number Sample」을 예로 들어 JSF를 설명한다.

이 어플리케이션은 , 유저에게1~10까지의 번호를 입력시켜, 서버측에서 랜덤에 생성한 값과 일치하는지를 판정하는 것이다. 「Guess Number Sample」을 클릭한 후, 다음의 페이지로 「Click here to gess Duke`s number」을 클릭한다.

어플리케이션이 시작되면, 화면에 적당한 수치를 입력하고 「Submit」을 클릭한다. 입력한 문자가 서버측에서 계산한 수치와 일치하는지 그 결과가 돌아 온다..

사용자 삽입 이미지
사용자 삽입 이미지
「Guess Number Sample」의 화면. 입력한 수치와 컴퓨터가 발생시킨 숫자를 비교해 결과를 표시한다.

그러면 , 이 어플리케이션의 코드를 보겠다. 우선 , 수치를 입력하는 페이지부터 살펴보자.

리스트1 greeting.jsp
1:<HTML>
2:    <HEAD> <title>Hello</title> </HEAD>
3:    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
4:    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
5:    <body bgcolor="white">
6:    <h2>Hi. My name is Duke.  I'm thinking of a number from 0 to 10.
7:    Can you guess it?</h2>
8:    <jsp:useBean id="UserNumberBean"
 class="guessNumber.UserNumberBean" scope="session" />
9:    <f:use_faces>
10:    <h:form id="helloForm" formName="helloForm" >
11:        <h:graphic_image id="wave_img" url="/wave.med.gif" />
12:        <h:input_number id="userNo" numberStyle="NUMBER"
13:                         valueRef="UserNumberBean.userNumber">
14:            <f:validate_longrange minimum="0" maximum="10" />
15:        </h:input_number> 
16:     
<h:command_button id="submit" 
action="success" label="Submit" commandName="submit" />

17:         <p>
18:       <h:output_errors id="errors1" for="userNo"/>
19:    </h:form>
20:    </f:use_faces>
21:</HTML>

JSF에는 각 UI 컴퍼넌트(UIForm, UIInput 등)을 HTML에 렌더링하기 위한 커스텀 태그 라이브러리가 제공되고 있어 이 태그 라이브러리를 사용해 JSP를 개발한다. 리스트의 3,4행에서는 JSF의 태그 라이브러리를 import하고 있다. 이것은 JSF을 이용하는 JSP에서는 정해진 서식이 된다. 8행에서는 JSP의jsp:useBean 액션을 사용해 guessNumber.UserNumberBean 클래스를 UserNumberBean ID로 Session scope에 인스턴스화하고 있다.

9행에 처음으로 JSF 태그가 등장한다. use_faces 태그는 다른 JSF 태그의 컨테이너 태그로 모든 JSF 코어, 컴퍼넌트 태그는 <use_faces>로 시작되어 ,</use_faces>로 끝나는 태그내에 기술해야 한다.

10행의 form태그는 HTML의 form에 대응하는 태그로 HTML과 같이 form 태그내에 텍스트 박스, submit 버튼 등에 대응한 태그를 정의한다. 12~15행의 것input_number가 HTML의 텍스트 박스에 대응하며, 여기에서는 다양한 JSF의 기능을 사용하고 있다.

우선, numberStyle="NUMBER"요소에 대해서 알아 보면, 여기에서는 JSF의 컨버터 기능을 사용하고 있다. 컨버터는 input 값를 Java에 대응하는 타입으로 변환하기 위한 기능으로써, JSF에는 표준으로 다양한 컨버터가 제공되고 있다. 그리고, 개발자 자신이 컨버터를 개발해, 기능을 추가하는 일도 가능하다. 여기에서는, JSF가 표준으로 제공하는 컨버터를 이용하고 있으며, numberStyle에 Number가 지정되어 있으므로 입력 문자를 수치형으로 변환한다.

다음에 등장하는 태그는 validate_longrange 태그이다. 이것도 방금전에 살펴본 컨버터와 같이 JSF가 표준으로 제공하는 validator의 기능을 사용하고 있다. validator는 입력된 값이 어플리케이션측에서 기대하는 규칙에 따르고 있는지를 검증(필수 필드의 체크 , 문자 입력 패턴의 체크등)하는 기능으로, 여기에서는 minimum="0",maximum="10"라고 지정함으로써 , 값이 0~10의 범위에 있는지를 검증하고 있다. 시험삼아 범위외의 값을 입력해 보기 바란다. 에러 메세지가 표시될 것이다. 그리고 13행의 valueRef="UserNumberBean.userNumber"에 대해서는 다음에 다룰 JavaBeans에서 설명을 할 것이다. 16행의command_button은 HTML의 submit에 대응하는 태그로써, 이 태그내에서 사용되고 있는 action에 대해서는 뒤에 설명한다. 18행의 태그는 input form에 알파벳등을 넣었을 경우에 에러 메세지를 표시한다.

다음에리스트1greeting.jsp중에서 인스턴스화하고 있는JavaBeans의 코드를 살펴 보겠다 (리스트2).

리스트2 JavaBeans의 코드(UserNumberBean.java)
1: import java.util.Random;
2: public class UserNumberBean {
3: 
4:    Integer userNumber = null;
5:    Integer randomInt = null;
6:    String response = null;
7:    
8:    public UserNumberBean () {
9:    Random randomGR = new Random();
10:    randomInt = new Integer(randomGR.nextInt(10));
11:    }
12:    public void setUserNumber(Integer user_number) {
13:        userNumber = user_number;
14:    }
15:    public Integer getUserNumber() {
16:        return userNumber;
17:    }
18:    public String getResponse() {
19:        if(userNumber.compareTo(randomInt) == 0)
20:        return "Yay! You got it!"; 
21:    else 
22:        return "Sorry, "+userNumber+" is incorrect.";
23:    }
24:}

이 클래스는 JSF의 기능을 특별히 사용하고 있지 않으며, 일반적인 JavaBeans이다. 이 클래스에서는 유저가 입력한 값을 보관 유지하면서, 랜덤에 생성한 값과 비교해 일치하고 있으면 「Yay! You got it!」라는 메세지를, 값에 차이가 나면 「 Sorry, "+userNumber+" is incorrect」을 돌려준다. 덧붙여 캐릭터 라인의 표시는 response.jsp으로 가고 있다.

그런데, 여기까지 봐 와 분 빌리고라고 생각합니다만 , 이 JSF 샘플 어플리케이션에서는 일반적으로 Web 어플리케이션에 있는 것처럼, ServletRequest의getParameter로 input 값를 받아, 값을 체크해서, 비지니스 로직이 끝나면, RequestDispacher를 사용해 다른 JSP로 forward한다는 코드가 필요 없다.

즉 input 값의 수취로부터 비지니스 로직의 종료까지는 input_number 태그내의 valueRef="UserNumberBean.userNumber"를 사용한다. 이렇게 지정을 하면, 유저가 데이터를 submit했을 때에, UserNumberBean의 userNumber 필드에 값이 설정되어 있었다고 하는 것이다. 그리고 결과를 표시하기 위한 페이지는 코딩 중에 직접 기술하지 않고, faces-config.xml라고하는 JSF의 고유 설정 파일에 정의된다 (리스트3).

리스트3 faces-config.xml
1: <?xml version="1.0"?>
2: 
3: <!DOCTYPE faces-config PUBLIC
4:  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
5:  "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
6:
7: <faces-config>
8:
9:  <navigation-rule>
10:    <from-tree-id>/greeting.jsp</from-tree-id>
11:    <navigation-case>
12:      <from-outcome>success</from-outcome>
13:      <to-tree-id>/response.jsp</to-tree-id>
14:    </navigation-case>
15:  </navigation-rule>
16:
17:  <navigation-rule>
18:    <from-tree-id>/response.jsp</from-tree-id>
19:    <navigation-case>
20:      <from-outcome>success</from-outcome>
21:      <to-tree-id>/greeting.jsp</to-tree-id>
22:    </navigation-case>
23:  </navigation-rule>
24:
25: </faces-config>

9~15행의 <navigation-rule>정의가 페이지의 지정이다. 12행 <from-outcome>의 값 「success」은 greeting.jsp의 command_button 태그의 것action의 값(success) 에 대응하고 있어, input 값의 변환, 값의 타당성의 검증에 성공하면, <to-tree-id>로 지정된 페이지(response.jsp)에 진행하라는 룰이 된다.

리스트4 respnse.jsp
1:<HTML>
2:    <HEAD> <title>Guess The Number</title> </HEAD>
3:    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
4:    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
5:    <body bgcolor="white">
6:    <f:use_faces>
7:    <h:form id="responseForm" formName="responseForm" >
8:        <h:graphic_image id="wave_img" url="/wave.med.gif" />
9:    <h2><h:output_text id="result" 
10:                 valueRef="UserNumberBean.response"/></h2>
11:    <h:command_button id="back" label="Back" action="success"
12:        commandName="back" /><p>
13:
14:    </h:form>
15:    </f:use_faces>
16:</HTML>

이렇게 해서 전편은 종료된다. JSF를 사용하면 Web 어플리케이션의 기술이 얼마나 간단하게 될지 이해하였으리라 생각한다.

다음번의 후편에서는 JSF의 기능을 충분히 사용하여 어플리케이션을 개발하는 순서에 대해 상세하게 설명한다.