사용자의 입력을 받아서 Dynamic하게 데이터를 보여줘야 하는 필요가 있었다. 이 필요를 위해 웹 서비스를 만드는 것이 나을지, 아니면 fxruby같은 GUI tool을 써서 OS independent 어플리케이션을 만드는 것이 나을지 고민을 했다. 고민의 결과는… 어차피 매우 간단한 프로그램인만큼 둘 다 해 보기로 했다.
우선 fxruby부터 시작. 사실 위젯을 그리고 GUI를 만드는데 있어서 fxruby는 매우 쉬운 도구이다. 게다가 이미 이에 관한 좋은 책도 구매를 했기 때문에 정보가 없어서 중간에 막히는 일은 없을거라는 생각이 들었다. 더 좋은 점은 fox toolkit이 OS에 상관 없이 돌아가기 때문에, fxruby를 사용해서 만든 어플리케이션은 지난번에 사용한 적이 있는 ocra를 이용하여 쉽게 바이너리로 배포할 수 있다는 점이다.
디자인을 하고 GUI를 만드는데까지는 그렇게 어렵지 않았다. 그런데, 이 데이터들을 csv 파일 형태로 가지고 작업을 하다보니 귀찮은 부분이 꽤 있었다. 특히 해당 csv 파일이 가지고 있는 필드만을 뽑아서 다이내믹하게 보여주는 부분에서 시간을 꽤 쓰고도 만족스러운 결과를 만들어내지 못했다. 그래서 결국은 더 쉬운 웹 서비스로 이동! (나중에 여유 시간을 좀 내서 이 부분을 다시 해 볼 생각이다.)
Ruby로 웹 서비스를 만든다면 당연히 Rails를 생각할 수 있겠지만, Rails는 내가 생각하는 목적을 놓고 생각해보면 너무 무겁고 복잡한 프레임워크라는 생각이 들었다. 그래서 선택한 것이 바로 Sinatra! 간단하게는 소스 파일 하나와 템플레이트 파일 하나만 있으면 바로 잘 작동할 수 있다는 것이 마음에 들었다. (홈페이지를 보면, 이 프레임워크가 얼마나 간단한 것인지 쉽게 짐작할 수 있다. 아마, 홈페이지 처음에 쓸 내용이 별로 없었을거라고 생각된다.) 복잡한 기능을 요구하는 프로젝트가 아니었으니, 파일 자체의 개수를 줄이는 것이 필요했는데, 지가 알아서 많은 파일을 생성해 놓는 Rails보다는 Sinatra가 이런 측면에서 훨씬 가벼운 것이다. 선택해야 하는 것이라고는 템플레이트 엔진으로 무엇을 써야 하는가 하는 정도 뿐. 사실 haml을 선택하는 것이 더 시류에 맞는 것이겠지만, 짧은 시간 안에 로직과 디자인을 모두 해야 한다는 측면에서는 그냥 대충 html 코드를 만들고 그 중에 필요한 부분에만 ruby 코드를 사용할 수 있는 erb가 좀더 상황에 어울리는 듯 했다. 그래서 sinatra와 erb를 쓰기로 결정.
Sinatra가 좋은 점 중의 하나는 바로 route 로직을 디자인할 수 있다는 것, 그리고 이걸 통해서 쉽게 사용자 입력을 받을 수 있다는 점이다. 말하자면 맨 처음부터 RESTful 어플리케이션이라는 것. 이렇게 개발을 하면 처음부터 사용자가 어떤 방식으로 이 서비스를 사용할 것인지를 염두에 두게 되므로 빠르고 간단하게 개발을 하는데 도움이 되는 것 같다. 그리고 서버 셋팅을 메인 코드 안에 간단하게 넣을 수 있으므로, 기본적인 기능만을 구현하는데는 단 한 개의 소스 파일이면 충분하다. 이렇게 해서 내가 만든 ruby 코드는 모두 72줄! erb 파일 두개의 라인 수까지 모두 합쳐도 200줄이 안된다. (물론 자세한 주석이 없다. 근데 72줄짜리 소스에 주석이 많이 필요할까?) 이 정도의 소스를 가지고 간단한 웹 서비스를 (몇 시간만에) 개발할 수 있다는 것은 축복이 아닐 수 없다.
소스 파일은 대충 이런 모양으로 생겼다.
require 'rubygems' require 'sinatra' require 'fastercsv' require 'ruport' require 'erb' set :public, File.dirname(__FILE__) + '/../compounds' get '/' do # Only get erb :index end get '/:id/:property' do # No post @library = params[:id].to_s # Do I need to_s here? @property = params[:property].to_s @data = parse_csv_table(params[:id], params[:property]) erb :view end def parse_csv_table lib_name, an ... # data manipulation logic end |