reCAPTCHA를 웹서비스에 적용시켜 보거나 또는 적용된 웹서비스를 이용하면서 두 단어를 입력하는 것에 대해서 더 정확하게 판별을 할려나 보다 외에는 별다른 생각이 없었다. 몇일전 TED에서 reCAPCHAR를 만든 루이스 폰 안의 '대규모 온라인 협업'이란 강연을 보면서 그 이유를 알 수가 있었다.



reCAPCHA의 주목적은 내가 알고 있던 실제 인간을 판별하기 위한 것 뿐만 아니라 책들을 디지털라이징을 하는데 도움을 주기위한 것도 있었다. 스캔후 OCR로 판독하기가 어려운 상태가 좋지 않은 문자들을 reCAPTCHA에 구별을 위한 문자와 같이 보여줌으로써 인간의 도움을 빌린다는 것이다. reCAPTCHA 인증시 나오는 단어중 하나만 실제 인간인지 판별하는 용도로 사용되고 나머지 하나는 컴퓨터가 판독하기에 불분명한 단어들을 확인하기 위해 사용한다는 것이다. 참으로 기발한 아이디어인 것 같다.

다만 reCAPTCHA를 이용하는 서비스 사용자들의 책들의 디지털라이징에 도움을 주는 이러한 참여가 누구를 위한 것인지는 의문이 든다. reCAPTCHA는 구글에 인수되었는데 구글북스의 디지털라이징에 사용되는지는 모르겠다. 광고를 보고 클릭함으로써 구글의 서비스를 무료로 이용하는 것처럼 문자 판독에 작은 도움을 주고 서비스들을 무료로 사용하는 대가중 하나로 봐야 하는 것인인지...

용도와 목적이야 어찌되었던 이런 개인들의 작은 노력이 합쳐져 커다란 결과물을 낼 수 있는 도구들이 많아 진다는 것은 좋은 현상인 것 같다. 물론 그 목적이 모두가 누릴 수 있는 공익이라면 더 보람과 가치가 있을 것이다. 그동안 IT에 별로 관심이 없었더니 오래전 부터 시작된 일을 이제서야 혼자 감동 받고 뒷북을 치고 있으니 조금 난감하기는 하다.

루이스 폰 안은 위의 TED 강연에서 Duolingo란 새로운 서비스를 소개한다. 웹사이트들을 많이 사용되는 여러 언어로 번역을 하는 서비스이다. 이 역시 여러 사용자들의 자발적인 참여를 통해 번역을 하게되며 사용자들은 Duolingo 서비스를 통해 번역할려는 다른 외국어를 학습하며 번역을 한다.


사이트를 가보니 베타 테스트 중이며 아직 지원하는 언어가 많지 않은 것 같다. 어떤 방법으로 사용자에게 외국어 학습과 함께 번역에 기여할 수 있게 하는 가는 잘 모르겠지만 뭔가 재미있는 것이 나올 것 같기도 하다. 영어가 모국어인 사람들도 많지만 전체로 보면 영어를 배우고 싶어하는 사람이 더 많을 것이다. 그런데 현재 모습만 보면 왠지 외국어를 배우고 싶어하는 영어 사용자들을 위한 단방향 서비스인 것 같기도 하다. 영어에 익숙해지기 위해 많은 시간을 투자해야만 하는 한국에서 이런 비슷한 서비스가 한글 전용으로 나오는 것도 괜찮을 것 같다.

'이야기들 > 소소한 이야기' 카테고리의 다른 글

Xcode 재설치  (6) 2012.03.09
reCAPTCHA와 집단지성의 활용  (0) 2012.01.31
꿩 대신 닭?  (2) 2012.01.11
2012년...  (0) 2012.01.02
아이맥 구입  (8) 2010.04.25
아이폰 개발자 프로그램 갱신  (2) 2009.11.05
모든 댓글을 환영합니다. (욕설과 광고는 삭제합니다.)


개발 툴 2010.02.27 19:31
작년말 구글에서 나온 새로운 개발언어인 Go를 맥에 설치해 보았습니다. 시스템 프로그래밍을 위한 언어라고 하는데 아직 자세히 살펴보지는 못하고 설치만 해보았습니다. 제가 사용한 설치 방법입니다.

1. 다운로드
* MacPorts
설치가 안되어 있을 경우에는 해당 사이트에서 다운로드 받아서 설치합니다. 설치파일이 있어 간단히 설치할 수 있습니다.

