기타 2010/02/11 10:42
몇일전 주문한 모토로이를 받아 조금 사용해 보았습니다. 넥서스원이면 모를까 모토로이는 전혀 구매할 의사가 없었지만 현재 진행하고 있는 안드로이드 프로젝트 때문에 어쩔 수 없이 구입했습니다. 이전에 테스트용으로 잠시 써본적이 있어 전혀 관심이 가지 않는 제품이었습니다. 하지만 개발할 때도 쓰겠지만 집사람 핸드폰으로 구입한 것이고 집사람은 DMB만 되면 되니 괜찮을 것 같고 당장은 선택의 여지가 없어 바로 예약판매시 신청했습니다.


휴대용 젠더/DMB 안테나, 크래들, USB, 헤드셋, 차량용 충전기 등 구성품은 푸짐했습니다. 특히 크래들과 차량용 충전기는 아주 괜찮은 것 같습니다.

아이폰을 사용할때와 비해서 반응속도도 느리고 정확하지 않으며 스크롤시 딱딱 끊기는 느낌이 있습니다. 넥서스원을 사용해본 분의 이야기를 들어보면 같은 안드로이드지만 전혀 다른 OS라는 생각이들정도로 차이가 많이나고 모토로이가 부족하다고 했습니다. 내장되어 있는 문자인식 어플리케이션으로 책표지의 안드로이드란 큰 글씨를 인식시켜 보았는데 안드로메다로 인식하더군요. 묘한 기분이 들었습니다.

그나저나 안드로이드 개발을 하면서 구형 맥북의 한계를 느끼게 되는 일이 종종 있네요. 이로인해 조만간 아이맥을 구입하지 않을까 하는 걱정이 드는데 현실이 될 것 같습니다.
저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

모토로이  (6) 2010/02/11
역시 그냥 껐다 키는 것이...  (8) 2009/09/24
아이폰 3GS  (2) 2009/09/17
블로그를 또 다시 이전했습니다.  (4) 2009/05/11
실버라이트2 동영상 재생 속도  (0) 2009/02/13
sqlite3 둘러보기  (0) 2009/02/02

파이썬에서 사용할 수 있는 BeautifulSoup을 이용해 xml 데이터를 sqlite3 DB에 넣는 툴을 만들는 간단한 예입니다.

1. BeautifulSoup 다운로드 및 설치
필요한 파일은 BeautifulSoup 사이트에서 다운로드 받으실 수있습니다. 파이썬 버젼이 2.*이면 3.0* 버젼을 3.*이면 3.1* 버젼중 최신버젼을 다운로드 받습니다. 다운로드가 완료되면 압축을 풀고 터미널에서 아래와 같이 setup.py를 실행합니다.

>python ./setup.py install

2. BeautifulSoup 사용예
1) 셈플 xml 파일 (test.xml)
테스트를 위해 간단히 작성해본 XML 입니다.
<?xml version='1.0' encoding='UTF-8'?>
<alcohol>
    <cate1 tt="술">
        <cate2 tt="소주">  
            <item>참이슬</item>
            <item>처음처럼</item>
            <item>잎새주</item>
        </cate2>   
        <cate2 tt='맥주'>  
            <item>카스</item>
            <item>라거</item>
            <item>하이트</item>
        </cate2>   
    </cate1>    
    <cate1 tt="안주">  
        <cate2 tt="고가">
            <item>회</item>
            <item>등심</item>
            <item>양곱창</item>
        </cate2>
        <cate2 tt="저가">
            <item>참치캔</item>
            <item>날계란</item>
            <item>새우깡</item>
        </cate2>
    </cate1>   
</alcohol>

2) 파이썬 소스파일 (con_data.py)
  1. #!/usr/bin/python
  2. #  -*- coding: utf-8 -*-
  3.  
  4. import sys
  5. import sqlite3
  6. from BeautifulSoup import BeautifulStoneSoup
  7.  
  8. argCount = len(sys.argv)
  9. if argCount is not 3:
  10.     print 'Usage:con_data.py [xml file] [db file]'
  11.     sys.exit(0)
  12.  
  13. xml_file = sys.argv[1]
  14. db_file = sys.argv[2]
  15.  
  16. #XML open
  17. src = open(xml_file)
  18. soup = BeautifulStoneSoup(src)
  19.  
  20. #DB & Table create
  21. db = sqlite3.connect(db_file)
  22. cursor = db.cursor()
  23.  
  24. cursor.execute("CREATE TABLE item(cate1, cate2, name)");
  25.  
  26. #Insert data
  27. for cate1 in soup.alcohol('cate1'):
  28.     query1 = 'INSERT INTO item VALUES("' + cate1['tt'] + '", "'
  29.     print 'CATE1: ' + cate1['tt']
  30.    
  31.     for cate2 in cate1('cate2'):
  32.         query2 = query1 + cate2['tt'] + '", "'
  33.         print   '\tcate2: ' + cate2['tt']
  34.      
  35.         for item in cate2('item'):
  36.             query3 = query2 + item.string + '")'
  37.             print '\t\t' + item.string
  38.  
  39.             cursor.execute(query3)
  40.     print "---------------------"
  41.  
  42. #Close
  43. cursor.close()
  44. db.commit()
  45. db.close()

3) 테스트
아래와 같이 실행하면 test.db가 생성되어 있음을 확인하실 수 있습니다.


해당 사이트에서 문서 페이지를 읽어 보시면 보다 세부적인 기능과 상세한 사용법을 확인하실 수  있습니다.  사용한 con_data.py외 test.xml은 압축하여 첨부하였습니다. 테스트 시에는 터미널에서 chmod +x ./con_data.py로 실행권한을 설정하셔야 합니다.


저작자 표시 비영리 변경 금지

여지껏 아이폰으로 잘 개발하고 있다가 오늘 Xcode를 실행해보니, 빌드가 안되는 것이었습니다. 빌드가 잘될 때랑 지금이랑 Xcode도 그렇고 아이폰도 그렇고 바뀐 것은 아무것도 없었습니다. 오거나이즈를 열어 보니 아래와 같은 메시지가 나타났습니다.


Provisioning과 Application 정보가 나와야 할 곳에 "Could not support developement"란 오류메시지가 보였습니다. "Xcode cannot find the software image to install this version"는 말그대로 Xcode가 인스톨할 새로운 OS 이미지가 없다는 것으로 이전부터 나온 메시지였습니다.

인터넷에서 검색을 해보기에 앞서 이전부터 뜬금없이 나오는 프로비저닝 오류에서도 리부팅을 하면 된적이 있어 리부팅을 해보았습니다. 결과는 성공이고 초록색불과 함께 정상적으로 기기를 사용할 수 있었습니다.

한번은 오거나이즈에서 "This device is not currently connected."란 메시지가 나왔습니다. 그때는 Xcode를 재실행하니까 되더군요. 우연인지 모르겠지만 터치로 개발할 때보다 아이폰으로 개발할 때 이런 일들이 더 자주 일어 나는 것 같습니다.

이유는 모릅니다만 "안되면 껐다 켜라"라는 컴퓨터 사용시의 진리가 아이폰과 터치에서도 통하는 것 같습니다.

저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

모토로이  (6) 2010/02/11
역시 그냥 껐다 키는 것이...  (8) 2009/09/24
아이폰 3GS  (2) 2009/09/17
블로그를 또 다시 이전했습니다.  (4) 2009/05/11
실버라이트2 동영상 재생 속도  (0) 2009/02/13
sqlite3 둘러보기  (0) 2009/02/02

기타 2009/09/17 11:23
일때문에 아이폰 3GS를 잠시 가지고 있게 되었습니다. 다들 아시다시피 터치와 다른점은 조금 더 두껍고 카메라가 달렸다는 것입니다. 어플리케이션은 전화, 메시지와  나침반 정도가 눈에 뜁니다.

제가 만든 사전을 돌려보니 터치 2세대에서는 검색시 약간의 멈춤이 있었는데 3GS에서는 멈춤없이 바로 실행되더군요. 정확한 스펙은 보지 않았지만 속도도 많이 빨라진 것 같습니다.

전화는 개통되지 않았기 때문에 화면의 버튼들만 눌러 보았습니다. 제가 그동안 블랙잭만 써서 그런지 번호를 누르기가 정말 편하게 되어 있는 것 같았습니다.

카메라와 동영상의 화질도 블로그에 올리는 등 웹상에서 사용하기에 전혀 무리가 없을 정도로 괜찮았습니다. 혐오스러운 사진일 수도 있겠지만 3GS를 들고 다니며 찍은 사진이 없어 이것으로 올려 봅니다.


제 개인 블로그에는 주로 먹고 마시는 소소한 일상들을 많이 올리고 있습니다. 주로 블랙잭으로 많이 찍어 화질이 조금 아쉬웠는데 이정도면 괜찮을 것 같다는 생각이 듭니다. 한달전쯤 집사람의 핸드폰이 고장났습니다. 9월 초 아이폰이 나온다는 소문이 있어서, 아이의 핸드폰을 사용하며 기다려 보다가 출시되면 같이 아이폰을 사기로 했습니다.

늘 그렇듯이 역시나 잘못된 소문이었네요. 집사람은 다른 핸드폰을 사고 전 계속 아이폰을 기다리고 있습니다. 아이폰 하나면 되는데 항상 블랙잭과 터치, 두개를 가지고 다니기 번거롭고 빨리 나와주었으면 좋겠는데, 늘 소문만 무성하네요. 애플의 아이폰 발매 국가 페이지의 Coming Soon에 나오기전까지는 잊고 살자고 했는데, 막상 실제 아이폰을 보니 가지고 싶은 마음에 또 조급해집니다.

저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

모토로이  (6) 2010/02/11
역시 그냥 껐다 키는 것이...  (8) 2009/09/24
아이폰 3GS  (2) 2009/09/17
블로그를 또 다시 이전했습니다.  (4) 2009/05/11
실버라이트2 동영상 재생 속도  (0) 2009/02/13
sqlite3 둘러보기  (0) 2009/02/02

sqlite3에서 csv(comma separated values) 포맷의 파일을 불러오고 내보내는 간단한 방법입니다.

