오늘 오전에 유프리에 관련된 포스트를 보았습니다. 관련된 글을 읽다 아래와 같은 내용을 보았습니다.
ETRI는 유프리를 공개SW로 배포하여 자신이 필요한 각종 SW를 사용자가 직접 개발할 수 있게 유도하고 유프리 센터를 통해 배포하여 공개SW의 활성화에 기여할 수 있을 것이라고 기대했다.
내용 중 "사용자가 직접 개발"이란 문구를 보고 바로 사이트로 가 보았습니다. 웹 주소가 http://www.youfree.or.kr/flex/로 뒤에 flex가 눈에 확 들어 오더군요. 아~ 아도비의 플렉스를 이용한 기술인가 보다 하고 많은 기대를 하였습니다.

제가 못 찾은 것인지 사이트 어디에서도 개발자 버젼은 찾을 수가 없었습니다. 그래서 일반 사용자 버젼인 YouFREE 베이직을 다운 받았습니다. 다운로드 받은 압축 파일을 풀다 보니 *.dll, *.exe 파일들이 보이더군요. 확인을 해봤었어야 했는데 윈도우즈 전용이었습니다.

다시 비스타에서 다운로드 받아서 설치를 해 보았습니다. 아파치와 MySQL에서 사용하는 포트를 현재 다른 프로그램에서 사용중이라고 정상적인 실행이 안된다고 메시지가 나왔습니다.(사용하는 프로그램 없는데...) etri 사이트에 가서 보니 비스타와 리눅스는 아직 지원하지 않는다는 내용을 보고 지웠습니다.

내용을 자세히 읽어 보지 않아서 그런지, 관련 사이트의 글들을 보고는 뭐하는 프로그램인지 정확히 모르겠네요. 아쉬움에 플렉스라도 깔아 보자라는 생각으로 아도비 사이트에서 다운로드 받고 설치해 보았습니다.

30일 사용 가능한 무료 버젼을 다운로드 받았는데, 사이트에서 가격을 보니 249달러 였습니다. 설치는 쉽게 되고 튜토리얼중 하나를 따라해 보았습니다. 막연히 플랙스는 플래쉬와 유사한 것으로 생각했었는데 일단 처음 본 모습과 언어는 제 생각과 틀렸습니다. 통합개발툴은 이클립스를 기반으로 만들어진 것 같습니다.

사용자 삽입 이미지

튜토리얼 내용을 보면서 New/Flex Project를 클릭했습니다.  뭔지 모르지만 Basic을 선택하고 Next를 클릭했습니다. 그리고 프로젝트명에 Test를 입력하고 Finish를 클릭했습니다.

사용자 삽입 이미지

그 후 소스파일 편집에 튜토리얼에서 본 내용중 블로그 주소만 제 블로그의 RSS 주소로 변경하였습니다.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="feedRequest.send()" layout="absolute">

    <mx:HTTPService
        id="feedRequest"
        url="http://www.cocoadev.co.kr/rss/"
        useProxy="false"/>

    <mx:Panel x="10" y="10" width="475" height="400" title="{feedRequest.lastResult.rss.channel.title}">

        <mx:DataGrid id="dgPosts" x="20" y="20" width="400" dataProvider="{feedRequest.lastResult.rss.channel.item}">
            <mx:columns>
                <mx:DataGridColumn headerText="Posts" dataField="title"/>
                <mx:DataGridColumn headerText="Date" dataField="pubDate" width="150"/>
            </mx:columns>
        </mx:DataGrid>

        <mx:TextArea x="20" y="175" width="400"/>
        <mx:LinkButton x="20" y="225" label="Read Full Post"/>
    </mx:Panel>
</mx:Application>

그리고 실행하니 아래와 같이 파이어폭스에서 실행되었습니다.

사용자 삽입 이미지

제가 아는 한에서는 가장 단시간에 만든 RSS 리더기입니다. 브라우져에서 HTML 소스를 보니 아래와 같았습니다.
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="AC_OETags.js" language="javascript"></script>
<style>
body { margin: 0px; overflow:hidden }
</style>
<script language="JavaScript" type="text/javascript">
<!--
// -----------------------------------------------------------------------------
// Globals
// Major version of Flash required
var requiredMajorVersion = 9;
// Minor version of Flash required
var requiredMinorVersion = 0;
// Minor version of Flash required
var requiredRevision = 0;
// -----------------------------------------------------------------------------
// -->
</script>
</head>

