IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
한국 developerWorks   >   Open developerWorks  > developerworks

그 동안 몰랐던 서버 사이드 자바스크립트 이야기, Part 3: 리노 기반 웹 프레임워크, 헬마



김영후김영후 zerohoo.kim@gmail.com

웹 개발 기술과 매킨토시에 관심이 많은 스물여섯 살 개발자다. 능력과 시간을 전부 창조하는 작업에만 쓸 수 없을까 궁리 중이며 현재 병역 특례 업체에서 플렉스를 주로 다루고 있다.


난이도 : 중급
2008년 11월 18일


연재순서
1회(2008년9월): 다시 보는 자바스크립트의 역사
2회(2008년10월): 자바로 만든 자바스크립트 엔진, 리노
3회(2008년11월): 리노 기반 웹 프레임워크, 헬마


[오픈 developerWorks]는 여러분이 직접 필자로 참가하는 코너입니다.

Part 2에선 가장 널리 사용되는 서버 사이드 자바스크립트 기술인 리노를 알아보았다. 이번 회에선 리노를 활용한 기술들을 살펴보겠다. 본격적으로 들어가기 전에 간단한 글을 소개하고 싶다. 폴 그레이엄이 만든 해커뉴스에 "우리 남은 모든 인생을 위한 언어 하나를 꼽아보면 무엇일까?"란 질문이 올라온 적이 있다. 구글에서 검색 엔지니어로 일하다가 서버 사이드 자바스크립트 기술을 이용한 스타트업을 만들고 있는 애런 아이바(Aaron Iba)의 답은 다음과 같다.

자바스크립트는 문법이 있는 스킴과 흡사하며, ‘쿨’한 웹 애플리케이션에 필수적이고, 표현력이 뛰어나며, 클로저와 렉시컬 스코프를 지원해요. 또한 리노를 통해 자바 코드를 쓸 필요 없이 자바 라이브러리를 이용할 수 있으며 서버 사이드나 데스크톱 애플리케이션을 상관하지 않고 어느 플랫폼에서나 효율적으로 작동하니까 진정한 ‘모든 것을 다하는’ 언어에요. (원문)

그럼 이 "남은 인생의 언어"를 웹 애플리케이션 개발의 서버 사이드 측면에 활용할 수 있는 기술들을 본격적으로 알아보자.


앱젯

앞서 자바스크립트에 대한 찬양(?)성 답변을 했던 애런 아이바는 현재 앱젯(appjet.com)이라는 흥미로운 웹 사이트를 만들었다. 앱젯은 사용자들이 웹 브라우저를 통해 코딩하고 자신들이 만든 웹 애플리케이션을 바로 런칭할 수 있게 해주는데, 이때 사용자들이 사용하는 언어가 바로 자바스크립트다. 앱젯의 서버 사이드 시스템 역시 리노를 이용한 자바스크립트이며 뒤이어 알아볼 헬마(Helma) 웹 프레임워크를 이용하였다.

앱젯은 모든 개발을 앱젯 사이트의 브라우저와 콘솔, 디버거를 이용해 할 수 있고 자체적인 간단한 데이터베이스가 있어 쉽고 가벼운 애플리케이션 개발과 배포를 시스템적인 걱정 없이 언어 하나만 알면 쉽게 이용할 수 있다. 단 개발과 배포의 모든 과정이 앱젯 자체의 웹 IDE에서 이루어지고, 프로그래머가 아니거나 쉽게 이용하려는 사람들을 위한 단순한 API와 데이터베이스를 이용하는 점에서 사실 아주 심각한 프로젝트엔 적절하지 않다고 볼 수 있다.

