1. C 표준 라이브러리 함수

int getDayOfWeek(int year, int month, int day)
{
struct tm *pResultTime;
struct tm targetTime = { 0, 0, 0, day, month-1, year - 1900 };
time_t targetSec = mktime(&targetTime);
pResultTime = localtime(&targetSec);
return pResultTime->tm_wday;
}

 
2. Cocoa 클래스

참조: NSDateComponents Class Reference

- (int)getDayOfWeek:(int)year month:(int)month day:(int)day

{
    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    [dateComponents setYear:year];
    [dateComponents setMonth:month];
    [dateComponents setDay:day];
    
    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSGregorianCalendar];
    NSDate *date = [gregorian dateFromComponents:dateComponents];
    NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:date];
    
    return [weekdayComponents weekday] - 1;
}


3.  첼러의 공식

참조: WikiPedia - Zeller's congruence

int getDayOfWeek2(int year, int month, int day)
{
    if(month <= 2) {
        year--;
        month += 12;
    }
    
    int year1 = year/100;
    int year2 = year%100;
    
    int weekDay =  (day + 26*(month+1)/10 + year2 + year2/4 + year1/4 - year1*2) % 7 - 1;
    if (weekDay < 0) {
        weekDay += 7;
    }
    
    return weekDay;


참조: Determination of the day of the week # Sakamoto's method

int dow(int y, int m, int d)
{
   static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};

    y -= m < 3;   
    
    return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;


AND

파이썬에서 사용할 수 있는 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로 실행권한을 설정하셔야 합니다.


'기타 > 자잘한 Tip' 카테고리의 다른 글

특정 날짜 요일 구하기  (0) 2012.02.04
sqlite3에서 csv import/export  (0) 2009.08.26
Python에서 sqlite3 사용하기  (1) 2009.08.26
텍스트파일 문자셋 변환 스크립트  (6) 2008.08.25
Xcode에서의 Ruby on Rails  (8) 2008.08.20
AND

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

* '[' 와 ']'는 입력하지 않습니다.
AND

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()

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

AND

간혹 euc-kr로된 파일들을 utf-8로 변경할 경우가 있어 파이썬으로 아래와 같이 iconv를 이용하는 간단한 스크립트를 만들어 사용했습니다.

#!/usr/bin/python

import os, sys

for arg in sys.argv[1:]:
    if os.path.isfile(arg):
        os.rename(arg, arg + '.chg')
        command = 'iconv -f euc-kr  -t utf-8 ' + arg + '.chg' + ' > ' + arg
        os.system(command)

파이썬 인자관리의 편리한 기능으로 위와 같이 단순한 코드로도 '*.txt'나 '*'와 같은 와일드카드도 자동으로 처리되어 별다른 불편함 없었습니다.

그런데 이번에는 반대로 utf-8을 euc-kr로 변경할 경우가 생겨 스크립트를 변경하면서 옵션을 추가하여 보았습니다. 몇 번 사용해 보았는데 별 문제가 없어 올려 봅니다. (오류나 잘못된 부분이 있으면 알려주시면 감사하겠습니다. ^^;;) 기본 사용법은 아래와 같습니다.

사용자 삽입 이미지

1) 옵션
  • -h: 위와 같은 사용법을 출력합니다.
  • -r: 서브디렉토리의 파일들도 변환합니다.
  • -f: 디렉토리가 아닌 인자로 넘어 온 파일들을 변경합니다.
  • -x: 이전 파일의 백업파일을 남기지 않습니다.
  • -d: 작업 디렉토리를 지정합니다.
  • -s: 이전 파일을 백업할 파일 확장자를 지정합니다.
  • -e: 변경할 파일의 확장자를 지정합니다.
  • -o: 변경될 파일의 현재 문자셋을 지정합니다.
  • -n: 변경될 문자셋을 지정합니다.

-f는 파일 단위로 -d는 디렉토리 단위로 변환하며, 두 옵션을 같이 사용할 수 없습니다. 현재 파일의 문자셋은 euc-kr로 변경될 문자셋은 utf-8이 기본으로 설정되어 있습니다. -d 옵션에선 사고(?)를 방지하기 위해 변경될 파일의 확장자가 'txt'가 기본으로 설정되어 있으며, 이는 -e[확장자] 옵션으로 변경할 수 있습니다.

이전 파일은 [파일명].chg로 동일 디렉토리에 저장되며, 이 확장자는 -s[확장자] 옵션으로 변경할 수 있습니다. -x 옵션을 사용하면 이전 파일을 저장하지 않습니다.

2) 사용예
* 현재 디렉토리의 data.txt 파일 변경 (euc-kr -> utf-8)
$ chgchar -f data.txt

* 현재 디렉토리의 data.txt 파일 변경 (utf-8 -> euc-kr)
$ chgchar -outf-8 -neuc-kr -f data.txt

* 현재 디렉토리의 *.txt 파일 변경
$ chgchar -f *.txt

* test 디렉토리 내의 모든 txt 파일 확장자를 가진 모든 파일 변경
$ chgchar -d./test -etxt

* 현재 디렉토리 내의 모든 파일과 서브 디렉토리의 파일도 변경
$ chgchar -r -e* -d./

3) 주의사항
파일을 변경하는 위험한(?) 작업인데 테스트와 사용횟수가 부족하기 때문에, 아래의 사항에 유의하시면서 사용하셔야 합니다.
  • 백업파일을 저장하지 않는 '-x' 옵션 사용하지 않는 것이 좋습니다.
  • 와일드카드(*)는 가능한 사용하지 않는 것이 좋습니다.
  • 대상 디렉토리와 파일을 확인하고 실행해 주세요.

4) 다운로드
아래의 압축파일을 다운로드 받아서 압축을 푸시고 'chmod +x ./chgchar'로 파일의 실행권한을 추가하시고 사용하시면 됩니다.

* 2008.10.21 추가
"nakada님으로 부터 파일 접근권한을 설정하지 않은 문제가 있는 것을 알게되었습니다. 자세한 내용은 nakada님의 포스팅을 참조하시기 바랍니다. nakada님이 작업하신 내용은 이곳에서도 변경해 놓았습니다. nakada님께 감사 드립니다. ^^"



* 아래의 'more..'를 클릭하시면 스크립트의 내용을 확인하실 수 있습니다.

'기타 > 자잘한 Tip' 카테고리의 다른 글

sqlite3에서 csv import/export  (0) 2009.08.26
Python에서 sqlite3 사용하기  (1) 2009.08.26
Xcode에서의 Ruby on Rails  (8) 2008.08.20
Dashcode로 올블로그 RSS 위젯 만들기  (2) 2008.05.22
자주 사용하는 MySQL 명령어  (4) 2008.02.28
AND

