2004년 출시된 Ruby on Rails는 웹 애플리케이션 개발에 사용되는 가장 대중적인 프레임웍으로 자리를 잡아가고 있다. Rails 또는 RoR로 알려진 이 오픈 소스 프로젝트는 Model-View-Controller (MVC) 아키텍처, Ruby 객체 지향 스크립팅 언어, "convention over configuration"과 "don't repeat yourself" 같은 단순한 원리를 사용한다. 개발자들은 중복이 적은 코드와 설정 파일을 사용하여 애플리케이션을 더욱 빠르고 쉽게 구현할 수 있고, 애플리케이션의 필요를 채울 수 있는 커스텀 확장을 구현할 수 있는 유연성도 있다. 데이터베이스 영속성에 대한 지원으로, 이 프레임웍을 사용하는 웹 애플리케이션들은 데이터베이스 서버와 빌트인 WEBrick 웹 서버를 사용하여 개발될 수 있다.
RubyForge 커뮤니티 포털에서 릴리스 된 IBM_DB Rails 어댑터와 Ruby 드라이버 덕택에, Ruby on Rails 프레임웍은 공식적으로 테스트 되고, 모든 DB2 데이터 서버에서 지원된다. DB2 Express-C라고 하는 무료 DB2 9 데이터베이스도 이 커뮤니티네 사용할 수 있다. DB2 Express-C 데이터 서버를 자유롭게 개발, 전개, 배포할 수 있기 때문에 크기, 시간, 사용자 제한이 없고, DB2 on Rails용 Starter Toolkit에 포함된다. 이 패키지를 사용하여 DB2를 사용하여 RoR 환경에서 빠르고 쉽게 웹 애플리케이션들을 설정 및 개발할 수 있다.
Rails 프레임웍에 설정될 수 있는 다양한 데이터 스토어들이 있지만, DB2 데이터 서버는 고유하고 뚜렷한 장점들이 있다. DB2 9에 pureXML™을 도입한 이래, IBM_DB 어댑터와 드라이버는 IBM 데이터 서버에서 사용될 때 네이티브 XML 데이터 유형을 지원한다.
DB2를 사용하여 Rails 개발 환경을 설정하는 두 가지 대안들이 있다. 여러분이 DB2 환경을 처음 다루는 것이라면, DB2 on Rails용 Starter Toolkit은 DB2 on Rails 애플리케이션 개발을 시작하는 가장 편리한 방법이다. Starter Toolkit version 2.1은 alphaWorks에서 다운로드 가능하고, 구 버전의 IBM_DB 어댑터를 설치한다. 이 버전은 i5와 zOS 플랫폼 기반 DB2를 지원하지 않지만, 업데이트 작업이 진행 중이고 곧 다운로드도 가능할 것이다.
하지만, 기존 DB2 환경에서 Rails 애플리케이션을 개발하려면, IBM_DB 어댑터와 드라이버 gem과 플러그인이 릴리스 되었기 때문에 "수동" 옵션도 사용할 수 있다. 최신 버전(Production/Stable release 0.6.0은 4월 30일부터 사용 가능)용 RubyForge rubyibm project를 확인해 보라.
DB2 Express-C 데이터 서버와 Rails 런타임 환경을 다운로드 및 설정해보자. IBM_DB 어댑터와 드라이버 최신 버전은 DB2 9, FixPack 2 또는 DB2 8, FixPack 15를 필요로 한다. 다음은 DB2 Express-C 데이터 서버와 Rails 런타임 환경을 다운로드 및 설정하는 방법이다.
- 웹 사이트로 가서 DB2 Express-C 9 FixPack 2 를 다운로드 한다.
- One-click Ruby Installer 를 다운로드 한다. (Ruby와 Rubygems 포함).
-
Rails gem과 종속물들들을 설치한다.
gem install rails --include-dependencies
Rails 플러그인과 비교되는 Ruby gem으로서 IBM_DB 어댑터와 드라이버 설치하기
Ruby gem과 Ruby 플러그인의 차이를 이해할 수 있도록 다음과 같이 런타임 환경에 대한 간단한 설명을 보자.
RubyGems는 Ruby 런타임 환경에서 라이브러리와 애플리케이션들을 위한 표준 패키징 및 설치 프레임웍이다. gem이라고 하는 각 번들용 단일 파일은, 중앙 저장소에 배포 및 저장되는 패키지 포맷에 순응하면서, 같은 라이브러리나 애플리케이션들의 여러 버전들의 동시 전개가 가능하다. 리눅스 배포판 패키징 관리 및 번들(rpm, .deb)과 비슷하게, 이러한 gem들은 gem 엔드 유저 유틸리티를 통해 쿼리, 설치, 설치 해제, 조작될 수 있다. gem 유틸리티는 원격 RubyForge 중앙 저장소를 완벽하게 쿼리하고, Rails 개발자의 삶을 편하게 해주는 많은 유틸리티들을 검색하여 설치한다. IBM_DB gem이 설치되면, 이 기능은 Ruby 런타임 환경의 어떤 스크립트(애플리케이션)에 의해서도 즉각 액세스 될 수 있다.
- require 'rubygems'
- gem 'ibm_db' (require_gem has been deprecated and replaced by gem in Rubygems 0.9)
ActiveRecord 어댑터로서, IBM_DB gem은 Rails 프레임웍에서 사용되기 전에 RAILS_CONNECTION_ADAPTERS (active_record.rb)의 리스트에 있는 추상 어댑터에 의해 등록되어야 한다. 일단 등록되면, IBM_DB gem과 이것의 종속물들(ibm_db Ruby 드라이버와, ODBC와 CLI용 IBM Driver)이 로딩된다. 이로써, Rails를 포함한 Ruby 환경에서 애플리케이션은 IBM 데이터 서버들과 상호 작동 할 수 있다. IBM_DB gem README 파일에서 언급된 것처럼(참고자료), Ruby 런타임은 IBM 데이터 서버로의 액세스에 실행된다.
Ruby Gem으로서 IBM_DB 어댑터와 드라이버 설치하기-
gem 명령어를 실행하여 IBM_DB 어댑터와 드라이버를 설치한다.
D:\>gem install ibm_db
-
Rails 프레임웍에 있는 연결 어댑터의 리스트에 'ibm_db'를 등록한다.
수동 방식으로는 ibm_db를 gems\1.8\gems\activerecord-1.15.3\lib\active_record.rb:에 추가한다.
RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite ... ibm_db )
Rails 플러그인은 프레임웍 고유의 확장 메커니즘을 나타낸다. 이것은 특정 및 개별 Rails 애플리케이션의 범위 내에서 기능을 확장할 수 있는 수단을 제공한다. 결국, IBM_DB gem이 Ruby 런타임 환경에 전개되지 않을 때 IBM 데이터 서버에 액세스 하는 또 다른 수단을 제공한다. Rails 플러그인이 Ruby gem만의 버전 관리를 제공하지 않는다면, IBM_DB 플러그인이 초기화 동안 Rails 레지스트리로 삽입할 수 있는 유용한 초기화 메커니즘을 제공한다. 따라서, 애플리케이션에 플러그인으로서 IBM_DB를 설치한 후에, Rails 프레임웍에 이를 로딩하기 위해 수동 단계가 필요 없다. IBM_DB 플러그인 README 파일과 RubyForge의 rubyibm project documentation에 설명된 것처럼, Rails는 플러그인 소스를 등록하고 Rails 애플리케이션 설치 스크립트를 실행함으로써 IBM 데이터 서버 액세스를 가능케 한다. RubyForge는 Subversion (SVN) 저장소로 HTTP 액세스를 실행하지 않지만(프로젝트 지원은 현재 SVN 프로토콜뿐이다.), Windows 기반 Rails 플러그인은 SVN 클라이언트 인스톨을 필요로 한다. 대부분의 리눅스® 및 유닉스® 배포판에서, SVN 클라이언트는 기본적으로 사용 가능하고, 이는 IBM_DB 플러그인을 더욱 완벽하게 만든다.
IBM_DB 어댑터(ibm_db_adapter.rb)는 ibm_db 드라이버를 직접적으로 의존하는데, Open Database Connectivity (ODBC)용 IBM 드라이버와 Call Level Interface (CLI)를 사용하여 IBM 데이터 서버에 연결한다. IBM CLI는 IBM 데이터 서버에 대한 호출 가능한 SQL 인터페이스이고, 이는 ODBC에 순응한다.
IBM_DB 어댑터와 드라이어가 많이 세분화 되었다.
-
IBM Driver for ODBC와 CLI 설치는 IBM_DB 요구 사항에 부합해야 한다.
IBM Driver for ODBC와 CLI를 완전한 DB2 데이터베이스와 함께 설치하거나, "IBM DB2 Driver for ODBC와 CLI 개요"와는 개별적으로 컴포넌트를 얻을 수 있다.
-
CLI 키워드를 사용하여 Ruby 애플리케이션 밖에서 드라이버 작동을 수정할 수 있다.
CLI 키워드를 사용하여 Rails 애플리케이션 밖에서 특정 트랜잭션 작동을 바꿀 수 있다. 예를 들어, 현재 스키마를 설정하는데 사용하거나, autocommit 작동을 조정하는 것 같은 트랜잭션 엘리먼트를 바꾸는데 사용할 수 있다. CLI 키워드에 관련한 상세는 다음 Info Center 문서를 참조하라.
-
진단 내용을 수집할 때에는 CLI 드라이버 트레이싱 장치가 필요하다.
IBM_DB 드라이버를 통한 모든 요청이 IBM Driver for ODBC와 CLI에서 제공하는 API를 사용하여 구현되듯이, CLI 트레이스는 IBM_DB 어댑터와 드라이버를 사용하는 애플리케이션에서의 문제들을 규명하는데 중요한 트레이싱 장치이다.
CLI 트레이스는 IBM driver for ODBC와 CLI (모든 인풋 매개변수들 포함)에 대한 모든 API 호출을 포착하고, 드라이버에서 애플리케이션으로 리턴된 모든 값들을 포착한다. 이것은 애플리케이션이 IBM driver for ODBC와 CLI와 상호 작동하는 방법을 파악하기 위해 설계된 인터페이스 트레이스이고, 드라이버의 내부 작동에 대한 정보를 제공한다.
늘 변하는 환경에서, 애플리케이션들은 새로운 요구 사항들과 도전을 다루어야 한다. 애플리케이션 개발자들이 애플리케이션을 바꿀 때, 예를 들어, 새로운 객체나 클래스를 추가할 때, 기반 영속성을 수정하여 그 데이터베이스가 애플리케이션과 연동되도록 해야 한다. 데이터베이스 스키마를 바꾸는 전통적인 방법은 새로운 SQL 스크립트를 만드는 것이다. 하지만, SQL 스크립트를 통해 애플리케이션과 데이터베이스를 버전 별로 유지하는 것이 문제이다. 더욱이, 데이터베이스 개발자들은 애플리케이션 변경과 관련된 데이터베이스 스키마에 이루어진 변경 사항들을 거의 바꾸지 않는다. 대부분의 개발 환경에서, 변경 사항들은 모든 데이터베이스 객체들을 없애고 SQL (Data Definition Language [DDL]) 스크립트의 이전 버전을 사용하여 이들을 다시 만듦으로써 바뀐다.
많은 개발자들에게 있어서, Rails의 비장의 무기는 마이그레이션을 통한 스키마 진화이다. 데이터베이스 개발자들은 DDL 또는 Data Manipulation Language (DML)를 통해 SQL을 사용하지만, 대부분의 애플리케이션 개발자들은 Ruby 언어와 라이브러리에 더 많이 의존한다. Rails는 확실한 마이그레이션을 제공한다. ActiveRecord 추상화를 활용하여 시퀀스 버전 별로 테이블과 칼럼 같은 데이터베이스 객체들을 생성 및 수정하는 단순하고 효율적인 인프라스트럭처이다. Rails 마이그레이션은 대부분 스키마 진화와 관련된 데이터베이스 관리 태스크이다. Rails 프레임웍은 개발을 단순화 하지만, 관련 툴 역시 데이터베이스를 변경하고 애플리케이션 코드를 테이블 구조에 동기화 하는데 매우 효과적이다.
Ruby on Rails 마이그레이션은 데이터베이스와 데이터 구조 변화를 포함하여 위에 언급된 일부 문제들을 해결한다. 이제, Rails 마이그레이션이 데이터베이스 스키마 진화를 활용하는 방법에 대해 알아보자.
Rails 애플리케이션 진화와 관련하여 일부 데이터베이스 객체 변화를 시도하면서, IBM_DB 어댑터를 사용하는 Rails 마이그레이션 예제를 살펴보자. 하지만 먼저, Rails 개발 환경 기반의 DB2가 앞서 설명된 대로 설치 및 설정되었는지를 확인해야 한다.
우리 예제에서는 Team Room을 구현할 것이다. 이 애플리케이션은 등록된 멤버들이 이미지, 실행 파일, 프리젠테이션, 기타 미디어를 포함하여 텍스트나 바이너리 포맷으로 된 다양한 문서들을 공유할 수 있다. 또한 XML 문서들이 공유되고, pureXML 데이터 유형을 통해 DB2 9에 저장될 수 있다. 이 예제는 또한 빌트인 계층 구조를 활용하는 좋은 방법도 제시하고 있다.
-
"teamroom"이라고 하는 Rails 프로젝트를 만든다.
Listing 1. Team Room Rails 프로젝트 만들기D:\rails>rails teamroom create create app/controllers create app/helpers create app/models create app/views/layouts create config/environments create components create db <etc ......> create log/server.log create log/production.log create log/development.log create log/test.log
Rails 프레임웍은 프로젝트의 디렉토리 구조를 자동으로 생성한다. 여기에서 D:\rails\teamroom 디렉토리에 있는 것으로 간주한다. 따라서 앞으로 언급하는 모든 경로들은 Team Room 프로젝트 디렉토리 내의 상대 경로이다.
-
이미 기존 DB2 데이터베이스가 있다면, 이 단계를 건너뛰고 3 단계로 가서 데이터베이스 연결 설정을 시작한다.
어떤 부분에서는 DB2에 XML을 저장해야 할 경우를 예상하고, UTF-8 codeset을 사용하여 XMLDB 데이터베이스를 만들어 보자. UTF-8 codeset은 XML 칼럼들이 DB2 테이블에 정의되도록 하기 위해 필요하다.
DB2 Command Line Processor에서, 다음 명령어를 실행한다.
Listing 2. XMLDB 데이터베이스 구현하기db2 create db xmldb using codeset utf-8 territory us
-
Now edit the D:\rails\teamroom\config\database.yml 파일을 편집하여 DB2 9 XMLDB 데이터베이스로 연결할 수 있다.
Listing 3. database.yml 파일 편집하기# IBM DB2 Database configuration file # # Install the IBM DB2 driver and get assistance from: # http://www.alphaworks.ibm.com/tech/db2onrails development: adapter: ibm_db database: xmldb username: user password: secret schema: teamroom application: TeamRoom account: devuser workstation: devbox # == remote TCP/IP connection (required when no local database catalog entry available) # host: bigserver // fully qualified hostname or IP address # port: 50000 // data server TCP/IP port number
DB2용 연결 애트리뷰트는 아래 테이블에 설명되어 있다.
표 1. database.yml용 DB2 연결 애트리뷰트
| 연결 애트리뷰트 | 설명 | 필요 여부 |
|---|---|---|
| Adapter | Ruby 어댑터 이름, DB2의 경우 'ibm_db'이다. | Yes |
| Database | Rails 프로젝트가 연결할 데이터베이스 | Yes |
| Username | DB2 데이터베이스로 연결하는데 사용되는 사용자 아이디 | Yes |
| Password | 사용자 아이디에 대한 패스워드 | Yes |
| Schema | 네임드 객체들의 컬렉션. 이 스키마는 데이터베이스 내에 로컬로 객체들을 그룹핑 하는 방식을 제공한다. 이 예제에서, 'teamroom' 데이터베이스 스키마 밑에 Rails Team Room 프로젝트용 모든 데이터베이스 객체들을 그룹핑 한다. 이로서 여러 Rails 프로젝트가 하나의 데이터베이스를 공유한다. | 선택적으로, 기본 스키마는 현재 세션 사용자의 권한 아이디로 설정될 수 있다. (주 4 참조) |
| Application | DB2 Connect를 사용할 때 호스트 데이터베이스 서버로 보내지는 클라이언트 애플리케이션 이름을 규명하는데 사용되는 문자 스트링. DB2 Connect에서, 'db2 list applications'를 실행하면 Ruby 실행 파일 대신에 'application' 이름을 보여준다. | Optional |
| Account | DB2 Connect를 사용할 때 호스트 데이터베이스 서버로 보내지는 클라이언트 계정 스트링을 구분하는데 사용되는 문자 스트링 | Optional |
| Workstation | DB2 Connect를 사용할 때 호스트 데이터베이스 서버로 보내지는 클라이언트 워크스테이션 이름을 구분하는데 사용되는 문자 스트링 | Optional |
| Host | 데이터베이스가 있는 원격 서버의 호스트 이름 | Optional (주 5 참조) |
| Port | 이 매개변수에는 데이터베이스 서버가 원격 클라이언트에서 통신을 기다리는데 사용하는 TCP/IP의 이름이 포함되어 있다. | Optional (주 5 참조) |
이제 실제 마이그레이션을 시작할 준비가 되었다.
우선, 모든 문서들과 미디어 파일들이 호스팅 된 애플리케이션의 사용자들간 공유될 수 있도록 스토리지 영역에서 시작해야 한다. 따라서, Documents 테이블을 만들어서 팀 멤버들이 공유할 모든 미디어 파일들을 저장한다.
다음 칼럼들을 정의하여 공유 파일의 내용을 기술한다.
표 2. DOCUMENTS 테이블 칼럼과 설명
| 컬럼 이름 | 데이터 유형 | 설명 |
|---|---|---|
| ID | Integer | 기본 키 |
| Name | VARCHAR | 문서의 이름 |
| Size | Integer | 파일 크기 |
| Data | BLOB | 바이너리 모드로 저장된 파일, 최대 크기 2 메가바이트 |
| Content_type | VARCHAR | .doc, .ppt, .pdf, .sw, .exe, .a, .so, .gif, .jpeg, .mov, .avi, .mpeg, .bmp 등의 문서 유형 |
a) 마이그레이션 방법으로 이를 수행하려면, ruby script\generate migration create_docs_store를 실행함으로써 DOCUMENTS 테이블용 마이그레이션을 만든다. Rails는 마이그레이션을 만들고 db/migrate/001_create_docs_store.rb를 생성한다. 유닉스에 ruby script/generate migration create_docs_store를 타이핑한다. (슬래시 "/"는 Windows와 유닉스 모두 사용할 수 있다.)
Listing 4. ruby script/generate migration create_docs_store 실행하기
D:\rails\teamroom>ruby script/generate migration create_docs_store
create db/migrate
create db/migrate/001_create_docs_store.rb
|
001_ create_docs_store.rb.는 db/migrate에 생성되고, 001이라는 번호가 매겨졌다. 이 단계부터 순서대로 번호가 붙은 파일들이 각 마이그레이션 단계마다 db/migrate에 생성될 것이다. 이것은 Rails가 마이그레이션 순서를 관리하고 있다는 것을 보여준다.
b) create_docs_store.rb를 편집하여 다음과 같이 한다.
Listing 5. create_docs_store.rb 편집하기
class CreateDocsStore < ActiveRecord::Migration
def self.up
create_table :documents do |t|
t.column :name, :string, :null => false
t.column :size, :integer, :null => false
t.column :content_type, :string, :null => false
t.column :data, :binary, :limit => 2.megabytes
end
end
def self.down
drop_table :documents
end
end
|
Rails 애플리케이션에서, 스키마 변화는 마이그레이션을 통해서 발생한다. 데이터베이스 스키마에 대한 변화는 버전 관리가 되고 벤더에 독립적인 신택스를 포함하고 있는 Ruby 스크립트로 정의된다. 더욱이, 이 변경 사항을 실행 취소하는 것은 각 마이그레이션 스크립트가 두 개의 클래스 메소드, up 메소드와 down 메소드를 사용하고 있는 동안 사용하는 것만큼 쉽다. 논리적 데이터베이스 스키마 변경을 하는데 필요한 모든 코드는 self.up 메소드에 있다. 변경 사항을 실행 취소하는데 필요한 코드는 self.down 메소드에 있다.
c) rake db:migrate 명령어로 마이그레이션을 실행한다.
Listing 6. 첫 번째 마이그레이션을 실행하여 DOCUMENTS 테이블 생성하기
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== CreateDocsStore: migrating =================================================
-- create_table(:documents)
-> 0.2010s
== CreateDocsStore: migrated (0.2010s) ========================================
|
d) DB2 명령어 프롬프트로 가서 db2 list tables for schema teamroom을 실행하여 DOCUMENTS 테이블이 생성되었는지를 확인한다.
Listing 7. 생성된 DB2 테이블 리스팅
D:\>db2 list tables for schema teamroom
Table/View Schema Type Creation time
------------------------------- --------------- ----- --------------------------
DOCUMENTS TEAMROOM T 2007-04-21-21.00.18.131001
SCHEMA_INFO TEAMROOM T 2007-04-21-21.00.17.740001
2 record(s) selected.
|
DOCUMENTS 테이블은 기대했던 대로 생성되었다. 데이터 유형은 아래와 같다.
Listing 8. DOCUMENTS 테이블에 생성된 컬럼 체크하기
D:\>db2 describe table teamroom.documents
Column Type Type
name schema name Length Scale Nulls
------------------------------ --------- ------------------ -------- ----- ------
ID SYSIBM INTEGER 4 0 No
NAME SYSIBM VARCHAR 255 0 No
SIZE SYSIBM INTEGER 4 0 No
DATA SYSIBM BLOB 2097152 0 Yes
CONTENT_TYPE SYSIBM VARCHAR 255 0 No
5 record(s) selected.
|
또한, 이 마이그레이션 단계 동안 Rails는 SCHEMA_INFO라고 하는 두 번째 테이블을 만들었다. SCHEMA_INFO는 rake db:migrate 명령어를 통해 생성되었다. SCHEMA_INFO 테이블을 쿼리하면 다음과 같은 결과가 나온다.
Listing 9. SCHEMA_INFO 테이블 쿼리하기
D:\>db2 select * from schema_info
VERSION
-----------
1
1 record(s) selected.
|
버전 컬럼의 값 '1'은 버전 1의 마이그레이션 단계에 있다는 것을 알려준다. (db/migrate/001_ create_docs_store.rb를 실행했다는 것을 기억해보라.)
rake db:migrate는 다음을 수행한다.
- SCHEMA_INFO 테이블이 없다면 이 테이블을 만들고, 버전 컬럼에 '0'을 삽입한다.
- 가능한 모든 마이그레이션을 실행한다. 점점 큰 순서대로 현재 마이그레이션 보다 큰 넘버를 가진 모든 마이그레이션의
up메소드를 실행한다. 첫 번째 마이그레이션은 버전 값 '1'로 시작한다. - 마지막 버전의 마이그레이션으로 SCHEMA_INFO 테이블을 업데이트 한다. 위 예제에서, 이 버전은 '1'로 업데이트 된다. 이것은 Rails 프로젝트의 첫 번째 마이그레이션이기 때문이다.
Step 2: DOCUMENTS와 관련된 추가 애트리뷰트
DOCUMENTS 테이블이 생성된 후에, OS 플랫폼, 업로드 시간, 마지막 변경 시간 같은 각 문서에 대한 추가 정보를 저장해야 한다고 생각해 보자. DOCUMENTS 테이블에는 다음과 같은 컬럼이 포함되어야 한다. (추가될 새로운 컬럼은 볼드체로 강조한다.)
표 3. DOCUMENTS 테이블 컬럼과 설명
| 컬럼 이름 | 데이터 유형 | 설명 |
|---|---|---|
| ID | Integer | 기본 키 |
| Name | VARCHAR | 문서 이름 |
| Size | Integer | 파일 크기 |
| Data | BLOB | 바이너리 모드로 저장된 파일, 최대 크기 2 메가바이트 |
| Content_type | VARCHAR | .doc, .ppt, .pdf, .sw, .exe, .a, .so, .gif, .jpeg, .mov, .avi, .mpeg, .bmp 같은 파일 유형 |
| Created_at | TIMESTAMP | 파일이 업로딩 된 시간 (주 9 참조) |
| Updated_at | TIMESTAMP | 문서의 마지막 업데이트 타임 스탬프 (주 9 참조) |
| Platform | VARCHAR | 파일 플랫폼 관련 정보 |
두 번째 마이그레이션을 생성하여 이 애트리뷰트들을 DOCUMENTS 테이블에 추가한다.
a) ruby script/generate migration add_docs_attributes를 실행한다.
db/migrate/002_add_docs_attributes.rb 파일이 만들어 진다.
Listing 10. DOCUMENTS 테이블에 컬럼을 추가하기 위해 두 번째 마이그레이션 생성하기
D:\rails\teamroom>ruby script/generate migration add_docs_attributes
exists db/migrate
create db/migrate/002_add_docs_attributes.rb
|
b) 002_add_docs_attributes.rb를 다음과 같이 편집한다.
Listing 11. SCHEMA_INFO 테이블 쿼리
class AddDocsAttributes < ActiveRecord::Migration
def self.up
add_column :documents, :created_at, :timestamp
add_column :documents, :updated_at, :timestamp
add_column :documents, :platform, :string, :limit => 10
end
def self.down
remove_column :documents, :created_at
remove_column :documents, :updated_at
remove_column :documents, :platform
end
end
|
c) rake db:migrate를 실행하여 두 번째 마이그레이션을 수행한다.
Listing 12. 두 번째 마이그레이션을 실행하여 DOCUMENTS 테이블에 컬럼 추가하기
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== AddDocsAttributes: migrating ===============================================
-- add_column(:documents, :created_at, :timestamp)
-> 0.0500s
-- add_column(:documents, :updated_at, :timestamp)
-> 0.0100s
-- add_column(:documents, :platform, :string, {:limit=>10})
-> 0.0000s
== AddDocsAttributes: migrated (0.0600s) ======================================
|
조직이나 커뮤니티의 많은 사람들은 문서에 관심이 있기 때문에, 이 같은 사용자와 액세스를 관리할 방법이 필요하다. USERS 테이블을 추가해 보자. 외래 키 'user_id'를 DOCUMENTS 테이블을 추가하여 특정 문서를 업로딩 했던 사용자를 알 수 있도록 한다.
다음은 이러한 태스크를 수행하는 절차이다.
a) db/migrate/003_create_users_table.rb 파일을 만들 ruby script/generate migration create_users_table을 실행한다.
b) db/migrate/003_create_users_table.rb 파일을 편집한다.
Listing 13. 003_create_users_table.rb 편집하기
class CreateUsersTable < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :usertype, :string, :limit => 5, :null => false
t.column :firstname, :string, :limit => 30
t.column :lastname, :string, :limit => 30
t.column :extension, :string, :limit => 4
end
add_column :documents, :user_id, :integer
end
def self.down
drop_table :users
remove_column :documents, :user_id
end
end
|
c) rake db:migrate를 실행하여 USERS 테이블 생성한다.
Listing 14. 마이그레이션을 통해 USERS 테이블 만들기
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== CreateUsersTable: migrating ================================================
-- create_table(:users)
-> 0.1400s
-- add_column(:documents, :user_id, :integer)
-> 0.0000s
== CreateUsersTable: migrated (0.1400s) =======================================
|
d) ruby script/generate scaffold document를 실행하여 DOCUMENTS 테이블용 스카폴드를 만든다. 빠른 스카폴딩은 클래스 객체들의 리스팅, 보여주기, 생성, 업데이트, 파괴에 대한 표준 액션들을 제공함으로써 Active Record 클래스를 온라인으로 만든다. 아래 Listing 15에서, 한 개의 컨트롤러와 많은 뷰들이 스카폴드 생성 동안 /app/controllers와 /app/views에 만들어졌다.
Listing 15. 문서용 스카폴드 만들기
D:\rails\teamroom>ruby script/generate scaffold document
exists app/controllers/
exists app/helpers/
create app/views/documents
create app/views/layouts/
create test/functional/
dependency model
create app/models/
exists test/unit/
exists test/fixtures/
create app/models/document.rb
create test/unit/document_test.rb
create test/fixtures/documents.yml
create app/views/documents/_form.rhtml
create app/views/documents/list.rhtml
create app/views/documents/show.rhtml
create app/views/documents/new.rhtml
create app/views/documents/edit.rhtml
create app/controllers/documents_controller.rb
create test/functional/documents_controller_test.rb
create app/helpers/documents_helper.rb
create app/views/layouts/documents.rhtml
create public/stylesheets/scaffold.css
|
이제, 스카폴드가 어떤 일을 했는지를 볼 준비가 되었다. 컴포넌트 프롬프트에서 ruby script/server를 타이핑 하여 Rails용 빌트인 WEBrick 웹 서버를 시작한다.
Listing 16. 빌트인 WEBrick 웹 서버 시작하기
D:\rails\teamroom>ruby script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2007-04-26 16:54:57] INFO WEBrick 1.3.1
[2007-04-26 16:54:57] INFO ruby 1.8.5 (2006-12-25) [i386-mswin32]
[2007-04-26 16:54:57] INFO WEBrick::HTTPServer#start: pid=444 port=3000
|
포트 넘버를 주목하라. 기본은 3000이지만, 포트 3000이 이미 시스템에서 사용되고 있으면 달라질 수 있다. 웹 브라우저를 열고 http://localhost:3000/으로 가면, Welcome 메시지가 나올 것이다. http://localhost:3000/documents 문서를 검색하면 다음을 볼 수 있다.
그림 1. 문서 리스팅
e) 생성된 /app/models/document.rb 파일을 다음과 같이 편집한다.
Listing 17. /app/models/document.rb 편집하기
class Document < ActiveRecord::Base
belongs_to :user
end
|
이러한 제휴는 각 문서가 하나의 사용자와만 제휴될 수 있다는 것을 나타낸다. DOCUMENTS 테이블이 user_id 외래 키 컬럼을 갖고 있다면 belongs_to :user를 모델링 한다.
/app/models/document.rb에 코드를 추가하여 DB2 9 데이터베이스에 문서를 업로딩 하고 파일을 저장할 수 있다. 코드 구현은 다운로드 섹션을 참조하라. 많은 문서들을 Team Room에 추가하면 브라우저 모습은 다음과 같이 된다.
그림 2. 문서 리스팅
f) ruby script/generate scaffold user를 실행하여 USERS 테이블용 스카폴드를 만든다. /app/models/user.rb를 다음과 같이 편집한다.
Listing 18. /app/models/user.rb 편집하기
class User < ActiveRecord::Base
has_many :document
end
|
초반 마이그레이션 단계를 상세히 이해했다면, 나머지 마이그레이션 단계를 통해 남아있는 테이블과 제휴들을 만들어 보자.
Step 4: 점점 증가하는 공유 문서들의 컬렉션 관리하기
커뮤니티가 기여할 수 많은 문서들을 범주화 할 방법이 도움이 되기 때문에 콘텐트 주제에 기반한 분류법이 추가될 수 있다. SUBJECTS 테이블이 문서들을 범주화 하기 위해 생성된다. 하나의 주제에 많은 문서들이 포함되지만, 각 문서는 한 주제에만 속한다. 이러한 SUBJECTS와 DOCUMENTS간 일대일 관계를 설명하기 위해 Subject ID 외래 키를 DOCUMENTS에 추가해야 한다.
이 태스크를 수행하는 절차는 다음과 같다.
a) db/migrate/004_create_subjects_table.rb 파일을 생성할 ruby script/generate migration create_subjects_table을 실행한다.
b) db/migrate/004_create_subjects_table.rb를 다음과 같이 편집한다.
Listing 19. SUBJECTS 테이블 생성하기
class CreateSubjectsTable < ActiveRecord::Migration
def self.up
create_table :subjects do |t|
t.column :name, :string, :limit => 20
t.column :size, :integer
t.column :description, :text
t.column :tag, :string, :limit => 10
end
add_column :documents, :subject_id, :integer
end
def self.down
drop_table :subjects
remove_column :documents, :subject_id
end
end
|
c) rake db:migrate를 실행하여 SUBJECTS 테이블을 만들고 subject_id 외래 키를 추가한다.
d) ruby script/generate scaffold subject를 실행하여 SUBJECTS 테이블용 스카폴드를 만든다.
e) has_many :document 제휴를 새롭게 생성된 /app/models/subject.rb 파일에 추가한다.
Listing 20: 제휴를 주제 모델에 추가하기
class Subject < ActiveRecord::Base
has_many :document
end
|
f) 두 번째 제휴인 belongs_to :subject를 Step 3(d)에서 생성된 /app/models/document.rb 파일에 추가한다.
Listing 21: 제휴를 문서 모델에 추가하기
class Document < ActiveRecord::Base
belongs_to :user
belongs_to :subject
<... code to assist with document uploading ...>
<... ...>
end
end
|
새로운 문서가 특정 카테고리에 업로드 될 때 사용자가 공지를 받을 수 있는 방법이 있다면? SUBSCRIPTIONS 테이블에 공지에 대한 요구 사항들을 모들 수 있다면 쉽게 이루어질 수 있다. 사용자, 주제, 등록 간 관계도 고려되어야 한다.
먼저 사용자 케이스 시나리오를 설명해 보자. 사용자 Anthony는 새로운 문서가 특정 주제, programming, Linux, fishing에 업로딩 될 때마다 공지를 받고 싶다. 지금까지 생성했던 모든 주제들을 디스플레이 하는 페이지를 검색하고, 위에 리스팅 된 주제와 관련된 박스를 체크한다. 새로운 문서가 세 가지 주제에 업로드 될 때마다, 애플리케이션은 이들을 포함하고 있는 섭스크립션의 소유자에게 이메일로 보낼 공지 메시지를 생성한다. 이 모든 것은 다음과 같은 관계 세트로 변환된다.
- 각 사용자는 하나의 섭스크립션을 갖고 있지만, 섭스크립션은 의무 사항은 아니다. (예를 들어, one-to-none, one... relationship)
- 외래 키 user_id는 SUBSCRIPTIONS 테이블에 추가되어야 한다.
- 일대일 관계는 사용자와 섭스크립션 모델 사이에 추가되어야 한다.
- 각 사용자 섭스크립션에는 몇 가지 선호 주제들이 포함될 수 있다. (예를 들어, 일대다 관계) 사용자에게는 이 모든 주제들에서 선택할 수 있는 수단이 제공된다.
- 외래 키 subscription_id는 SUBJECTS 테이블에 추가된다.
- 일대다 관계는 섭스크립션과 주제 모델 사이에 추가되어야 한다.
전에 여러분이 사용했던 것과 비슷한 마이그레이션 단계를 사용하여 데이터베이스 디자인 목표를 달성할 수 있다.
a) ruby script/generate migration create_subscriptions_table을 실행하면 db/migrate/005_create_subscriptions_table.rb 파일이 만들어진다.
b) db/migrate/005_create_subscriptions_table.rb를 편집한다:
Listing 22: SUBSCRIPTIONS 테이블
class CreateSubscriptionsTable < ActiveRecord::Migration
def self.up
create_table :subscriptions do |t|
t.column :name, :string, :limit => 20
t.column :description, :text
t.column :user_id, :integer
end
add_column :subjects, :subscription_id, :integer
end
def self.down
drop_table :subscriptions
remove_column :subjects, :subscription_id
end
end
|
c) rake db:migrate를 실행하여 SUBSCRIPTIONS 테이블을 만들고 외래 키 컬럼을 SUBJECTS에 추가한다.
d) ruby script/generate scaffold subscription을 실행하여 SUBSCRIPTIONS용 스카폴드를 생성한다.
e) has_many :subject 제휴를 Step 4 d 에서 생성된 /app/models/subscription.rb 파일에 추가한다.
f) 상응하는 제휴인 belongs_to :subscription 새롭게 생성된 /app/models/subject.rb 파일에 추가한다.
g) has_one :subscription 제휴를 Step 3 f에서 생성된 /app/models/user.rb 파일에 추가한다.
h) belongs_to :user 제휴를 새롭게 생성된 /app/models/subscription.rb 파일에 추가한다.
사용자들에게 Team Room 업데이트에 대해 공지하는 한 가지 방법 중에 이메일이 있다. 이렇게 하려면, 각 사용자에게 이메일 연락처를 추가해야 하므로, 또 다른 마이그레이션을 통해 USERS 테이블에 이메일 컬럼을 추가한다.
a) ruby script/generate migration addEmailToUser를 실행한다. db/migrate/006_add_email_to_user.rb 파일이 만들어 진다.
b) 006_add_email_to_user.rb를 편집한다.
Listing 23: USERS 테이블에 이메일 정보를 추가하기
class AddEmailToUser < ActiveRecord::Migration
def self.up
add_column :users, :email, :string, :limit => 30
end
def self.down
remove_column :users, :email
end
end
|
c) rake db:migrate를 실행하여 USERS 테이블에 이메일 컬럼을 추가한다.
다음은 Step 1에서 6까지 했던 것을 나타낸다.
그림 3. 다양한 모델들 간 제휴
Step 7: Team Room에 XML 문서 저장하기
오늘날의 엔터프라이즈 환경에서, 문서들은 XML 포맷에 저장되어야 하고, 이 같은 구조화 된 문서들이 무정형 바이너리 객체들과 다르게 취급되는 것은 아니다. 우리는 이 애플리케이션에 다른 것을 시도하면서, DOCUMENTS 테이블에 이미 정의된 BLOB 데이터 유형과 다른 데이터 유형에 XML 문서를 저장한다.
DB2 9 데이터 서버를 사용하고, 네이티브 XML 데이터 영속성을 활용하는 동안, 잘 형성된 XML 문서들은 계층적 폼으로 저장된다. XML 컬럼은 DB2 9에서 XML 데이터 유형으로 선언되고, 이는 우리가 새로운 마이그레이션에서 사용할 것이다.
a) ruby script/generate migration add_xml_doc_column을 실행한다.
db/migrate/007_add_xml_doc_column.rb가 만들어 진다.
b) 007_add_xml_doc_column.rb를 편집한다:
Listing 24: XML 컬럼을 DOCUMENTS에 추가하기
class AddXmlDocColumn < ActiveRecord::Migration
def self.up
add_column :documents, :xmldata, :xml
end
# Currently, a column that is part of a table containing an XML column
# cannot be dropped. To remove the column, the table must be dropped
# and recreated without the previous XML column.
def self.down
drop_table :documents
create_table :documents do |t|
t.column :name, :string, :null => false
t.column :size, :integer, :null => false
t.column :data, :binary, :limit => 2.megabytes
t.column :content_type, :string, :null => false
t.column :created_at, :timestamp
t.column :updated_at, :timestamp
t.column :platform, :string, :limit => 10
t.column :user_id, :integer
t.column :subject_id, :integer
end
end
end
|
c) rake db:migrate를 실행하여 새로운 컬럼을 DOCUMENTS 테이블에 추가한다.
add_column은 이미 익숙하지만, remove_column을 사용하는 대신, 전체 컬럼들이 누락되었다가 다시 생성되어야 한다는 것에 놀랬을 것이다. 전혀 놀랄 필요가 없는 것이, 이것이 XML이 네이티브 데이터 유형으로서 테이블에 가져온 중요한 변화이다. 이는 XML 컬럼 제거가 지원될 때까지 다소 불편하지만, 다음 시리즈에서는 대안 데이터베이스 스키마 디자인도 제공할 것이고, 네이티브 XML 데이터 유형 지원이 가져온 긍정적인 부분도 설명할 것이다. 하지만 먼저, "무정형" blob 데이터를 사용한다.
d) XML 문서에 수집되고 포맷팅 된 마케팅 데이터를 분석한다.
수집된 마케팅 데이터에 나타난 모든 Toronto 주민들을 결정한다. Team Room에 게시된 문서들에서 고객의 우편 번호 정보를 추출한다. http://localhost:3000/을 검색하면서 문서 스카폴드를 사용하고 샘플 코드에서 제공된 teamroom/test/fixtures/CAN-Central.xml 문서를 업로드 한다. 그리고 나서, 다음 액션을 documents_controller.rb에 추가한다.
Listing 25: XML 포맷 마케팅 데이터 분석하기
def zips
@id = params[:id]
@xmldata = Document.find_by_sql "select xmlquery(\
'<zipcodes>\
{for $i in $t/marketinfo/sales/customer/address\
where $i/city = \"Toronto\"\
return <zip>{$i/zip/text()}</zip>} \
</zipcodes>'\
passing c.xmldata as \"t\")\
from documents c where id = #{@id}"
p @xmldata[0]
redirect_to :action => 'list'
end
|
이 애플리케이션의 현재 단계에서, 복잡한 SQL과 삽입된 XQuery의 결과는 서버 콘솔에만 프린트 되고, 이전에 업로딩 된 CAN-Central.xml 문서용 zip 링크가 뒤따라 나온다. 결과에는 CAN-Central.xml 문서에 존재하는 Toronto 고객들과 관련된 우편 번호 리스트가 포함된다. SQL 문에 삽입된 XQuery는 처음 보면 복잡해 보이지만, 대부분의 경우, XPath 쿼리 식이 단순화 할 수 있다.
Listing 26: XML 마케팅 데이터에서 Toronto 시의 우편 번호 찾기
Document.find_by_sql "select xmlquery('<zipcodes>\
{$t/marketinfo/sales/customer/address/zip[../city = \"Toronto\"]}\
</zipcodes>' passing c.xmldata as \"t\")\
from documents c where id = #{@id}"
|
다음 시리즈에서는, SQL에 삽입된 XQuery와 XPath 식을 통해 Rails 애플리케이션 인터랙션을 단순화 하는 방법을 모색할 것이다. 큰 XML 문서에서 작은 부분을 찾기 위해 전체 콘텐트를 검색해야 할 필요가 없을 것이다. 이는 DB2 네이티브 XML 데이터 스토어 내부에서 수행될 수 있으며, DB2 엔진 옵티마이저를 활용한다.
그림 4는 Team Room 데이터베이스 객체가 Step 7의 끝에 보이는 모습이다.
그림 4. Team Room 데이터베이스 스키마 다이어그램
결국 다 해냈다. 하지만, 이 모든 변경 사항들을 실행 취소 하고 싶다면? 매우 간단하다. rake db:migrate VERSION=number 를 실행한다. 여기에서 number는 취소하고자 하는 버전을 나타낸다. 예를 들어, XMLDB 데이터베이스에 Rails Team Room 프로젝트에 만들었던 테이블을 없애고 지금까지 수행했던 모든 변경 사항들을 실행 취소하고 싶다면, rake db:migrate VERSION=0을 실행한다. Rails는 각 마이그레이션 단계를 순서대로 거슬러 올라가면서, 가장 큰 마이그레이션부터 변경을 취소하고, 데이터베이스를 버전 0으로 강등시킨다.
Listing 27. 마이그레이션을 통해 변경 사항 취소하기
D:\rails\teamroom>rake db:migrate VERSION=0
(in D:/rails/teamroom)
== AddXmlDocColumn: reverting =================================================
-- drop_table(:documents)
-> 0.0150s
-- create_table(:documents)
-> 0.1880s
== AddXmlDocColumn: reverted (0.2030s) ========================================
== AddEmailToUser: reverting ==================================================
-- remove_column(:users, :email)
-> 0.1250s
== AddEmailToUser: reverted (0.1250s) =========================================
== CreateSubscriptionsTable: reverting ========================================
-- drop_table(:subscriptions)
-> 0.0000s
-- remove_column(:subjects, :subscription_id)
-> 0.1560s
== CreateSubscriptionsTable: reverted (0.1560s) ===============================
== CreateSubjectsTable: reverting =============================================
-- drop_table(:subjects)
-> 0.0000s
-- remove_column(:documents, :subject_id)
-> 0.1570s
== CreateSubjectsTable: reverted (0.1570s) ====================================
== CreateUsersTable: reverting ================================================
-- drop_table(:users)
-> 0.0000s
-- remove_column(:documents, :user_id)
-> 0.1400s
== CreateUsersTable: reverted (0.1400s) =======================================
== AddDocsAttributes: reverting ===============================================
-- remove_column(:documents, :created_at)
-> 0.1250s
-- remove_column(:documents, :updated_at)
-> 0.1870s
-- remove_column(:documents, :platform)
-> 0.1260s
== AddDocsAttributes: reverted (0.4380s) ======================================
== CreateDocsStore: reverting =================================================
-- drop_table(:documents)
-> 0.0000s
== CreateDocsStore: reverted (0.0000s) ======================================== |
IBM_DB 어댑터/드라이버와 DB2 데이터 서버를 사용하여 Rails 애플리케이션 개발을 시작하는 방법을 살펴보았다. Starter Toolkit for DB2 on Rails는 DB2와 Ruby on Rails가 처음인 사람들에게 가장 쉬운 방법을 제공한다. 하지만, 기존 DB2 개발자들에게는 IBM_DB 어댑터와 드라이버 gem 또는 플러그인이 더 적합하다.
또한 Rails 마이그레이션을 상세히 다루었다. 데이터베이스 스키마 변경을 관리하는 일은 매우 지루한 일이다. Rails 마이그레이션 기능은 애플리케이션 개발자들이 스키마 진화를 관리하면서, 애플리케이션 코드와 데이터베이스 객체들간 변화를 쉽게 연결시킬 수 있도록 한다. Rails 마이그레이션을 활용하고 Ruby 파일의 데이터베이스 스키마 변경 사항들을 정의함으로써, 변경 사항들의 버전 관리가 논리적 순서대로 발생한다. 더욱이, Rails의 ActiveRecord는 벤더 스팩이 아니기 때문에, 개발자는 하나의 Ruby 마이그레이션 파일을 만들어서 여러 데이터베이스 플랫폼들에 같은 변경 사항들을 다루면서, 다양한 ActiveRecord 어댑터들을 사용한다.
Ruby on Rails 시리즈 Part 2를 기대해 주기 바란다. DB2 on Rails와 XML 지원에 대해 상세히 다루도록 하겠다. Ruby on Rails를 통한 XML 관리가 더욱 상세히 다루어질 것이다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| Team room sample code | teamroom1.zip | 10KB | HTTP |
교육
-
"Ruby on Rails and J2EE:Is there room for both?"
(developerWorks, 2005년 7월)
-
"Crossing borders: Exploring Active Record"
(developerWorks, 2006년 3월)
-
"Crossing borders: What's the secret Sauce in Ruby on Rails?"
(developerWorks, 2006년 5월)
-
"An introduction to Ruby on Rails for DB2 developers"
(developerWorks, 2006년 6월)
-
"Crossing borders: Rails migrations"
(developerWorks, 2006년 8월)
-
"RadRails와 Eclipse로 Ruby on Rails를 쉽게! (한글)"
(한국 developerWorks, 2007년 5월): Ruby on Rails를 단계별로 소개합니다..
-
ActiveRecord association 문서.
-
technology bookstore
제품 및 기술 얻기
- DB2®, Lotus®, Rational®, Tivoli®, WebSphere® 등의 IBM 제품 평가판 다운로드.
-
DB2 Express-C 다운로드.
-
Rails Adapter/Driver for IBM Databases (rubyforge.org)
-
IBM_DB adapter/driver gem과 플러그인 다운로드.
-
Starter Toolkit for DB2 on Rails 다운로드.
-
RadRails 다운로드.
토론
John Chun은 DB2 Advanced Support 팀의 전문가로서, 애플리케이션 개발과 툴링 분야에서 일하고 있다. IBM DBT Toronto 연구실에서 Java, C, C++, Perl, REXX, C#을 포함한 다양한 언어들로 DB2 애플리케이션 문제를 해결하고 있다. DB2 CLI와 OLEDB 드라이버 및 .NET 프로바이더 관련 수 많은 프로젝트를 수행했다. DB2 Certified Solutions Expert 및 Certified WebSphere Administrator이다.
Alex Pitigoi는 IBM Toronto Lab의 소프트웨어 엔지니어이다. 1998년 이후 Information Management 분야에서 다양한 소프트웨어 개발 프로젝트에 참여했으며, 웹 기술과 데이터베이스 관리를 전문으로 했다. 최근에는 SQLModel 개발 프로젝트를 이끌었고, 이것은 현재 Eclipse Data Tools Project로 통합되었고, 많은 IBM 데이터 서버들에서 데이터베이스 관리 웹 툴용 아키텍처로서 사용되고 있다. DB2 Satellite Administration Center에서도 일했으며 DB2용 최초의 웹 툴 개발도 이끌었다. 현재 새로운 오픈 소스 기술(Ruby, Python, PHP)을 위한 IBM의 데이터 서버 인에이블먼트에 집중하고 있다.
Naomi Ngan은 2000년 캐나다의 토론토대학교에서 컴퓨터 공학과 통계학과를 우수한 성적으로 졸업했다. 졸업 후에, IBM에 입사했으며, 애플리케이션 개발 환경에서 IBM DB2 RDBMS 제품 결함과 문제 해결 책임을 맡았다. IBM에서 4년을 근무한 후, UCSF에 있는 Ernest Gallo Clinic and Research Center로 옮겨와서 바이오인포매틱스 소프트웨어를 개발했다. 데이터베이스 객체, JSP, 자바 독립 애플리케이션, 리눅스와 윈도우즈 플랫폼 기반 XML 환경에서의 저장 프로시저의 디자인과 개발을 담당했다. 현재, Autonomy Corporation의 소프트웨어 엔지니어로서 J2EE 엔터프라이즈 소프트웨어를 개발하고 있다. DB2의 애플리케이션 개발과 툴링에 해박한 지식을 갖고 있으며, DB2, XML, WebSphere, Java/J2EE 등 수 많은 IBM 및 Sun 개발자 인증을 보유하고 있다.