메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

Tapestry: 컴포넌트 중심 프레임워크

한빛미디어

|

2006-10-27

|

by HANBIT

12,076

제공: 한빛 네트워크
저자: Hemangini Kappla, 이대엽 역
원본: Tapestry: A Component-Centric Framework

Tapestry는 자바로 작성된 오픈소스 웹 애플리케이션이다. 이 프레임워크를 이용하여 높은 상호작용성과 풍부한 컨텐츠를 제공하는 애플리케이션을 쉽게 개발할 수 있다.

Tapestry는 고성능의 대단위 풀링 전략(coarse-grained pooling strategy), 고도의 코드 재사용, 라인단위의 정밀한 오류 보고, 그리고 그 이상의 많은 것들을 포함한 이점을 제공해 준다. Tapestry 애플리케이션은 100 퍼센트 컨테이너에 의존하지 않기 때문에 어떠한 서블릿 컨테이너에서도 실행될 수 있다.

Tapestry 프레임워크를 도입하면 Tapestry가 서블릿 API의 최상단에서 구축되어 있더라도 서블릿을 작성하고 서블릿으로 전달되는 URL과 쿼리 파라미터를 만들지 않게끔 해준다. 개발자는 애플리케이션의 기능에 대한 코딩에만 집중할 수 있는데, 왜냐하면 Tapestry가 그러한 삽질코드(plumbing code; URL 생성, 들어오는 요청에 대한 디스패치, 서버측 상태 관리 등)를 알아서 처리해 주기 때문이다.

Tapestry 배포판

Tapestry 배포판은 아파치 사이트의 Tapestry 홈페이지에서 다운로드 가능하다.

Tapestry 배포판은 그림 1에 나타나 있는 것과 같이 다음의 구성요소들로 이루어져 있다:
  • 메인 Tapestry 프레임워크: Tapestry 프레임워크의 모든 핵심 컴포넌트들로 구성되어 있다. 또한 페이지와 컴포넌트에 서비스를 제공하는데 사용되는 다른 클래스들 또한 포함하고 있다.
  • 기여된 컴포넌트: 커뮤니티로부터 기여된 Tapestry를 위한 강력한 애드온(add-on) 컴포넌트들의 집합이다. 이것은 페이지를 보여주기 위해 HTML 응답을 생성하는 데 사용되는 컴포넌트를 포함하고 있다. 이러한 컴포넌트들은 애플리케이션에서 사용되어 HTML 템플릿내에 로직 구성요소를 결합시킨다.
  • 어노테이션 지원 클래스: 이 라이브러리는 어노테이션을 포함하고 있다. 이러한 어노테이션들을 실행하려면 JDK 1.5가 필요하다. 어노테이션들은 코드에 추가될 수 있는 변경자들이다. 그것은 단지 페이지나 컴포넌트 스펙에 기술되어 있을 자바 코드내에서 특정한 오퍼레이션을 수행할 수 있다.
  • 포틀릿(Portlet) 지원: Tapestry을 이용하여 JSR-168 스펙의 포틀릿을 생성할 수 있도록 해주는 Tapestry용 애드온 모듈이다.
그림1
그림 1. Tapestry 배포판의 구성내용

Tapestry는 수많은 추가 런타임 의존요소(dependencies)을 가지는데, 이들 모두는 다운로드하여 Tapestry 웹 애플리케이션의 WEB-INF/lib 폴더에 위에서 설명한 JAR 파일에 패키징되어 있어야 한다. 이것은 Tapestry용 Ant 빌드 스크립트를 이용하여 수행될 수 있는데, 빌드 스크립트는 이러한 의존요소들을 자동으로 다운로드 할 것이다. 이 빌드 스크립트가 작동하기 위해서는 몇 가지 환경설정이 필요한데, 자세한 사항은 Tapestry Wiki에서 알아볼 수 있다. 다른 방법으로 이러한 의존요소들을 Howard Lewis Ship의 quick start 디렉토리에서 tapestry-libraries.tar.gz (21.7 MB) 파일로 다운로드 할 수도 있다. 의존요소들을 WEB-INF/lib 폴더나 공유된 라이브러리 폴더로 복사하여 JAR 파일들이 Tapestry 프레임워크에 기반하여 개발될 애플리케이션에서 사용될 수 있도록 만들어 준다. Tapestry는 라이브러리이므로 이러한 필요로 하는 모든 것들이 설치 단계에서 이루어져야 한다.