1. Import
sqlite>.separator ,
sqlite>.import [csv 파일명] [테이블명]

또는 쉘상에서 아래와 같이 실행하여 입력할 수 있습니다.
$ sqlite3 -separator , [sqltie3 db 파일명] ".import [csv 파일명] [테이블명]"


2. Export
sqlite>.mode csv
sqlite>.output [csv 파일명]
sqlite>select * from [테이블명];
sqlite>.quit

* '[' 와 ']'는 입력하지 않습니다.
저작자 표시 비영리 변경 금지

python에서 sqlite3를 사용하는 샘플입니다. mysql등 다른 데이터베이스를 사용하는 방법과 동일하며 간단한 스크립트이기 때문에 보시면 쉽게 이해가 되실 것입니다.

#!/usr/bin/python
#  -*- coding: utf-8 -*-

import sqlite3

# DB 연결
db = sqlite3.connect("test.db")
cursor = db.cursor()

datas = [(1, "cheetah"), (2, "puma"), (3, "leopard")]

# 테이블 생성
cursor.execute("create table animal (no, name)")

# 데이터 INSERT
cursor.executemany("insert into animal values (?, ?)", datas)

# 최종 INSERT된 rowid 출력
print 'Last rowid: ' + str(cursor.lastrowid)
# Row count 출력
print 'Row count: ' + str(cursor.rowcount)

# 쿼리
cursor.execute("select * from animal")
for row in cursor:
    print row[1]

cursor.execute("update animal set name='jaguar' where no=3");

cursor.execute("select * from animal")
print cursor.fetchall()

cursor.execute("select * from animal where no=1")
row = cursor.fetchone()
print 'No 1 is ' + row[1];

# 종료
cursor.close()

db.commit()
db.close()

스크립트를 실행하면 아래와 같이 출력되는 것을 확인하실 수 있습니다.

저작자 표시 비영리 변경 금지

지인의 소개로 알게된 텍스트큐브 서비스로 옮겼다가 다시 티스토리로 돌아 오기로 했습니다. 왔다 갔다 해서 죄송합니다. 분위기도 한번 바꾸어 볼겸 구글에서 하는 서비스의 장점도 있을 것 같고해서 옮겼다가 몇시간도 안되어 돌아 왔습니다. 네임서버에서 cocoadev.co.kr를 다시 티스토리 서버로 변경하였습니다. 다시 돌아온 이유는 두가지입니다.

첫번째 이유는 티스토리에서 정이 많이 들은 것 같습니다. 블로거, 테터툴즈, 이글루스, 티스토리등 자주 옮겨 다녔던 개인블로그를 텍스트큐브로 옮겼을 때는 아무 감정이 없었습니다. 하지만 티스토리에서 시작해 지금까지 하고 있는 이 블로그는 좀 틀리네요. 비슷하긴 하지만 관리자 페이지를 몇번 들어가 본후 고향 생각이 났다고 할까요? 이 블로그가 있어야 할 곳은 티스토리다라는 생각이 들었습니다.

두번째 이유는 텍스트큐브에서 하는 우수 블로그 지원 이벤트 때문이었습니다. 제 블로그는 되지도 않을 뿐더러 지원도 하지 않았지만 왠지 들어가는 시점이 묘하기 때문입니다. 마치 상품에 눈이 멀어 블로그를 옮기는 모양새가 되어버리는 것 같습니다. 흔히 이야기하는 파워블로그를 유치할려는 목적이겠지만, 이런 이벤트는 자의적으로 옮길려는 사람들에겐 오히려 악재가 되는 것이 아닌가 하는 생각이 듭니다.

아무튼 잠시 가출 소동을 벌여 죄송합니다.

저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

역시 그냥 껐다 키는 것이...  (8) 2009/09/24
아이폰 3GS  (2) 2009/09/17
블로그를 또 다시 이전했습니다.  (4) 2009/05/11
실버라이트2 동영상 재생 속도  (0) 2009/02/13
sqlite3 둘러보기  (0) 2009/02/02
버그추적 시스템 Mantis 설치  (6) 2009/01/07

이 부분에 대해서 방법을 찾고 있는데 현재는 미디어 플레이어의 rate를 설정하는 것처럼 실버라이트2에선 재생 속도를 변경하는 방법이 없는 것 같습니다. 꽁수로 재생시간을 조금씩 더 해보았는데 자연스럽지 않고 소리가 끊기면서 나와 옛날 비디오의 빨리감기를 보는 정도까지만 가능했습니다. 아래는 관련부분 소스입니다.

static double TIMER_INTERVAL = 300;
static double MOVE_MSECONDS = 10000;
static int MOVE_FF = 1;
static int MOVE_RW = -1;

public Page()
{
   
    /** 타이머 설정 */
    timerStoryboard.BeginTime = TimeSpan.Zero;
    timerStoryboard.Duration = new Duration(TimeSpan.FromMilliseconds(TIMER_INTERVAL));
    timerStoryboard.Completed += new EventHandler(timerCompleted);
}

private void ChangeSpeed()
{
    if (playSpeed == 0)
        return;

    double currentPos = mediaPlayer.Position.TotalMilliseconds;
    double newPos = currentPos + (MOVE_MSECONDS * playSpeed);
    double maxPos = mediaPlayer.NaturalDuration.TimeSpan.TotalMilliseconds;
    double downloadPos = Math.Floor(mediaPlayer.DownloadProgress * maxPos);

    mediaPlayer.Pause();
    
    /* 유효범위 검사 */
    if (newPos >= 0 && newPos < downloadPos)
    {
        mediaPlayer.Position = TimeSpan.FromMilliseconds(newPos);
        mediaPlayer.Play();

        timerStoryboard.Begin();
    }
    else
    {
        playSpeed = 0;
    }
}

private void timerCompleted(object sender, EventArgs e)
{
    ChangeSpeed();
}

/** 뒤로보기 클릭 */
private void btnRewind_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    playSpeed = MOVE_RW;
    ChangeSpeed();
}

/** 빨리보기 클릭 */
private void btnFast_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    playSpeed = MOVE_FF;
    ChangeSpeed();
}

ChangeSpeed()에서 mediaPlayer.Pause()와 mediaPlayer.Play()를 하지않고 빨리보기를 하면  어느정도 괜찮게 보이지만 역시 소리 부분은 부드럽게 재생이 안되네요. Position을 다시 설정하는 부분에 부하가 있어 밀리세컨드 단위의 세세한 제어는 힘든 것 같습니다. 또한 Progressive Download가 아닌 Streaming일 경우에는 저 방법으로는 대책이 없습니다. 저만 방법을 모르고 삽질중이라는 불길한 예감도 듭니다. ㅠㅠ

저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

아이폰 3GS  (2) 2009/09/17
블로그를 또 다시 이전했습니다.  (4) 2009/05/11
실버라이트2 동영상 재생 속도  (0) 2009/02/13
sqlite3 둘러보기  (0) 2009/02/02
버그추적 시스템 Mantis 설치  (6) 2009/01/07
애플스크립트(AppleScript) 둘러보기  (4) 2009/01/06

기타 2009/02/02 14:03
iPhone SDK를 사용하면서 데이터베이스로는 내장된 sqlite3를 조금 사용해 보았습니다. ruby on rails나 이전에 조금 본적은 있지만, 실제로 사용하다 보니 기존의 일반적인인 데이터베이스에 비해 몇가지 재미있고 색다른 부분이 있는 것 같습니다.

1. 특징 & 둘러보기
1) ROWID
SQLite3의 테이블등은 생성시 기본적으로 rowid란 칼럼을 가지고 있습니다. auto increment되는 primary key와 같은 역활을 하지만 vacuum에 의해 변경될 수가 있다고 하니, 이런 용도로는 테이블의 특성에 맞게 사용해야 될 것 같습니다.


select *로는 rowid가 출력되지 않고 명시를 해주어야지 값을 확인할 수있습니다. 마지막으로 인서트된 항목의 rowid는 sqlite3_last_insert_rowid 함수의 반환값으로 확인할 수 있습니다.

2) 데이터 타입
타입이 컬럼에 일괄적으로 적용되는 다른 데이터베이스와는 달리 sqlite3는 각각의 로우별로 동적으로 타입이 결정됩니다. 그렇기 때문에 칼럼타입에 어떤 문자를 주던지 혹은 생략하더라도 테이블 생성이 가능합니다. 아래와 같이 테이블을 만든 후에 어떤 타입의 값들을 넣더라도 모두 저장이 가능합니다.


아래와 같이 각 컬럼의 값들에 따라 데이터타입이 결정됩니다.


한 컬럼에는 기본으로 1GB까지 저장이 가능하며 컴파일시에 SQLITE_MAX_LENGTH 값을 설정하여 2GB까지 가능합니다. 하지만 이전에 간단히 테스트를 해보았는데 OS X에서는 3MB 정도까지만 가능했습니다. 아마 애플에서 제한크기를 낮추어 설치하지 않았나 짐작을 하고 있습니다. 리눅스에서는 몇 백MB까지 인서트가 가능했습니다.

2. 기본 명령어
1) 시작
sqlite는 파일을 기반으로 한 컴팩트한 DB입니다. 대부분의 DB들이 파일을 기반으로 하지만 sqlite3는 데이터베이스 오픈시 인자로 파일을 받습니다.

> sqlite3 [file-name]
파일이 존재할 경우에는 기존 db파일을 열고 존재하지 않을 경우에는 새로 생성합니다. 쉘에서는 쿼리와 구별하여 명령어에 '.'이 접두사로 사용됩니다.

2) 종료
.quit 또는 .exit는 sqlite3를 종료하는 명령어입니다.
sqlite3>.quit
sqlite3>.exit

3) 도움말
sqlite3>.help
sqlite3 쉘에서 사용가능한 명령어들을 보여 줍니다.

4) 테이블 목록
sqlite3>.tables
현재 데이터베이스에 등록된 테이블들의 목록을 확인할 수 있습니다.