사용자 삽입 이미지
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)가 최상의 웹 개발환경인 것 같은데, 생각 처럼 그렇게 많은 곳에서 사용하지는 않는 것 같습니다. 제가 모르는 어떤 이유가 있는 것 같습니다.
AND

이전에 올블로그 위젯을 올린 적이 있는데 RSS 리더기나 다른 좋은 관련 툴들이 많이 있어 업그레이드를 하지 않았습니다. 후에 Dashcode를 이용해 다시 만들어 볼려고 했는데 데모 사용기간이 지나 한동안 잊고 있다가 레오퍼드를 사용하면서 다시 Dashcode를 쓸 수 있게 되었습니다.
 
그래서 Dashcode를 사용하여 다시 만들어 볼려고 했는데, RSS 템플릿을 쓰니 다운로드 받고 설치하는 것 보다 그냥 만드는게 빠를 정도로 너무 쉽기 때문에 RSS 템플릿을 사용하여 위젯을 만든는 방법만 간단하게 설명할려고 합니다.

1. 프로젝트 생성
Dashcode를 처음 사용하시는 분들은 이전 관련 포스팅을 참조 하시면 도움이 되실 것 입니다. 먼저 Dashcode를 실행합니다. 아래와 같이 템플릿 선택화면이 나오면 'RSS 템플릿'을 선택하고 우측 하단의 'Choose' 버튼을 클릭합니다.

사용자 삽입 이미지


2. 기본 이미지/아이콘 변경
아래의 이미지를 다운로드 하여 사용하시거나 원하는 디자인으로 직접 배경과 아이콘 이미지를 사용하셔도 됩니다.

아래와 같이 좌측의 Default Image를 선택한 후에 배경파일(all.png)을 드래그 하여 가져다 놓습니다. 동일하게 하단의 Widget Icon을 선택한 후에 Icon.png 파일을 드래그 하여 놓습니다.

사용자 삽입 이미지


3. 전면(front) 설정
사용자 삽입 이미지

상단에서 front를 선택하면 좌측과 같이 front를 구성하고 있는 목록들을 볼 수 있습니다.

이중에서 fontImg, topRectangleShape, bottomRectangleShape, feedTitle을 선택한 후에 delete 키를 눌러 삭제합니다.

 







다시 배경 이미지 파일을 마우스로 드래그 해서 아래와 같이 위치 시킵니다.
사용자 삽입 이미지


4. RSS URL 설정
사용자 삽입 이미지
이제는 RSS를 가져올 주소를 설정해 보겠습니다. 위의 과정은 생략하시고 이 부분만 설정하시면 3초만에 자신만의 RSS 리더기를 만들 수 있습니다.

설정을 위해서 좌측과 같이 Provide RSS feed에서 RSS Properties 앞의 삼각형 버튼을 클릭합니다.



화면에서 Properties 하단의 Feed URL 입력 부분에 아래와 같이 올블로그의 '가장 많이 추천 받은 글'의 RSS주소를 입력합니다.
사용자 삽입 이미지


5. 실행
메뉴에서 'File/Save'를 클릭하여 프로젝트를 저장하고 'File/DeployWidget to Dashboard'를 클릭하여 제작한 위젯을 대쉬보드로 보냅니다. 이제 대쉬보드에서 아래와 같이 올블로그 위젯을 보실 수 있습니다.
사용자 삽입 이미지

사용자 삽입 이미지
하단의 설정버튼(i)을 클릭하면 좌측과 같이 출력될 내용의 길이를 설정 할 수 있습니다.

AND

중요도나 용도에 상관없이 제가 자주 사용하는 MySQL의 툴과 명령어를 정리해 보았습니다. 개인적인 참조로 쓰기 위한 것이므로 자세한 설명은 생략하였습니다. 자세한 내용은 한국 MySQL의 메뉴얼 페이지를 참조하세요. OS X에서 mysql 설치는 제 이전 포스트를 확인하시면 됩니다

* 데몬 시작
> mysqld_safe --user=[아이디] &

* 종료
> mysqladmin -u [아이디] -p[패스워드] shutdown

* 재실행
> mysqladmin -u [아이디] -p[패스워드] reload

* 계정 추가
localhost가 %일 경우 모든 IP에서의 접근을 허용합니다.
mysql> grant all privileges on [database].* to [아이디]@"localhost" identified by "[패스워드]"

* 패스워드 변경
mysql> SET PASSWORD FOR [아이디]@localhost=PASSWORD('[패스워드]')  

* 테이블 필드 변경
명령어별 옵션은 아래와 같습니다.
  • add : add [기존필드] [타입] after [필드]
  • change : change [변경될 필드]  [새로운 필드명] [타입]
  • drop : drop [삭제될 필드]

mysql> ALTER TABLE [테이블 명] (add | change | drop) ...

* 데이터 백업
데이터 백업 시 아래와 같이 사용합니다. 테이블 명을 생략하면 database의 전체 테이블을 백업합니다. 자주 쓰이는 옵션은 아래와 같습니다.
  • -d:  테이블 생성 정보만 백업
  • -f: 데이터만 백업

> mysqldump -u [아이디] -p[패스워드] [database] [테이블 명] > [파일명]

* 테이블 검사
mysql>CHECK TABLE [테이블 명]

* 테이블 복구
mysql>REPAIR TABLE [테이블 명]

repair로 고쳐지지 않는 다면 쉘에서 아래와 같이 시도합니다.
> myisamchk -safe-recover [mysql data path]/[테이블 명]

* 바이너리 로그
MySQL은 select와 같은 데이터에 변동이 없는 내역을 제외하고 data 디렉토리에 바이너리 로그로 저장합니다. 아래와 같이 mysqlbinlog로 텍스트화 된 내용을 확인할 수 있으며, 변경된 내역을 가지고 있기 때문에 데이터 복구시에도 사용할 수 있습니다.
> mysqlbinlog [로그파일 명]

* 파일로 저장
mysql>SELECT * INTO OUTFILE "[filename]" FROM [테이블 명];

엑셀에서 사용하기 위해 CSV(Comma Separated Value) 포맷으로 저장할 경우에는 아래와 같이 사용합니다.
mysql>SELECT * INTO OUTFILE "[filename]" FIELDS TERMINATED BY ',' FROM [테이블 명];

* CSV 파일 로드
LOAD DATA LOCAL INFILE "[CSV 파일패스]" INTO TABLE [테이블명] FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';
"로 필드가 구분되었을 경우에는 ENCLOSED BY '\"'를 추가합니다.

* 테이블 최적화
mysql>OPTIMIZE TABLE [테이블 명]

* mysqladmin
서버의 상태를 감시하고 동작을 제어 합니다. 명령어들은 아래와 같습니다.
  • ping : 서버가 실행중인지 확인합니다.
  • status: 현재 서버의 상태를 출력합니다.
  • processlist: 실행중인 쓰레드의 정보를 출력합니다.
  • kill [Id]: 특정 쓰레드를 종료합니다.
  • variables: mysql 환경변수 값을 출력합니다.

