저번 포스트 에서 Clojure 와 Emacs 와 Slime 을 연동 시키는 방법을 했다면, 이제 실제 클로져 코드를 짜야 하는 일이 생길 것입니다. 그런데 전역으로 환경을 세팅하는 것이 아니기 때문에 다른 클로져 라이브러리를 포함 시키는 것이 어려울 것 같습니다. 특히 clojure-contrib 같은 거의 필수 라이브러리는

lein 으로 만들어준 프로젝트의 project.clj 를 열어줍니다.

$ lein new test-project
$ cd test-project
$ emacs project.clj


다음 과 같이

                 [org.clojure/clojure-contrib "1.2.0"]


의 내용을 :dependencies 에 추가해 줍니다.


아래에 붙어 있는 congomongo 는 무시하세요.

$ lein deps


를 실행해 주면 clojure-contrib 를 다운 받아서 프로젝트 환경에 추가해 줍니다.
이제 Emacs 상에서 Clojure 랑 Slime 을 연동시켜서 원하는 코드를 만들어 주면 됩니다.

M-x clojure-jack-in


지금 일하는 곳이 버추얼박스 (VirtualBox) 에서 네트워크 드라이버가 안잡히게 하는 멋진 보안 환경 때문에 공유폴더를 이용해서 파일을 복사하여 수동으로 설치하게 되어 있습니다. 따라서 GTK 를 써야만 하는 X 를 지원하는 Emacs 는 엄두도 못 내고 , Console 모드로 컴파일 해서 사용할려고 하다가 에러가 발생해서 해결하는 방법을 알아보겠습니다.

Emacs (23.4) 를 우분투 (11.10) 에서 수동으로 컴파일 할때 발생하는 문제입니다.

make[1]: *** No rule to make target `/usr/lib/crt1.o', needed by `temacs'.  Stop.


crt1.o 때문에 에러가 발생한 것임을 알 수가 있습니다.

$ gcc -print-file-name=crt1.o
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o

이렇게 위치 확인을 해주고

$ ./configure --without-x --with-crt-dir=/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/


이런식으로 crt 가 위치하는 디렉토리를 포함시켜서 configure 를 다시 실행해주고

$ make
$ sudo make install

하면 됩니다. 열악한 환경에서 서버 개발을 하는 모든 개발자들 분 파이팅!!




UITextView 에서 단어 개별에 관한 특정 작업(색을 다르게 입힌다던가, 애니메이션, 이미지 추가)을 위해서는 단어가 출력되는 좌표와 크기를 알아야 합니다. 그 개별 개별 단어의 크기와 좌표를 알아내는 방법에 관한 글 입니다. 

iPhone apps 개발하는 중에 문장이 쓰여져 있는 UITextView 에서 특정 단어에 효과를 주고 싶었습니다. UIWebView 를 이용해서 화면에 글을 출력하고 CSS 와 Javascript 를 이용해서 개발하면 된다는 소리가 있기는 하던데, 제가 잘 아는 분야와는 조금 거리가 있어서, UITextView 를 수정하기로 했습니다. 

원리

원리는 쉽습니다. UITextView 에서 문장을 출력하는 경우라고 하면

1. 문장을 각 단어별로 쪼개서 NSArray 로 저장합니다. 

2. 쪼개진 단어가 표시되는 좌표와 테두리 크기를 알아냅니다. 

3. 변경을 주고 싶은 단어 위에 같은 크기(단어 와)의 UILabel 을 살짝 얹어줍니다. 

4. UILabel 에 이미지나 폰트, 글자색을 변경해 줍니다. 



즉 이렇게 보이는 화면이 있으면 , 아래쪽에 보이는 'Hello' 라는 버튼을 터치하면 



이런식으로 각 단어들이 보이는 듯이 색이 입혀집니다. 

구현

원리는 쉽지만, 막상 구현할려고 하니 힘들더군요. 비슷한 코드가 있나 찾아보는데만 반나절 이상을 소비했습니다. (결국 못찾아서 직접 만들어 줬습니다) 화면에 문장이 출력되는 부분에서 패딩을 생각 못해줘서 또 시간 많이 소비했구요. 