5) 스키마 정보
sqlite3>.schema [table-name]
지정된 테이블의 스키마를 확인할 수 있습니다. 테이블명을 입력하지 않으면 모든 테이블의 스키마가 출력됩니다. "ALTER TABLE"도 있는데 add와 rename만 가능한 것 같습니다.

6) 쿼리결과를 파일로 저장
sqlite3>.mode insert
sqlite3>.output db.sql
sqlite3>select * from mytable;
sqlite3>.quit
mode는 출력될 타입을 지정하며 csv, column, html, insert, line, list, tabs, tcl등으로 설정할 수 있습니다. output은 저장될 파일을 지정합니다. 위와 같이 실행 후 종료하면 mytable의 데이터들이 insert로된 sql문으로 db.sql 파일로 저장되어 있습니다.

7) 테이블 변경
sqlite3>alter table [table_name] rename to [new_table_name];
sqlite3>alter table [table_name] add [new_column_name];
alter는 테이블명의 변경과 테이블 컬럼의 추가만 가능한 것 같습니다.

8) vacuum
sqlite3>vacuum
데이터베이스의 테이블의 로우를 재정렬하고 delete, drop으로 인한 빈공간을 제거하는 최적화 작업을 수행합니다. insert, delete, drop등의 명령을 자주 수행하는 DB들은 정기적으로 vacuum을 실행해 주는 것이 좋습니다.

3. 자주 사용되는 C 함수
1) Open & Close
int sqlite3_open(const char *filename, sqlite3 **ppDb);
int sqlite3_close(sqlite3 *pDb);

sqlite3 데이터베이스 파일을 열고 닫는 함수 입니다.

사용 예)
sqlite3 *db;
NSString* path = @"./mydb.sqlite3";

if (sqlite3_open([path UTF8String], &db) != SQLITE_OK)
    NSLog(@"Fail to open sqlite3: %s", sqlite3_errmsg(db));
    sqlite3_close(db);
   
    return NULL;
}

2) 쿼리 실행
nt sqlite3_prepare_v2(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail);
int sqlite3_step(sqlite3_stmt* stmt);
int sqlite3_finalize(sqlite3_stmt *pStmt);

쿼리는 prepare -> step -> finalize의 단계로 실행되고 종료됩니다. prepare는 쿼리실행에 앞서 쿼리를 컴파일하여 바이트코드로 변경합니다. step은 prepare에서 준비된 코드를 실행하며 실행될때 마다 다음 데이터를 가지고 옵니다. finalize는 prepare와 쌍으로 할당된 sqlite3_stmt의 메모리를 해제합니다.

사용 예)
if (sqlite3_prepare_v2(prevDB, "SELECT * FROM cross_temp", -1, &statement, NULL) == SQLITE_OK) {
    while (sqlite3_step(statement) == SQLITE_ROW) {
        int pid = sqlite3_column_int(statement, 0);
        NSLog(@"pid %d", pid);
    }
}
sqlite3_finalize(statement);

3) 결과값
int sqlite3_column_int(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);

스텝에서 각 컬럼의 값들은 column_ 함수로 가져올 수 있습니다. 위는 int와 char*의 예이며 이외에도 각 타입에 맞는 함수들이 제공됩니다.

4) 쿼리 실행 - exec
int sqlite3_exec(sqlite3*, const char *sql, int (*callback)(void*,int,char**,char**), void *, char **errmsg);

exec은 위의 prepare, step, finalize를 동시에 실행하여 편리하게 사용할 수 있습니다. select와 같은 쿼리에서 각 단계의 데이터들은 콜백함수를 구현하여 처리할 수 있습니다.

사용 예)
if (sqlite3_exec(db, "SELECT * FROM item_info limit 10", setData, NULL, &error)) {
    NSLog(@"EXEC ERROR: %s", error);
    sqlite3_free(error);
}

콜백함수의 첫번째 인자는 sqlite3_exec의 4번째 인자에서 넘긴 사용자 데이터가 넘어 옵니다. cols는 전체 컬럼의 갯수이며 value, name에 각각 값과 컬럼명이 넘어 옵니다.
int setData(void* data,int cols, char** value, char** name) {

    for (int i = 0; i < cols; i++) {
        NSLog(@"%s, %s", value[i], name[i]);
    }
    return 0;
}


* 아이폰에서 쓰기 가능한 DB
어플리케이션은 실행시에 번들 내부의 파일에는 쓰기 권한이 없습니다. 그렇기 때문에 번들 내부에 있는 sqlite3 파일은 insert, update, delete와 같은 DB를 변경하는 쿼리가 실행되지 않습니다.

이를 해결하기 위해서는 Documents 디렉토리로 DB파일을 복사하고 이곳의 파일로 열어야 쓰기가 가능합니다. 애플의 아이폰 개발자 센터에 있는 SQLiteBooks 샘플에서 AppDelegate.m의 createEditableCopyOfDatabaseIfNeeded 메소드를 확인하시면 구현에 대해서 잘 나와있습니다. 그리고 아이폰에서 sqlite3 구현에 대한 간단한 내용은 이전 아이폰 SQLite3 샘플이란 포스팅에서 확인하실 수 있습니다.
저작자 표시 비영리 변경 금지

맨티스 1.1.1 버젼을 사용하다가 이번에 1.1.6 버젼으로 업그레이드를 했습니다. ChangeLog를 살펴보니 1년동안 업그레이드를 착실히 해온 것 같습니다. 새로운 버젼을 설치 하면서 과정과 사용법을 간단히 정리해 보았습니다.

맨티스 설치사양은 아래와 같습니다.

  • MySQL 4.1.1 이상
  • PHP 4.3.0 이상
  • 아파치, IIS등의 웹서버

1. 다운로드 및 설치
1) 다운로드
맨티스 다운로드 페이지나 혹은 프롬프트 상태에서 아래와 같이 맨티스 설치 파일을 다운로드 받은 후에 압축을 풉니다.
 
> wget http://downloads.sourceforge.net/mantisbt/mantisbt-1.1.6.tar.gz?modtime=1228833846&big_mirror=0
> tar xvzf mantisbt-1.1.6.tar.gz

2) 링크
mantis로 접근하기 위해 압축이 풀린 디렉토리에 심볼릭링크를 걸어줍니다.

> ln -s ./mantisbt-1.1.6 mantis

3) 설치
웹브라우져에서 http://[YOUR-DOMAIN]/mantis/admin/install.php를 실행하여 설치를 시작합니다. 먼저 아래와 같은 첫화면에서 DB 접속정보를 입력합니다.


MySQL 관리자 권한이 있는 계정을 'Admin Username'과 'Admin Password' 필드에 입력하시면 설정한대로 Database와 계정을 생성합니다. 입력을 완료한 후에 'Install/Upgrade Database' 버튼을 클릭합니다.

다음단계에서는 'Write Configuration File(s)'에 오류가 발생합니다. 이는 mantis 루트에 config_inc.php 파일을 생성할 권한이 없어서 입니다. 아래의 작업으로 해결할 수 있습니다.

4) config_inc.php 설정
기존 샘플 파일(config_inc.php.sample)을 아래와 같이 복사합니다.

> mv config_inc.php.sample ./config_inc.php

config_inc.php 파일을 열어 오류메시지에 있는 내용대로 아래와 같이 DB를 설정합니다.
$g_hostname = 'localhost';
$g_db_type = 'mysql';
$g_database_name = 'bugtracker';
$g_db_username = '[USER-NAME]';
$g_db_password = '[USER-PASSWORD]';

기본 메일계정을 설정합니다.
# --- email variables -------------
$g_administrator_email  = 'admin@YOUR-DOMAIN';
$g_webmaster_email      = 'admin@YOUR-DOMAIN';

# the "From: " field in emails
$g_from_email           = 'noreply@YOUR-DOMAIN';

# the return address for bounced mail
$g_return_path_email    = 'admin@YOUR-DOMAIN';

기본으로 한글사용을 위해 아래와 같이 추가합니다.
$g_default_language = "korean";

* admin 디렉토리 삭제
마지막으로 ./admin 디렉토리를 삭제합니다. admin 디렉토리는 초기설치와 관련된 파일들이 위치해 있어 설치후에는 필요가 없이 권한없이 접근할 수 있기 때문에 삭제합니다. 삭제하지 않으면 로그인 화면에서 오류가 표시됩니다.

> rm -dfr ./admin/

5) 로그인
웹브라우져에서 http://YOUR-DOMAIN/mantis 로 들어 갑니다. 아래와 같이 맨티스 사이트가 나오면 오류없이 설치된 것 입니다.

관리자 아이디인 'administrator'와 초기 기본 패스워드인 'root'를 입력하고 로그인 합니다. 관리자 패스워드는 계정관리로 들어가 반드시 변경해야 합니다.

2. 사용자 계정
'관리/사용자 관리' 메뉴로 들어가 '계정생성' 버튼을 클릭하여 사용자를 추가합니다. 계정 생성후에 상세한 옵션이나 권한을 설정할 수 있습니다.


이메일로 계정등록이 발송되기 때문에 이메일 주소를 정확히 입력하셔야 합니다. 테스트를 하여보니 제 서버에서는 이메일이 발송 되지 않았습니다. 

* 이메일 발송 오류
맨티스 루트디렉토리에 있는 config_defaults_inc.php에서 아래의 g_phpMailer_method를 0으로설정되어 있던 것을 아래와 같이 1로 변경하였더니 이메일이 정상적으로 발송되었습니다.

# select the method to mail by:
# 0 - mail()
# 1 - sendmail
# 2 - SMTP
$g_phpMailer_method     = 1;
 
같은서버에 있던 이전 버젼은 0으로 mail()을 사용해도 발송되었는데 이번 버젼에 문제가 있는 것인지 다른 문제가 있는 것인지 모르겠습니다. 저는 0일 경우에는 발송이 안되고 1과 2일 경우에는 발송이 되었습니다.

3. 프로젝트
1) 프로젝트 생성
'관리/프로젝트 관리' 메뉴로 들어가 새로운 프로젝트를 생성합니다. 역시 등록 후에 아래와 같은 상세한 설정을 할 수 있습니다.


2) 서브 프로젝트
연관된 서브프로젝트를 생성하고 관리할 수 있습니다.