> mysqladmin -u [아이디] -p[패스워드] 명령

* 쉘에서 UTF8
character_set_client가 latin1로 되어 있으면 mysql 쉘에서 한글이 깨어져 나오는 경우가 있습니다. 아래와 같이 현재 문자셋을 알아 봅니다.
mysql> show variables like '%char%';

character_set_client이 utf8로 되어 있지 않을 경우에는 my.cnf 파일에서 아래와 같이 설정합니다.
[mysql]
default-character-set = utf8

'기타 > 자잘한 Tip' 카테고리의 다른 글

Xcode에서의 Ruby on Rails  (8) 2008.08.20
Dashcode로 올블로그 RSS 위젯 만들기  (2) 2008.05.22
flex2 - xml을 이용한 동적 메뉴 예제  (0) 2008.02.01
PHP에서 RSS 가져오기  (0) 2007.12.08
OS X에 MySQL 설치  (4) 2007.10.12
AND

flex2로 만든 Tree로 메뉴를 보여주는 샘플 입니다. xml에서 데이터를 읽어 오기 때문에 메뉴 이름이나 URL이 변경되더라도 다시 컴파일할 필요가 없습니다. 그리고 제목을 클릭해도 오픈/클로즈가 가능하고 링크가 있을 시에는 해당 링크가 오픈됩니다.


lmenu.mxml (flex2 소스 파일)
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    creationComplete="initData()" width="180" height="200" fontSize="11">
    <mx:Script>
        <![CDATA[
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import flash.net.navigateToURL;

            /* murl 파라미터에서 설정된 url로 부터 xml 데이터를 가져 온다. */
            private function initData():void {
                xmlService.url = Application.application.parameters.murl;
                xmlService.send();
            }
           
            /* xml 가져오기 오류 시 메시지 출력 */
            private function faultHandler(event:FaultEvent):void {
                mx.controls.Alert.show(event.fault.message);
            }
           
            /* Tree 마우스 클릭 이벤트 처리 */
            private function onItemClicked(event:Event):void {
                if(event.currentTarget.selectedItem.@data) {
                   
                    /* 현재 선택된 아이템의 데이터 값을 가져 온다. */
                    var dataString:String = "";
                    dataString = event.currentTarget.selectedItem.@data;
                   
                    /* data(link)가 있을 시에는 url을 연다 */
                    if(dataString.length > 0)
                    {
                        var url:URLRequest = new URLRequest(dataString);
                        navigateToURL(url);
                    }   

                    /* 아이템이 열려 있으면 닫고, 닫혀있으면 연다 */
                    var openFlag = !(menuTree.isItemOpen(event.currentTarget.selectedItem) == true);
                    menuTree.expandItem(event.currentTarget.selectedItem, openFlag);   
                }
            }
        ]]>
    </mx:Script>

    <mx:HTTPService id="xmlService" resultFormat="e4x" fault="faultHandler(event)" useProxy="false" />
    <mx:XMLListCollection id="xc" source="{xmlService.lastResult.item}" />

    <mx:Tree id="menuTree" labelField="@label" showRoot="true"
        x="0" y="0" width="180" height="200"
        dataProvider="{xc}" click="onItemClicked(event);" />
</mx:Application>
현재 창에서 링크가 열리기를 원하시면 navigateToURL(url)을 navigateToURL(url, "_self")로 변경합니다.

test.html (html 샘플 파일)
<html lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Flex Menu Test</title>
<script type="text/javascript">
function goURL(url)
{
    document.location.href = url;
}
</script>
</head>
<body>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
            id="flexMenu" width="500" height="400"
            codebase= "http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="[swf url]?murl=[xml url]" />
<param name="quality" value="high" />
<embed src="[swf url]?murl=[xml url]" quality="high" bgcolor="#efefef"
                width="500" height="400" name="flex" align="middle"
                play="true"
                loop="false"
                quality="high"
                type="application/x-shockwave-flash"
                pluginspage="http://www.adobe.com/go/getflashplayer">
            </embed>
    </object>
</body>
</html>
murl로 xml 파일의 url을 전달합니다.

[swf url] 컴파일된 swf 파일의 url입니다.
[xml url] 메뉴 구조가 정의된 xml의 url입니다. 구조는 아래와 같습니다.

src와 movie에서의 내용을http://www.domain1.com/lmenu.swf?murl=http://www.domain2.com/menu.xml 과 같이 입력하시면 됩니다.

menu.xml (메뉴 구조 샘플 파일)
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <item label="포탈 사이트">
        <item label="네이버" data="http://www.naver.com"/>
        <item label="다음" data="http://www.daum.net"/>
        <item label="야후" data="http://www.yahoo.co.kr"/>
        <item label="엠파스" data="http://www.empas.com"/>
    </item>
    <item label="블로그">
        <item label="내 블로그" data="http://www.cocoadev.co.kr"/>
        <item label="올블로그" data="http://www.allblog.net"/>
        <item label="티스토리" data="http://www.tisotry.com"/>
    </item>
</root>
서브 메뉴를 포함하고 있을 때는 "<item>[.. sub item]</item>"과 같이 포함하지 않으면 "<item />"과 같이 사용하시면 됩니다. 링크가 필요한 경우에는 item의 data 필드를 이용합니다.

crossdomain.xml
<?xml version="1.0"?>
<cross-domain-policy>
    <allow-access-from domain="*"/>
</cross-domain-policy>

swf가 있는 도메인과 xml이 있는 도메인이 다를 경우에는 xml이 있는 곳에 위와 같은 crossdomain.xml 파일이 존재하여야 합니다.
AND

요새 저희 가족 홈페이지를 만들고 있습니다. 한가한 토요일 오후라 블로그 RSS를 가져 오는 루틴을 만들고 있었는데, 실컨 하다가 php 홈페이지에서 문서를 보니 SimpleXMLElement라는 방법이 있었습니다. PHP5부터 지원한다고 하네요.

<?
$rss = file_get_contents("http://www.cocoadev.co.kr/rss");
$xml = new SimpleXMLElement($rss);

print "Blog: <a href='".$xml->channel[0]->link."'>";
print $xml->channel[0]->title."</a><br>";

print "<ul>";
foreach($xml->channel[0]->item as $item)
{
    print "<li><a href='".$item->guid."'>".$item->title."</a> ";
print "(".$item->pubDate.")</li>";
}
print "</ul>";
?>

사용자 삽입 이미지

편한 방법을 찾은 건 다행인데, 왠지 허무하기도 하고 만들 의욕이 그냥 팍 다운되네요. 컴퓨터는 그만 끄고 아들녀석이랑 놀아 줘야 겠습니다.
AND