Object-C 와 아이폰 개발에 익숙치 않아서 , 문법이 이상한 것들이 조금 보이더라도 고수분들께서는 이해해주시기 바랍니다. (지적도 감사합니다 )


- (IBAction) rePaintWord: (id) sender 
{
    // color Array 를 만든다. 
    NSArray * color_array = [NSArray arrayWithObjects:[UIColor grayColor] , [UIColor redColor] , 
                                     [UIColor greenColor], [UIColor blueColor], [UIColor yellowColor],
                                     [UIColor orangeColor], [UIColor brownColor], nil];
    

    // 단어들 tokenizing 한다
    NSArray * myWords = [overLookTextView.text componentsSeparatedByString:@" "]; // 문장에 쓰인
    NSInteger count = [myWords count] ;

    // 실제로  contents 가 뿌려지는 textview 크기 보정을 한다. padding 크기를 
    // 보정 안해주면 반나절 이상 테스트 한다고 해도 제대로 결과가 나오지 않는다. 
   
    // padding size 이 패딩 사이즈는 일명 마법숫자(magic number)이다.
    // 원리도 모르고 어딘가에서 표시도 되지 않았다. -ㅅ- 
    int padding_size = 11; 

    CGSize content_size = CGSizeMake (overLookTextView.contentSize.width - padding_size ,
                                      overLookTextView.contentSize.height - padding_size);

    // 높이가 변하게 되는 단어를 지정하기 위한 산물이다. 즉 갑자기 높이가 변하는 단어는 lineBreak
    // 됐다고 보면 된다. 바로 그 시점의 높이와 Range 를 저장하기 위해서 이다. 

    CGSize last_string_size = CGSizeMake(0,0);
    NSRange last_result_range = NSMakeRange(0, 0);

    NSRange result_range = NSMakeRange(0, overLookTextView.text.length);

    for(int i = 0 ; i < count ; i++)
    {

        // 전체 문장에서 정확히 원하는 단어를 검색하기 위해서 이다. 정규표현식을 썼으며 
        // 단어 인 것들만 찾기 위해서 썼다. NSRegularExpressionSearch 는 
        // iOS 4.0 이상부터 지원한다고 한다. 
        result_range = [overLookTextView.text 
                         rangeOfString:[NSString stringWithFormat:@"\\b%@",
                          [myWords objectAtIndex:i]]
                         options:NSRegularExpressionSearch range:result_range] ;
       

        // 실제로 찾고자 하는 단어가 차지하는 영역 크기 
        CGSize wordSize = [[myWords objectAtIndex:i] 
                        sizeWithFont:overLookTextView.font forWidth:content_size.width 
                        lineBreakMode:UILineBreakModeWordWrap];


        // 시작부터 단어를 포함한 줄까지 잘라내기 
        NSString* head = [overLookTextView.text 
                  substringToIndex:result_range.location + result_range.length];

        // 위에서 잘라낸 단어줄의  content 크기 알아내기 , 이는 높이를 비교하기 위해서
        //  알아보는 것이다. 지난번 결과로 저장된 높이랑 틀려진다면
        // 줄이 바꼈음을 알고 바로 그 시점이 마지막 범위와 높이가 저장되는 시점이다. 
        CGSize string_size = [head sizeWithFont:overLookTextView.font 
               constrainedToSize:content_size lineBreakMode:UILineBreakModeWordWrap];
        if (string_size.height != last_string_size.height)
        {
            last_result_range = result_range ; // 줄바뀌는 첫번째 단어 의 시작 위치를 저장
            last_string_size = string_size ;
        }


        // head 는 문장의 처음부터 단어를 포함하고 있는 문자열까지 잘라낸 것이다. 
        // tail 은 줄이 바뀐 첫 단어부터 단어를 포함하는 곳까지 잘라낸 것이다. 
        NSString * tail = [head substringFromIndex:last_result_range.location];

        // lineSize 는 줄이 바뀐곳부터 단어를 포함한 곳까지의 크기를 얻어내서 저장하는 곳이다. 
        CGSize lineSize = [tail sizeWithFont:overLookTextView.font forWidth:content_size.width 
                                                    lineBreakMode:UILineBreakModeWordWrap];

        // temp_rect 는 단어가 위치하는 좌표값과 크기가 저장된다. 하지만 이는 
        // 실제로 위치한 곳과 확실하게 일치시켜 줄려면
        // textView 가 위치한 실제 좌표 값과 글자가 실제로 출력되는 
        // 위치까지의 'padding' 값을 더해 주어야 한다. 
        // 심각한 문제는 여기서 더해주는 padding 은 위에서 content 
        // 윈도 크기를 보정하기 위해서 더해주는 padding_size 값과는
        // 다르다는 것이다. 

        CGRect temp_rect = CGRectMake (lineSize.width - wordSize.width , 
                         last_string_size.height - wordSize.height ,
                                       wordSize.width , wordSize.height);


        // Test 삼아서 위치보정해주고 (textview , padding) 실제 글자 위치에 
        // 작은 Label 을 한개 만들어서 덮어놓는 함수를 작성했다.
        [self make_label_on_screen:[myWords objectAtIndex:i] 
              rect:temp_rect color:[color_array objectAtIndex:( i % [color_array count]) ]];

        // 검색 범위를 변경해 주는 곳이다. 단어를 찾은 크기만큼 이동해 주는 모듈
        int new_location = result_range.location + result_range.length ;
        result_range = NSMakeRange(new_location , overLookTextView.text.length - new_location);
    }
        
}