3) 버젼
버젼을 등록하고 관리합니다.

3) 분류
이슈등록시 지정할 분류를 관리합니다.

4) 사용자
프로젝트에 관련된 사용자를 추가하고 권한을 설정할 수 있습니다.


4. 이슈 등록 및 확인
1) 사용자 등록
사용자 계정(testID)로 로그인하여 '이슈보고하기' 메뉴를 클릭합니다. 해당 프로젝트를 선택하고 버튼을 클릭하여 필드를 입력하고 등록합니다.


아래는 등록된 이슈목록입니다.

2) 관리자 확인
다시 관리자로 로그인 하면 메인화면에서 새로운 이벤트를 확인할 수 있습니다. 할당되지 않은 이슈에는 담당자를 할당하거나 바로 처리할 수 있습니다.


5. 기타
1) 위키
위키설정은 사실 큰 의미는 없습니다. config_default_inc.php파일에서 g_wiki_enable 속성을 ON으로 하면 메뉴에서 wiki의 링크가 추가됩니다.

#####################
# Wiki Integration
#####################
 
 # Wiki Integration Enabled?
 $g_wiki_enable = ON;

 # Wiki Engine (supported engines: 'dokuwiki', 'mediawiki', 'xwiki')
 $g_wiki_engine = 'dokuwiki';

 # Wiki namespace to be used as root for all pages relating to this mantis installation.
 $g_wiki_root_namespace = 'mantis';

 # URL under which the wiki engine is hosted.  Must be on the same server.
 $g_wiki_engine_url = $t_protocol . '://' . $t_host . '/%wiki_engine%/';

2) 사용자화
웹에서 관리 메뉴와 config_default_inc.php 파일을 변경하여 용도에 맞게 변경할 수 있습니다.

* 커스텀 필드 등록
아래와 같이 사용자 필드를 등록할 수 있습니다. 이외에 권한등 다양한 옵션이 있습니다.

등록된 필드를 프로젝트에 링크하며 해당 프로젝트의 이슈 등록시 사용자 등록필드가 출력됩니다.

* 디자인 변경
core 디렉토리의 html_api.php의 함수들을 수정하여 페이지마다 공통적인 top, bottom과 그외 다른 디자인을 변경할 수 있습니다.

이외에도 공지사항, 문서관리등과 함께 편리하게 이용할 수 있는 기능들이 많이 있습니다. 장단점이 있지만 개인적으로는 Trac보다는 Mantis가 편한 것 같습니다.

저작자 표시 비영리 변경 금지

그동안 OS X와 Xcode를 사용하면서 애플스크립트(AppleScript)란 단어를 간혹 들어 보고 샘플 코드를 본적은 있지만 실제 사용해 본적은 없었습니다. 코코아와 Objective-C를 둘러 보기도 벅찬데 애플스크립트까지 볼 여유가 안나서 차일피일 미루고 있었던 것 같습니다.

하지만 아무래도 맥을 잘 사용하고 어플리케이션을 효율적으로 만들기 위해서는 애플스크립트를 알고 있어야 할 것 같아 간단히 살펴 보았습니다. 아래는 애플스크립트 Example 폴더에 있는 'Finder Windows - Hide All'이란 샘플코드입니다.
보시다시피 프로그래밍 언어라기 보다는 일반 영어문장에 더 가까운 것 같습니다. 애플스크립트를 지원하는 여러 어플리케이션들의 기능과 조합하여 사용하면 다양한 작업을 할 수 있습니다. 이전까지는 그냥 쉘스크립트에서 확장된 언어인줄만 알았는데, 쉽고 재미있는 문법과 함께 편리하게 맥을 사용하고 개발을 할 수 있는 막강한 기능을 가지고 있는 것 같습니다.

 
1. 스크립트 편집기
애플스크립트를 작성하기 위해서는 스크립트 편집기를 사용합니다. 위치는 응용프로그램 / AppleScript 폴더 내에 있습니다. 이 폴더내의 Example Scripts를 보시면 각종 예제들을 확인하실 수 있습니다. 스크립트 편집기를 실행하면 아래와 같이 스크립트 편집기가 오픈됩니다.


1) 사전
애플스크립트의 장점은 애플과 다른 서드파티의 OS X 어플리케이션에서 제공하는 애플스크립트 지원기능을 사용하여 편리하게 어플리케이션을 조작할 수 있다는 것입니다. 지원하는 어플리케이션과 기능은 스크립트 에디터의 사전 목록에서 확인하실 수 있습니다. 스크립트 에디터의 메뉴에서 '파일/사전열기'를 클릭하거나 단축키(Command + Shift + O)을 입력합니다.
해당 어플리케이션을 더블클릭하면 속성과 기능들을 아래와 같이 확인하실 수 있습니다. 클릭하면 포함된 속성과 명령어들이 나오며 하단에서 항목에 대한 간단한 설명을 보실 수 있습니다. 

2) 코드 자동입력
스크립트 에디터에서 마우스 우클릭을 하면 아래와 같이 항목별로 자주 사용되는 코드들이 나열되어 있습니다. 필요한 항목을 선택하면 자동으로 에디터에 입력됩니다.

아래는 Tell Blocks의 Tell "Finder"를 클릭후에 자동으로 생성된 코드입니다.
tell application "Finder"
    -- insert actions here
end tell

3) 기록
스크립트 에디터의 툴바를 보면 '기록'이란 버튼이 있습니다. 기록은 지원하는 어플리케이션일 경우 사용자의 동작을 자동으로 스크립트로 변환해 주는 기능입니다. 사용방법은 '기록' 버튼을 클릭하고 해당 어플리케이션에서 스크립트로 생성될 행동을 하고 완료 후에는 '중단' 버튼을 클릭합니다.

아래는 파인더에서 어플리케이션 폴더를 열고 스크립트 에디터를 실행하는 과정이 스크립트로 자동으로 기록된 내용입니다. 
tell application "Finder"
    activate
    set target of Finder window 1 to folder "Applications" of startup disk
    set target of Finder window 1 to folder "AppleScript" of folder "Applications" of startup disk
    open application file "Script Editor.app" of folder "AppleScript" of folder "Applications" of startup disk
end tell

자동으로 소스코드를 생성해주는 것도 편하지만 문법을 잘 모를 경우에 이 '기록' 기능을 이용하여 확인하면 편리할 것 같습니다.


2. 예제
1) Hello World!
간단히 다이알로그박스를 열고 Hello World를 읽어주는 스크립트를 작성해 보겠습니다. 아래의 내용을 스크립트 에디터 상단의 편집창에 입력하고 컴파일 버튼을 클릭합니다.

display dialog "Hellow World!" buttons {"닫기", "말하기"} default button "말하기"
if the button returned of the result is "말하기" then
    say "Hellow World"
end if

컴파일전에는 보라색으로 소스가 출력되지만 오류가 없이 컴파일이 완료되면 아래와 같이 문법이 컬러링 되어 출력됩니다.

이제 스크립트 에디터의 실행버튼을 클릭하면 아래와 같이 다이알로그박스가 열리며, 우측의 말하기 버튼을 클릭하면 Hello World 음성이 출력됩니다.

2) 새 메시지
메일에서 새로운 메시지를 작성하는 간단한 애플스크립트를 작성해 보겠습니다. outgoing messqage의 subject, content, visible 프로퍼티를 설정하여 메일의 새로운 메시지 창을 오픈하는 스크립트 입니다.
(*
아래의 내용으로 새로운 메일을 생성합니다.

제목: 안녕하세요?
내용: 반갑습니다.
수신: zzerrrrr@gmail.com
*)
tell application "Mail"
    -- 새로운 메일 생성
    set newMessage to make new outgoing message with properties {subject:"안녕하세요?", content:"반갑습니다", visible:true}
   
    -- 수신자를 설정한다   
    tell newMessage
        make new to recipient with properties {name:"zzerr", address:"zzerrrrr@gmail.com"}
    end tell
   
    activate
end tell

* 주석
주석은 (*로 시작하여 *)로 종료됩니다. 다른 언어의 '/* */' 방식과 동일합니다. 한줄 주석은 '--'를 앞에 붙여 사용합니다.

* tell 
tell은 메시지를 수신할 해당 객체를 지정합니다. 각 구문은 'tell'로 시작하여 'end tell'로 종료합니다. tell application "Mail"은 메일 어플리케이션에 메시지를 발송한다는 의미입니다.

* set ~ to ~ 
객체에 값을 설정합니다. set A to B는 말 그대로 A를 B로 설정한다는 의미입니다.
 
* with properties {name:value, ...}
생성된 오브젝트 속성들의 값을 지정합니다.

실행버튼을 클릭하면 아래와 같이 스크립트에서 지정한 속성으로 새로운 메시지를 보내는 창이 오픈됩니다. 

3. 기타
1) 실행파일로 저장
스크립트 편집기의 메뉴에서 파일/별도저장을 클릭하면 아래와 같이 몇가지 파일포맷을 지정하여 저장할 수 있습니다.


파일포맷중 응용 프로그램이나 응용 프로그램 번들로 저장하면 스크립트 에디터 없이 바로 실행할 수 있는 실행파일로 저장할 수 있습니다.

2) 참고 자 및 사이트
저도 잠시 사용해보고 글을 올리는 것이라 부정확하고 틀린 내용이 많이 있을 것 같습니다. 자세하고 정확한 내용은 아래의 관련 문서와 사이트들을 참조하시기 바랍니다.

저작자 표시 비영리 변경 금지

안드로이드 개발환경을 조금 더 살펴 볼려고 간단히 어플리케이션을 만들어 보았습니다. 처음 대쉬보드 바이오리듬을 시작한뒤로 바이오리듬을 너무 우려먹고 있는 것 같습니다. SDK의 설치나 사용방법은 이전에 포스팅한 구글 Android 개발환경 둘러 보기를 참조하시면 좋을 것 같습니다. 아래의 이미지는 에뮬레이터에서 실행한 모습입니다.


