BLOG ARTICLE sqlite | 2 ARTICLE FOUND

  1. 2008.11.25 아이폰 SQLite3 샘플 (6)
  2. 2008.08.20 Xcode에서의 Ruby on Rails (8)

iOS 2008.11.25 14:18
SQLite는 경량화된 DB로 맥과 아이폰/아이팟 터치에 기본적으로 내장되어 편리하게 사용할 수 있습니다. 자세한 내용은 SQLite 공식 홈페이지와 아래의 문서들을 참조하시면 도움이 되실 것입니다.


이와함께 애플의 iPhoneDev Center SQLite Book List란 샘플을 보시면, 아이폰 SDK에서 사용하는 방법이 잘 나와있습니다. SQLite의 개발자인 Richard Hipp이 구글 테크토크에서 직접 SQLite에 대해서 설명하는 'An Introducion to SQLite'란 동영상도 참고하면 좋습니다.



아래는 제가 SQLite를 테스트 해보기 위해 만들어 본 간단한 샘플코드입니다. 아이폰에서 사용자로 부터 입력을 받은 후에 SQLite DB에 저장하는 간단한 샘플입니다. DB를 오픈하는 부분과 SELECT, INSERT하는 부분만 참고하시면 쉽게 사용하실 수 있습니다.

* SQLiteTestAppDelegate.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>

@interface SQLiteTestAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    sqlite3 *db;
    NSMutableArray *dataList;

    IBOutlet UITextField *newString;
    IBOutlet UITableView *dataTable;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

- (void)updateDataList;

- (IBAction)addRow:(id)sender;
   
@end


SQLiteTestAppDelegate.m
#import "SQLiteTestAppDelegate.h"

@implementation SQLiteTestAppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching:(UIApplication *)application {   

    // Override point for customization after application launch
    [window makeKeyAndVisible];
   
    /* 어플리케이션 패스를 구한다. */    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"mydata.db"];
       
    /* 데이터베이스를 오픈한다 */
    if(sqlite3_open([path UTF8String], &db) == SQLITE_OK) {
        char *error = NULL;
        const char* query = "SELECT count(*) from mytable";
       
        /* mytable을 쿼리해보고 오류가 있으면 mytable을 생성한다. */
        if (sqlite3_exec(db, query, NULL, 0, &error) != SQLITE_OK) {
            sqlite3_free(error);
           
            /* 테이블 생성 */
            if (sqlite3_exec(db, "CREATE TABLE mytable ('name' CHAR(16))", NULL, 0, &error) != SQLITE_OK) {
                NSLog(@"TABLE CREATE ERROR: %s", error);
                sqlite3_free(error);
            }   
        }
    } else {
        /* DB 오픈 에러 */
        sqlite3_close(db);
        db = NULL;
       
        NSLog(@"DB OPEN ERROR: '%s'", sqlite3_errmsg(db));   
    }
   
    dataList = [[NSMutableArray alloc] initWithCapacity:100];
   
    [self updateDataList];
}

- (void)applicationWillTerminate:(UIApplication *)application {
    if (db) {
        sqlite3_close(db);
    }
}

- (void)dealloc {
    [dataList release];
   
    [window release];
    [super dealloc];
}

/** 현재 DB에 있는 데이터를 dataList에 등록 */
- (void)updateDataList {
   
    /* 이전 데이터를 모두 삭제 */
    [dataList removeAllObjects];
   
    const char *query = "SELECT name FROM mytable";
    sqlite3_stmt *statement;
   
    if (sqlite3_prepare_v2(db, query, -1, &statement, NULL) == SQLITE_OK) {
        while (sqlite3_step(statement) == SQLITE_ROW) {
           
            /* dataList에 쿼리결과 등록 */
            NSString* str = [[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
            [dataList addObject:str];
            [str release];
        }
    }
    sqlite3_finalize(statement);

    [dataTable reloadData];
}


#pragma mark IBACTION

- (IBAction)addRow:(id)sender {

    char *error = NULL;
   
    /* 사용자가 입력한 값을 DB에 추가한다 */
    NSString *query = [NSString stringWithFormat:@"INSERT INTO mytable VALUES ('%@')", [newString text]];
    sqlite3_exec(db, [query UTF8String], NULL, 0, &error);
   
    [self updateDataList];
}


#pragma mark TextField Delegate method

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
   
    [textField resignFirstResponder];
    return YES;
}


#pragma mark TableView Delegate method

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return @"Table Items";
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [dataList count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   
    static NSString *cellIdentifier = @"Cell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier] autorelease];
    }
    cell.text = [dataList objectAtIndex:indexPath.row];
   
    return cell;
}

@end


사용자 삽입 이미지
OS X 10.5에는 Ruby(1.8.6), Rails(1.2.6), SQLite3(3.4.0)가 기본으로 설치되어 있습니다. 그렇기 때문에 추가적인 설치나 설정 없이 편리하게 RoR 환경에서 손쉽게 웹사이트를 만들 수 있습니다.