- (void) make_label_on_screen:(NSString *) word rect:(CGRect) 
                                        label_rect color:(UIColor *) color
{

    // 실제 위치를 표기해 주는 패딩과 textview 위치 찾기
    CGFloat ui_padding_size = 7.9;

    label_rect.origin.x += overLookTextView.frame.origin.x ; 
    label_rect.origin.y += overLookTextView.frame.origin.y ; 

    label_rect.origin.x += ui_padding_size;
    label_rect.origin.y += ui_padding_size;



    UILabel * nameLabel = [[UILabel alloc] initWithFrame:label_rect];
    nameLabel.text = word ;
    nameLabel.textColor = color;
    nameLabel.backgroundColor = [UIColor clearColor];
    nameLabel.textAlignment = UITextAlignmentRight;
    nameLabel.font = overLookTextView.font ;
    
    [self.view addSubview: nameLabel];
    [nameLabel release];
}
'Hello' 버튼에 대응되는 함수와 UILabel 을 한개 얹어주는 함수 두개를 만들어 줬습니다. 혹시 몰라서 Test 로 만들어본 프로젝트를 첨부 합니다. 




잠시 아이폰 (제가 쓰는 것은 아이팟 터치 1세대) 에서 개발을 해서 프로토 타입을 만들 일이 다시 생겨서 Xcode 를 다시 손대게 되었습니다.

예전 포스팅 에서 탈옥한 상태의 아이폰(아이팟 터치)에서 개발이 가능하게 만들어 줬었습니다. 그 당시 아이폰 OS 3.1.2 였었습니다. 문제 없이 개발을 잘 하고 프로토 타입 개발이 끝났었는데, 최근에 보니 iPhone SDK 가 4.0 으로 업그레이드가 되어 있더군요. 그래서 iPhone SDK 4.0 을 설치하고 개발을 할려고 하니 탈옥한 제 아이팟 터치에 프로그램이 인스톨이 안되는 문제가 생겼습니다. 아이팟 터치 1세대는 아이폰 OS 4.0 지원도 안해주더니 개발까지 속을 썩이더군요.

"Version 3.2.3 이 되버리면서 안되더군요"


예전 포스팅 과 동일하게 탈옥을 해주고 있는 상태니 XCode 설정만 바꾸어 줍니다.

  
   3-1. /Developer/Platforms/iPhoneOS.platform/Info.plist 파일을 열어서
   3-2. 52 번째 줄에서 XCiPhoneOSCodeSignContext 를 XCCodeSignContext 로 바꾸어 줍니다.
   3-3. 87 번째 줄에서 XCiPhoneOSCodeSignContext 를 XCCodeSignContext 로 바꾸어 줍니다.
   3-4. 파일 저장합니다.
   3-5. XCode 를 재시작합니다.

과거에 파일에서 바꿔준 부분을 다시 찾아서 바꾸어 줍니다.  라인수만 바뀌었다고 보시면 됩니다. 자 이렇게 까지 해 줬으니 제가 가지고 있는 Device (iPod touch 1G - 3.1.3)에 어플리케이션이 인스톨 되어야 하지만 안되더군요. 그래서 친구 iPod touce 2G 를 빌려서 인스톨 해보니 잘 되는 것 까지 확인해 봤습니다.