Tapestry 컴포넌트 세계

Tapestry 애플리케이션은 다른 오퍼레이션 중심의 프레임워크(예를 들면, 스트러츠, PHP 등)에 기반하는 전통적인 웹 애플리케이션과는 다르다. Tapestry 애플리케이션은 웹 페이지의 집합이며 각각의 웹 페이지는 순서를 가지는 컴포넌트들로 구성된다. Tapestry에서 웹 페이지는 단순히 HTML 페이지(JSP가 아닌)에 지나지 않으며 HTML 템플릿이라 불려진다. 전체 웹 애플리케이션은 이러한 템플릿과 스펙으로부터 최소한의 자바 코드를 사용하면서 만들어진다.

Tapestry 프레임워크는 Tapestry 애플리케이션과 Java 서블릿 컨테이너 사이의 하나의 레이어로서 동작한다. Tapestry는 이미 존재하는 서블릿 컨테이너안에 포함되어 있는 표준 서블릿 API 객체와 함수들을 사용한다. 애플리케이션 컴포넌트들이 Tapestry 컴포넌트들에 접근하므로 개발된 애플리케이션들은 서블릿 API에 대해 전적으로 인식할 필요가 없어진다.

Tapestry기반의 애플리케이션에서는 모든 웹 페이지상의 요소들(폼, 링크, 텍스트 박스 등)은 컴포넌트로서 표현된다. 설계의 핵심에는 org.apache.tapestry.IComponent 인터페이스가 위치한다. Tapestry 기반의 페이지에 동적인 컨텐츠를 제공하는데 사용될 수 있는 모든 객체들은 이 클래스에 의해 표현된다.

그림 2는 몇몇 클래스와 그들의 관계를 보여준다. 한 마디로 폼의 모든 것들, 즉 텍스트 영역, 텍스트 필드, 히든 필드, 전송 버튼, 링크와 같은 폼의 컴포넌트들은 객체, 메소드, 속성(각각의 컴포넌트들은 자기자신만의 id를 가진다)으로서 표현된다. 이것이 유일한 컴포넌트 객체 모델(Component Object Model; COM)이다.

그림2
그림 2. Tapestry 컴포넌트들간의 관계를 보여주는 클래스 다이어그램(전체 크기의 이미지를 보려면 클릭하라)

Tapestry와 MVC

모델-뷰-컨트롤러(Model-View-Controller, MVC)는 애플리케이션의 사용자 인터페이스를 도메인 로직으로부터 분리하는 것에 기반한 설계 패러다임이다. Tapestry의 MVC 모델 2 구현은 MVC 패턴의 가장 순수한 구현 중 하나이다.
  • 모델: 모델은 도메인 객체와(혹은) 데이터베이스로 구성될 수 있다.
  • 뷰: Tapestry에서 뷰는 컴포넌트의 사용을 정의하는 특별한 표식을 가지는 단순 HTML 파일이다.
  • 컨트롤러: 여기에서 컨트롤러는 XML 페이지 명세이다(.page 파일). 페이지 객체(org.apache.tapestry.IPage 인터페이스를 구현하는)는 컨트롤러로서 페이지 명세 파일을 보조하기도 한다.
간단한 Tapestry 예제

Tapestry 프레임워크를 이해하는 가장 단순한 방법은 그것이 실제로 어떻게 돌아가는지 보는 것이다. 아래는 얼마나 쉽게 애플리케이션이 이 프레임워크를 사용하여 개발될 수 있는지 보여주는 예제이다.