<body scroll="no">
<script language="JavaScript" type="text/javascript" src="history.js"></script>
<script language="JavaScript" type="text/javascript">
<!--
// Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);

// Version check based upon the values defined in globals
var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);


// Check to see if a player with Flash Product Install is available and the version does not meet the requirements for playback
if ( hasProductInstall && !hasRequestedVersion ) {
// MMdoctitle is the stored document.title value used by the installation process to close the window that started the process
// This is necessary in order to close browser windows that are still utilizing the older version of the player after installation has completed
// DO NOT MODIFY THE FOLLOWING FOUR LINES
// Location visited after installation is complete if installation is required
var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
var MMredirectURL = window.location;
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
var MMdoctitle = document.title;

AC_FL_RunContent(
"src", "playerProductInstall",
"FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
"width", "100%",
"height", "100%",
"align", "middle",
"id", "Test",
"quality", "high",
"bgcolor", "#869ca7",
"name", "Test",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else if (hasRequestedVersion) {
// if we've detected an acceptable version
// embed the Flash Content SWF when all tests are passed
AC_FL_RunContent(
"src", "Test",
"width", "100%",
"height", "100%",
"align", "middle",
"id", "Test",
"quality", "high",
"bgcolor", "#869ca7",
"name", "Test",
"flashvars",'historyUrl=history.htm%3F&lconid=' + lc_id + '',
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else { // flash is too old or we can't detect the plugin
var alternateContent = 'Alternate HTML content should be placed here. '
+ 'This content requires the Adobe Flash Player. '
+ '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
document.write(alternateContent); // insert non-flash content
}
// -->
</script>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id="Test" width="100%" height="100%"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="Test.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#869ca7" />
<param name="allowScriptAccess" value="sameDomain" />
<embed src="Test.swf" quality="high" bgcolor="#869ca7"
width="100%" height="100%" name="Test" align="middle"
play="true"
loop="false"
quality="high"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
</noscript>
<iframe name="_history" src="history.htm" frameborder="0" scrolling="no" width="22" height="0"></iframe>
</body>
</html>

swf 파일로 봐서는 플래쉬와 무관한 것 같지는 않습니다. 아직은 정확히 플랙스가 무엇인지 어떻게 돌아 가는 것인지 알지도 못하지만 흥미있는 툴 같습니다. 다만 공짜였으면...

유프리가 웹기반이고 etri에서 만들었단 말 때문에 맥에서 실행되는 개발툴이 우리나라에서 나온줄 알고  많은 기대를 했었는데, 아직은 윈도우즈 전용이라 다소 아쉽습니다. 곧 리눅스도 지원한다고 하는데 하는 김에 맥까지 바라는 것은 욕심이겠죠?

AND

기타 2007. 11. 30. 14:31
Xcode란 이름을 처음 들었을 때는 별다른 느낌이 없었습니다. 한 단어로 자주 사용되는 X가 주는 여러 의미도 있고, OS X의 X도 있고 code와 합쳐져 그냥 Xcode인가 보다 하고 생각했습니다.

하지만 cocoa는 약간 흥미가 가는 이름이었습니다. 처음에는 코코아란 차를 생각하고 Java와 뭔가 비슷한 이유로 이름을 지은 것이 아닐까 생각했습니다. cocoa 개발자들이 개발중에 코코아 차를 자주 마셔서 지은 이름이 아닐까? 별로 중요한 내용은 아니지만 cocoa를 시작도 하기전에 이 죽일 놈의 호기심이 또 발동해서 구글 등에서 이름의 내역을 대충 알게되었습니다.

이제 다시 당시에 알아낸 내용과 위키피디아를 통해서 cocoa 이름의 유래에 관해서 정리해 볼려고 합니다.


사용자 삽입 이미지
우선 코코아가 정확히 뭔지 알아 보겠습니다. 저는 카카오, 코코아, 코코넛 세개의 정확한 의미를 몰라 혼돈이 있었습니다. 코코넛은 코코스 야자 나무의 열매이고, 카카오는 카카오 나무의 열매입니다. 이 카카오를 가공하여 분말로 만든 것을 코코아라고 부릅니다.(저만 헤깔리는 것이 겠죠.)


일단 코코아가 무엇인지는 알았고, Xcode의 cocoa에 이름이 붙여진 이유에 대해서 알아 보겠습니다. 1991년도 경 애플에서는 KidSim이란 프로젝트가 진행되고 있었습니다. 이 프로젝트는  ATG(Advanced Technology Group)에서 이루어졌습니다. KidSim은 Kid+Simulation의 조합과 같은 이름에서 암시하듯이 프로그래밍 언어를 배우지 않고도 어린이들에게 쉽게 애니메이션, 시뮬레이션, 게임등을 만들게 해주는 툴입니다.


보시는 바와 같이 어디선가 본듯한 모습인데 앨런케이옹의 스퀵이 떠 오릅니다. 아래는 스퀵과 관련한 제 이전 포스트 입니다.

아무튼 이 당시 앨런케이옹도 애플의 ATG에서 비슷한 연구를 한 것으로 보입니다.

잠시 ATG에 대해서 살펴 보면 ATG는 1986에 만들어져 1997까지 유지된 애플의 새로운 기술을 개발하는 연구소입니다. 구성원은 컴퓨터 발전과 객체지향에 지대한 영향을 끼친 앨런케이, 제록스에서 레이저 프린팅 시스템을 처음 개발한 게리 스타크웨더, 초기 애플 GUI 소프트웨어 개발의 주축이었던 레리 테슬러(ATG 를 만들었습니다.)등 초호화 맴버입니다.

드림팀 답게 이들은 이곳에서 애플 기술의 초석이 되는 많은 결과물들을 만들어 내었습니다. 위키피디아에서 가져온 이들이 개발한 주요 내용들 입니다.

QuickDraw, QuickTime, QuickTime VR, QuickDraw 3D, 3DMF the 3D metafile graphics format, ColorSync, HyperCard, Apple events, AppleScript, Apple's PlainTalk speech recognition software, Apple Data Detectors, the V-Twin software for indexing, storing, and searching text documents, Macintalk Pro Speech Synthesis, the Newton handwriting recognizer, the component software technology leading to OpenDoc, MCF and HotSauce, Squeak Smalltalk, Cocoa

대충봐도 눈에 익은 것들이 많습니다. 하지만 1996년 앨런케이도 애플을 떠나고, 1997년 스티브잡스가 애플로 복귀하면서 비생산적인 부서를 정리하는 구조조정(?)을 감행하면서 ATG도 역사속으로 사라지게 됩니다.

다시 KidSim으로 돌아와 1994년 이 프로젝트는 Cocoa로 이름을 변경합니다. 이후 1996년 이 프로젝트는 공식적으로 세간에 발표됩니다. 하지만 ATG가 없어 지면서 위의 래리 테슬러와 기존 cocoa의 개발자들은 Stagecast 소프트라는 회사를 만들어 떠납니다.

이때 스티브 잡스는 NeXTSTEP을 이용해 새로운 애플의 OS를 개발하게 됩니다. 애플은 Xcode의 시조인  NeXTSTEP의 개발환경을 새로운 OS로 가져 오게 됩니다. 그런데 새로 트레이드마크를 등록하는데 드는 시간을 줄이기 위해, Stagecast의 동의하에 이미 등록되어 있는 Cocoa란 이름을 사용합니다.

알고보니 허무합니다. 사실인지 아닌지 확인할 길은 없지만, 시간이 없어서 그냥 가지고 왔답니다. 끝.

아무튼 ATG에 당대의 개발자들이 모여 시간과 돈에 얽매이지 않고 자유롭게 연구한 UI, 그래픽/네트워크 기술, 교육용 소프트웨어 등 많은 결과물이 오늘날 애플 제품들의 초석이 되지 않았나 생각됩니다.


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

블로그 RSS 읽어오는 C++ class  (7) 2007.12.14
OS X용 정규 표현식 테스트 어플리케이션 - Reggy  (1) 2007.12.12
맥용게임 Doukutsu  (3) 2007.11.21
미국의 맥개발자 구인 내용  (8) 2007.10.20
맥용 게임 Thumblebugs  (0) 2007.10.19
AND

파이프(pipe)란 그 이름과 같이 한 프로세스의 표준 출력을 다른 프로세스의 표준입력으로 연결하여 주는 프로세스간의 통신을 위한 방법입니다. 파이프는 아래와 같이 많이 사용됩니다.

사용자 삽입 이미지

ps로 현재 프로세스를 출력하는데 결과가 파이프(|)를 통해 grep의 입력으로 전달됩니다. 그래서 출력 내은 grep으로 전달되고, 현재 프로세스중 iTerm의 문자열이 있는 프로세스만 출력해줍니다.

이번장에선 파이프를 이용하여 command line, GUI의 두 어플리케이션간에 통신을 하고, 프로젝트를 또 다른 프로젝트에 임포트 시키는 프로그램을 간단히 만들어 보겠습니다.


1. getDouble 커멘트라인 툴

먼저 커메드라인 툴을 만들어 보겠습니다.

Xcode의 New Project 메뉴를 클릭하시고, 프로젝트 타입에서 Command Line Utility/Starndard Tool 을 선택합니다. 전 getDouble이란 이름으로 프로젝트를 생성하였습니다. main.c 소스파일을 열고 아래의 내용을 추가합니다.

#include <stdio.h>

int main (int argc, const char * argv[]) {
    // insert code here...
    int num;
   
    scanf("%d", &num);
    printf("%d", num * 2);
   
    return 0;
}

보시는 바와 같이 사용자로 부터 한 수를 입력 받아 2를 곱해서 출력해주는 간단한 프로그램입니다. 테스트를 위해 빌드 후에 실행 합니다.
사용자 삽입 이미지
위와 같이 Run Log 창에서 3[return]을 입력하고, 결과는 두배인 6이 출력되었습니다. 이제 프로젝트를 닫습니다.


2. testPipe GUI 어플리케이션

다시 New Project를 클릭하고 Application/cocoa application를 선택합니다. 저는 이름을 위와 같이 testPipe로 하였습니다.

New File에서 Objective-C class를 선택하시고 AppController란 이름으로 새로운 클래스를 생성합니다. 아래의 내용을 추가합니다.

1) AppController.h 파일

#import <Cocoa/Cocoa.h>

@interface AppController : NSObject {
    NSTask* task;
   
    /*
사용자로 부터 숫자를 입력받는 텍스트필드 입니다. */
    IBOutlet NSTextField* inputText;
   
    /*
입력받은 수를 처리한 결과를 보여 줄 텍스트필드 입니다. */
    IBOutlet NSTextField* outputText;
}

/* 버튼이 클릭되었을 경우에 입력 받은 값을 getDouble 을 실행시켜 넘겨 줍니다. */
- (IBAction) buttonClicked:(id) sender;

/*
getDouble로 부터 받은 결과값을 outputText에 출력합니다. */
- (void) setData: (NSNotification *) noti;

@end


2) AppController.m 파일

#import "AppController.h"

@implementation AppController

- (IBAction) buttonClicked:(id) sender
{
     /* getDouble을 실행하기 위해 NSTask를 사용합니다. NSTask는 한 어플리케이션에서 다른 어플리케이션을 서브프로세스로 실행시키고 관리할 수 있습니다. 리소스 폴더에 있는 getDouble을 실행합니다.

    */
    task = [[NSTask alloc] init];
    NSBundle* aabundle = [NSBundle mainBundle];
    NSString* appPath = [aabundle pathForResource: @"getDouble" ofType: @""];
   
    [task setLaunchPath: appPath];
   
    /*  입출력 파이프를 준비합니다. 유닉스에서는 파이프도 파일로 취급하기 때문에 NSFileHandle 오브젝트로 관리합니다.
    */
    NSPipe* inPipe = [[NSPipe alloc] init];
    NSPipe* outPipe = [[NSPipe alloc] init];
   
    NSFileHandle* inputFile = [inPipe fileHandleForWriting];
    NSFileHandle* outputFile = [outPipe fileHandleForReading];
   
    [task setStandardInput:inPipe];
    [task setStandardOutput:outPipe];
   
    [inPipe release];
    [outPipe release];
   
    /* getDouble로 부터의 출력이 종료되었을 때 호출된 함수(setData)를 설정하도록 옵저버로 등록합니다.
    */

    [[NSNotificationCenter defaultCenter]
        addObserver: self
           selector: @selector(setData:)
               name: NSFileHandleReadToEndOfFileCompletionNotification
             object: outputFile];
    
    /* 백그라운드로 파일을 읽고 종료시에 
읽은 데이터를 NSDicionary 타입의 userInfo에 NSFileHandleNotificationDataItem 키로 읽은 데이터를 넘겨줍니다.
     */

    [outputFile readToEndOfFileInBackgroundAndNotify];
   
    /* getDouble을 실행합니다. */
    [task launch];
   
    /* 사용자가 입력한 값을 파이프(inputFile)를 통해 getDouble 프로세스에 넘겨 줍니다. */
    NSString* str = [inputText stringValue];
    NSData* data = [str dataUsingEncoding:NSASCIIStringEncoding];
    [inputFile writeData: data];
   
    [inputFile closeFile];

}

- (void) setData: (NSNotification *) noti
{
    /* getDouble에서 printf로 출력한 값을 텍스트필드에 출력합니다. */
    NSDictionary* dic = [noti userInfo];
    NSData* data = [dic objectForKey: NSFileHandleNotificationDataItem];
   
    NSString* str = [[NSString alloc] initWithData: data encoding:NSASCIIStringEncoding];

    [outputText setStringValue: str];
   
    [str release];
    [task release];
}

@end


3) 인터페이스 빌더에서 작업

아래의 작업이 이해가 가시지 않는 분은 이전 포스트를 참조해주세요.

사용자 삽입 이미지
위의 소스파일을 저장하고 인터페이스빌더를 실행하고 Window에 텍스트필드 2개와 버튼하나를 좌측과 같이 위치시킵니다.




Xcode의 Groups & Files에서 AppController.h을 드래그하여 열려진 MainMenu.nib의 Instances 판넬에 놓습니다. 그리고 Classes에서 AppController를 우클릭하여 Instantiate AppController를 실행하여 인스턴스를 생성합니다.

AppController를 컨트롤키와 함께 드래그하여 좌측의 텍스트 필드를 inputText 아울렛에 우측의 텍스트 필드를 outputText 아울렛에 연결합니다. 반대로 버튼 컨트롤을 컨트롤키와 함께 AppConrtoller 인스턴스로 드래그하여  buttonClicked 액션에 연결합니다.

각각의 인스펙터에서 아래와 같이 연결되었음을 확인합니다.
사용자 삽입 이미지

 
3. getDouble 프로젝트 추가

실행 또는 배포 시에는 번들의 리소스 디렉토리에 getDouble 실행 파일을복사해 놓으시면 되지만 여기서는 getDouble 프로젝트를 testPipe 프로젝트로 임포트 시켜보겠습니다.

사용자 삽입 이미지

위와 같이 getDouble 프로젝트의 디렉토리에서 getDouble.xcodeproj 파일을 드래그 하여 Xcode(testPipe) 좌측의 Groups & Files에 Resources  하위에 놓습니다.

이제 getDouble이 변경되었을 때에도 testPipe에서 반영될 수 있도록 Dependencies에 추가합니다.
사용자 삽입 이미지
Groups & Files의 Targets 서브의 testPipe를 더블클릭하여 좌측의 info 창을 오픈합니다. 좌측 하단의 [+] 버튼을 클릭하여 getDouble을 선택하시고 좌측과 같이 추가된 것은 확인합니다.



이제 모든 작업이 완료되었습니다. getDouble이 정확히 포함되었는지 아래 이미지와 같이 세개의 붉은색 화살표 부분을 확인합니다.

사용자 삽입 이미지

testPipe를 빌드 후에 터미널에서 아래와 같이 리소스 디렉토리에 getDouble 실행파일을 확인합니다.
사용자 삽입 이미지


4. 실행 및 확인

사용자 삽입 이미지

빌드 후에 testPipe를 실행합니다. 위와 같이 3을 입력한 후에 [X 2] 버튼을 클릭하면 getDouble을 실행하고 파이프를  통해 3을 전달합니다. getDouble은 scanf를 통하여 파이프로 들어온 값에 2를 곱하고 출력합니다. 이 출력값은 다시 설정된 파이프를 통해 testPipe에서 받은 후 출력합니다.

이번 장에선 간단히 파이프에 대해서 알아 보았습니다. 파이프는 소켓처럼 네트워크를 통해서 프로세스간에 통신을 할 수는 없지만 로컬에서 사용할 수 있는 간단한 방법입니다. 직접 구현을 하지 않고도 존재하는 실행파일 또는 프로세스에서 간편한게 정보를 가져오거나 가공할 수 있는 편리한 방법을 제공합니다.

유닉스에서 간단하고 직관적으로 pipe를 사용하던 방법과 비교해 보면 cocoa의 특징을 잘 보여주는 것 같습니다.

'Xcode 2 > Tip' 카테고리의 다른 글

Xcode에서 Flex 개발하기  (2) 2007.12.08
Xcode에서 파이어폭스 플러그인 컴파일 하기  (0) 2007.12.04
Cocoa에서 MySQL 라이브러리 사용하기  (6) 2007.11.13
Xcode에 Subversion 적용하기  (6) 2007.11.10
Xcode 단축키  (2) 2007.10.26
AND