XCode 3.2.3 에서 개발해서 예전 iOS 버젼에서 돌려줄려고 하면 (특히 이번 경우에는 3.1.3 버젼) '빌드'는 상관이 없고 Deployment System 쪽만 수정해 주면 됩니다.

XCode - File - Get Info

순으로 메뉴에서 찾아서 눌러주시면



"Build" 탭에서 아래로 쭈욱 내려주다 보면 "iPhone OS Deployment Target" 에서 자신의 Device 에 설치되어 있는 OS 버젼을 선택해 주시면 됩니다.

돈은 없으신데 가지고 있는 디바이스에서 프로토타입을 개발하시고 싶은 분들에게 추천하고 싶은 방법입니다. 생각보다 힘들지도 않고요.




Android 를 개발하기에 제일 좋은 환경은 Eclipse 입니다.  android-sdk 에서 따로 plug-in 을 제공하고 공식문서에서 기본으로 설명하는 것이기 때문에 가장 좋은 환경이라고 할 수 있습니다. 이클립스는 기본적으로 진화된 Emacs 라고 불릴정도로 많은 기능과 다양한 플러그-인 쉬운 UI 인터페이스등 정말 좋은 IDE라고 할 수 있습니다.

그럼에도 불구하고 나는 독하게 Emacs 를 쓰시겠다고 하는 분들만 아래에 쓰여질 내용을 보시면 됩니다.

1.  Emacs 를 Android 개발 환경으로 쓸려고 하면 android-mode 를 설치해야 합니다. git 가 설치되어 있다고 가정하고

git clone git://github.com/remvee/android-mode.git


과 같이 입력합니다. 그러면 android-mode 라는 디렉토리가 생깁니다. 제 경우에는 그 디렉토리를 "~/.emacs.d/android-mode" 로 복사해줬습니다.

2. 그리고  저번 포스팅인 "[Android] Snow Leopard 에 SDK 설치하기" 에서 설치됐던 Android SDK 가 위치한 곳 (제 경우에는 저번 포스트에서 "~/work/android" 였습니다.) "PATH_ANDROID_SDK/tools/lib"밀에 있는 android.el 을 "~/.emacs.d/android-mode" 밑에 같이 복사해 줍니다.

3. 그리고  .emacs 파일에 다음과 같이 추가해 줍니다.