온라인 은행을 예로 들고 있는데, 사용자는 자신의 잔고를 볼 수 있고, 대출을 위한 신청을 할 수 있으며, 혹은 자신의 프로필을 수정할 수 있다. 다른 모든 애플리케이션처럼 Home.html이라 불리는 홈 페이지가 있다.

  
    An Online Bank 
  
  
    

Welcome to MyBank>/h1>

Please select action:>/h2> View Balance . . .

Java web component ID를 의미하며 Tapestry에 유일한 jwcid라는 하나의 요소를 제외하면 얼마나 단순한 HTML인지 보라. 앞서 언급했듯이, Tapestry 프레임워크의 모든 컴포넌트들은 자신만의 유일한 ID를 가진다. 이 HTML 페이지가 읽혀질 때 컴포넌트들은 생성되어 자신의 jwcid로 구별된다. 그러면 Tapestry가 어떻게 어떤 타입의 컴포넌트를 생성할지 결정하는가? 이 정보는 Home.page 파일에 지정되어 있어야 한다. 아래에 Home.page에서 발췌한 코드가 나타나 있다:

    
.
.
.

이 경우 jwcid인 viewBalanceLink로 구별되어지며 타입은 DirectLink인 컴포넌트가 생성될 것이다. 이것이 이루어지는 뒷단, 즉 페이지가 읽혀지기 전 Tapestry는 org.apache.tapestry.html.BasePage 타입의 페이지 객체를 생성한다. 두 번째 단계는 .page 파일 내에 기술된 모든 컴포넌트를 생성하여 페이지(Page) 객체와 연결하는 것이다. 그런 다음 페이지 객체는 페이지에서 보여줄 정보를 위해 HTML 파일을 읽어 들인다. ID가 viewBalanceLink인 컴포넌트를 만나면 링크를 분리하기 위해 이 객체로 컨트롤이 전달된다. 이 컴포넌트는 보여지게 될 페이지에 대한 결과 HTML 링크를 만들어낼 것이다. 이러한 전체 과정에서 HTML 페이지는 단지 참조를 위해 사용되며 템플릿이라 부른다. 아래에 Home.java에서 발췌한 코드가 나타나 있다:
public abstract class Home extends BasePage{
    
    public abstract AccountBalance getAccountBalancePage();
    .
    .
    .
}
페이지는 성공적으로 보여진다.

그런데 어째서 메소드가 추상 메소드이며 구현은 어디에 있는가? 그렇다, Tapestry가 여러분을 위해 그런 작업들을 하는 것이다. Tapestry가 구현되지 않은 접근자(getter) 메소드를 만나면 Tapestry는 그것을 위한 속성을 생성한다.

그러면 사용자가 이 링크에 클릭을 했을 때 어떤 일이 발생할까? 다음의 코드를 Home.page에 집어넣었다:

  