하지만 이 연재를 쓰는 도중에 앱젯은 자신들의 "앱젯 시스템"을 공개해 굳이 앱젯 사이트를 통해 개발하고 배포하지 않더라도 어느 서버에서나 이용할 수 있게 했다. 본래는 '장난감 기술'로 볼 수 있는 앱젯에 대해서는 언급하지 않고 본격적으로 헬마를 알아볼 계획이었으나 앱젯이 그들의 시스템 appjet.jar를 공개하면서 충분히 다룰 가치가 있는 프로젝트가 되었다. appjet.jar는 리노와 헬마, 제티(Jetty) 서버, 객체 데이터베이스를 모두 포함하고 있어 자체적으로 리노 위에 구현된 경량급 웹 프레임워크라 볼 수 있다.


앱젯 설치와 실행

앱젯은 http://appjet.com/download에서 받을 수 있다. 앱젯을 실행하기 위해 테스트 앱젯 애플리케이션을 만들어보자.


printp("Enter your favorite food:")
printp(form("/", "food"))
printp(request.param("food"), " is my favorite too!")


이 파일을 myapp.js로 저장하고 java -jar appjet.jar myapp.js를 수행하면 제티 서버와 리노, 앱젯 프레임워크와 라이브러리가 올라온 후에 myapp.js를 실행한다. http://127.0.0.1:8080에 접속하면 좋아하는 음식을 입력하는 웹 폼을 볼 수 있을 것이다.

앱젯에서 사용자 요청을 핸들링하고, 데이터베이스를 이용하고 라이브러리를 쓰는 등의 자세한 내용을 알고 싶으면 http://appjet.com/docs에서 참조할 수 있다.

앱젯 사이트는 자바스크립트를 이용한 프로그래밍 초심자를 위한 구글 앱엔진(App Engine)이라 볼 수 있으며 appjet.jar를 이용해 자체 호스팅을 할 수 있는 선택권을 준 것이다.



위로


헬마 웹 프레임워크

앱젯이 아직까지는 초심자를 위한 단순화된 웹 프레임워크라면 헬마는 훨씬 심각한 목적으로도 이용할 수 있는 리노의 장고(Django)나 리노의 레일즈(Rails)라 볼 수 있다. 웹 애플리케이션에 아주 널리 이용되는 이 웹 프레임워크들과 마찬가지로 헬마는 객체 지향적인 MVC(Model-View-Controller) 설계를 바탕으로 세션 관리, 쉽고 이해할 수 있는 URL 생성과 해석, HTML을 생성하기 위한 템플릿, 데이터베이스와의 객체 지향적 연결을 위한 ORM 등 이른바 "풀 스택 웹 프레임워크"의 거의 모든 면을 지원한다고 할 수 있다. 여기에 리노에 기반을 둔 프레임워크로 받을 수 있는 보너스로서 JVM 기반의 좋은 성능을 기대할 수 있다.


설치와 실행

http://dev.helma.org/download에서 헬마 최신판을 각 OS에 맞게 받을 수 있다. 다운로드한 파일을 적당한 폴더에 압축을 풀자. helma-1.6.2 폴더가 생길 것이다. 날짜에 따라 버전은 다를 수 있다.

헬마는 제티 웹 서버와 리노, 프레임워크에 필요한 각종 라이브러리 jar 파일을 모두 포함하기 때문에 자바 최신판만 설치되어 있다면 start.bat(유닉스와 맥에서는 start.sh) 파일만 실행해 헬마가 올라온 웹 서버를 실행할 수 있다.



위로


제티 서버

장고와 레일즈 같은 최신 웹 프레임워크에선 대부분 개발자 컴퓨터에서 로컬 개발을 위한 작고 실행이 빠른 개발 서버가 프레임워크에 포함되어 배포되며, 실제 사이트 런칭을 위해선 아파치나 Lighttpd 같은 '진짜 웹 서버'를 이용하는 것이 보통이지만 헬마에 포함되어 배포되는 제티 서버는 개발뿐 아니라 실제 배포에 이용해도 성능상 문제가 거의 없는 '배포용 웹 서버'인 것이 특징이다. 상황에 따라 역시 아파치 등 타 웹 서버와 연동할 수 있지만 대부분 실제 배포가 되는 것과 똑 같은 환경에서 개발하는 이점을 누릴 수 있다.


HelloWorld와 액션