1. 다운로드
MySQL 다운로드 사이트에서 현재 사용하시는 맥의 CPU와 OS X 버젼에 맞는 패키지를 선택하고 다운 받습니다. 여기서는 package format을 다운 받고 이를 예로 들겠습니다.

해당 파일에서 Pick a Mirror를 클릭하면 회원가입 또는 로그인 화면이 나옵니다. 로그인이나 회원가입을 안하실 분은 하단의 "» No thanks, just take me to the downloads!"를 클릭하면 다운로드 받을 수 있는 미러사이트들이 나옵니다. 이 중 선택하셔서 다운로드 받으시면 됩니다.

2. 설치
사용자 삽입 이미지
다운로드 받은 dmg 파일을 클릭하면 아래와 같은 파일들이 나옵니다.
 
mysql-5***.pkg  : mysql 설치 파일
MySQL_S**.pkg  : 부팅 시 자동 시작 설정 파일
MySQL_pre*.pkg : 시스템 환경설정 등록 파일
ReadMe.txt          : 설치 안내 파일

설치는 매우 쉽습니다. 아래와 같이 각각의 파일들을 클릭하여 설치 합니다.

1) 먼저 mysql-5.0.**.pkg 파일을 클릭하여 MySQL을 설치 합니다.
2) MySQL_Startup**.pkg 파일을 클릭하여 설치합니다.
3) MySQL_prefPane을 클릭하여 환경설정에 MySQL을 추가 합니다.

이제 모든 설치가 완료되었습니다. 시스템 환경설정/기타에서 MySQL 아이콘을 확인하고 클릭합니다.
사용자 삽입 이미지

 위의 화면에서 [Start MySQL Server] 버튼을 클릭하여 MySQL을 시작하고, 위의 화면과 같이 상태가 running임을 확인 합니다.  아래의 체크 옵션은 시스템 시작 시에 MySQL을 자동으로 시작할지를 선택합니다. 필요에 따라서 체크를 하시면 됩니다.
 
3. 설정
이제 MySQL이 실행되고 있는지 확인해 보겠습니다. iTerm등의 터미널을 실행 합니다.
(지금 부터의 내용이 어려우신 분들은 제 이전 포스트를 참고 하세요.)

MySQL은 /usr/local/mysql-[버젼명] 디렉토리에 설치되어 있으며, 해당 디렉토리에서 mysql로 심볼릭 링크되어 있습니다.

사용 상의 편의를 위해 MySQL 실행(bin) 디렉토리를 패스에 추가 합니다. 사용자 root 디렉토리에서 > vi .bash_profile로 열어 아래와 같이 한줄을 추가 합니다.

PATH=${PATH}:/usr/local/mysql/bin
위의 내용을 입력하고 :wq로 저장하고 vi를 나옵니다.
 
다시 터미널로 로그인 하여 > sudo mysql 타이핑 하면, 아래와 같은 MySQL이 실행 된 화면을 보실 수 있습니다. (패스워드 입력창이 나오면 root권한 사용 시 입력하는 패스워드를 입력하시면 됩니다.)
사용자 삽입 이미지

4. Database, 사용자 추가
1. 데이터 베이스 생성
위의 프롬프트 상에서 mysql> create database cocoadev[enter]를 입력하여 cocoadev란 데이터베이스를 생성합니다.

2. 사용자 등록
mysql> grant all privileges on cocoadev.* to test@"localhost" identified by '1111';
와 같이 입력하여 localhost(현재 컴퓨터)의 test 사용자를 패스워드 1111로 생성하여  cocoadev 데이터베이스에 접근할 수 있도록 합니다.

아래와 같이 진행됨을 확인합니다.
사용자 삽입 이미지

quit 명령어로 mysql을 나옵니다.

3. 사용자 로그인
이제 위에서 등록한 test 사용자로 mysql에 로그인 해 보겠습니다.

> msyql -u [userid] -p[password] [database]과 같이 로그인 하며 위의 이미지를 참고 하시면 됩니다. 아래와 같이 정상적으로 mysql에 로그인 되는지 확인 하시면 됩니다.

사용자 삽입 이미지

자세한 사항은 패키지의 ReadMe.txt를 읽어 보시고, 그외 자세한 설명은 mysql 사이트의 메뉴얼을 참고 하세요.

여기서는 나중에 Cocoa Tutorial에서 MySQL과 연동하는 어플리케이션을 제작할 때 다루어 보겠습니다.

AND

이전에 급조해서 만들어 놓았던 리눅스용 서버 프로세스 감시 어플리케이션 소스 입니다. 실행되면 특정 프로세스가 실행 되는지 검사하다 프로세스가 없으면 정해진 파일을 다시 실행합니다.

proc 파일 시스템을 이용하기 때문에 이 소스로는 proc 파일 시스템을 사용하지 않는 맥 OS X에서는 동작하지 않습니다. 현 소스는 Linux에서 사용했고 freeBSD에서도 디렉토리와 몇 가지만 바꾸면 사용하는데 이상이 없을 겁니다. 원래 freeBSD에서 사용했던 것을 Linux로 옮겨 왔습니다.

일단 소스입니다. 보시면 알겠지만 제가 있던 환경만을 생각해서 만들었고, 여러 상황이나 오류에 대한 고려가 없으니 만약 사용 시에는 아래의 사항을 반드시 확인해 보세요.
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <stdlib.h>
    
/* 검사 주기(초) */
#define CHECK_SECOND        30  

/* 실행 서버 패스 및 이름 */
#define APP_PATH            "/root/ztsvr/ztsvr"
#define APP_NAME            "ztsvr"

int check_process();
void get_timef(time_t, char *);

int main()
{
    int rt;
    time_t  the_time;
    char buffer[255];
    char app[255];

    sprintf(app, "nohup %s &", APP_PATH);

    printf("START\n");
    fflush(stdout);
    while(1)
    {
        time(&the_time);
        get_timef(the_time, buffer);

        rt = check_process();

        if(rt == 0)
        {
            printf("DIE: %s\n", buffer);

            /** 새로 뛰움 **/
            system(app);
            printf("RELOAD: %s\n", buffer);
        }
        else
        {
            printf("OK: %s\n", buffer);
        }

        fflush(stdout);
       
       /* 검사 후, process sleep */
        sleep(CHECK_SECOND);   
    }
    return 0;
}