여기서 리스너(listener)라는 새로운 표현을 볼 수 있는데, 사용자가 링크를 클릭하면 컴포넌트에 대한 바인딩(binding)을 가진 리스너가 Tapestry에 의해 호출된다. 이와 같이 리스너 메소드는 페이지 클래스에 정의되어 있어야 한다:
public IPage onClickViewBalanceLink() {
        //do something to give a Account Balance Page
}
시나리오상에서 링크를 클릭하는 것의 효과는 계정의 잔고 페이지를 보여주는 것이다. 그래서 AccountBalance.html, AccountBalance.page, 그리고 페이지 객체 클래스인 AccountBalance.java가 있는 것이다. 하지만 어떻게 홈 페이지와 AccountBalance 페이지간의 관계를 정의할까? 아래를 보시라:
public abstract class Home extends BasePage{
    .
    .
    @InjectPage("AccountBalance")
    public abstract AccountBalance getAccountBalancePage();
    
    
    public AccountBalance onClickViewBalanceLink() {
        return getAccountBalancePage();
    .
        .
}
여기에서의 가장 흥미로운 변화는 @InjectPage 어노테이션이다. 어노테이션은 J2SE 5.0 (코드명 타이거)의 새로운 기능이며 메타데이터를 제공하기 위해 사용된다. 어노테이션은 앳 기호(@)의 형태를 띠며 다음에 어노테이션의 이름이 따라온다. 그래서 여러분은 데이터가 필요할 때 "이름=값" 쌍으로 어노테이션에 데이터를 주면 된다.

@InjectPage 어노테이션을 사용함으로써 컴포넌트에 AccountBalance 페이지를 삽입하였다. 이제 이 페이지에서 리스너 메소드를 이용하여 값을 변경하거나 뒷단의 시스템과 인터랙션 하거나 혹은 단순히 이 리스너 메소드가 리턴한 응답으로서 AccountBalance라는 이름의 페이지를 보여주는 것이 가능해 진다. 그리고 정확히 이것이 지금까지 했던 것들이다!

계정 잔고 페이지에서 잔고는 태그를 이용하여 보여진다:

Your account balance is: $

말할 것도 없이 accountBalance는 AccountBalance.java 클래스의 속성이다. 따라서 다음의 태그를 대신해서 포함하면 동일한 결과가 보여진다:

Your account balance is: $

값에는 Object Graph Navigational Language (OGNL) 표현이 들어있다는 것을 주의하라. OGNL은 자바 객체의 속성을 가져오고 설정하는데 사용되는 강력한 오픈소스 표현 언어이다. Tapestry가 ognl을 만나게 되면 Tapestry는 다음에 이어지는 것이 OGNL 표현이며 문자열 상수가 아니라는 것을 인식한다.

검증과 오류보고

뱅킹 애플리케이션에서 사용자가 자신의 프로필을 수정하는 시나리오를 생각해보자. "프로필 수정" 페이지에는 이름과 생년월일과 같은 몇몇 필수 입력 필드가 있다. 이러한 검증은 Tapestry에서 최소한의 코딩만으로도 가능하다. 뱅킹 애플리케이션에서 개인 상세 정보를 갱신하는 HTML 파일(PersonalDetails.html)과 XML 템플릿(PersonalDetails.page), 그리고 페이지 객체 클래스(PersonalDetails.java)가 있다.

페이지 객체 클래스를 수정하는 것으로부터 시작하자면 ValidationDelegate 속성 타입을 추가한다. 이 속성은 검증이 실패했을 경우를 대비하여 오류 메시지의 목록을 가진다. 하지만 어떻게 Tapestry가 무엇을 검증할지 알까? 여기에 해답이 있다: Tapestry에 컴포넌트 이름이 필수라는 것을 알려주기 위해 페이지 명세를 갱신한다. 또한 컴포넌트에 특정한 검증 오류를 기록하기 위하여 ValidationDelegate를 폼(personalDetailsForm)에 바인딩한다.

        
            .
            .

    .
    .
        
    .
    .
    
    .
    .

게다가 검증이 실패한 다음에 오류 메시지를 보여줄 컴포넌트가 필요하다. 이 객체는 오류를 기록하며 ValidationDelegate 객체에 저장된다.

    

이러한 방식은 검증을 위한 페이지 객체 클래스내의 코드를 아무것도 필요로 하지 않는다. 비록 사용자정의 검증을 하기 위해서는 페이지 클래스의 onSubmit()에 그런 부분들에 대해 알려주어야 하기는 하겠지만 말이다.

마지막으로 HTML 페이지에는 기록된 오류 메시지를 보여주도록 다음의 변경이 필요하다:

    
  • 결론

    이 기사는 Tapestry를 이용하여 웹 애플리케이션을 개발하는 것이 얼마나 단순한지를 보여주고 있다. Tapestry는 웹 개발에 컴포넌트 접근법을 도입하고 있으며 이는 애플리케이션에서 모든 지루한 삽질코드들을 프레임워크로 옮기는 것을 가능케 해준다. 따라서 Tapestry 프레임워크를 이용하여 개발된 애플리케이션은 자연스럽게 Tapestry의 철학인 단순성, 일관성, 효율성, 그리고 피드백에 적응하게 된다.

    리소스 Hemangini Kappla는 현재 인도의 봄베이에 위치한 EDS 회사인 Mphasis에서 근무하고 있다.
    TAG :
    댓글 입력
    자료실