RACK속에 들어간 레일스
세상에는 무수히 많은 웹 서버들이 있다. 그리고 또 무수하게 많은 웹 프레임워크들도 존재한다. 루비도 예외는 아니다. 물론 루비 하면 레일스가 먼저 떠오르긴 하지만, 레일스를 차지하고서도 Merb, Camping, Ramaze, Maveric, Sinatra, Halcyon 등 얼핏 생각해도 제법 많은 프레임워크들이 있다. (물론 이들 대부분의 프레임워크들이 아직은 초기 버전이고 또한 어떤 식으로든 레일스 프레임워크로부터 영향을 받은 프레임워크들이긴 하지만.) HTTP를 제공하는 서버들도 예외는 아니어서 WEBrick, Mongrel, Thin, Ebb 등 제법 많은 웹 서버들이 속도와 경량성을 앞세워 우후죽순 생겨나고 있어 따라가기가 버거울 정도가 되었다. 여기다 JRuby까지 포함시키면 Tomcat이나 GlassFish같은 컨테이너들도 마찬가지로 루비의 배포 환경 속에 들어온다.
그런데 이렇게 새로 생겨나는 HTTP서버들과 웹 프레임워크들을 보다보면 아주 재미있는, 숨어있는 '프레임워크'를 하나 더 발견하게 되는데, 바로 Rack 이라고 하는 물건이다. 간단하게 말해서 Rack은 이렇게 다양한 웹서버들과 다양한 웹 애플리케이션 프레임워크들 사이에 위치하여 표준적인 인터페이스를 제공하는, 일종의 '프레임워크의 프레임워크'라고 할 수 있다. 물론 Rack은 파이썬 프로그래머들에게는 이미 익숙한 WSGI를 루비 식으로 구현한 것에 불과하기에, 그다지 새로운 개념은 아닐 수 있다. 아니 오히려 때늦은 감이 있다고도 할 수 있을 것이다. 사실 웹 프로그래밍에서 HTTP서버와 외부 프로그램(프로세스) 간에 인터페이스를 표준화하려는 시도들은 아주 예전부터 있어왔다. CGI가 그 대표적인 예일 테고, Servlet API나 WSGI 역시 그런 맥락에서 이해할 수 있을 것이다.

과거는 잊고, 다시 실용으로 돌아와서 Rack을 보자. Rack이 없는 세상에서라면 루비로 웹 프레임워크를 만드는 사람들은 지구 상에 나와 있을 여러가지 웹 서버들을 가능한 모두 고려하여 자신의 프레임워크를 설계해야 했다. 그렇지만 이제는 Rack API 스펙만 고려하여 프로그래밍하면 그 많은 웹 서버들 모두(아직 출시되지 않은 미래의 웹 서버들을 포함하여)에서 자신의 프레임워크가 정확하게 작동하게 할 수 있게 되는 것이다. HTTP 서버를 개발하는 측도 마찬가지여서, Rack용 핸들러(handler)만 하나 제공하면 그 많은 웹 프레임워크들과 다 잘 어울리는 웹 서버가 되는 것이다. 결국 n*m 이던 것이 Rack 덕에 n+m으로 줄어든 셈이다.

이번에는 Rack의 API를 한번 보자. 다음에 나온 한줄의 코드는 Rack과 연결하기 위해서 웹 프레임워크가 구현해 줘야 할 인터페이스의 전부를 말해준다.
lambda { |env| [200, {}, ‘Hello World!’ }
즉, env를 매개변수로 call() 메서드를 호출만 할 수 있으면 된다. 그리고 반환값은 위 코드에서 보듯 HTTP의 통상적인 반환값인 [결과코드, 헤드, 본문] 의 형태면 그만이다. 실제로 Rack 속에 들어 있는 Camping 프레임워크의 핸들러 코드는 채 열줄도 안된다.

이렇듯 Rack은 다양한 웹 서버와 다양한 웹 프레임워크들 간의 단순한 '가교' 역할을 담당하는 외에, 실제로 하나의 '미들웨어(middleware)'로서도 제 값을 톡톡히 해 낸다. 프레임워크로 가는 웹 요청을 중간에서 가로채기도 하고 예외처리나 표준 로깅 같은 기능을 추가해 주기도 하고, 파일 업로드와 같은 작업을 프레임워크 대신 처리해 줄 수도 있으니, Rack 속에 들어감으로써 생기는 3%의 부담 정도는 기꺼이 감수할 만하다. (Mongrel 서버를 기준으로 테스트를 했을 경우, Rack을 쓸 때와 안썼을 때 3% 정도의 성능차이가 난다고 한다)

실제로 최근에 나오는 루비 웹 프레임워크들 대부분은 Rack 기반이다. 예를 들어, Merb의 경우도 Rack을 사용하고 있기 때문에 다음과 같은 명령으로 손쉽게 웹서버를 갈아탈 수가 있다.
$ merb -a mongrel -p 3000 # 3000번 포트에서 Mongrel서버 실행
$ merb -a thin -p 4242 # 4242번 포트에서 Thin서버 실행
JRuby를 사용한다면, WAR 파일의 배포방식 역시 Rack을 통해 바뀌게 된다. WAR 파일 패키징을 해주는 Warbler 역시 최근에 기존의 Goldspike를 사용하던 방식에서 JRuby-Rack을 사용하는 방식으로 변경하였다. Erlang 프로그래머들에게 친숙한 Yaws 웹서버 역시 Fuzed를 이용하면 루비 웹 프레임워크에서 사용할 수 있다.

마지막으로 레일스. 레일스는 공식적으로는 Rack에 기반하고 있지는 않다. 그렇지만 이미 Rack 핸들러가 나와 있기 때문에 Rack 속에서 사용하는 것이 어렵지는 않다. 예를 들어, 다음과 같이 간단한 한줄짜리 파일을 config/rack.ru 라는 파일로 만든 다음,
run Rack::Adapter::Rails.new
명령행에서 다음 명령을 주면, Rack을 통해 Thin 서버에서 실행되는 레일스를 만날 수 있다.
$ rackup config/rack.ru -p 3000 -s thin -r thin
물론 아직 가야할 길은 멀다. Rack은 이제 겨우 0.3 버전에 불과하고, JRuby-Rack이나 레일스 어댑터 같은 것도 아직은 부족한 부분이 많은 게 사실이다. 그렇지만 Rack이 만든, 그리고 앞으로 만들어 나갈 가능성은 무궁무진하다. 갈수록 재미있어 지는 루비 세상을 기대해 보자!
by thinkr | 2008/05/18 00:16 | 트랙백 | 덧글(1)
트랙백 주소 : http://thinkr.egloos.com/tb/1893428
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Commented by deepblue at 2008/05/18 01:05
http://brainspl.at/articles/2008/04/25/hey-rails-nice-rack 이런 시도도 있으니, 조만간 Rack이 천하일통 하겠죠?

:         :

:

비공개 덧글

< 이전페이지 다음페이지 >