/** 프로세스 검사 */
int check_process()
{   
    DIR* pdir;
    struct dirent *pinfo;
    int is_live = 0;

    pdir = opendir("/proc");
    if(pdir == NULL)
    {
        printf("err: NO_DIR\n");
        return 0;
    }

    /** /proc 디렉토리의 프로세스 검색 */
    while(1)
    {
        pinfo = readdir(pdir);
        if(pinfo == NULL)
            break;

        /** 파일이거나 ".", "..", 프로세스 디렉토리는 숫자로 시작하기 때문에 아스키코드 57(9)가 넘을 경우 건너뜀 */
        if(pinfo->d_type != 4 || pinfo->d_name[0] == '.' || pinfo->d_name[0] > 57)
            continue;

        FILE* fp;
        char buff[128];
        char path[128];

        sprintf(path, "/proc/%s/status", pinfo->d_name);
        fp = fopen(path, "rt");
        if(fp)
        {
            fgets(buff, 128, fp);
            fclose(fp);

            /** 프로세스명과 status 파일 내용과 비교 */ 
            if(strstr(buff, APP_NAME))
            {
                is_live = 1;
                break;
            }
        }
        else
        {
            printf("Can't read file [%s]\n", path);
        }
    }

    closedir(pdir);

    return is_live;
}

/** 현재 시간을 설정 */
void get_timef(time_t org_time, char *time_str)
{
    struct tm *tm_ptr;
    tm_ptr = localtime(&org_time);

    sprintf(time_str, "%d/%d/%d %d:%d:%d",
                    tm_ptr->tm_year+1900,
                    tm_ptr->tm_mon+1,
                    tm_ptr->tm_mday,
                    tm_ptr->tm_hour,
                    tm_ptr->tm_min,
                    tm_ptr->tm_sec);
}

0. 용도
서버 자체가 든든 해서 어떠한 상황에서도 죽는 일이 없어야 겠지만, 중요한 서비스라면 일단 자동으로 살려 놓고 원인을 찾아야 할 경우를 위해 만들어 놓았습니다.

1. 설정
#define CHECK_SECOND        30  
검사 주기를 초단위로 설정합니다. 이 설정으로는 검사를 한 후 30초 sleep상태로 잠들어 있다 30초 마다 다시 검사합니다.

#define APP_PATH            "/root/ztsvr/ztsvr"
실행해야 될 서버 실행파일의 전체경로와 파일명입니다.

#define APP_NAME            "ztsvr"
실행 프로세스명(파일명) 입니다.

sprintf(app, "nohup %s &", APP_PATH);
system 합수로 실행해야될 명령어를 설정합니다. 참고로 nohup [실행파일 패스] &로 실행을 하면 실행파일은 백그라운드에서 실행되며 터미널의 연결이 종료되어도 계속 실행됩니다.

콘솔 출력 내용은 생성되는 nohup.out 파일 에서 확인할 수 있습니다. 위에서 printf로 출력되는 내용은 모두 nohup.out에 저장됩니다.

2. 주의 사항
if(strstr(buff, APP_NAME))
위와 같이 strstr로 간단한 검사만 합니다. "abc"란 프로세서가 죽었더라도 "abcdef"란 프로세스가 있으면 살아 있는 것으로 간주됩니다.  서버 이름이 절대 중복되지 않으면 상관 없지만, 안전을 위하여, 해당 시스템의 stat 파일의 포멧을 보고 파싱해서 정확하게 검사해야 할 것 입니다.

nohup.out 파일의 크기
검사 주기가 작고 출력되는 내용이 많을 경우에는 nohup.out 파일의 크기가 지나치게 커질 수 있습니다. 콘솔로 출력되는 양을 줄이거나 주기적으로 파일의 크기를 체크해야 합니다.

2000년 초 제작 하여 몇 번을 사용 해 보고 이상이 없었으나, 백그라운드에서 while로 항시 돌아 가며 시스템에 접근하는 프로그램이기 때문에 사용 시 많은 테스트와 올바르게 동작 하는지 확인을 하셔야 합니다.

이 소스를 이용해서 일어나는 피해에 관해서는 일절 책임을 지지 않으니, 주의해서 사용하시기 바랍니다.

AND

얼마전 애플에서 공개된 위젯 개발툴인 Dashcode를 다운 받고, 이제서야 실행을 해 보았습니다.

하지만 OS X를 10.4.10으로 버젼업 때문인지, 아니면 Dashcode의 영향인지 PPC  iMac에선 매우 불안정한 모습을 보이고 있습니다. Dashcode가 이유없이 다운된다던지, 응용프로그램 사용 중에 바람개비가 자주 나타납니다.

그 외에 Dashcode에서 타이틀 등에 한글을 사용하면 오동작을 하였습니다. 이 것도 지금 사용중인 제 맥만 그런 것인지 Dashcode 오류인지는 확인하지 못했습니다.

1. Dashcode 둘러보기

1) 다운로드 및 설치

Dashcode는 현재 베타 버젼으로 애플 ADC 홈페이지에서 다운로드 받을 수 있습니다. Xcode와 마찬가지로  ADC 회원만 다운로드 받을 수 있습니다.

사용자 삽입 이미지
설치를 완료하면 실행파일은  /Developer/Applications/ 에 위치 합니다. 좌측과 같이  Xcode와 유사한 Dashcode의 아이콘을 발견할 수 있습니다.



2) 실행

Dashcode를 실행하면, 아래와 같이 제공하는 템플릿들과 시작할 수 있는 윈도우가 나옵니다. 일반적인 위젯을 만들기 위해 Custom을 선택 합니다.
사용자 삽입 이미지


3) 둘러보기

사용자 삽입 이미지

Attribute
현재 선택된 오브젝트들의 속성과 이벤트를 설정할 수 있는 윈도우 입니다.
 
Library
사용가능한 UI,  텍스트, 이미지, 동영상등을 가지고 있는 팔레트 입니다. 이 곳에서 원하는 오브젝트를 드래그 해서, 위젯에 배치 합니다.

Main 윈도우
좌측에는 위젯에 사용된 오브젝트들의 목록이 있습니다. front는 일반적으로 보는 위젯의 앞면이며, back은 옵션을 설정을 하는 위젯의 뒷면입니다.

그 밑에는 위젯의 속성, 기본 이미지, 아이콘을 설정할 수 있는 버튼들이 있습니다.

사용자 삽입 이미지
하단에는 Workflow Steps 가 위치해 있으며, 위젯을 제작하는 작업이 순서대로 나와 있습니다.

좌측과 같은 순서로 위젯을 만들어 나가면 됩니다. 항목을 클릭하면 각각의 세부 작업을 확인할 수 있습니다.



 
2. 바이오리듬 위젯 제작

이제 간단하게 바이오리듬을 대충 만들어 보겠습니다. 이 예제는 Dashcode의 개략적인 사용법을 위한 예제입니다. 바이오리듬 계산 방법은 이 전에 다른 언어로 작성되어 있었던 소스를 자바스크립트로 변경하였습니다. 변경 후 정확한 값이 출력되는지는 확인하지 않았습니다.

우선 메뉴의 File/Save에서 ZBiorhythm으로 프로젝트를 저장하고 시작합니다. 프로젝트명은 개인의 취향대로 변경하시면 됩니다.