요즘 개발환경으로는 드물게 마우스 사용없이 GUI를 구현해야 하지만 레이아웃을 편집하면서 확인할 수 있으니 큰 불편은 없는 것 같습니다. 아래는 사용한 소스들과 간단한 설명입니다. 이클립스에서 안드로이드 프로젝트로 Biorhythm을 생성하고 각각의 소스를 아래와 같이 수정하시고, BioView.java를 추가하시면 위와 같이 실행해 보실 수 있습니다.

* Biorhythm.java
package com.zzerr;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class Biorhythm extends Activity {
    private BioView bioView;
    private EditText inputYear, inputMonth, inputDay;
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        setContentView(R.layout.main);
       
        bioView = (BioView)findViewById(R.id.myView);
       
        inputYear = (EditText)findViewById(R.id.inputYear);
        inputMonth = (EditText)findViewById(R.id.inputMonth);
        inputDay = (EditText)findViewById(R.id.inputDay);
       
        /** 버튼이 클릭되었을 경우 바이오리듬 출력 */
        Button button = (Button)findViewById(R.id.showButton);
        button.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                bioView.setBirthDay(Integer.parseInt(inputYear.getText().toString()),
                        Integer.parseInt(inputMonth.getText().toString()),
                        Integer.parseInt(inputDay.getText().toString()));
               
                bioView.invalidate();
            }
        });
    }
}


* BioView.java
View 클래스에서 상속 받아 main.xml에서 정의한 myView를 서브클래싱하는 클래스입니다. 바이오리듬을 계산한 후에 출력을 합니다.
package com.zzerr;

import android.view.View;
import android.content.Context;
import android.util.AttributeSet;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;

import java.util.Date;

public class BioView extends View {
    /** 상수 */
    private static final int mMaxDays = 30;
    private static final int mMaxType = 3;
    private static final long mTDV = (60*60*24*1000);
    private static final double mPI = 3.14159;
   
    private static final double mBioValues[] = { 23.0, 28.0, 33.0 };
    private static final int mColors[] = { 0xff0000ff, 0xffff00ff, 0xff00ffff };
   
    /** 멤버변수 */
    private Paint mPaint;
    private Rect mRect;
    private double mStartDays;
    private Date mBirthDate, mTodayDate;
       
    public BioView(Context context, AttributeSet attrs) {
        super(context, attrs);
       
        mRect = new Rect();
        mPaint = new Paint();
       
        mRect.top = 0;
        mRect.bottom = getWidth();
        mRect.left = 0;
        mRect.right = getHeight();

        mTodayDate = new Date();
        Date startDate = new Date(mTodayDate.getYear(), mTodayDate.getMonth(), 1);
       
        mStartDays = startDate.getTime()/mTDV;
        mBirthDate = new Date();
       
        mBirthDate.setYear(0);
    }
   
    public void setBirthDay(int year, int month, int day) {
        mBirthDate.setYear(year);
        mBirthDate.setMonth(month);
        mBirthDate.setDate(day);
    }

   @Override
   protected void onDraw(Canvas canvas) {
        int cellWidth = getWidth()/mMaxDays;
       
        mRect.top = 0;
        mRect.bottom = getWidth();
        mRect.left = 0;
        mRect.right = getHeight();
       
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(0xFFFFFFFF);

        int x = 0, y = 0, oldY = 0;
         
        // 세로줄 출력
        for (int i = 0; i <= mMaxDays; i++) {
            x += cellWidth;
            canvas.drawLine(x, mRect.top, x, mRect.bottom, mPaint);
        }
         
        // 가로줄 출력
        canvas.drawLine(0, mRect.bottom/2, mRect.right, mRect.bottom/2, mPaint);
      
        // 오늘 날짜 출력
        mPaint.setColor(0xFFFFFF00);
        x = cellWidth * mTodayDate.getDate();
        canvas.drawLine(x, mRect.top, x, mRect.bottom, mPaint);
              
        // 바이오리듬 출력
        if (mBirthDate.getYear() != 0) {
            Log.e("LOG", "year:" + mBirthDate.getYear() +
                    "month:" + mBirthDate.getMonth() +
                    "day:" + mBirthDate.getDate());
           
            double startDays = mStartDays;
            double birthDays = mBirthDate.getTime()/mTDV;
                 
            for (int k = 0; k < mMaxType; k++) {
                x = 0;
             
                mPaint.setColor(mColors[k]);
             
                for (int i = 0; i <= mMaxDays; i++) {
                    double gab = birthDays - startDays;
                    double p = (int)(Math.sin((gab/mBioValues[k]) * 2.0 * mPI) * 100.0);
   
                    y = mRect.bottom/2 + (int)(p * ((mRect.bottom/2.0)/100.0));
                   
                    if (i != 0)
                        canvas.drawLine(x, oldY, x + cellWidth, y, mPaint);
                   
                    oldY = y;
                    startDays++;
                    x += cellWidth;
                }
            }
        }
        
        super.onDraw(canvas);
    }
}

* main.xml
GUI를 정의하는 곳입니다. 이곳에서의 수정은 아래의 R.java의 R 클래스에 자동으로 적용이 됩니다. com.zzerr.BioView와 같이 사용자 클래스도 정의하여 사용할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#666666"
    >

<com.zzerr.BioView android:id="@+id/myView"
    android:layout_width="fill_parent"
    android:layout_height="330px"
    android:background="#000000"
    />
   
<TextView android:id="@+id/helpLabel"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/myView"
    android:layout_marginTop="20px"
    android:text="생년월일을 입력후에 보기버튼을 클릭해 주세요."
    />

<EditText android:id="@+id/inputYear"
    android:layout_width="80px"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:text=""
    />

<EditText android:id="@+id/inputMonth"
    android:layout_width="60px"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/inputYear"
    android:layout_alignTop="@id/inputYear"
    android:text=""
    />

<EditText android:id="@+id/inputDay"
    android:layout_width="60px"
    android:layout_height="wrap_content"
    android:layout_below="@id/myView"
    android:layout_toRightOf="@id/inputMonth"
    android:layout_alignTop="@id/inputMonth"
    android:text=""
    />
       
<Button android:id="@+id/showButton"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentRight="true"
     android:layout_marginLeft="10px"
     android:layout_toRightOf="@id/inputDay"
     android:layout_alignTop="@id/inputDay"
     android:text="보기"
     />

</RelativeLayout>

* R.java
주석에 설명되어 있는 것과 같이 자동으로 생성해 주는 파일입니다. main.xml을 편집하면 자동으로 그에 맞게 내용이 변경됩니다.
/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.zzerr;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int helpLabel=0x7f050001;
        public static final int inputDay=0x7f050004;
        public static final int inputMonth=0x7f050003;
        public static final int inputYear=0x7f050002;
        public static final int myView=0x7f050000;
        public static final int showButton=0x7f050005;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}

Xcode와 Objective-C를 사용하는 아이폰 개발과는 달리 많은 개발자들에게 익숙한 이클립스와 Java를 사용하고, 윈도우 PC에서도 개발이 가능하니 시작하기는 더 쉬울 것 같다는 생각이 듭니다. 개발자 등록도 25달러로 더 저렴하고요. ^^
저작자 표시 비영리 변경 금지

이번 장에서는 어느 페이지로 이동하던지 사이트 전체에서 상단과 하단의 내용을 동일하게 유지하기 위해, 사이트의 기본 레이아웃을 설정해 보겠습니다.   

1. 레이아웃 설정
어플리케이션 루트폴더에서 레이아웃 폴더(/app/views/layouts)로 이동합니다.

1) general.html.erb 생성
기본 레이아웃인 general.html.erb 파일을 작성합니다. ApplicationController에서 layout을 이 파일로 지정함으로써 모든 페이지에 적용되어 사용할 수 있습니다.

* general.html.erb
<%= render :partial => "layouts/header" %>
<%= @content_for_layout %>
<%= render :partial => "layouts/footer" %>

여기서는 공용으로 사용되는 헤더와 푸터를 출력하고 그 사이에 해당 View의 컨텐츠를 출력합니다. erb 파일에서는 "<%"와  "%>"내에서 eRuby 문법을 사용할 수 있습니다. "<%="는 해당 내용을 출력합니다.

<%= render :partial => "layouts/header" %>
partial의 layouts/header는 app/views/layouts 폴더에서 이름에 밑줄을 붙인 _header.html.erb 파일의 내용을 출력합니다.


2) _header.html.erb 생성
상단에 공통으로 보여질 헤더 템플릿입니다.

* _header.html.erb
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ko">
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<META http-equiv="Pragma" content="no-cache">
    <title>:: 내 ROR 홈페이지</title>
    <%= stylesheet_link_tag 'default' %>
    <%= javascript_include_tag :defaults %>
</head>
<body>
<h1 id="site-title">내 ROR 홈페이지</h1>
<ul id="main-menu">
    <li>소개</li>
    <li>앨범</li>
    <li>게시판</li>
</ul>
<div id="contents-body">

타이틀과 메타태그와 기본 스타일시트와 자바스크립트의 링크를 지정하고 상단에서 항상 출력할 사이트 제목과 메뉴목록을 지정합니다.

<%= stylesheet_link_tag 'default' %>
/public/stylesheets의 default.css 파일을 스타일시트의 링크를 생성합니다.

<%= javascript_include_tag :defaults %>
/public/javascripts에는 레일즈가 생성해 놓은 기본으로 사용하는 자바스크립트 파일들이 있습니다. 위의 설정으로 모든 기본 자바스크립트의 링크가 생성됩니다.


3) _footer.html.erb 생성
페이지의 하단에서 공통적으로 출력될 내용입니다. 여기서는 간단한 인사말만 출력해 봅니다.

* _footer.html.erb
</div>
<div id='footer'>반갑습니다. 여기는 제 홈페이지입니다.</div>
</body>
</html>


4) 레이아웃 지정
app/controllers/application.rb을 열어 아래와 같이 layout 'general'을 추가하여, 위에서 작성한 general 템플릿 파일을 기본 레이아웃으로 지정합니다.

* ApplicationController.rb
class ApplicationController < ActionController::Base
  layout 'general'
  helper :all # include all helpers, all the time

  protect_from_forgery # :secret => 'ccc2786e4f2c9f0b9fd22843cd5fc608'
end