(add-to-list 'load-path "~/.emacs.d/android-mode")
(require 'android-mode)
(require 'android)
(setq android-mode-sdk-dir "~/work/android")

이렇게 하면 android-mode 의 기능과 android 에서 자체적으로 지원하는 android 기능을 두가지 다 쓸 수가 있습니다.

이제 실제로 프로젝트를 만들어 보기로 하지요. http://developer.android.com/guide/developing/other-ide.html 이클립스를 쓰지 않고 다른 IDE 를 쓸 경우에 참조해야 하는 곳입니다. 그중에서 프로젝트 만드는 것을 참조하기로 하겠습니다.

android create project \
--target <target_ID> \
--name <your_project_name> \
--path path/to/your/project \
--activity <your_activity_name> \
--package <your_package_namespace>
라는 식으로 만들게 되어 있습니다. 다 일반적인 내용이고 실제로 몇번 만들어 보시면 어떤식으로 돌아가는지 아실 수 있습니다. 참조한 사이트에서 설명도 충분하고요. 다만 target 을 실제로 어떤것을 써야 할지 감이 안오실 수 있을 실텐데요. Terminal 창을 한개 여시고

android list targets.

라고 입력하시면 target 에 대한 설명이 자세히 나옵니다. 저번 포스팅 "[Android] Snow Leopard 에 SDK 설치하기" 에서 만들어본 testMachine 이라고 하는 AVD 는 타겟이 "10" 입니다.

이렇게 만들어진 프로젝트에서 "path/to/your/project/<your_project_name>/src/<your_package_namespace 를 갈라서 디렉토리로표현>/<your_activity_name>.java" 파일을 열어서

M-x

android-ant-install

라고 입력하시면 프로젝트가 컴파일이 되고 알아서 인스톨이 됩니다.

android-mode 에서 쓸만한 단축키를 보여드리겠습니다.

"\C-c \C-c" 를 입력한 상태에서

   
    ("d" . android-start-ddms)
    ("e" . android-start-emulator)
    ("l" . android-logcat)
    ("c" . android-ant-compile)
    ("i" . android-ant-install)
    ("r" . android-ant-reinstall)
    ("u" . android-ant-uninstall)

단축키에 따라서 실행되는 명령들 입니다.

여기까지는 쉽게 따라할 수 있는 부분입니다. 이제부터가 어려운데 특히나 Snow Leopard 에 설치하는 것이라 더 힘들었던것 같습니다.

위에 나와 있는 내용대로 포스팅을 하면 그냥 노트패드 같은 에디터에서 개발하는 것과 별 차이가 없습니다. 기본적으로 code generation 이나 code auto-completion 등이 되지 않으면 쓰기에 많이 불편합니다. 그래서 JDEE (Java Development Environment for Emacs) 를 설치해서 사용하게 됩니다.

Emacs + JDEE 가 딱 자바용 Eclipse 라고 보시면 됩니다. 다시금 Eclipse 를 설치해서 개발하면 편하다는 것을 말씀드리고 싶습니다.

1. JDEE 를 다운 받습니다. http://sourceforge.net/projects/jdee/files/ 에서 받으시고. 2.4.0.1 버젼을 받으시면 됩니다. 압축을 푸시고 "~/.emacs.d/jdee-2.4.0.1/" 로 복사해 두시면 됩니다.

2. ELIB 이 필요합니다. JDEE 를 받은곳에 포함되어 있습니다. http://sourceforge.net/projects/jdee/files/ 에서 받으시고 버젼은 1.0 입니다. elib-1.0.zip 을 받으시고 압축풀고 "~/.emacs.d/elib-1.0/" 으로 복사해 두시면 됩니다.

3. CEDET (Collection of Emacs Development Environment Tools) 이 필요합니다. http://cedet.sourceforge.net/ 에서 다운이 가능합니다. http://sourceforge.net/projects/cedet/files/ 에서 cedet-1.0pre7.tar.gz 을 다운 받으시고 압축을 푸신 다음에 "~/.emacs.d/cedet/" 으로 복사합니다.

4. USER_HOME 에 (제 경우에는 /Users/crazia ) 에 있는 .bash_profile 파일을 열고 다음과 같은 내용을 추가합니다.

export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
export JAVAC=$JAVA_HOME/bin/java

저장하고 Terminal 창을 한개 열고

source .bash_profile


이라고 바로 효과가 나타나게 해 줍니다.

5. 이제 .emacs 파일에 다음과 같은 내용을 추가해 줍니다.  (추가 설명을 해 가면서 붙이기 하겠습니다)

(add-to-list 'load-path "~/.emacs.d/cedet/common")
(add-to-list 'load-path "~/.emacs.d/cedet/contrib")
(require 'cedet)

JDEE 는 기본적으로 CEDET 을 필요로 합니다. CEDET 을 설정하는 부분입니다.

(add-to-list 'load-path "~/.emacs.d/elib-1.0")
(add-to-list 'load-path "~/.emacs.d/jdee-2.4.0.1/lisp")
(require 'jde)

elib 과 jdee 의 path 를 추가해 주는 부분입니다. 그리고 jde 를 불러줍니다.

(setq jde-run-mode-hook t)

이상하게 jde-mode-hook 이 안불려지는 버그가 있더군요. 그래서 추가해 줍니다. 강제적으로 mode-hook 을 불러서 실행해줍니다.

(setq
 jde-sourcepath '( "/Users/crazia/work/android/project" )
 jde-db-option-connect-socket '(nil "28380")
 jde-jdk-registry (quote (
              ("1.5" . "/System/Library/Frameworks/JavaVM.framework/Versions/1.5/")
              ("1.6" . "/System/Library/Frameworks/JavaVM.framework/Versions/1.6/")
              )
             )
 jde-jdk `("1.6")
)

jdk 버젼을 조정할 수 있게 구현해 주는 부분입니다. OSX 다 보니 java 가 깔려 있는 곳의 디렉토리가 일반적인 unix 와는 조금 다릅니다.

;; cua-mode 끄기
(cua-mode nil)

\C-RET 은 정말 편하게 쓸 수 있는 단축키 인데 cua-mode 가 항상 점유하고 있으면서 바꿔지지도 않습니다. 아예 cua-mode 를 꺼버리면 편하게 쓸 수 있습니다.

(add-hook 'jde-mode-hook
          (lambda()
            (define-key jde-mode-map [(control return)] 'jde-complete)
        (define-key jde-mode-map [(meta return)] 'jde-complete-minibuf)
        (define-key jde-mode-map [(shift return)] 'jde-complete-in-line)))

자동 완성 단축키를 지정합니다. 제일 많이 쓰는 것이 "\C-RET" 다 보니 그 단축키를 jde-complete 함수에 묶었습니다.

이제부터 Emacs 에서 Android 개발이 쉬워지게 세팅을 끝냈습니다.



저자: 제레미 키스
옮김: 윤석찬

항상 웹을 배워볼려고 하다 보면 HTML 에서 끄적거리며 이거저거를 해보다가 포기하곤 했었습니다. "웹 자체가 어려운건 아니다" 라는 소리를 항상 들어오곤 했었습니다. 하지만 모르는게 너무 많다보니 배워야 할게 쌓여 있다 보니 웹 자체로 접근하기가 매우 힘들었습니다.

그런 의미에서 이 책은 아주 마음에 드는 책이였습니다. 기본은 Javascript 에 관한 책이였지만 HTML도 CSS도 다루고 있습니다. 그리 많이 다루지는 않지만 따라서 개발하기에 아주 충분할 정도로 잘 다루고 있습니다.

아무 생각없이 따라가다 보면 훌륭하게 결과물이 나오는 모습을 볼 수 있습니다. System Programming 하고는 또 다른 세상을 만나게 해주더군요.

결론적으로 말하면 이제 웹 이란 것이 어떤것일까? 맛좀 볼까? 하시는 분들에게 강력하게 추천합니다. 그렇기는 하지만 기본적으로 어느정도 코딩을 하실 수 있으면 더 좋겠더군요.

웹 서비스의 시작을 맛보시려는 분에게 꼭 필요한 책이라 생각합니다.


항상 이런 종류의 것을 부탁 받으면 고민되는 것이 프로그램을 잘 만드느냐? 하면 그것도 아니고 (손 놓은지가 꽤 됨) 그렇다고 글 솜씨가 탁월하는가? (방문자 숫자를 보면...) 하면 그것도 아닙니다.

하지만 이렇게 요청을 들어온 것을 보면 역시 살아가는데는 '인맥'이 제일 중요하다는 생각이 들기도 하지만 사실 어떠한 인맥보다는 '등가교환법칙'에 의함이 더 큽니다. 그렇다!! '등가교환법칙'은 비지니스의 법칙을 뛰어넘어 우주의 법칙입니다. (주는 대신 뭔가를 얻기로 한 것이죠..)

하지만 바쁜 회사일에 치여서 언제 써 줄지 모르는 상황이긴 합니다. 그래도 계속 계속 미뤄둘 수 없는 일이기 때문에 일단 제 블로그에라도 초안을 올리고 그것을 다듬어서 요청하는 쪽에 올리는 방향으로 가기로 했습니다. 



프로토타입으로 빠르게 개발 가능성만 타진했던 용도로 개발 했습니다. 소스는 나중에 전부 공개될 예정인데 그래픽 리소스만 제외될 것입니다.

어려운 기술도 아니라서 쓰ㄱ
UIImage 를 이용해서 화면에 출력하는데 정상적으로 출력시키는데도 화면상에서 계속해서 이미지가 반전해서 뿌려집니다. 열심히 구글링 해서 답을 알아냈습니다. 그 문제에 답을 올린 사람들하고 마음이 공유되는군요. '왜 애플은 모든것을 귀찮고도 어렵게 만드는 것일까?'

어찌됐건 해결을 했습니다.

원문보기: http://stackoverflow.com/questions/506622/cgcontextdrawimage-draws-image-upside-down-when-passed-uiimage-cgimage/511199#511199

UIImage *image = [UIImage imageNamed:@"testImage.png"];    
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);      

CGContextTranslateCTM(context, 0, image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextDrawImage(context, imageRect, image.CGImage);

위와 같은 식으로 코딩을 하면 반전되는 현상을 해결 할 수가 있다고 합니다. 좌표계 일치 시켜줘야 한다는 것이지요. 제일 이해가 안가는 것이. UIImage 의  drawInRect 메서드를 사용했을 경우 이미지가 반전이 되는 것이지요 ^^;

암튼 해결했습니다. 슈슝..

어제 후배와 모바일 플랫폼에 관한 이야기를 하던중에 생각난 것이 있어서 정리했습니다.

후배 생각에 아이폰이니 안드로이드니 요즘 개발자들이 크게 동요를 하고 있는데, 그걸로 돈을 많이 번 개발자가 나왔다던지 하지만 왠지 실제 이득을 보는 사람들은 따로 있는것 아니냐? 라고 이야기를 합니다.

전 세상일에 그렇게 까지 비평적일 필요는 없다고 봅니다. 하지막 '목적'이 어디에 있는것인지 잘 파악을 해야 한다는 것이지요. 아이폰이나 안드로이드 플랫폼은 지금 비약적으로 성장하고 있는 신흥시장은 분명합니다. 아니 이미 주력 시장에 들었다고도 볼 수가 있겠지요. 본질을 보자면 아이폰 어플이나 안드로이드 어플이나 그 근본은  util 일 수 밖에 없습니다. 데스크탑 시장에서의 solution 개념이지요

폭발적으로 성장하던 solution 시장은 나락으로 떨어졌습니다. 버티지 못했던 solution 회사들은 사라져 갔습니다. 예전 벤쳐에서 시작해서 크게 자리를 잡은 회사들의 CTO 들이 모여서 나눈 이야기 중에

"서비스와 컨설팅 만이 살아남을 것이다" 라는 이야기를 한 적이 있습니다. '안철수 연구소'의 사업모델이 solution 판매에서 서비스와 컨설팅으로 이동하는 것이 단적인 예라고 볼 수 있다는 것입니다.

그렇다면 모바일 플랫폼을 공부하는 것이 의미가 없겠느냐? 라고 던진 후배의 질문에 철저하게 제 생각만을 말해 줬습니다. 사용자에게 인터페이스를 제공하는 측면에서는 'Yes' 다. 그렇다고 모바일 플랫폼이 모든것이 되지는 않는다고 말해줬습니다. 그 이유에 대해서는 예전부터 제가 생각한 것이 있습니다.

정보! 정보가 중요한 것은 두말하면 잔소리겠지요. 정보의 흐름이 생산되는 곳, 그리고 그 정보가 모이는 곳이 계속되는 사업으로 유지되는 경향이 있습니다. 아이폰 어플 아무리 잘 만들어도 유행기간이 사라지는 순간 다른 어플이 치고 올라오는 것은 시간문제입니다. 정보가 아이폰에만 머무르기 때문이라고 생각합니다. 오직 정보가 끊임없이 생산되고 그 정보가 모이며 유지될 수 있는 곳,

그렇습니다. 바로 '웹' (인터넷, 소셜 네트워크.. 등등) 입니다. 아이폰이나 안드로이드 플랫폼은 그 서비스에 대한 '단말'로서 동작을 하는 것이지요.

후배와 길고 긴 이야기를 나누었지만 결론은 쉬웠습니다.

"향후 모바일 디바이스로 계속해서 인터넷에 접속되는 세상이 올 수밖에 없을 것이다. 예전에도 그랬지만 앞으로도 결국 웹 서비스가 대세가 되는 분위기가 될 수밖에 없다. 모바일 플랫폼 공부도 중요하지만 그 util 의 중심에는 웹 서비스가 있어야 할 것이다. 조금 어려운 이야기 겠지만 정보의 흐름을 창출하고 정보가 모일 수 있는 웹서비스를 만들어야 한다. 만약 웹쪽 서비스 개발분야가 약하다면 제일 먼저 웹 개발부터 익혀라"


프로그램을 오래 짜 왔지만, 주로 시스템 베이스의 프로그램만 만들어 왔습니다. Windows 나 unix 시스템 계열의 코딩만 하다보니, c/c++ 에 너무 익숙해져서 뭔가 허전하더군요. 요즘 대세인 web programming 도 못하고, 그러던 차에 몇년전 부터 후배의 꼬임에 넘어가서 emacs 라는 툴을 다루기 시작하면서 lisp 에 관한 관심이 가더군요. 무지하게 매력적인 lisp 이란 언어에 푹 빠졌습니다.

뭐 사업하면서 코딩을 하고 있을 수는 없고 해서, emacs 라는 툴만 간간히 다루고 마음속에만 담아두고 있었는데, 요즘 회사 일손이 부족하여 저도 본격적으로 코딩을 다시 시작하게 됐습니다. 3년만에 다시 잡는 코딩이라 많이 생소한 느낌에 또 새로운 분야(아이폰 앱스 개발)라 진행도가 느린데 일과는 별도의 간단한 어플리케이션을 짤 일이 생겼습니다. 그래서 다시 lisp 을 찾아보게 됐습니다.

서두가 길었는데요, 리습은 emacs lisp 과 common lisp 그리고 수많은 방계 언어들이 많습니다. emacs lisp 은 익혀두면 모든것이 emacs 안에서 이루어지는 프로그램을 짤 수 있는데요, 유연함은 아무래도 common lisp 에 비해서 떨어집니다. common lisp 은 개발하기 위한 환경만 떨렁 갖춰두고 있었는데요,(slime + sbcl) 개발 환경만 가지고는 뭔가 만들었다는 기분이 들지가 않더군요.

개발하고 있는 것과는 별도로 데이타베이스의 사용자 테이블에 누가 있는지 궁금해서 서버팀에게 종종 물어봤는데, 일 방해하는것 같아서 직접 sql 모드로 들어가서 알아보다가, 반복적인 작업을 계속 하는 것 같아서 결국 프로그램을 짜기로 했습니다.

함수는 2개 입니다. 접속하는 함수 한개, 쿼리 날리는 함수 한개입니다. 이것을 패키징 해보겠습니다.

* db_user.lisp *

(in-package :db_user)
(require 'clsql)

(defun connect-our-db ()
 ....
))

(defun search-person (name)
...
)


뭐 이런식입니다. 함수형 언어니 함수 몇개를 만들면 되겠지요. (더 복잡한 것은 아직 모름..)

package 로 만들기 위해서는 2가지 파일이 더 필요합니다. 관련 파일들의 정보인 package.lisp 파일과 이것들을 묶어서 사용하게 해줄 asdf 파일인 db_user.asd 파일입니다. 그것들을 살펴보기로 하지요.

* package.lisp *

(in-package :cl-user)
(defpackage :db_user (:use :cl :clsql)
            (:export :connect-our-db
                     :search-person))


package 선언 부분이 들어 있는데요. db_user.lisp 에서 선언한 :db_user 를 선언하고 있지요. 거기에 db_user 에서 사용하는 다른 패키지에 관한 정보도 표현되어 있습니다. (예를 들면 clsql  같은 정보) 그리고 외부에서 불러서 써야할 함수들을 export 정보를 통해서 표현하고 있습니다.

* db_user.asd *

(defpackage :db_user (:use :asdf :cl))
(in-package :db_user)

(defsystem db_user
  :name "db_user"
  :depends-on ("clsql")
  :components ((:file "package")
               (:file "db_user" :depends-on ("package")))
  )


거의 비슷하고요. 다만 package.lisp 에서 써줬던 clsql 을 여기서 종속 관계로 명시해줘야 한다는 것입니다.
:depends-on("clsql") <-- 이부분
:components 부분은 연결된 파일을 차례로 써줘가는 것입니다. 처음에 package.lisp 이고, 그것과 연관된 세부 파일들을 세세하게 적어주는 것이지요.

여기 까지 만들어 줬으면 , 이 세개의 파일을 담고 있는 디렉토리를 *central-registry* 에 넣어두고 slime prompt 에서 (sbcl 인 경우)

(require 'db_user)


하면 패키지 로드되고

(db_user:connect-our-db) (db_user:search-person "crazia")


이런식으로 함수를 쓸 수가 있습니다.

다른 훌륭한 패키지들도 이런식으로 하나 하나 추가해 나가는 방식입니다.


+ Recent posts