1) Front 화면 설정

기본으로 생성되어 있는 Hello World! 텍스트를 삭제합니다. 라이브러리 윈도우의 Parts 항목에서 canvas를 끌어다 아래와 같이 배치 합니다.
사용자 삽입 이미지

사용자 삽입 이미지
canvas 속성에서 크기를 180 X 120으로 설정합니다. 속성창은 오브젝트가 선택된 상태에서 상단의 [inspector] 버튼을 클릭하거나, 키보드에서 [option + command + i]를 같이 누르시면 됩니다.



사용자 삽입 이미지
이제 라이브러리 윈도우에서 텍스트를 위젯의 상단에 배치 합니다. 텍스트를 더블클릭하여 위젯의 이름을 입력합니다. 저는 위와 같이 ZBiorhythm이라고 이름 지었습니다.

사용자 삽입 이미지
그 다음 속성창에서 텍스트의 속성을 설정합니다. Style을 Bold로, Size는 12pt로 설정하였습니다. 타이틀, 스타일, 색상, 크기 등은 취향대로 선택하시면 됩니다.





사용자 삽입 이미지
Library Parts에서 텍스트를 세개 더 드래그해서 아래와 같이 배치 합니다. 위와 같이 해당 텍스트를 더블클릭하면 텍스트를 변경할 수 있습니다.

각각 Physical, Sensibility, Intellectual이라고 입력하고, 속성창에서 색상을 blue, red, green으로 지정해 줍니다. (처음에 말씀드린 것과 같이 한글을 입력하면 오류가 나서, 영문으로 하였습니다.)


Library Parts에서 Text Field를 세개 가지고 와서 좌측과 같이 배치하고, 크기를 조절합니다.  아래와 같이 속성창에서 ID를 위에서 부터 각각 bio0, bio1, bio2로 설정합니다.
사용자 삽입 이미지


2) Back 화면 설정

이제 좌측 오브젝트 목록에서 back을 클릭하여, 옵션을 설정할 수 있는 위젯의 뒷면을 만들어 보겠습니다. 라이브러리에서 텍스트 필드를 드래그로 back 화면으로 가지고 옵니다. Birthday로 타이틀을 변경하고, 잘 보일 수 있도록 속성창에서 색상을 white로 변경합니다.

그 하단에 세개의 텍스트 필드(Text Field)를 배치하여, 바이오리듬 계산을 위해 사용자의 생년월일을 입력 받도록 합니다. 첫번째 텍스트 필드부터 속성창의 ID를 각각 b_year, b_month, b_day로 설정합니다.
사용자 삽입 이미지

이제 Workflow Steps의 Lay out interface에 해당하는 작업을 완료하였습니다. 그 하단의 Add handlers & code 작업을 해보겠습니다.

3) 소스코드 작성

좌측 Workflow Steps 항목에서 Add handlers & code를 클릭하면 나타나는 Source code editor 왼쪽의 삼각형 아이콘을 클릭합니다. 아래와 같이 우측 하단에 소스창이 나옵니다.
사용자 삽입 이미지

현재 소스가 ZBiorhythm.js 임을 확인하시고, 아래의 내용을 상단에 입력합니다. 제목 그대로 Dashcode 맛보기 이므로, 자세한 설명 없이 간단한 주석으로 대체하겠습니다.
/***
* MyCode
**/
var MAX_TYPE = 3;  // 신체, 감성, 지성의 분류 갯수 설정
var PI = 3.14159;  // 바이오리듬 계산을 위한 원주율
var TDV = (60*60*24*1000); // 밀리세컨드(1/1000초)를 일로 환산하기 위한 값

var curDate = new Date(); // 오늘 날짜
var startDate = new Date(curDate.getYear(), curDate.getMonth(), 1); // 출력 시작일
var birthDate = new Date(); // 사용자 생년월일

/** bio_info - 바이오리듬 계산과 출력을 위한 정보
    23, 28, 33 -> 각각의 바이오리듬을 계산할 값
    ble, red, green -> 출력 색상
*/
var bio_info = new Array(MAX_TYPE);

bio_info[0] = new Array(23, "blue");
bio_info[1] = new Array(28, "red");
bio_info[2] = new Array(33, "green");

/*
바이오리듬 타입에 맞추어, 한달 치 배열값(해당 바이오리듬 값)을 반환한다.
idx -> 바이오리듬 타입 0-신체, 1- 감성, 2-지성
*/
function getBioData(idx)
{
    var data = new Array(31);

    var c_days = startDate.getTime()/TDV;
    var b_days = birthDate.getTime()/TDV;
    
    var cc = bio_info[idx][0];
    for(i = 0; i <= 30; i++)
    {
        var gab = c_days - b_days;
       
        var p = parseInt(Math.sin((gab/cc) * 2 * PI) * 100);
        data[i] = p;
       
        c_days++;
    }
    
    return data;
}

/** 바이오 리듬 출력 */
function showGraph()
{
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    
    context.lineWidth = 1.0;
    context.shadowBlur = 1;

    // 가로 기준선 출력    
    context.strokeStyle = "7f7f7f";
    context.moveTo(0, 60);
    context.lineTo(180, 60);
    context.stroke();

    // 세로 기준선 출력
    context.strokeStyle = "#efefef";
    for(i = 0; i <= 30; i++)
    {
        context.moveTo(i*6, 0);
        context.lineTo(i*6, 120);
       
        // 오늘 날짜일 경우에는 짙은 색으로 출력
        if(i == curDate.getDate() - 1)
            context.strokeStyle = "7f7f7f";

        context.stroke();
        if(i == curDate.getDate() - 1)
            context.strokeStyle = "#efefef";
    }
    
    // 바이오 리듬 출력
    context.lineWidth = 1.0;
    context.shadowBlur = 3;
    for(k = 0; k < MAX_TYPE; k++)
    {
        var data = getBioData(k);
        context.strokeStyle = bio_info[k][1];
        for(i = 0; i <= 30; i++)
        {
            context.moveTo(i * 6, (100 - data[i])/2 + 10);
            context.lineTo((i + 1) * 6, (100 - data[i+1])/2 + 10);
       
            context.stroke();
           
            // 오늘 날짜일 경우에는 입력창에 각각의 바이오리듬 값을 출력
            if(i == curDate.getDate() - 1)
            {
                document.getElementById("bio" + k).value = data[i];
            }
        }    
    }    
}

/* 사용자 생년월일을 세팅하고, 저장된 생년월일이 없으면 false를 반환한다. */
function setBirthDay()
{
    if(window.widget)
    {
        if(widget.preferenceForKey("b_day"))
        {
            birthDate.setYear(widget.preferenceForKey("b_year"));
            birthDate.setMonth(widget.preferenceForKey("b_month"));
            birthDate.setDate(widget.preferenceForKey("b_day"));
       
            return true;
        }
    }
    return false;
}