5) 확인
리로드를 하여 현재까지의 작업을 확인합니다.


2. public 폴더 작업
위에서 기본 레이아웃을 위한 템플릿 파일들을 만들어 보았습니다. 이제 스타일시트를 작성해 보겠습니다.
 
1) 자바스크립트
public 폴더의 javascripts 폴더에는 기본적인 자바스크립트 파일들이 ROR에 의해서 생성되어 있습니다. 빈 application.js와 프로토타입, 스크립타큘러스의 js 파일들이 있습니다. 이 파일들은 erb에서 'javascript_include_tag :defaults'를 사용하여 간편하게 모든 자바스크립트 파일들을 링크할 수 있습니다.

* 프로토타입
프로토타입은 1.6.0.1버젼입니다. 최신버젼은 1.6.0.3이며 필요하시면 해당사이트에서 최신버젼을 다운로드 받아 교체할 수 있습니다.

* 스크립타큘러스
기본적인 controls.js, dragdrop.js, effects.js 파일이 설치되며, 몇가지 파일들은 빠져 있습니다. 필요하시면 해당사이트에서 최신버젼을 다운로드 받아 설치할 수 있습니다. 다운로드 받은 후에 압축을 풀고 test 폴더를 웹에서 확인하시면 쉽게 사용방법을 익힐 수 있습니다. 


2) 스타일시트 작성
public 폴더의 stylesheet 폴더에서 기본 레이아웃으로 사용할 default.css를 아래와 같이 또는 변경하여 작성합니다.

* default.css
body {
    padding:10px;
    color:#3f3f3f;
    font-size:10pt;
    font-family:돋움, Gulim, Arial, sans-serif;
}

#site-title {
    color:#64A8C3;
}

#main-menu {
    float:left;
    padding:0;
}

#main-menu li {
    float:left;
    font-size:1.2em;
    font-weight:bold;
    list-style:none;
    margin-right:12px;
}

#contents-body {
    clear:both;
    width:600px;
    margin:20px 0;
    padding:10px;
    border:2px dotted #efefef;
    background-color:#f5f5f5;
}

#footer {
    width:600px;
    text-align:center;
}

3) 확인
이제 리로드를 하여 지금까지의 작업을 확인합니다.

 
사진을 올릴 수 있는 앨범과 간단한 게시판을 하나 만들어 보고 삽질기를 끝낸 후에, 실무 프로젝트에 도입을 해볼려고 합니다. 구현방법이나 용어등에 모두 자신이 없네요. 역시나 많은 지도편달 부탁 드립니다.
저작자 표시 비영리 변경 금지

구글이 안드로이드 플랫폼 소스를 공개하였습니다. 플랫폼 전체 를 오픈소스로 만들어 버리는 것을 보면 과연 구글이라는 생각이 듭니다. 좌측은 안드로이드 캐릭터의 오픈소스 버젼입니다. 뚜껑을 열어 머릿속을 훤히 보여 주고 있습니다. ^^

다운로드 받아 볼까 했는데 파일크기가 2.1GB이고 6GB의 공간이 필요하기 때문에 다음 기회로 미루었습니다. '설치를 위해서는 Linux 또는 OS X가 필요하고 윈도우즈는 아직 지원하지 않는다'는 흔히 볼 수 없는 문구도 재미있습니다. 

이와 함께 안드로이드 개발자 블로그를 보면 Android Market: Now available for users란 제목으로 애플의 앱스토어와 유사한 어플리케이션 마켓을 런칭했다는 포스팅이 올라왔습니다. 현재까지는 50개의 어플리케이션이 올라와 있고 10월 27일 부터는 일반 개발자들도 어플리케이션을 등록할 수 있다고 합니다.

흥미로운 것은 개발자들에게 70%의 수익이 돌아 가는 부분은 애플의 앱스토어와 같지만, 나머지 30%에서도 구글은 수익을 가지고 가지 않는다고 합니다. 아무리 구글의 모토가 "Don't be evil"이지만 어지간히 통 큰 기업이 아닐 수 없네요.

개발자는 쉽게 유통시킬 수 있고 사용자는 경쟁적인 저렴한 가격에 소프트웨어를 구입할 수 있으니, SDK를 제공하고 온라인 상점을 이용해 개발자와 사용자를 직접 이어주는 이런 서비스가 많이 생기는 것은 양쪽 모두가 반길만한 일이라고 생각됩니다. 요즘 경제위기와 함께 IT의 빙하기가 도래한 우리나라 개발자들에게는 더 반가운 소식일 것 같습니다.

아이폰을 기다리다 지쳐 아이팟을 구입했는데, 문득 잘 한 것 같다는 생각이 듭니다. 휴대폰은 구글폰으로 구입해서 구글폰과 아이폰을 같이 가지고 다니면 심심할 일이 별로 없을 것 같습니다.
저작자 표시 비영리 변경 금지

이전에 생성한 어플리케이션을 브라우져에서 확인해 보기위해 웹서버를 구동합니다. 어플리케이션 폴더에서 아래와 같이 실행합니다.

> script/server

레일즈의 웹서버는 일반적으로 3000 포트를 사용하기 때문에 "URL:3000/"과 같이 주소창에 입력하셔야 합니다. 브라우져에서 Rails의 기본페이지가 보이며, 아래와 같이 해야할 작업들이 나와 있습니다.

1. Use script/generate to create your models and controllers
To see all available options, run it without parameters.

2. Set up a default route and remove or rename this file
Routes are set up in config/routes.rb.

3. Create your database
Run rake db:migrate to create your database. If you're not using SQLite (the default), edit config/database.yml with your username and password.

위에서 지시하는대로 작업을 해보겠습니다.

1. Home 컨트롤러 생성
1) HomeController 를 생성
script내의 generate는 이름 그대로 레일즈에서 컨트롤러, 모델, 스케폴드등을 간편하게 생성할 수 있게 합니다. 시작 페이지를 만들기 위해 아래와 같이 index 뷰를 가진 home 컨트롤러를 생성합니다.

> script/generate controller Home index
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/home
      exists  test/functional/
      create  app/controllers/home_controller.rb
      create  test/functional/home_controller_test.rb
      create  app/helpers/home_helper.rb
      create  app/views/home/index.html.erb

실행이 되면 위와 같이 생성되는 디렉토리와 파일들을 확인할 수 있습니다. app/controllers 디렉토리에서 home_controller.rb가 아래와 같이 생성되어 있습니다.

class HomeController < ApplicationController
  def index
  end

end

2) index.html 삭제
public 디렉토리 아래의 index.html을 삭제합니다. index.html이 존재하면 아래에서 작업할 routes.rb에서의 설정이 무효화됩니다.

> rm public/index.html


2. routes.rb 설정
config 디렉토리 아래의 routes.rb 파일을 오픈합니다. 주석으로 처리된 부분을 제외하면 아래와 같습니다. map.root를 home 컨트롤러로 설정하도록 푸른색으로 된 부분을 추가합니다.

ActionController::Routing::Routes.draw do |map|
  map.root :controller => "home"
  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
end

이제 웹 루트('/') 요청을 받게 되면 /home/index로 연결됩니다.

3. 데이터 베이스 설정

1) 데이터베이스, 계정 생성
mysql에서 개발, 테스트, 배포에 필요한 데이터베이스와 계정을 생성합니다.

mysql> create database www_development;
mysql> create database www_test;
mysql> create database www;
mysql> grant all privileges on www_development.* to www_user@'localhost'  identified by '1111';
mysql> grant all privileges on www_test.* to www_user@'localhost'  identified by '1111';
mysql> grant all privileges on www.* to www_user@'localhost'  identified by '1111';

2) database.yml 수정
이제 config 폴더 밑의 database.yml을 오픈하여 위에서 생성한 정보로 변경합니다.

development:
  adapter: mysql
  encoding: utf8
  database: www_development
  username: www_user
  password: 1111
  socket: /tmp/mysql.sock

test:
  adapter: mysql
  encoding: utf8
  database: www_test
  username: www_user
  password: 1111
  socket: /tmp/mysql.sock

production:
  adapter: mysql
  encoding: utf8
  database: www
  username: www_user
  password: 1111
  socket: /tmp/mysql.sock

위의 파일에서 주석으로 되어 있는 부분을 보면 테스트를 위한 데이터베이스는 테스트 실행시 디비를 초기화 하기 때문에 개발과 배포를 위한 데이터베이스는 별도로 만들어야 한다고 경고하고 있습니다.

4. index.html.erb 파일
1) erb
index.html.erb 파일은 HTML과 eRuby 문법을 같이 사용할 수 있는 템플릿 파일입니다. eRuby는 템플릿 파일에서 사용할 수 있는 루비입니다. '<%' 와 '%>'의 사이에서 루비코드를 사용할 수 있습니다.

레일즈에 의해 이전에 생성된 app/views/home/index.html.erb의 내용은 아래와 같습니다.

<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>

2) 동작 확인
db등 변경된 부분을 새로 적용하기 위해 실행되고 있는 script/server를 컨트롤+C를 눌러 종료한 후에 script/server를 재시동합니다. 

브라우져에서 리로드를 하면 아래와 같이 위에서 작업된 내용들이 적용되어 초기화면이 아래와 같이 Home 컨트롤러로 연결되어 있는 것을 확인할 수 있습니다.

제가 루비온레일즈에서 해본 것중 70% 정도까지 온 것 같습니다. 해본 것도 이해를 정확히 못하고 있는데 조금만 있으면 진짜 삽질기로 들어 갈 것 같습니다.

저작자 표시 비영리 변경 금지

1. 어플리케이션 생성

아래와 같이 rails를 실행하여 루비온레일즈 어플리케이션을 생성할 수 있습니다.

rails application_name (-d database)

  • application_name: 생성될 어플리케이션이름(패스)입니다. 상위 디렉토리의 생성이 필여하면 자동으로 생성합니다.
  • -d database: 사용할 데이터베이스를 설정합니다. 입력하지 않으면 sqlite3가 기본 데이터베이스로 설정합니다.
이제 서버의 적당한 패스에서 아래와 같이 입력하여 www란 어플리케이션을 생성합니다. 실행되면 새로 생성되는 디렉토리와 파일들의 목록이 출력됩니다.