헬마를 실행했으면 우리의 첫 번째 헬마 애플리케이션을 만들어보자. helma 폴더 안의 apps.properties 파일을 보면 아래와 같은 내용이 있을 것이다.


welcome
welcome.mountpoint = /
welcome.repository.0 = apps/welcome/code/
welcome.repository.1 = modules/helmaTools.zip
welcome.static = apps/welcome/static
welcome.staticMountpoint = /static
welcome.staticHome = index.html,default.html
welcome.staticIndex = true
welcome.uploadLimit = 2048


이것은 welcome 애플리케이션에 대한 설정 내용이다. 지금은 이 설정에 대해 신경쓰지 말고 가장 아래에 hello라는 줄을 추가하자. 추가 후 저장을 하면 apps 폴더에 hello 디렉터리가 자동으로 생성된 것을 볼 수 있을 것이다. 그리고 웹 브라우저를 통해 http://127.0.0.1:8080/hello에 접속하면 'Error in application hello Action not found' 메세지를 볼 수 있다.

쉽게 추측할 수 있듯이 설정 파일을 이용해 hello라는 새 애플리케이션을 정의했지만 아무런 코드도 작성하지 않았기 때문에 헬마는 수행할 액션(action)이 없다고 알려준다. 액션은 헬마에서 '웹에서 접근되는 함수'를 의미하는 용어다.

그럼 실제 액션을 구현해 보자. apps에 새로 생성된 hello 디렉터리 밑에 Root란 이름의 디렉터리를 새로 만들자. 그리고 Root 디렉터리 안에서 .js로 끝나는 아무 이름의 자바스크립트 파일을 만들자. 필자는 handler.js라고 이름 지었다. 그리고 다음과 같이 코드를 작성한다.


function main_action() {
  res.write('Hello World!');
}


이제 http://127.0.0.1:8080/hello에 접속하면 우리의 첫 번째 애플리케이션 Hello World를 볼 수 있을 것이다.

하나씩 과정을 살펴보자. 헬마는 URL을 해석하고 이에 알맞은 컨트롤러(controller)를 실행하는 과정이 루비온레일즈나 장고와는 약간 다르기 때문에 이해가 약간 필요하다. 우선 자바스크립트는 루비나 파이썬 같은 모듈 시스템이 없다는 것을 생각해보자. 그럼 hello 디렉터리에 만든 Root는 무엇일까? 헬마는 모듈 시스템을 흉내내기 위해 자바스크립트의 프로토타입(prototype)을 이용한다. Hello 디렉터리 안에 있는 모든 디렉터리는 hello 애플리케이션의 '프로토타입'으로 간주된다(자바스크립트의 프로토타입에 대해 아직 이해하지 못했다면 당장은 다른 객체 지향의 '클래스' 정도로만 생각해도 본 기사를 계속 읽어가는 데는 별 무리가 없다. 다만 '왜 이렇게 하였는가?'를 이해하고 싶으면 프로토타입에 대해 어느 정도 알아보는 것이 좋을 것이다).

헬마 애플리케이션이 실행될 때 애플리케이션 디렉터리 -hello- 밑에 있는 모든 디렉터리에 대한 프로토타입 객체를 만든다. 목적에 따라 어떠한 프로토타입 객체라도 만들 수 있지만 몇 가지 특별하게 간주하는 프로토타입 객체들이 있으며 Root가 그 중 하나다. 헬마 애플리케이션은 실행될 때 기본적으로 Root 프로토타입부터 실행 가능한 액션을 찾는다. Root 디렉터리 안의 파일명은 아무 의미가 없으니 어떠한 이름이라도 상관없다. 자바스크립트에는 모듈 개념이 없다는 것을 다시 상기하자.

헬마는 _action으로 끝나는 함수를 자동으로 액션으로 인식하고 실행할 수 있다. main 액션은 index.html과 비슷하게 애플리케이션 뒤에 특정한 액션명이 없을 경우 자동으로 호출된다. 같은 파일에 다른 액션을 추가해 보자.