Dashcode가 생성해 준 소스에서 아래의 내용을 추가합니다.
function load()
{
    setupParts();
   
    // 사용자가 설정을 하지 않았을 경우, 설정창(back)으로 간다.
    if(setBirthDay() == false)
    {
        showBack(null);   
    }
}

function show()
{
    // your widget has just been shown.  restart any timers
    // and adjust your interface as needed
    showGraph();
}

function showBack(event)
{
    // your widget needs to show the back

    var front = document.getElementById("front");
    var back = document.getElementById("back");

    if (window.widget)
        widget.prepareForTransition("ToBack");

    front.style.display="none";
    back.style.display="block";
   
    if (window.widget)
    {
        setTimeout('widget.performTransition();', 0);
       
        /** 저장된 값이 있으면, 옵션의 입력필드에 설정 한다. */
        document.getElementById("b_year").value = widget.preferenceForKey("b_year");
        document.getElementById("b_month").value = widget.preferenceForKey("b_month");
        document.getElementById("b_day").value = widget.preferenceForKey("b_day");
    }
}

function showFront(event)
{
    // your widget needs to show the front

    var front = document.getElementById("front");
    var back = document.getElementById("back");

    if (window.widget)
        widget.prepareForTransition("ToFront");

    front.style.display="block";
    back.style.display="none";
   
    if (window.widget)
    {
        setTimeout('widget.performTransition();', 0);
   
        /** 사용자의 입력을 저장한다. */
        var b_year = document.getElementById("b_year").value;
        var b_month = document.getElementById("b_month").value;
        var b_day = document.getElementById("b_day").value;
       
        widget.setPreferenceForKey(b_year, "b_year");
        widget.setPreferenceForKey(b_month, "b_month");
        widget.setPreferenceForKey(b_day, "b_day");
    }
    /** 그래프를 출력한다. */
    showGraph();
}

사용자 삽입 이미지
이제 Add handlers & code까지 작업을 완료하였습니다. 작업이 완료 되면 좌측의 Workflow Steps에서 해당 항목의 [Make as Done]을 클릭하면 완료된 작업으로 표시됩니다.

현재 어디까지 작업이 되어 있는지 확인할 수 있습니다. 취소는 [Make as Not Done]을 클릭하시면 됩니다.


4)  위젯 설치 및 실행

다음은 Set attributes 작업입니다.  여기선 변경없이 기본설정 사항을 사용하겠습니다. Attributes 버튼을 클릭하시면, 설정사항을 확인할 수 있습니다.

다음은 Preview default image 입니다. default image는 위젯이 처음 로딩될  때나, 설치 확인 시 나오는 이미지 입니다. 다음은 아이콘 설정인데 이역시 모두 생략하겠습니다.

사용자 삽입 이미지
이제 위젯을 사용해 보도록 하겠습니다. 메뉴에서 File을 클릭하면 좌측과 같이 Deploy Widget... 메뉴가 있습니다. 이 메뉴는 작성한 위젯을 위젯 포맷에 맞추어 저장하여 줍니다. 저장된 위젯(디렉토리)을 압축하여 배포하시면 됩니다.

다음의 Deploy Widget to Dashboard... 는  위젯을 지금 사용중인 컴퓨터에 설치하여 줍니다.




Deploy Widget to Dashboard... 로 제 컴퓨터에서 실행해 본 모습니다. 역시 급조한 만큼 눈에 거슬리는 부분이 많이 있습니다.
사용자 삽입 이미지 사용자 삽입 이미지

사용자 삽입 이미지
대쉬보드 설정화면에서 하단을 보면, 좌측과 같이 ZBiorhythm의 아이콘이 보입니다. 아이콘을 설정을 하지 않았기 때문에 빈 아이콘으로 보입니다.

 


3. ToDo...
제가 Dashcode를 테스트 삼아 처음 사용해 보면서, 작업한 내역을 그대로 올렸기 때문에 실제 사용 시에는 문제가 작성될 수 있습니다. 아래의 몇 가지 사항들만 추가하면 실제로 사용할 수 있을 것 입니다.

1. 버그 확인 및 수정
버그 테스트 없이 한번 실행해 보고 올리는 것이라, 오류가 있을 수 있습니다.

2. 바이오리듬 데이터 확인
이전에 언급한대로 다른 언어로 되어 있는 내용을 옮겼기 때문에, 옮기는 중간에 오류가 있을 수도 있습니다.

3. 사용자 입력 확인
사용자 생일을 입력시, 숫자인지, 유효한 날짜인지, 모두 입력하였는지 확인하는 소스를 추가 합니다. Dashcode에서 Run할 때 랑 실제 위젯에서 입력창의 크기가 틀렸습니다. 역시 수정하지 않았습니다.

4. 그래프 디자인 변경
그래프 배경이나 바이오리듬 곡선등의 색상이나 바탕색, width 및 기타 설정 등을 조절합니다.

5. 날짜 변경
front에서 년월을  선택할 수 있도록 합니다.

이상 간단하게 둘러보기를 마치겠습니다. 저도 더 많이 사용해 보고, 어느 정도 알게되면 맛보기란 제목이 아닌 사용하기란 제목으로 다시 한번 제대로 된 위젯을 작성해 보겠습니다.
 
AND

맥은 unix를 기반으로 하고 있지만, 일반적인 사용자들은 맥을 터미널 환경에서 유닉스로 사용할 일이 거의 없습니다. 하지만 터미널을 이용하면 맥을 유닉스 답게 사용할 수 있고, UI 상에서는 접근할 수 없는 파일이나 디렉토리에 접근 할 수 있어 OS X의 구조를 이해하는데 도움이 됩니다.

C를 공부하시는 분들은 /usr/include 밑의 C 헤더파일 들에서 많은 정보를 얻으실 수 있습니다. C 강좌에서 include하는 stdio.h 파일도 여기에 있습니다.

이제 맥 터미널에서 한글 입출력을 가능하게 하고, 편리하게 사용할 수 있는 몇 가지 작업을 해 보겠습니다.

1. iTerm 다운로드 및 설정
맥에서는 기본적으로 터미널 어플리케이션을 제공합니다. 하지만 빈약한 기능과 한글 사용의 문제로 iTerm을 사용하시는 것이 좋습니다.

iTerm은 터미널에 비해 많은 기능을 가진 코코아로 작성된 맥용 공개 터미널 프로그램입니다. http://iterm.sourceforge.net/에서 iTerm의 최신 버전을 다운 받고 실행합니다.

Bookmarks 메뉴에서 Manage Profiles...를 실행합니다.  Terminal Profiles/Default에서 Type와 Encoding을 아래와 같이 설정합니다.
사용자 삽입 이미지