* gmake
MacPorts 설치후에는 터미널에서 아래와 같이 gmake를 설치합니다.
> sudo /opt/local/bin/port install gmake

* mercurial
해당 사이트에서 OS X 버젼에 맞는 파일을 다운로드 받아서 설치합니다. MacPorts와 마찬가지로 간단히 설치할 수 있습니다.

2. 설치
Go가 설치될 디렉토리를 계정 루트에 생성합니다.
> mkdir go
> mkdir bin

설치에 앞서 설치환경을 먼저 설정합니다.
> export GOROOT=$HOME/go
> export GOARCH=386
> export GOOS=darwin
> export GOBIN=$HOME/bin

이제 아래와 같이 Go를 설치합니다.
> hg clone https://go.googlecode.com/hg/ $GOROOT
> cd go/src/
>./all.bash

vi와 같은 에디터를 이용하여 bin path를 .bash_profile에 추가합니다.
export PATH=${PATH}:${HOME}/bin

3. Hello, World
새로운 언어를 설치하였으니 Hello, World를 출력해 봅니다. vi등 에디터를 이용하여 아래와 같이 입력하고 hello.go라는 이름으로 저장합니다.

hello.go
package main

import "fmt"

func main() {
    fmt.Printf("Hello, world!\n");
}

터미널에서 아래와 같이 컴파일하여 실행합니다.
> 8g hello.go
> 8l hello.8
> ./8.out
Hello, world!

'개발 툴' 카테고리의 다른 글

PhoneGap 설치  (4) 2012.02.14
OS X에서 Go 설치  (0) 2010.02.27
실버라이트2 둘러보기  (10) 2008.12.16
프로젝트 관리 도구 OpenProj  (2) 2008.03.21
적당히 참견하는 Xcode  (4) 2008.02.25
OS X의 파이썬  (0) 2008.02.20
모든 댓글을 환영합니다. (욕설과 광고는 삭제합니다.)


이전에 포스팅한 "NSXMLParser로 RSS 읽어오기"와 유사한 방법으로 구글 날씨 RSS를 가져오는 것을 만들어 보았습니다. 그런데 한글이 깨져나와 확인해 보니 문자셋이 euc-kr이었습니다. 문자셋을 확인하는 방법은 URLConnection의 델리게이트 메소드에서 확인할 수 있습니다.
  1. - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
  2.     NSLog(@"Encoding: %@", [response textEncodingName]);
  3. }

전송이 끝난 후에 아래와 같이 NSData를 euc-kr을 utf-8로 변환하여 사용할 수 있습니다. 변경된 data를 NSXMLParser의 initWithData의 인자로 사용하면 됩니다.
  1. - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
  2.     NSString *str = [[NSString alloc] initWithData:receiveData encoding:0x80000000 + kCFStringEncodingDOSKorean];
  3.     NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
  4.    
  5.     NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
  6. .
  7. .
  8. .
  9. }

한가지 이상한 점은 웹브라우저에서 확인하면 같은 URL이지만 utf-8로 넘어 옵니다. 아마 서버에서 헤더를 검사에서 각각 다른 인코딩으로 넘겨주는 것이 아닌가 하는 생각이 듭니다. 헤더의 항목들을 변경해서 보았는데 User-Agent를 설정해서 보내보니 euc-kr이 아닌 utf-8로 넘어 왔습니다.
  1.     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/ig/api?weather=seoul"]];
  2.      
  3.     [request addValue:@"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ko; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" forHTTPHeaderField:@"User-Agent"];
  4.  
  5.     xmlConnection = [[NSURLConnection alloc]
  6.                      initWithRequest:request
  7.                      delegate:self];


구글의 날씨 API에서는 이와 같이 User-Agent를 보내면 utf-8로 보내기때문에 위와같이 인코딩의 변환이 필요하지 않습니다. 아마 예측가능한 User-Agent는 utf-8로 보내고 그외에는 euc-kr로 보내는 것 같습니다. 이는 영문도 마찬가지이며 http://www.google.com/ig/api?weather=seoul와 같이 co.kr에서 com으로 변경하면 문자셋이 iso-8859-1로 넘어 옵니다. User-Agent를 추가하면 역시 utf-8로 넘어 옵니다.