> rails www -d mysql

완료되면 어플리케이션이 생성된 디렉토리로 들어 갑니다. 아래와 같이 파일과 디렉토리들이 생성되어 있습니다.
 

README 파일에는 레일즈 어플리케여션에 대한 소개와 전반적인 사용방법에 대한 간단한 설명이 있습니다. 처음 사용하시는 분들은 한번씩 읽어 보시는 것이 좋습니다.


2. Rails 프레임워크 디렉토리 구조
생성된 각각의 디렉토리는 아래의 용도로 사용됩니다. 아래의 내용들은 위의 README 파일과 아주 잠깐 살펴 보았던 경험을 참조하였습니다.

[?] 로 되어 있는 부분은 아직 한번도 살펴 본적이 없어 용도를 정확히 모르는 곳입니다. 부족하고 틀린 내용들은 조금씩 해 보고 배우면서 계속 보완해 나가고 [?] 를 제거해 나가겠습니다.

/app
어플리케이션의 model, view, controller가 위치하는 폴더 입니다. 사용자가 작성하는 대부분의 코드는 이곳에 위치합니다.

/controller

컨트롤러들이 위치하는 곳 입니다. 컨트롤은 ApplicationController의 서브클래스이며 *_controller.rb와 같은 파일명으로 저장됩니다.

/helpers [?]
핼퍼들이 위치하는 곳입니다. 핼퍼들은 *_helper.rb와 같은 파일명으로 저장되어 있습니다. 핼퍼는 아직 정확한 용도를 모르며 존재여부와 뷰와 연관이 있다고 짐작만 하고 있습니다.

/models
모델들이 위치하는 곳입니다. 모델은 대부분 ActiveRecord의 서브클래스이며, 데이터베이스와 연동하여 데이터에 접근하고 관리하는 역활을 합니다.

/views

HTML 출력을 위한 템플릿 파일들이 위치하는 곳입니다. 각각의 템플릿 파일들은 views 밑에 연관된 컨트롤러 이름으로 된 서브 디텍토리에 위치하며, *html.erb와 같은 파일명으로 저장됩니다.

/layouts

뷰에서 사용하는 header, footer등의 일반적인 레이아웃 템플릿 파일들이 위치하는 곳입니다.

/config

Rails 환경하의 속성, 라우팅, 데이터베이스, 배포등의 설정에 관한 파일들이 위치합니다.

/environments
[?]
배포모드에 따른 설정 파일들이 위치해 있는 것 같습니다.

/initializers
[?]
초기 설정들이 위치해 있는 것 같습니다.

/db
DB 테이블을 생성하는 schema.rb가 위치하는 곳입니다.

/migrate

DB 스키마의 모든 마이그레이션 정보를 가진 파일들이 위치하는 곳입니다.

/doc
[?]
자동으로 생성되는 문서들이 위치하는 곳 같습니다.

/lib
내부적으로 사용되는 라이브러리들이 위치하는 곳이며, 실행시에 기본으로 path내에 포함되어 있습니다.

/tasks
[?]

/log
실행로그들이 위치하는 곳입니다.

/public
document root에 해당하는 웹환경에서 기본이 되는 폴더 입니다. 사이트의 일반적인 구성요소인 html, javascript, stylesheet, 이미지 파일들이 위치합니다.

/images

사용하는 이미지들이 위치하는 곳입니다.

/javascripts

자바스크립트파일(*.js)들이 위치하는 곳입니다.

/stylesheets

스타일쉬트파일(*.css)들이 위치하는 곳입니다.

/script
rails 프레임워크에서 사용하는 각종 스크립트들이 위치하는 곳입니다.

/performance
[?]
성능측정 도구들이 위치하는 곳 같습니다.

/process
[?]
프로세서들을 관리하는 도구들이 위치하는 곳 같습니다.

/test [?]
유닛, 기능, 통합 테스트등에서 사용되는 곳 같습니다.

/fixtures
[?]
·····················

/functional
[?]
기능 테스트시 사용되는 곳 같습니다.

/intergration
[?]
통합 테스트시 사용되는 곳 같습니다.

/unit
[?]
유닛 테스트시 사용되는 곳 같습니다.

/tmp [?]
레일즈에서 사용하는 임시파일들이 저장되는 곳입니다. 아직 어떤 용도로 사용되는지 확인하지 못했습니다.

/cache
[?]
캐쉬가 저장되는 곳 같습니다.

/pids
[?]
프로세스아이디와 관계된 곳 같습니다.

/sessions
[?]
세션이 저장되는 곳 같습니다.

/sockets
[?]
소켓에서 사용하는 곳 같습니다.

/vendor
어플리케이션에서 사용하는 외부 라이브러리 위치하는 곳입니다.

/plugins
[?]
플러그인이 위치하는 곳 같습니다.

부실한 내용과 곳곳에 위치한 [?] 를 보시면 현재 저의 상태(?)와 많은 관심과 애정이 필요하다는 것을 아실 수 있습니다. 많은 지도 부탁 드리겠습니다. ^^;;
저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

구글 안드로이드 소스 공개와 마켓 오픈  (2) 2008/10/23
3. Rails 어플리케이션 기본 설정  (4) 2008/10/21
2. Rails 어플리케이션 생성  (0) 2008/10/20
1. Ruby on Rails 설치 및 설정  (2) 2008/10/15
아이팟 터치 2세대  (10) 2008/10/10
OS X 루트계정 활성화  (6) 2008/10/08

Ruby on Rails로 회사 홈페이지를 만들어 보기로 했습니다. Ruby는 몇가지 예제만 만들어 보았고 Rails 역시 간단한 샘플만 따라 해 본 정도입니다.

현재 'rails www'로 프로젝트를 만들어 놓고 관망중인 상태입니다. 실질적으로 만들어 볼려고 하니 경험이 없어 막히는 부분도 많고 진도가 잘 나가지 않네요.

주위에 편하게 물어 볼 사람도 없고 혼자서 계속 삽질만 하고 있습니다. 잘 쓰시는 분들로 부터 지도편달도 받고 배워가는 것을 정리도 하고 동기부여도 할겸 공개적으로 삽질과정을 블로그에 올릴려고 합니다.

제가 설치한 환경은 아래와 같습니다.

  • 리눅스(CentOS 5)
  • Apache 2
  • MySQL 5

아래의 관련 사이트들에서 자료와 문서들을 구할 수 있습니다.


필요한 설치 파일들은 루비온레일즈 다운로드 페이지에 소개되고 링크되어 있습니다. 아래의 방법외에 사용하시는 리눅스 배포본예 따라 yum이나 apt-get을 이용하여 간편하게 설치할 수 있습니다.


1. ruby 설치
루비의 다운로드 페이지에서 최신버젼을 다운로드 받습니다. 현재 안정된 최신 버젼은 1.8.7입니다.

1) 설치
> wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p22.tar.bz2
> tar -xvjf ruby-1.8.7-p22.tar.bz2
> cd ruby-1.8.7-p22
> ./configure
> make
> make test
> make install

2) 확인
쉘상에서 irb를 실행하여 확인할 수 있습니다. irb는 대화형 루비쉘입니다.

> irb
irb> puts "hello"
hello
=> nil
irb> quit


2. RubyGems 설치
RubyGems는 루비 패키지 관리툴입니다. RubyGmes로 루비 프로그램이나 라이브러리등을 손쉽게 설치할 수 있습니다.

> wget http://rubyforge.org/frs/download.php/43985/rubygems-1.3.0.tgz
> tar -xvzf rubygems-1.3.0.tgz
> cd rubygems-1.3.0
> ruby setup.rb


3. Rails 설치
Rails는 위에 설치한 RubyGems로 아래와 같이 간편하게 설치할 수 있습니다.

> gem install rails --include-dependencies


4. MySQL/Ruby 설치
루비에서 MySQL을 사용할 수 있도록 사용할 수 있게 해주는 모듈입니다. 루비에서 공식적으로 지원하는 다른 방법이 있는지는 모르겠습니다.

1) 설치
> wget http://tmtm.org/downloads/mysql/ruby/mysql-ruby-2.8.tar.gz
> tar -xvzf mysql-ruby-2.8.tar.gz
> cd mysql-ruby-2.8pre4
> ruby extconf.rb --with-mysql-dir=/usr/local/mysql
> make
> make install

2) 확인
아래와 같이 test_db.rb 파일을 만들고 쉘상에서 ruby test_db.rb로 실행하여 확인하실 수 있습니다.

require "mysql"
db = Mysql::new("HOST", "USER_ID", "PASSWORD", "DATABASE")
res = db.query("select * from TABLE_NAME")
res.each_hash do |row|
  puts row['FIELD_NAME']
end 


5. passenger 설치
rails는 자체 웹서버를 구동할 수 있지만 아파치와 연동해서 가상 호스트로 사용하는 것이 편하기 때문에 passenger를 설치합니다. passenger외에도 다양한 웹서버가 존재하지만 설치가 가장 간편하기 때문에 passenger를 선택했습니다.

개발시에는 로그나 오류메시지를 친절하게 보여주는 Webrick이나 Mongrel을 사용하는 것이 더 편할 것 같습니다.

1) 설치
현재 버젼은 2.0.3이며 gem으로 설치할 수 있습니다.

> gem install passenger
> passenger-install-apache2-module

2) httpd.conf 파일 수정
메시지를 확인해 보시고 엔터를 입력합니다. 아파치 httpd.conf에 아래의 내용을 추가합니다. (서버의 환경과 버젼에 따라 수정해야될 부분이 있을 수도 있습니다)

LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3/ext/apache2/mod_passenger.so

PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3
PassengerRuby /usr/local/bin/ruby

3) 가상 호스트 등록
httpd-vhosts.conf에 사용할 호스트를 추가하고 아파치를 재시작 합니다. 도메인과 디렉토리는 환경에 맞게 수정합니다.

<VirtualHost *:80>
    ServerName DOMAIN
    DocumentRoot /home/zzerr/www/public
</VirtualHost>


6. 테스트