function get_bye() {
  return "Good Bye"
}

function bye_action() {
  res.write(this.get_bye());
}

function onRequest() {
  res.write('Hi And ');
}


이 액션은 http://127.0.0.1:8080/hello/bye를 통해 실행할 수 있다. onRequest 함수를 정의하면 모든 액션이 실행되기 전에 onRequest가 실행되어 Hi And Good Bye라는 결과를 볼 수 있다. onRequest는 당연히 main 액션에도 적용되기 때문에 Hi And Hello World를 볼 수 있을 것이다. 또한 bye 액션에서 _action으로 끝나지 않는 일반 자바스크립트 함수 get_bye를 사용하는 데 아무런 문제가 없음을 알 수 있다. 단 get_bye를 호출할 때 this를 사용한 것은 지금까지 헬마를 어느 정도 이해하였는지에 대한 좋은 질문이 된다. 답은 Root 디렉터리의 함수들은 모두 Root 프로토타입 객체로 정의되기 때문이다.

경우에 따라 웹에서 실행할 수 있는 액션과 그렇지 않은 함수를 섞어두는 것이 마음에 들지 않을 수 있는데, 헬마는 이를 위해 .hac 파일을 액션으로 인식하는 데 사용한다. 함수들을 작성한 파일에서 bye_action 함수를 제거하고 bye.hac 파일을 Root 디렉터리 밑에 새로 만들자.


res.write(this.get_bye());


다시 http://127.0.0.1:8080/hello/bye로 접속해 보면 이전과 같은 결과를 볼 수 있을 것이다. 즉 .hac의 경우 파일명이 액션 이름이 되는 하나의 액션이다. .hac 파일을 쓰는 것과 _action 함수를 쓰는 것은 완전히 동일하지만 액션을 좀 더 명시적으로 분리하고 싶을 경우엔 .hac를 쓰는 것이 좋다.



위로


스킨과 매크로

액션은 MVC 패턴의 컨트롤러 단에 해당하는 기능이다. 루비온레일즈를 생각하면 컨트롤러 클래스의 메서드라고 볼 수 있으며, 장고 프레임워크의 '뷰 함수'에 해당한다. 다음은 실제 HTML 레이아웃과 기능의 인터페이스를 나타내는 뷰(view) 역할을 살펴보자. res.write 함수만으로 HTML을 전부 작성하는 것은 힘든 일이기 때문에 헬마 역시 타 웹 프레임워크처럼 템플릿 기능을 지원한다. 헬마에선 템플릿을 스킨(skin)이라고 부르며, 스킨에서 사용하는 동적인 코드들을 매크로(macro)라고 부른다. 매크로는 스킨과 애플리케이션간의 브릿지 역할을 담당한다고 볼 수 있을 것이다.

스킨을 이용하기 전에 우선 onRequest 함수를 제거하자. 아래의 today 액션을 추가하자.


function today_action() {
  var date = new Date();
  res.data.today = date.format("yyyy-MM-dd");
  this.renderSkin('today');
}


쉽게 이해할 수 있겠지만 이 액션은 오늘 날짜를 response의 데이터에 today란 이름으로 전달한다. 그리고 today란 이름의 스킨을 이용해 렌더링을 한다. today.skin 파일을 Root 디렉터리가 생성한 다음 다음과 같이 작성하자.


<p> Today is <% response.today %> </p>


이제 http://127.0.0.1:8080/hello/today에 접속하면 'Today is 2008-11-14' 같은 오늘 날짜를 볼 수 있다. 스킨을 사용하는 방법과 액션에서 스킨으로 데이터를 전달하는 것을 쉽게 알 수 있다. today.skin은 프로그램을 전부 표현할 수 있는 적절한 HTML은 아니다. 루비온레일즈의 레이아웃과 같은 기능을 이용하려면 어떻게 할까?

우선 hello 애플리케이션 디렉터리 밑에 Global 디렉터리를 만들자. 이름에서 짐작할 수 있듯이 이 디렉터리 안에서 정의된 것들은 모두 글로벌하게 접근할 수 있다. Global 디렉터리 안에 html.skin 파일을 만든다.