이전부터 그냥 복사해서 올렸는데 오늘 보니 아래와 같이 나오는 건 너무 보기가 힘든 것 같아서, 예제코드를  Quick Highlighter를 사용해서 정리해 보았습니다.
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/ig/api?weather=seoul"]];
     
    [request addValue:@"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ko; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2" forHTTPHeaderField:@"User-Agent"];

    xmlConnection = [[NSURLConnection alloc]
                     initWithRequest:request
                     delegate:self];

보기도 조금 나아지지만 해당 클래스에 대한 애플의 문서로 바로 링크가 되는 것도 좋은 것 같습니다.

모든 댓글을 환영합니다. (욕설과 광고는 삭제합니다.)
  1. Favicon of http://icarusx.tistory.com BlogIcon ICARUSX 2009.10.29 18:46  댓글주소  수정/삭제  댓글쓰기

    또 잘보고갑니다 ㅎㅎ 매번 찾아봐야하는데..
    웹쪽이 급해서 우선공부를 하고있는지라..

    도움만 받고 갑니다 ^^

  2. Favicon of http://icarusx.tistory.com BlogIcon ICARUSX 2009.11.10 02:55  댓글주소  수정/삭제  댓글쓰기

    ㅎㅎ 또 방문했습니다 ㅎㅎ
    제가좀 알고있는 블로그도 많이 없고 ㅎㅎㅎ
    유독 코코아데브님 블로그만 자주오게됩니다 ㅎㅎ

    빨리빨리 아이폰SDK를 간파해야하는데 ㅠ_ㅠ

    http://www.icarusx.com - ICARUSX 라는 php+Ajax 무료 오픈 게시판 배포일정을
    잡고 매일 나홀로 철야 작업중이다 보니..

    도무자 아이폰관련 공부할 시간이 나질않는군요;;
    몇일있음 오픈이라.. 오픈후에 사용해줄 사람이 있을지 의문이지만..
    바빠지건 말건을 떠나.. 조금이나마 더 시간을 투자해서 공부해야할듯해요

    조금더 깁숙!!히 공부시작하면 귀찮게 해드릴 지도 모르겠습니다 ㅎㅎㅎ

    아무튼 겨울이 성큼! 다가왔네요.. cocoadev님 감기조심하시고 플루도 조심하시구요
    올겨울은 유난히.. 춥네요.. 가난해져서 그런가 -_-;; 쿨럭;;

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2009.11.16 09:47 신고  댓글주소  수정/삭제

      대단한 것을 만들고 계시네요. 사용하는 사람이 적더라도 만드는 동안의 경험의 이카루스님에게 소중한 자산이 될 것 같습니다.

      오늘도 무척 춥네요. 건강 조심하시고요. ^^

  3. Tim 2010.03.05 16:43  댓글주소  수정/삭제  댓글쓰기

    좋은 정보 감사 드립니다.

    그런데, 예전에 올려주신 내용 (http://cocoadev.co.kr/245) 과 위의 내용을 적용해서 해 보았는데요..

    didStartElement와 didEndElement는 정상적으로 호출이 되는데,
    foundCharacters는 호출이 되지 않습니다.
    (다른 RSS는 잘 되는데 구글의 날씨:http://www.google.com/ig/api?weather=seoul 만 안되는 것 같습니다.)

    제가 뭐를 잘 못한것 아닌지 조언을 부탁 드립니다.
    혹시 가능하시면, http://cocoadev.co.kr/245번 처럼 소스를 올려 주시면 더 이해가 쉬울것 같습니다.

    그럼.. 우울한 날씨지만.. 주말 잘 보내시기를..^^

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2010.03.08 09:35 신고  댓글주소  수정/삭제

      안녕하세요. 소스는 이부분만 따로 구현한 것이 없어 올려 드릴수가 없네요.

      foundCharacters가 호출되지 않는다면 그 전에 어떤 오류가 있는 것 같습니다. 오류 발생시 호출되는 델리게이트 메소드들을 구현하셔서 확인해 보셔야 할 것 같습니다.

      그럼 좋은 하루 보내세요. ^^

  4. Tim 2010.03.15 17:31  댓글주소  수정/삭제  댓글쓰기

    제가 xml에 대한 이해가 부족했던것 같습니다..^^;

    didStartElement에서
    NSString * strData = [attributeDict objectForKey:@"data"]; 를 사용하여
    Data들을 추출 하였습니다.

    혹시..
    Google에서 지역 정보를 얻어오는 부분에 대해 조언을 구할 수 있을까요..?
    네이버의 http://dev.naver.com/openapi/apis/data/local 와 같은 OPENAPI가
    구글에서는 어떻게 해야 하는지 도통 모르겠습니다.

    아래 두군데를 조금 찾아 봤는데..
    제가 잘 몰라서인지, 해결책이 안보이네요..^^;
    [구글 Open API for Object-c] http://code.google.com/p/gdata-objectivec-client/
    [구글 로컬 검색] http://code.google.com/intl/ko-KR/apis/ajaxsearch/local.html

    관련 내용에 대해 문의 드립니다.

  5. Tim 2010.03.18 11:22  댓글주소  수정/삭제  댓글쓰기

    넹.. 감사합니다.

    Local Search 쪽에서 원하는 Data를 가져 올수 있었습니다.
    ajax나 주변 여러가지 개념을 잘 모르는 상태이다 보니..
    한참을 헤맸던것 같습니다..

    다시한번 감사드리고요..
    좋은 하루 되시구요..^^

  6. tudo 2010.04.15 17:17  댓글주소  수정/삭제  댓글쓰기

    didStartElement에서
    NSString * strData = [attributeDict objectForKey:@"data"]; 를 사용하여
    Data들을 추출 하고 어떻게 부려주나요?
    [[cell textLabel] settext:[dict objectForKey:@"city"]];
    [[cell textLabel] settext:strData];
    이렇게 뿌려주면 될까요?

  7. cyan 2010.11.19 13:03  댓글주소  수정/삭제  댓글쓰기

    아이폰개발에 처음 접하고 나서 매우 많은 도움을 받고 있습니다. 이런 글로나마 감사를 드립니다.

    그런데 위의 예제에서

    NSString *str = [[NSString alloc] initWithData:receiveData encoding:0x80000000 + kCFStringEncodingDOSKorean];

    라는 부분은 release 를 어디서 해주어야 하는지요?
    Instrument에서는 저 부분에서 메모리 leak이 생긴다고 하는데,
    일단, connectionDidFinishLoading 메소드 내에서 해주면 어플이 그냥 죽어버립니다.

  8. 당근구리 2011.03.02 09:55  댓글주소  수정/삭제  댓글쓰기

    잘 보고 갑니다. 퍼가요~



안드로이드 개발환경을 조금 더 살펴 볼려고 간단히 어플리케이션을 만들어 보았습니다. 처음 대쉬보드 바이오리듬을 시작한뒤로 바이오리듬을 너무 우려먹고 있는 것 같습니다. 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. yuripapa 2008.12.03 16:53  댓글주소  수정/삭제  댓글쓰기

    그나마 가장 최근까지 봐오던 코드가 java, C#으로 안드로이드가 더 쉽게 접근이 가능하네요... ^^

    요것도 한 번따라해 보면 감각 익히는데 도움이 될 꺼 같네요...
    근데요. 맥북에서 간단한 코드 올리는데... 폰 에뮬레이터 넘 크고 뻘건게 넘 맘에 안듭니다. ㅠ.ㅠ
    이전에 흰색의 QWERTY자판의 에뮬이 더 이뻣던거 같습니다. 5554말고 스킨 바꿀수 없을까요?
    확실히 VM위에 돌리니깐 좀 더 무겁게 느껴지네요...

    암튼... 좋은 자료 올려주셔서 감사합니다. 난중에 술 한잔 거하게 사죠... 잉?

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2008.12.03 17:26 신고  댓글주소  수정/삭제

      현재까지는 5554 하나밖에 없는 것 같던데요. 메뉴에 있으니 아마 계속 추가될 것 같습니다. 해 가기전에 한번 거하게 마셔야죠. ^^

  2. 엘카이저 2009.04.13 18:05  댓글주소  수정/삭제  댓글쓰기

    강좌를 따라서 파일을 만들었습니다.

    사용자 정의 클래스를 가지고 와서 상당히 흥미롭고 막힌 곳을 뚫어주시네요.
    다만 현재 저 파일을 그대로 긁어서 프로젝트를 생성했는 데 실행을 하니 강제종료 됩니다.

    어떻게 하면 될 지 알려주시기 바랍니다.

    메일로도 알려주시면 감사하겠습니다.
    ncck2000@naver.com

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2009.04.17 11:27 신고  댓글주소  수정/삭제

      R.java는 자동으로 생성해주기 때문에 복사해서 가져 오시면 안될 것 같고요. 저도 포스팅 후에는 다시 해보지를 않아서 그동안 SDK의 변경이 있었는지는 잘 모르겠습니다. 잠깐경험해 본 것이라 정확한 답변을 드릴 수가 없네요. 죄송합니다.

  3. 따뜻한호빵 2010.04.06 16:08  댓글주소  수정/삭제  댓글쓰기

    엘카이저님. 아마도 main.xml 에서 "com.zzerr.BioView" 부분을 살펴보시는게 어떨지요? BioView 클래스 package 위치가 동일해야 실행됩니다.



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

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

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

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

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

아이폰을 기다리다 지쳐 아이팟을 구입했는데, 문득 잘 한 것 같다는 생각이 듭니다. 휴대폰은 구글폰으로 구입해서 구글폰과 아이폰을 같이 가지고 다니면 심심할 일이 별로 없을 것 같습니다.
모든 댓글을 환영합니다. (욕설과 광고는 삭제합니다.)
  1. 달룟 2008.10.24 10:13  댓글주소  수정/삭제  댓글쓰기

    윈도우즈만 지원되는 플랫폼들은 많이 봤지만,
    윈도우즈만를 빼고 지원하는 플랫폼은 처음보네요. 장난꾸러기 구글같아요^^

    오픈을 지향하는 구글, 패쇠를 지향하는 애플.
    어떤 분들은 깔끔한 계획도시를 좋아하고,
    또 다른 분들은 시끌벅적 활기가 넘치는 도시를 좋아하죠.

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2008.10.24 10:52 신고  댓글주소  수정/삭제

      짧은 IT 산업의 역사에서 애플과 구글은 앞으로 IT 업계가 추구해야 하는 방향을 보여주는 선구적인 기업이 아닌가 생각됩니다. :)



사용자 삽입 이미지
어제 구글의 Android SDK 공개 기사를 보고 설치해 볼려고 Android 사이트를 살펴 보았습니다. 하지만 인텔맥에서만 된다기에 좌절하고 퇴근후에 집의 인텔 맥미니에 설치를 해보았습니다.

좌측의 아이콘은 안드로이드 에뮬레이터 아이콘입니다. 귀엽습니다.

구글폰이나 Android 소식을 간간히 접하면서 맥의 위젯과 같이 막연히 Ajax를 사용하는 자바스크립트를 사용할 것 같다는 추측을 해보았습니다. 구글의 주력 서비스들이 웹 기반이고 구글의 오픈 API와 연동을 위해서도 웹 기반일거라 생각했습니다.

하지만 어제 다운로드 받아서 확인을 해보니 자바 스크립트가 아니고 자바였습니다. 구글의 능력으로 보았을 때는 충분히 새로운 개발환경(IDE)을 배포할 것 같았는데, 이클립스의 플로그인 형태로 배포 되었습니다.

완전히 새로운 개발환경보다는 이클립스라는 익숙한 개발 환경과 자바라는 대중적인 언어를 선택함으로 기존 개발자들이 쉽게 적응할 수 있을 것으로 보여 집니다.


1. Android SDK 및 이클립스 플러그인 설치
Apach Ant
JDK 5/6도 지원하지만 이클립스로 설치해 보았습니다. 구글도 이클립스를 적극적으로 지원하는 것 같습니다.

1) 이클립스 설치
이클립스가 설치되어 있지 않다면 먼저 이클립스를 다운 받습니다. 전 3.2 버젼이 깔려 있었습니다. 그런데 프로젝트를 만들 때 오류 메시지를 표시해 주지 않아서 헤매다가 3.3을 설치하니 정확히 동작했습니다.