1) 프로젝트 생성
이제 적당한 디렉토리에서 아래와 같이 실행하여 rails 프로젝트를 생성합니다.

> rails www -d mysql

2) 확인
웹브라우져에서 아파치에 가상호스트로 등록했던 도메인을 입력하여 아래와 같은 메시지가 나오는지 확인합니다.



이제 본격적으로 삽질할 준비를 완료했습니다. 루비온레일즈 초보자의 설치기를 올려 보았는데, 뭐 좋은 거(?) 알고 계신 분들은 많은 조언 부탁드리겠습니다.

저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

3. Rails 어플리케이션 기본 설정  (4) 2008/10/21
2. Rails 어플리케이션 생성  (0) 2008/10/20
1. Ruby on Rails 설치 및 설정  (2) 2008/10/15
아이팟 터치 2세대  (10) 2008/10/10
OS X 루트계정 활성화  (6) 2008/10/08
nib 파일 둘러보기  (6) 2008/09/01

기타 2008/10/10 15:08
아이팟 터치 2세대 8GB를 구입하고 이틀 써보았습니다. 28만원이란 가볍게 여길 수 없는 가격이지만 여지껏 제가 산 디지털 제품중에 이만큼 가격대비 만족을 주었던 제품은 없었던 것 같습니다.


iCal의 일정들과 주소록에 있던 연락처들을 아이튠즈를 통해 동기화를 시켜 들고 다니면서 맥과 패밀리룩의 UI에서 확인할 수 있다는 것 하나로 본전은 뽑았다는 생각이 들었습니다. 음악이나 동영상 기본적인 멀티미디어 파일을 플레이할 수 있어 좋고, 가속도 센서를 이용한 게임들도 아기자기하게 재미있는 것들이 많네요. 요즘 왠만한 곳에선 Wi-Fi로 연결되니 사파리나 이메일등 인터넷을 사용하는데도 큰 불편함은 없는 것 같습니다.

가장 감동적인 부분은 역시나 UI 였습니다. 물론 터치패드로 동작하지만 단 하나의 홈 버튼은 매우 직관적이며 사용을 쉽게 합니다. (눈에 잘 안뛰게 전원, 볼륨조절 버튼은 있습니다) 입력하는 부분이 걱정되었는데, 오히려 지금 사용하는 QWERTY 키보드를 내장한 애니콜 블랙잭 보다 더 편했습니다. 터치시 효과나 패스워드 입력시에는 잠시 입력된 내용을 확인할 수 있도록 한 후에  * 로 변환되는 모습은 참 인상적이였습니다. 그외 화면전환이나 곳곳에서 보이는 섬세한 에니메이션 효과도 감동적이었고요.

아이팟 터치, 모바일 미, 맥의 아이튠즈, 아이포토등의 어플리케이션과의 찰떡궁합이 사용하는 즐거움을 더 해주는 것 같습니다. 아이폰을 당장 구매할 수 없는 아쉬움을 달래려고 구입했는데, 터치에 핸드폰, 카메라, GPS등의 기능이 추가된 아이폰이 더욱 아쉬워집니다.

아이폰 개발자 등록은 생각지 않고 있었는데, 더 재미있게 가지고 놀기 위해선 이제 등록을 해야 할 것 같습니다. 아이팟 터치의 메뉴얼은 애플의 iPod 메뉴얼 사이트에서 받을 수 있습니다.
저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

2. Rails 어플리케이션 생성  (0) 2008/10/20
1. Ruby on Rails 설치 및 설정  (2) 2008/10/15
아이팟 터치 2세대  (10) 2008/10/10
OS X 루트계정 활성화  (6) 2008/10/08
nib 파일 둘러보기  (6) 2008/09/01
OS X의 번들(Bundle) 둘러보기  (2) 2008/08/28

루트계정을 활성화 할려고 했더니 10.5는 10.4에서 사용하던 NetInfo가 보이지 않았습니다. 검색을 해보니 어플리케이션/유틸리티 폴더에서 '디렉토리 유틸리티'에서 변경이 가능했습니다. OS X의 각 버젼별로는 애플에서 제공하는 Enabling and using the "root" user in Mac OS X 문서에 잘 설명되어 있습니다.
디렉토리 유틸리티를 실행하고 좌측하단의 자물쇠를 클릭한 후, 이름과 암호를 입력합니다. 메뉴의 편집에서 Root 사용자 활성화를 클릭합니다.



Root 계정의 패스워드를 입력하고 승인 버튼을 클릭합니다.


이제 터미널에서 root로 로그인이 가능합니다. sudo를 사용하면 OS X에서는 root 계정으로 로그인이 필요하지 않지만, root 계정이 편하신 분들은 활성화 해놓고 사용하시면 될 것 같습니다.

저작자 표시 비영리 변경 금지

'기타' 카테고리의 다른 글

1. Ruby on Rails 설치 및 설정  (2) 2008/10/15
아이팟 터치 2세대  (10) 2008/10/10
OS X 루트계정 활성화  (6) 2008/10/08
nib 파일 둘러보기  (6) 2008/09/01
OS X의 번들(Bundle) 둘러보기  (2) 2008/08/28
맥 OS X에서 CHM 파일 보기  (4) 2008/08/19

기타 2008/09/01 13:21
1. nib 파일이란?
Nib는 코코아 어플리케이션에서 사용하는 파일로 인터페이스빌더에서 생성한 윈도우, 메뉴, 컨트롤과 사용자가 만든 오브젝트들의 레이아웃과 속성등의 정보와 오브젝트간의 연결과 바인딩등의 정보를 포함하고 있는 파일입니다.

윈도우즈의 rc 파일과 개념이 비슷하지만 소스코드에서 처리하던 메시지 처리함수 연결과 바인딩등의 더 포괄적인 정보를 가지고 있습니다.

Xcode 3.1에서는 개발과정에선 nib 대신 xib란 XML 포멧의 파일을 사용합니다. (개발이 완료되고 릴리즈된 후에 nib의 역활은 이전과 동일합니다.) 3.1 이전의 자료에서는 Xcode에서 nib를 더블클릭하여 관련된 nib를 인터페이스 빌더로 실행하는 것으로 나와 있지만, 현 3.1 버젼에서는 xib를 더블클릭하여 실행합니다.


2. MainMenu.nib
사용자 삽입 이미지
MainMenu.nib는 어플리케이션에서 사용하는 메뉴, 메인윈도우, Application등 기본적인 오브젝트를 포함하고 있습니다. MainMenu.nib의 File's Owner는 NSApplication이며 또는 사용자가 생성한 NSApplication의 서브클래스를 지정할 수 있습니다. 그렇기 때문에 MainMenu.nib는 NSApplication에 의해 실행 초기(이벤트 루프에 들어 가기 전)에 자동으로 로딩됩니다.

그러므로 가능하면 다른 오브젝트나 컨트롤, 윈도우등은 모듈별로 각각의 nib를 만들어 작게 유지하며, 해당 모듈의 실행 시에만 메모리에 올라 오도록 하는 것이 좋습니다. MainMenu.nib가 많은 오브젝트나 리소를 가지고 있으면, 초기 런칭 속도가 느려지며 처음부터 많은 메모리를 사용하게 됩니다. 

MainMenu 외에 사용자가 직접 nib를 로딩해야 할 경우에는 NSBundle을 사용하여 아래와 같이 호출합니다.

[NSBundle loadNibNamed:@"[nib file name]" owner:self];


3. nib 파일 로딩
nib 파일은 로딩 시에 아래와 같은 순서로 처리됩니다.

1) 메모리 로딩
해당 Nib에 등록된 오브젝트, 관련된 리소스(이미지, 사운드 파일등)를 메모리 또는 캐쉬로 불러 옵니다.

2) 오브젝트 Unarchive
nib에 냉동포장 되어있던 오브젝트들을 해동합니다. 인터페이스 빌더의 오브젝트들에게는 initWithCoder 메시지를 발송하며, NSView의 서브클래스들에게는 initWithFrame, 그외 오브젝트들에게는 init 메시지를 발송합니다. 그리고 인터페이스 빌더에서 설정한 정보에 따라 오브젝트들간의 연결(actions, outlet)과 바인딩을 설정합니다.

3) awakeFromNib
nib내의 모든 오브젝트들에게 awakeFromNib 메시지를 발송하여, 오브젝트가 생성이 완료되었음을 알립니다. nib내의 오브젝트들은 이 메시지를 이용하여 초기화와 관련된 처리를 할 수 있습니다.

사용자 삽입 이미지
그리고 nib내의 윈도우중에 인터페이스 빌더의 Window/Behavior내의 'Visible at Launch' 속성이 체크되어 있는 윈도우를 오픈합니다.



4. 로컬라이징
nib 파일의 로컬라이징은 매우 쉽습니다. Xcode 내에서 해당 xib를 마우스 우클릭하여 나온 메뉴중에 'Get Info'를 클릭하여 정보창을 오픈합니다.
사용자 삽입 이미지
하단의 Add Localization 버튼을 클릭하여 해당언어를 추가합니다.

사용자 삽입 이미지
XCode에서 좌측과 같이 Korean이 추가되어 있는 것을 확인할 수 있습니다. 프로젝트 디렉토리내에는 Korean.lproj 디렉토리가 추가되고 그 안에 한국어 버젼의 MainMenu.xib이 위치합니다. 각 nib마다 컨트롤의 타이틀과 텍스트를 해당언어로 변경하면 됩니다.

어플리케이션이 실행되면 시스템에 설정된 현재언어를 우선으로 해당 nib가 존재할 경우에는 그 언어의 nib 파일이 로드됩니다.

nib에 대해 자세한 사항은 ADCResource Programming Guide 문서를 참조하시기 바랍니다.

'기타' 카테고리의 다른 글

아이팟 터치 2세대  (10) 2008/10/10
OS X 루트계정 활성화  (6) 2008/10/08
nib 파일 둘러보기  (6) 2008/09/01
OS X의 번들(Bundle) 둘러보기  (2) 2008/08/28
맥 OS X에서 CHM 파일 보기  (4) 2008/08/19
ClassDumper - 응용프로그램 Class Viewer  (0) 2008/08/07