사용자 삽입 이미지
Bookmarks/Manage Bookmarks...를 실행하고, 하단의 연필 아이콘 버튼을 클릭하여 Display 속성과 필요한 속성들을 변경합니다.

저는 classic iTerm Large이 가장 보기 좋은 것 같아 이것으로 선택하였습니다.







2. vi
1) vi의 기본 사용법

유닉스 계열에서는 에디터로 vi와 emacs를 주로 사용합니다. emacs는 막강한 기능을 가졌지만, 사용법이 vi 보다 복잡하고 어렵기 때문에 여기서는 vi를 예로 들겠습니다.

터미널로 로그인을 하고, 프롬프트 상태에서 vi를 실행(vi [return]) 합니다. 처음 시작되면 아래와 같은 메세지 화면이 나올 것입니다.
사용자 삽입 이미지

vi는 기본적으로 키보드만 가지고 사용되기 때문에, 입력 모드와 명령 모드로 나누어져 동작합니다. 일단 vi를 종료해 보겠습니다. 명령행 모드는 [esc] 키를 누르면 실행됩니다.

사용자 삽입 이미지
처음 시작시 명령 모드 이기 때문에, ":"를 입력하면 vi 좌측 하단에 ": "가 출력됩니다.  이 때 vi를 종료하는 q를 입력하고 [return]을 치면 vi가 종료됩니다.



이번엔 파일을 하나 만들어 보겠습니다. > vi text.txt 로 vi를 실행합니다. 여기서 i를 입력하면 입력모드가 실행됩니다. 아직 한글은 제대로 입력되지 않기 때문에 영문과 숫자를 입력해 봅니다.

입력이 완료되면 [esc]를 눌러 명령 모드로 변경하고, 위와 같이 ":wq"를 입력하고 [return]을 입력합니다. wq는 파일을 저장하고 종료하라는 명령어입니다.

설정을 위한 아주 기본적인 명령어만 알아 보았습니다. vi는 이외에도 사용을 편리하게 해주는 많은 명령어들이 있습니다. 하지만 기본적으로 15개 정도만 알아도 사용하는데 지장은 없습니다.


2) .vimrc 설정

이제 vi에서 한글입력이 가능하고, 사용하기에 편리하도록 만들어 보겠습니다. 계정의 루트 디렉토리(터미널 실행시 기본 디렉토리 이며, 프롬프트 상에서 cd[return]을 치면 됩니다)로 가서 vi .vimrc를 입력하고 실행합니다.

vi가 실행되면 아래의 내용을 복사하고 i로 입력모드로 만든 후 붙여 넣습니다. 그 후에 위와 같이 esc -> :wq[return]으로 저장하고 나옵니다.

set enc=UTF-8
set fileencodings=UTF-8

set nocompatible
set backspace=indent,eol,start

set tabstop=4
set shiftwidth=4
set cindent
set autoindent
set smartindent
set history=15
set ruler
set showcmd

set background=dark
set paste
set nu
set ai
syntax on
언어를 UT-8로 설정하고 코딩을 위한 들여쓰기, 탭크기, 문법 구분 등을 설정합니다. 이외에 자료를 찾아 보시고 개인별로 용도에 맞게 수정해서 사용하시면 됩니다.


3. 쉘 환경 설정

1) .bash_profile

다시 계정의 루트 디렉토리에서 vi .bash_profile을 입력합니다. .bash_profile은 사용자 별로 터미널 쉘 환경 설정을 저장하는 파일로 보시면 됩니다. 파일 앞의 "."을 꼭 입력하셔야 합니다. 아래의 내용을 복사하여 붙여 넣습니다.

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

alias ls='ls -vGF'

PS1="[\u@\h \W]\\$ "

처음 세 명령어는 삭제, 복사/이동시 같은 파일이 있을 경우 사용자에게 확인을 받도록 합니다.

alias ls='ls -vGF'
파일 목록을 보여주는 ls 명령어 실행시, 디렉토리를 한글명으로 표시하고 색상을 보여주도록 합니다.

PS1="[\u@\h \W]\\$ "
프롬프트 출력을 변경합니다. u는 사용자, h는 호스트명, W는 현재 디렉토리를 의미합니다.

이제 이전과 같은 방법으로 .bash_profile를 저장하고 나옵니다.


2) .inputrc

위와 같이 vi .inputrc를 열고 아래의 내용을 복사하고 저장합니다.
set convert-meta off
set meta-flag on
set output-meta on

위의 명령들로 프롬프트 상태에서 한글이 올바르게 입력되도록 합니다.

위의 변경된 사항들이 적용되게 하기 위해, 터미널을 닫고 다시 실행하여 로그인 합니다. 이제 터미널에서 제대로 한글이 보이고, 터미널 및 vi에서 한글을 입력하고 출력되는 것을 확인 할 수 있습니다.


3)  로그인 메시지 및 호스트 명 변경

이제 터미널로 로그인 시 출력되는 메시지를 변경해 보겠습니다.

sudo vi /etc/motd [return]
sudo는 루트권한을 사용할 수 있게 하는 명령어로 위와 같이 입력하면 패스워드를 확인합니다. 여기서는 프로그램 인스톨 시나 업그레이드시 입력하는 본인의 패스워드를 입력하면 됩니다.

저는 아래와 같이 입력하고, 저장하였습니다.
사용자 삽입 이미지

sudo scutil --set HostName iMac [return]
프롬프트에 나오는 호스트 명을 변경하고 싶을 때는 위와 같이 변경합니다. 위의 iMac 부분을 원하시는 호스트 명으로 변경하시면 됩니다.

이제 다시 로그인을 하면 아래와 같이 환영 메시지와 함께, 호스트 이름이 iMac으로 변경되어 있는 것을 확인할 수 있습니다.
사용자 삽입 이미지


4. 루트계정 활성화
root 권한으로 해야 할 작업이 많을 경우에는 sudo만으로는 불편함이 있습니다. 맥에서는 기본으로 root 계정을 사용할 수 없기 때문에, root 계정을 사용할 수 있도록 변경합니다. root는 중요한 파일을 실수로 삭제하면 시스템에 치명적일 수 있기 때문에, 이 부분은 필요성을 느끼는 분들만 변경하시면 됩니다.

사용자 삽입 이미지
어플리케이션/유틸리티에서 NetInfo 관리자를 실행합니다. 상단 메뉴의 보안에서 인증을 한 후, 보안 메뉴 하단의 루트계정 활성화을 클릭한 후 사용할 패스워드를 입력하고 활성화 합니다.



이제 위에서 입력한 패스워드로 루트 계정을 사용할 수 있습니다. 루트 계정 사용은 프롬프트 모드에서 su를 입력하고 위에서 설정한 패스워드를 입력하시면 됩니다.
AND