2) Android SDK 설치
이제 Android SDK를 다운 받습니다. Android는 OS X 10.4.8 이상의 인텔맥에서만 설치가 가능합니다. 압축파일만 풀면 되니 쉽게 설치하실 수 있습니다. Android SDK의 압축을 풀면 "android_sdk_darwin_m3-rc20a"와 같은 복잡한 이름의 디렉토리가 생성되는데 접근이 용이하게 Android로 변경해 주고 원하는 위치로 이동 합니다. 저는 잠시만 사용해 보고 삭제할 것이기 때문에 데스크탑에다 디렉토리를 가져다 놓았습니다.

설치가 완료되면 실행파일을 위한 패스를 지정해 줍니다. .bash_profile에 패스를 지정해 주거나 각자의 환경에 맞게 터미널에서 아래와 같이 실행합니다.
> export PATH=/Users/zzerr/Desktop/android/tools


3) ADT 설치
이제 ADT(Android Development Tools)라는 이클립스 플러그인을 설치합니다. 안드로이드 사이트에는 선택사항이라고 되어 있지만, 이클릭스를 사용한다면 필수로 설치를 해야 될 것 같습니다.

a. 이클립스의 헬프 메뉴에서 Software Updates > Find And Install...을 선택합니다.
b. Search for new features to...을 선택하고 Next를 클릭합니다.
c. 우측의 버튼중에 첫번째 New Remote Site...를 클릭합니다.
d. 아래와 같이 Name에 Android Plugin을 입력하고 URL에 https://dl-ssl.google.com/android/eclipse/ 을 입력한 후에 OK를 클릭하고 완료되면 Finish 버튼을 클릭합니다.
사용자 삽입 이미지











