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

루비로 만드는 아름다운 데스크톱 애플리케이션, Part 1: RubyCocoa 첫걸음 떼기



박진형
박진형 jenix@jinhyung.org

연세대학교 수학과를 휴학하고 넥스지(NexG)에서 병역 특례로 일하고 있다. 리눅스 커널 개발, 오브젝티브-C, 코코아(Cocoa) 애플리케이션 개발에 관심이 많으며 OSXDev(http://www.osxdev.org)의 공동 대표를 맡고 있다.


난이도 : 초급
2007년 8월 28일


[오픈 디벨로퍼웍스]는 여러분이 직접 필자로 참가하는 코너입니다. 이번 연재에서는 오픈소스 프로젝트인 RubyCocoa를 이용해 아름다운 데스크톱 애플리케이션을 만드는 데 필요한 기본기를 배워보겠습니다.

RubyCocoa란

이름에서 쉽게 알 수 있듯이, 루비(Ruby)와 오브젝티브-C(Objective-C) 사이의 브릿징이다. 이를 이용하면 루비에서 오브젝티브-C 객체를 다룬다거나 혹은 반대로 오브젝티브-C에서 루비 객체를 다룰 수 있다. 그래서 RubyCocoa를 이용하면 Mac OS X 환경에서 루비와 코코아로 네이티브 애플리케이션을 제작할 수 있다.
오브젝티브-C는 루비와 마찬가지로 스몰토크(SmallTalk)에서 많은 영향을 받은 언어다. 그래서 nil과 같이 C에서 NULL과 같은 역할을 하는 객체의 존재나 객체 간의 메시지를 주고 받는 메시징 메커니즘 등을 오브젝티브-C와 루비에서 동일하게 볼 수 있다. 이 덕분에 루비와 코코아의 연결이 더 자연스러워진다.

   소셜 북마크

   mar.gar.in mar.gar.in
    digg Digg
    del.icio.us del.icio.us
    Slashdot Slashdot

RubyCocoa를 어디에 쓸까

RubyCocoa는 단순히 재미를 위한 것일까? 물론 현재까지 실제로 RubyCocoa로 제작되어 상용화된 애플리케이션이 없으니 '재미만을 위한 것은 아니다'라고 딱 잘라 말할 순 없지만 앞으론 단순히 재미만을 위한 도구는 되지 않을 것임을 확신한다. 이유인즉, 바로 Mac OS X의 다음 버전인 Leopard(Mac OS X 10.5)에서 RubyCocoa가 PyObjc(Python의 오브젝티브-C 브릿지)와 더불어 Mac OS X에 기본으로 들어가기 때문이다. 실제로 애플(Apple) 측에서는 현재 애플의 오픈소스 프로젝트를 담당하는 Mac OS ForgeBridgeSupport()란 프로젝트를 새로 개설했다. 이는 다른 언어와 오브젝티브-C의 브릿징을 편하게 하기 위한 프로젝트로 실제 RubyCocoa에서는 이를 이용하여 오브젝티브-C의 브릿징을 구현하였다. 이렇게 Mac OS X의 모든 시스템에 기본으로 들어간다면, 아무 걱정 없이 RubyCocoa로 애플리케이션을 제작해 배포해도 괜찮을 것이다(필자는 Xcode 3.0에서 RubyCocoa가 기본으로 들어가 있고, RubyCocoa로 작성된 애플리케이션이 Mac OS X Leopard 개발자 프리뷰 버전에서 잘 동작함을 확인하였다)!


시작하기

현재 RubyCocoa 최신 버전은 0.11.1p1로, RubyCocoa 프로젝트 홈페이지(http://rubycocoa.sourceforge.net)에서 다운로드할 수 있다. RubyCocoa를 이용하려면 Mac OS X 10.4.8 이상과 Xcode SDK가 필요하다. Mac OS X Panther에도 설치는 할 수 있지만 RubyCocoa 프로젝트에서 더 이상 지원하지 않으므로 10.4.8 이상의 환경을 이용하자. 설치에 관한 내용은 http://rubycocoa.sourceforge.net/GettingStarted 페이지에도 나와 있으나 여기에서도 설명하겠다. 우선 루비 언어를 직접 설치할 것인지, 아니면 Tiger에 기본으로 설치된 것을 이용할 것인지 결정해야 한다. 직접 루비 언어를 새로 설치할 예정이라면 --enabled-shared 옵션으로 컴파일 옵션을 설정하여 공유 라이브러리를 이용하도록 한다. 이는 컴파일 설정 옵션에서 기본 값이 아니므로 꼭 지정해줘야 한다. 루비가 준비되었다면 RubyCocoa 설치는 간단하다. GettintStarted 페이지의 Files Repotitory에서 tgz 파일을 다운로드한 후 보통의 루비 패키지를 설치하듯 설치하면 끝이다.

  

$ ruby install.rb config	
$ ruby install.rb setup	
$ sudo ruby install.rb install


끝이다. 허무한가? 이제 RubyCocoa로 코코아 애플리케이션을 만들 준비가 모두 끝났다. 이번 연재에선 버튼을 눌러서 난수를 생성하는, 매우 간단한 애플리케이션을 만들어 볼 예정이다. 루비 스크립트로 작성한 컨트롤러 클래스와 인터페이스 빌더(Interface Builder)에서 만든 UI를 연결하는 법을 알고 나면 다른 거대한 애플리케이션 제작에도 별 무리가 없으리라 생각한다.



위로



Xcode 프로젝트 생성

Xcode를 실행한 후 New Projects로 새로운 프로젝트를 시작한다. 그림 1과 같이 Cocoa-Ruby Application이란 항목이 새로 추가되었음을 알 수 있다. 해당 프로젝트 유형으로 새로운 프로젝트를 시작한다.

Cocoa-Ruby Application
그림 1. Cocoa-Ruby Application

필자는 프로젝트 이름을 MyFirstRubyCocoApp으로 이름을 지었다. 프로젝트가 생성되면 다음과 같이 기본적인 코코아 프로젝트에 생성되는 파일 외에 rb_main.rb라는 파일이 추가된 모습을 볼 수 있다(그림 2).

rb_main.rb
그림 2. rb_main.rb

일반적인 코코아 애플리케이션을 만들 때와 마찬가지로 main.m은 물론, rb_main.rb 파일도 수정할 필요는 없다. 앞서 잠깐 언급했던 것처럼 RubyCocoa는 오브젝티브-C에서 루비를 사용할 수 있도록 하는데, 기존 코코아 애플리케이션의 main.m에서 루비 스크립트의 메인이 되는 rb_main.rb를 호출하고 이를 통해 애플리케이션의 뷰(View)나 컨트롤러(Controller)를 제어하는 다른 루비 스크립트들을 호출하게 된다. 특수한 경우가 아니라면 main.m이나 rb_main.rb는 수정할 일이 없을 것이다. MainMenu.nib를 더블 클릭하여 그림 3과 같이 인터페이스 빌더에서 애플리케이션의 뷰를 디자인한다. 메인 윈도우에 버튼과 텍스트 필드를 하나씩 추가하면 된다. 각각의 버튼 이름과 텍스트 필드에 내용을 입력하자.

MainMenu.nib - 메인 뷰 디자인
그림 3. MainMenu.nib - 메인 뷰 디자인

이제 디자인한 뷰를 제어할 컨트롤 객체를 만들어야 한다. 일반적인 코코아 프로그래밍과 마찬가지로, 인터페이스 빌더의 MainMenu.nib 윈도우에서 Classes 탭의 NSObject 항목을 선택한 후, Classes 메뉴의 Subclass NSObject 메뉴로 NSObject를 상속한 클래스를 만든다. 이름은 Foo라고 지어보자(그림 4).

NSObject를 상속한 객체, Foo
그림 4. NSObject를 상속한 객체, Foo

코코아를 이미 접해본 독자라면 약간 지겨울 수도 있지만 코코아를 처음 접하는 독자들을 위해 조금 더 자세하게 설명한다. 앞의 과정에서 Foo 클래스를 생성했다면 NSObject 항목 아래에서 Foo 클래스를 선택할 수 있을 것이다. 이를 선택한 후에 Shift+CMD+I 키를 누르거나 혹은 Tools의 Show Inspector 메뉴를 이용하여 그림 5에서 보이는 인스펙터 윈도우가 나타나도록 한다. 우선은 Outlet 탭에서 새로운 항목을 추가하는데, 그림 5와 같이 우리의 뷰에서 추가한 텍스트 필드 항목을 아웃렛으로 지정한다. 그리고 Action 탭으로 이동하여 generate: 액션을 추가하자(그림 6).

Outlet과 Action 추가 1
그림 5. Outlet과 Action 추가 1



위로


Outlet과 Action 추가 2
그림 6. Outlet과 Action 추가 2

이제 보통의 오브젝티브-C/코코아 애플리케이션이라면 Classes 메뉴에서 Create Files for ... 메뉴를 이용하여 새로 추가한 클래스의 파일들을 프로젝트에 추가하겠지만, 우리는 지금 RubyCocoa를 이용하고 있기 때문에, 이러한 작업은 넘어가도록 한다. 대신에 이제 이 클래스와 뷰를 연결하는 작업을 할 것이다.
Classes 메뉴에서 Instantiate Foo를 선택하여 MainMenu.nib 파일의 Instances 탭에 파란 정육면체의 Foo 인스턴스가 보이도록 한다. Foo 객체는 뷰의 텍스트 필드로 생성한 난수 결과를 표시할 것이고, 뷰는 Foo 객체에게 난수를 생성하라고 지시할 것이다. 이대로 연결을 해주면 된다. 그림 7에서 Foo 인스턴스에서 컨트롤 키를 누른 채 Window의 텍스트 필드로 드래그를 하면 출발점과 연결되는 선이 표시된다. 이렇게 이어주고 인스펙터 윈도우에서 textField를 선택한다. 반대로 그림 8과 같이 Window의 각각 버튼에서 컨트롤 키를 누른 채 Foo 인스턴스로 드래그를 하면 인스펙터 윈도우에서 Action을 선택할 수 있는데, "Generate random number"를 generate: 액션으로 연결을 해주자.

Foo 와 뷰 연결하기 1
그림 7. Foo 와 뷰 연결하기 1

Foo 와 뷰 연결하기 2
그림 8. Foo 와 뷰 연결하기 2

드디어 코드를 작성할 시간이다! 인터페이스 빌더에서 다시 Xcode로 돌아오자. 실제 코드를 입력하기 전에 생각해 보자. Foo 클래스를 루비에서 만든다면, 기본 구조는 어떻게 될까?

  

class Foo < NSObject
  attr_writer:textField
  def generate
  ...
  end
end


너무 간단한가? 정말 이렇게만 코드를 작성해도 애플리케이션이 작동하는 것인가? 실제로 해보자. 우선 새 루비 파일을 추가한다. File 메뉴에서 New File... 메뉴를 선택하면 그림 9와 같이 Ruby NSObject Subclass란 항목을 볼 수 있을 것이다.



위로


새 루비 파일 추가
그림 9. 새 루비 파일 추가

이를 선택하면 자동으로 NSObject를 서브클래싱한 루비 파일을 Xocde 프로젝트의 Classes 항목에 추가해 준다. 이름은 Foo.rb로 한다. 이 파일을 들여다보면 루비에서 코코아를 사용하기 위해 필요한 OSX 모듈을 사용했음을 볼 수 있다. 이제 다음과 같이 코드를 작성해 보자.

  

require 'osx/cocoa'

class Foo < OSX::NSObject
  attr_writer:textField
  def generate (sender)
    OSX.NSLog("Generate Button is pressed!");
  end
end


Xcode에서 Build and Go 아이콘을 클릭하고 뷰의 버튼을 클릭해 보도록 한다. Run Log 윈도우에 위의 "Generate Button is pressed!" 메시지가 나오는가? 다 되었다. 이제 generate 함수에서 난수를 발생하고 뷰의 텍스트 필드에 표시하는 일만 남았다. 코드는 다음과 같다.

  

require 'osx/cocoa'

class Foo < OSX::NSObject
  ib_outlet :textField

  def awakeFromNib
    @textField.setStringValue("My First RubyCocoa!")
  end

  def generate (sender)
    OSX.NSLog("Generate Button is pressed!");
    @textField.setStringValue(rand().to_s)
  end
  ib_action :generate

end


앞의 코드와 달라진 점은 무엇일까? 우선 attr_writer:textField가 ib_outlet :textField로 변경된 것, 그리고 awakeFromNib 함수의 추가, generate 함수 뒤로 ib_action :generate의 추가이다.
당연한 이야기겠지만, 뷰의 텍스트 필드를 가리키는 textField는 코코아 객체다. 따라서 이를 루비 클래스에서 인식할 수 있도록 해줘야 하는데, 이 부분이 바로 ib_outlet이란 키워드를 사용하는 것이다. 이렇게 함으로써 인터페이스 빌더에서 클래스에 추가한 아웃렛들에 접근할 수 있다.
awakeFromNib은 코코아에서 사용하는 독특한 초기화 메서드인데, 뷰에 필요한 객체들을 다 생성하고 만든 뒤에 호출해 주는 함수다. 예를 들어 텍스트 필드에 위와 같이 시작 문구를 출력하고 싶은데, initilize와 같은 함수에서 textField 등의 아웃렛에 접근하면, 뷰에 해당 객체가 생성되기 이전이라 런타임에 메시지를 nil에 보낸 것이 되어버린다. 이러한 경우를 위해 뷰의 객체가 다 준비된 다음에 컨트롤러 객체에서 뷰의 초기화를 할 수 있도록 도와주는 함수가 되겠다.
ib_action은 사실 꼭 필요한 키워드는 아니지만, RubyCocoa 0.11.0에서 새로 추가된 rb_nibtool.rb를 사용하기 위해선 있어야 한다. 이는 뷰에 관한 객체를 저장하는 nib 파일과 루비 파일들을 동기화해 주는 도구인데 후에 코드의 유지보수를 생각한다면 꼭 사용해야 하는 키워드라 할 수 있겠다.

완성된 애플리케이션
그림 10. 완성된 애플리케이션



위로



더 많은 예제와 다음 회에 배울 것

RubyCocoa로 정말 간단하게 코코아 애플리케이션을 만드는 법을 살펴보았다. RubyCocoa를 설치하면 코코아 예제가 들어있는 /Developer/Examples 디렉터리 아래에 RubyCocoa란 디렉터리가 새로 생긴다. 이 안을 열어보면, /Developer/Examples의 예제들을 RubyCocoa로 포팅한 예제들이 있으므로, 공부하는 데 많은 도움이 될 것이다.
다음 회에는 코코아 개발에 속도를 붙여주는 바인딩(binding)을 RubyCocoa와 함께 이용하는 법에 대해 알아보겠다.



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



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

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

로컬 컨텐츠

행사 및 세미나

기획 기사

개발자 입문

튜토리얼 및 교육

TOP 10 인기자료

SW 다운로드

RSS 피드

뉴스레터
  
자바스크립트가 작동이 중지되었습니다. 이 기능을 수행하시려면 브라우저에서 자바스크립스트를 작동시켜 주시거나 이곳을 클릭해주세요.
Special offers
Screencast
IBM SOA Sandbox 시험판
dW Student Community
로보코드
코드 트레이닝


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