<html>
<head>
   <title><% response.title %></title>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
    <h3>Hello Application Layout</h3>
    <% response.content %>
</body>
</html>


그리고 today_action을 다음과 같이 수정한다.


function today_action() {
  var date = new Date();
  res.data.today = date.format("yyyy-MM-dd");
  var content = this.renderSkinAsString('today');
  res.data.title = 'Hello Application - Today';
  res.data.content = content;
  renderSkin("html");
}


다시 http://127.0.0.1:8080/hello/today를 접속하면 레이아웃이 적용된 화면을 볼 수 있다. 마지막 줄의 renderSkin은 this.renderSkin이 아님을 유의하자. this.renderSkin과 this.renderSkinAsString은 현재 프로토타입 객체를 기준으로 - 즉 Root에서 - 수행되며 renderSkin은 글로벌한 호출을 의미한다.

매크로는 스킨에서 호출 가능한 함수로 스킨과 애플리케이션 로직의 연결을 담당한다고 볼 수 있다. 예를 들어 스킨에서 날짜를 다른 포맷으로 표현하고 싶다고 하면 이를 위한 매크로를 작성할 수 있다. 매크로는 액션과 마찬가지로 _macro로 끝나는 함수만이 스킨에서 매크로로 인식할 수 있다.


function today_macro(params) {
  return (new Date()).format(params.format);
}


이 매크로를 호출하도록 스킨을 수정하자.


<p> Today is <% response.today %> </p>

<p> Another format: <% this.today format="yyyy.MM.dd" %> </p>


이제 서로 다른 포맷으로 보이는 날짜를 볼 수 있을 것이다. 단 날짜를 문자열로 포매팅하는 과정이 중복되었으므로 매크로를 액션에서도 사용하여 중복을 제거하자.


function today_action() {
  res.data.today = this.today_macro({format: "yyyy-MM-dd"});
  var content = this.renderSkinAsString('today');
  res.data.title = 'Hello Application - Today';
  res.data.content = content;
  renderSkin("html");
}


마치며

지금까지 헬마 프레임워크의 설치와 기본이 되는 액션, 스킨, 매크로에 대해 알아보았다. 아마 최근의 웹 프레임워크를 접했던 독자들에겐 조금 어색한 감이 있을 것이다. 헬마는 본질적으로 객체를 확장하고 계층화해 웹 프로그래밍을 구조화할 때 생기는 모듈화 문제를 자바스크립트답게 해결한 프레임워크다. 이를 위해 헬마는 HopObject란 특수한 객체를 사용하며 이 객체의 특성을 이용하여 리퀘스트와 객체, 데이터베이스를 연결할 수 있는 아주 강력한 기법을 지원한다.

이제 기본적인 것들을 알았으니 다음 회에서는 HopObject를 이용하여 실제 데이터와 연동되는 애플리케이션을 만들어보자.




이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us

이제 전문가의 글을 단순히 ‘보는 것’에서, 직접 여러분이 developerWorks의 필자가 될 수 있습니다. IBM developerWorks를 통해 공유하고 싶은 지식이 있으신 분들은 원고 기획안을 접수해주세요. 채택되신 분께는 소정의 원고료를 드립니다.



[지난 Open dW 보기]
사이트 여행

dW 커뮤니티
포럼 | 블로그 | Spaces
dW Student Community

로컬 컨텐츠

행사 및 세미나

기획 기사

개발자 입문

튜토리얼 및 교육

TOP 10 인기자료

SW 다운로드

RSS 피드

뉴스레터
 
  
자바스크립트가 작동이 중지되었습니다. 이 기능을 수행하시려면 브라우저에서 자바스크립스트를 작동시켜 주시거나 이곳을 클릭해주세요.

Special offers
Screencast
IBM SOA Sandbox 시험판
dW Student Community
로보코드
코드 트레이닝


    IBM 소개 개인정보 보호정책 문의