e. 다음 단계에서 아래와 같이 Android Plugin을 체크하고 Next 버튼을 클릭합니다.
사용자 삽입 이미지




















f. 라이센스에 동의에 체크하고 Next 버튼을 클릭한 후에 Finish버튼을 클릭합니다.
g. Install All 버튼을 클릭하면 설치 후에 이클립스가 재실행 됩니다.

이클립스의 Preferences... 메뉴를 클릭하고 Android를 선택합니다. 아래와 같이 SDK Location에 이전 단계에서 설치한 Android SDK의 디렉토리를 설정합니다.
사용자 삽입 이미지

"이제 사용할 준비가 완료되었습니다."


2. 샘플 프로젝트 작성

1) 프로젝트 생성
이클립스에서 File > New > Project... 를 클릭하고, Android Project를 선택한 후에 Next 버튼을 클릭합니다.

Project name과 Package Name, Activity name, Application Name을 각각 입력하고 완료 버튼을 클릭합니다. 저는 아래와 같이 입력하였습니다. Application name에 testAndriod로 잘 못 입력하여 나중에 에뮬레이터 화면에서도 Andriod로 나옵니다.
사용자 삽입 이미지

2)  코드 작성
완료되면 아래와 같은 안드로이드 이클립스 개발환경이 나옵니다.
사용자 삽입 이미지