오늘 오전에 Ruby에 관련된 포스팅을 해서 그런지 문득 Xcode에서도 RoR 환경을 지원하는지 궁금하여 자료를 찾아 보았습니다. ADCDeveloping Rails Applications on Mac OS X Leopard 에서 관련된 내용을 찾을 수 있었습니다. 이 문서를 참조하여 간단히 설명해 보겠습니다.


1. Rails 업그레이드
Xcode에서 사용하기 위해서는 Rails 2.*로 업그레이드를 해야 합니다. (주의: 조금 지난 서적들과 예제들은 Rails 1.*로 설명이 되어 있습니다. 업그레이드를 하시면 변경된 부분 때문에 따라하기 어려울 수 있습니다.)

터미널에서 아래와 같이 명령어를 실행하여 최신버젼으로 업그레이드를 합니다.
$ sudo gem update --system
$ sudo gem install rails
$ sudo gem update rake
$ sudo gem update sqlite3-ruby

설치가 완료된 후에 'rails -v'로 버젼을 보면 현재 '2.1.0'으로 업그레이드 되어 있는 것을 확인할 수 있습니다.


2. 프로젝트 생성
터미널에서 아래의 명령어를 실행하여 프로젝트를 생성합니다. 결과가 출력되면서 해당 디렉토리 밑에 WishList란 디렉토리가 생성되어 있습니다.

$ rails WishList
$ cd WishList

WishList 디렉토리에서 아래와 같이 명령어를 입력하여 MyWish의 scaffold를 생성합니다.

$ script/generate scaffold MyWish name:string price:integer url:string memo:text


3. Xcode Organizer
1) WishList 등록
Xcode를 실행하고 메뉴에서 Window/Organizer를 클릭합니다.   
사용자 삽입 이미지

위와 같이 Organizer가 실행되되면 finder에서 위에서 만든 WishList 디렉토리를 좌측의 PROJECTS & SOURCES가 있는 영역으로 드래그하여 가져다 놓습니다. 아래와 같이 PROEJCTS & SOURCES 아래에 WishList가 등록된 것을 확인합니다.
사용자 삽입 이미지
목록에서 소스파일을 선택하면 좌측 편집창에서 수정할 수 있습니다.
사용자 삽입 이미지

2) migration
추가된 WishList를 클릭한 후에 툴바의 Action을 클릭한 채로 있으면 아래와 같이 실행 메뉴가 나옵니다. db:migrate를 선택합니다.

사용자 삽입 이미지

아래와 같이 성공적으로 실행되었다는 메시지창이 출력됩니다.
사용자 삽입 이미지

3) 웹서버 실행
사용자 삽입 이미지
툴바에서 Run을 실행하면 초기 설정창이 오픈됩니다. 좌측의 하단에 [+] 버튼을 클릭하고 좌측과 같이 'New Shell Script'를 선택합니다.





아래와 같이 제목을 'run server'로 변경하고 Directory를 'Top Level Organizer Item'으로 선택합니다. 그리고 Command에 'script/server'를 입력한 후 OK 버튼을 클릭하여 저장합니다.

사용자 삽입 이미지

실행되면 아래와 같이 서버가 3000 포트에서 실행되고 있다는 것을 확인할 수 있습니다.
WEBrick으로 실행될줄 알았는데 친절하게 Mongrel도 이미 설치되어 있는 것 같습니다.
사용자 삽입 이미지

4. 테스트

사파리나 파이어폭스의 주소창에서 'http://localhost:3000/'을 입력하면 아래와 같이 Ruby on Rails의 기본페이지를 확인할 수 있습니다.
사용자 삽입 이미지

이제 다시 주소창에서 http://localhost:3000/my_wishes 를 입력합니다. 목록 하단의 'New my wish'를 클릭하여 아래와 같은 입력폼이 나오면 각 필드를 입력 후에 하단의 'Create' 버튼을 클릭합니다.

사용자 삽입 이미지

목록으로 돌아 오면 아래와 같이 입력한 내용이 등록되어 있음을 확인할 수 있습니다.

사용자 삽입 이미지

터미널에서도 SQLite을 실행하여 테이블과 레코드를 확인할 수 있습니다.

사용자 삽입 이미지

혹시나 RoR을 Xcode를 이용할 수 있는지 알아 보았는데, 제가 아직 방법을 잘 몰라서 그런지 오히려 그냥 터미널에서 개발하는 것 보다 더 불편한 것 같습니다.

짧은 생각으로는 Ruby on Rails + (Prototype + script.aculo.us)가 최상의 웹 개발환경인 것 같은데, 생각 처럼 그렇게 많은 곳에서 사용하지는 않는 것 같습니다. 제가 모르는 어떤 이유가 있는 것 같습니다.