여기선 전 샘플코드를 둘러 보다가 그래픽 샘플코드에서 점을 랜덤하게 출력하는 소스를 복사해서 아래와 같이 만들어 보았습니다.

package com.cocoa;

import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.graphics.*;
import android.view.View;

import java.util.Random;
public class hello extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(new SampleView(this));
    }
   
    private static class SampleView extends View {
        private Paint   mPaint = new Paint();
        private float[] mPts = new float[1000];

        public SampleView(Context context) {
            super(context);
           
            Random rand = new Random();
            final int N = mPts.length >> 1;
            for (int i = 0; i < N; i++) {
                mPts[(i << 1) + 0] = rand.nextFloat() * 320;    // X
                mPts[(i << 1) + 1] = rand.nextFloat() * 240;    // Y
            }
        }
   
        @Override protected void onDraw(Canvas canvas) {
            Paint paint = mPaint;

            canvas.drawColor(Color.WHITE);

            paint.setColor(Color.BLACK);
            paint.setAntiAlias(false);
            paint.setStrokeWidth(10);
       
            canvas.drawPoints(mPts, paint);
        }
    }
}


사용자 삽입 이미지
이제 실행해 보면 좌측과 같은 다이알로그 박스가 나오는데 Android Application을 선택하시고  OK버튼을 클릭합니다
 







아래는 에뮬레이터에서 실행된 모습입니다. 이미지 사이즈를 줄였지만 상당히 큽니다. 맥미니에 연결된 24인치 모니터에 아래와 같은 것이 뜨니 처음에는 핸드폰 에뮬레이터가 아니라 무슨 타자기 에뮬레이터가 뜨는 줄 알았습니다.
사용자 삽입 이미지

기존 자바 개발자나 C#으로 윈도우 모바일 개발 경험이 있는 개발자들은 별다른 노력 없이 쉽게 구글폰 어플리케이션을 제작할 수 있을 것 같습니다. 구글에서 많은 상금이 걸린  Developer Challange도 개최하니 우리나라 개발자들이 많은 상금을 가져 올 수 있었으면 좋겠습니다.


3. 사족 - MS Windows Mobile

이런류의 기기들을 좋아해서 오래전 WinCE 1.0이 탑재된 LG PDA를 구입을 시작으로 현재는 윈도우즈 모바일 5.0의 삼성 블랙잭을 사용하고 있습니다. PC와 인터넷에서의 경쟁이 이제 윈도우즈 모바일을 탑재한 스마트폰, 애플의 아이폰, 구글의 구글폰으로 모바일에서 까지 달아 오르는 것 같습니다.

OS/개발환경/브라우져도 그렇고 경쟁자가 없으면 나태해지는 MS도 이제 바짝 달려야 할 것 같습니다. 다른 건 몰라도 디자인적인 측면에서  신경을 좀 써주었으면 합니다.

아래의 이미지가 제 블랙잭의 스크린샷입니다. 초기화면은 어디선가 다운로드 받은 맥 테마를 변경하여 사용하고 있습니다. 여느 아빠들과 마찬가지로 핸드폰 초기화면은 제 아들 녀석이 자리잡고 있습니다.

우측은 윈도우즈 모바일의 탐색기 이미지입니다. 흑백에서 칼라로 바뀐 것을 제외하고는 10년 전에 본 모습 그대로 입니다. 한때 디자이너가 없다던 소문이 돌던 구글 디자인 컨셉 같습니다.
사용자 삽입 이미지사용자 삽입 이미지

모바일 기기의 특성상 가능하면 메모리와 저장 공간을 줄여야 하는 것은 알지만 보기에도 좋았으면 좋겠습니다. 제 취향이 이상한 건지도 모르겠습니다. 간혹 급하게 메모할 일이 생길 때면 기본 메모장을 이용하는데 윈 3.1 시절의 향수를 느끼게 해줍니다. 언제 시간날 때 기능은 없고 보기에는 좋은 메모장이나 하나 만들어 볼려고 합니다.
모든 댓글을 환영합니다. (욕설과 광고는 삭제합니다.)
  1. Favicon of http://www.black2white.org BlogIcon 괴ㅈ 2007.11.14 10:03  댓글주소  수정/삭제  댓글쓰기

    현재 아이폰을 사용중이지만 안드로이드 베이스의 폰들도 기대가 큽니다.

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2007.11.14 10:09 신고  댓글주소  수정/삭제

      괴ㅈ님은 외국에 계신가 보네요. 아이폰을 사용하신다니 무지 부럽습니다. 블랙잭으로 몇 년 버티다 보면 저도 사용할 기회가 오겠죠. ^^

  2. Favicon of http://aboutyou.tistory.com BlogIcon NiCk 2007.11.14 19:18  댓글주소  수정/삭제  댓글쓰기

    글 잘 읽었습니다.
    구글 정말 대단합니다.
    일단 개방형이라는 것 자체에서도 큰 영향력과 경쟁력을 안고 시작하는 듯 합니다.
    이로써 엄청난 어플리케이션들이 쏟아질 듯 합니다.
    좋은 소식 감사합니다.
    이번에 핸드폰 사려고 하는데... 이 글 보니까 또 망설여 지내요~ ㅋ

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2007.11.14 19:58 신고  댓글주소  수정/삭제

      개발자도 만들기 쉽고 사용자도 어플리케이션이 많아서 좋고... 저도 어떤 프로그램들이 나올지 기대가 됩니다. 특히 핸드폰은 위치확인이 가능하니 구글맵을 이용한 재밌는 것들이 많이 나올 것 같습니다.

      방문해 주셔서 좋은 말씀 감사합니다. ^^

  3. 너구리군 2007.11.15 15:47  댓글주소  수정/삭제  댓글쓰기

    전 회사라 그런지 ADT Plug in 설치가 안 되네요.. ㅠ.ㅠ
    글은 잘 읽었습니다. ^^

    • Favicon of https://www.cocoadev.co.kr BlogIcon cocoadev 2007.11.15 16:04 신고  댓글주소  수정/삭제

      https라 443 포트가 방화벽에 막혀 있어서 그런가 봅니다. 많이 쓰이는 포트니 열어 달라 하심이.. ^^;;

      방문해 주셔서 감사합니다.

  4. Favicon of http://kharus.tistory.com BlogIcon Kharus 2007.11.18 21:00  댓글주소  수정/삭제  댓글쓰기

    저런... WinCE 바탕화면도 맥이로군요