[AS3] 이벤트 오브젝트

Programming/ActionScript 3.0 2007. 6. 16. 23:10
ActionScript 3.0의 새로운 이벤트 처리 시스템에 있는 이벤트 오브젝트는 2 개의 용도로 사용된다. 하나는 구체적인 개개의 이벤트를 표현해 해당 이벤트에 관한 정보를 각종 프롭퍼티에 적용하는 것이고 다른 하나는 각종 메소드를 사용하여 이벤트 오브젝트를 조작해 이벤트 처리 시스템의 동작을 변화시키는 것이다.

그러한 프롭퍼티와 메소드에 액세스 하기 쉽게 Flash Player API 에 있는 모든 오브젝트는 이벤트 오브젝트가 기본 클래스로 정의되어 있다. Event 클래스는 모든 이벤트 오브젝트에 공통되는 기본적인 프롭퍼티와 메소드를 갖추고 있다.

우선 Event 클래스의 프롭퍼티와 Event 클래스의 메소드에 대해 설명하고 마지막으로 Event 클래스에 서브 클래스가 존재하는 이유에 대해 알아보면 다음과 같다.

Event 클래스의 프롭퍼티
Event 클래스에는 이벤트 오브젝트에 관한 중요한 정보를 제공하는 다수의 읽기전용 프롭퍼티와 정수가 있다. 다음의 프롭퍼티는 특히 중요하다.

이벤트 오브젝트의 타입은 정수에 의해서 나타내져 Event.type 프롭퍼티에 적용된다.
이벤트의 디폴트 동작을 캔슬할 수 있을지 없을지를 Boolean 값에 의해서 나타내져 Event.cancelable 프롭퍼티에 넣게 된다.

디폴트 동작
이벤트에 응답하는 코드는 개발자가 기술하지 않으면 안 되는 것이 대부분이지만 이벤트에 대해서 어떠한 정해진 동작이 명확한 경우에는 일반적인 처리가 Flash Player에 의해서 자동적으로 실행되는 것들이 있다. (개발자가 이 동작을 캔슬하기 위한 코드를 기술했을 경우를 제외한다). Flash Player 에 의해서 자동적으로 실행되는 동작을 디폴트 동작이라고 부른다.

예를 들어, 유저에 의해서 TextField 오브젝트에 텍스트가 입력되었을 때 대부분의 경우는 입력된 텍스트를 그 TextField 오브젝트에 표시할 필요가 있다. 이것은 매우 일반적인 동작이므로 Flash Player 에 이미 정해진 동작이다. 이 동작이 불필요한 경우는 새로운 이벤트 처리 시스템을 사용해 디폴트 동작을 캔슬할 수 있다. 유저에 의해서 TextField 오브젝트에 텍스트가 입력되면 그 입력을 나타내는 행동은 TextEvent 클래스의 인스턴스가 Flash Player에 의해서 작성된다. 입력 텍스트가 Flash Player에 의해서 TextField 오브젝트내에 표시되는 것을 막으려면 그 특정의 TextEvent 인스턴스에 액세스하여 preventDefault() 메소드를 호출하여 처리할 수 있다..

디폴트 동작안에는 캔슬할 수 없는 것도 있다. 예를 들어, 유저에 의해서 TextField 오브젝트내의 단어가 더블 클릭 되면 Flash Player로부터 MouseEvent 오브젝트를 생성하게 된다. 이 경우의 디폴트 동작인 커서 위치에 있는 단어를 하이라이트 하는 처리는 개발자가 임의로 막을 수 없다.

디폴트 동작은 Flash Player로부터 송출되는 이벤트 오브젝트밖에 관련지을 수 없기 때문에ActionScript 의 프로그램으로 송출한 이벤트 오브젝트에 대해서는 실행되지 않는다. 이 점을 이해해 두는 것은 중요한데 예를 들어, EventDispatcher 클래스의 메소드를 사용해 textInput 타입의 이벤트 오브젝트를 송출할 수 있지만 그 경우는 이벤트 오브젝트에 디폴트 동작을 관련지을 수 없다. 따라서 프로그램으로부터 textInput 이벤트를 송출해도 그 결과를 Flash Player 에 의해서 TextField 오브젝트에 문자로 표시될 수는 없다.

이벤트 오브젝트의 타입
모든 이벤트 오브젝트에는 각각 이벤트 타입이 설정된다. 이벤트 타입은 스트링으로서 Event.type 프롭퍼티에 포함된다. 코드로 이벤트 오브젝트의 타입을 알 수 있으면 타입에 따라 오브젝트의 처리 방법을 구별할 수 있어 편리다. 예를 들어, 다음의 코드에서는 myDisplayObject 에게 건네지는 마우스 클릭의 이벤트 오브젝트 모두에 대해서 clickHandler() 청취자 함수가 응답하도록 지정하고 있다.

myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler);
Event 클래스 자체에 관련된 이벤트 타입의 수는 20 종류를 넘는다. Event 클래스 정의로부터 발췌한 일부 코드는 다음과 같다.

package flash.events
{
public class Event
{
// 클래스 정수
public static const ACTIVATE:String = "activate";
public static const ADDED:String = "added";
// 그 외의 정수는 생략
}
}
이러한 정수를 사용하면 특정의 이벤트 타입을 간단하게 참조할 수 있다. 각 정수가 나타내는 스트링을 직접 사용하는 것은 피하고 정수명으로 참조하는 것이 좋다. 코드에 입력한 정수명에 스펠링 미스가 있었을 경우는 컴파일러에 의해서 검출할 수 있으나 스트링의 값에 스펠링 미스가 있었을 경우는 컴파일시의 에러가 되지 않고 실행시에 예기치 않은 동작이 생겨서 곤란한 디버그 작업이 필요할 가능성이 있다. 예를 들어, 이벤트 청취자를 등록할 때는 다음과 같은 코드를 사용하는 것이 좋다.

myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler);
다음의 코드는 추천하지 않는 방법이다.

myDisplayObject.addEventListener("click", clickHandler);

디폴트 동작의 캔슬
코드로 cancelable 프롭퍼티를 조사하면 특정의 이벤트 오브젝트에 대한 디폴트 동작을 캔슬할 수 있을지를 알 수 있다. cancelable 프롭퍼티의 값은 Boolean 형태로 디폴트 동작에 대한 캔슬 가부를 나타낸다. 디폴트 동작의 캔슬이 가능한 이벤트는 소수이지만 해당하는 경우는 관련된 동작을 preventDefault() 메소드로 무효화할 수 있다.

이벤트 플로우 정보
Event 클래스의 다른 프롭퍼티에는 다음에 나타내는 것과 같이 이벤트 오브젝트 자체나 이벤트 플로우와의 관계에 관한 중요한 정보가 포함되어 있다.

bubbles : 그 이벤트 오브젝트의 전달 경로가 되는 이벤트 플로우의 구성요소에 관한 정보를 포함한다.
eventPhase  : 이벤트 플로우가 현재 어느 단계에 있는지를 나타낸다.
target : 이벤트 타겟의 참조.
currentTarget  : 해당 이벤트 오브젝트를 현재 처리하고 있는 표시 리스트 오브젝트의 참조.

bubbles 프롭퍼티
이벤트 오브젝트가 bubbling 단계에 있을 때(플로우의 역순으로 전달되는 상태)  그 오브젝트에 의해서 나타내지는 이벤트는 타겟 노드로부터 스테이지로 계층의 상위를 향해 돌아오는 도중에 있다. Event.bubbles 프롭퍼티에는 그 이벤트 오브젝트가 bubbling 단계를 경유할지를 나타낸다. Bubbling의 대상이 되는 이벤트는 반드시 캡쳐 단계와 타겟 단계의 대상이므로 이벤트 플로우의 3 단계 모두를 거치게 된다.이 프롭퍼티의 값이 true 의 경우 해당 이벤트 오브젝트는 3 개의 단계를 모두 경유한 것이고 값이 false 의 경우 해당 이벤트 오브젝트는 bubbling 단계를 경유하지 않은 것이다.

eventPhase 프롭퍼티
eventPhase 프롭퍼티를 조사하면 그 이벤트 오브젝트가 이벤트의 어느 단계에 있는지를 알수 있다. eventPhase 프롭퍼티에는 이벤트 플로우의 3 개의 단계 어느 쪽이든 나타내는 부호없는 정수치가 적용된다. 다음에 나타내는 코드의 발췌처럼 Flash Player API 에는 그러한 부호없는 정수치에 대응한다.  EventPhase 클래스는 flash.events 패키지에서 별도로 정의되어 있다.

package flash.events
{
public final class EventPhase
{
public static const CAPTURING_PHASE:uint = 1;
public static const AT_TARGET:uint = 2;
public static const BUBBLING_PHASE:uint = 3;
}
}
이러한 정수는 eventPhase 프롭퍼티에 대해 유효한 3 개의 값에 대응한다. 정수를 사용하면 코드의 읽기가 쉬워진다. 예를 들어, 이벤트 오브젝트가 타겟 단계에 있는 경우만 myFunc()라는 함수를 호출하도록 하려면 다음과 같은 코드로 조건을 판단할 수 있다.

if (e.eventPhase == EventPhase.AT_TARGET) {
myFunc();
}
target 프롭퍼티
target 프롭퍼티에는 해당 이벤트의 타겟인 오브젝트에 의해 참조가 적용된다. 타겟의 취급은 단순한 경우와 그렇지 않은 경우가 있다. 예를 들어, 마이크가 액티브하게 된 것을 나타내는 이벤트에서는 이벤트 오브젝트의 타겟은 Microphone 오브젝트인 것이 명확하지만 타겟이 표시 리스트내에 있는 경우는 표시 리스트의 계층 구조를 고려할 필요가 있다. 예를 들어, 복수의 표시 리스트 오브젝트가 서로 겹치는 지점이 유저에 의해서 마우스로 클릭되었을 경우 Flash Player는 스테이지로부터 가장 먼 계층에 있는 오브젝트가 이벤트 타겟으로서 선택된다. 그 형태는 다음과 같은 코드로 설명될 수 있다.

parent_mc.child_mc.addEventListener(MouseEvent.CLICK, childClickHandler);
parent_mc.addEventListener(MouseEvent.CLICK, parentClickHandler);

parent_mc.child_mc.buttonMode = parent_mc.buttonMode = true;

function childClickHandler(evt:Event):void{
trace(evt.target.name +" is a child");
}
function parentClickHandler(evt:Event):void{
trace(evt.target.name +" is a parent");
}

출력 :
child_mc is a child
child_mc is a parent

복잡한 SWF 파일에서는 target 프롭퍼티가 잘 기능하지 않는 것이 있다. 각 버튼에 대해서 오브젝트를 사용한 정형적인 수식 처리가 이루어지고 있는 경우는 target 프롭퍼티의 참조처가 버튼이 아니고 수식용의 오브젝트가 되어 버리는 상황이 발생할 수 있다. 이러한 상황에서는 버튼에 이벤트 청취자를 등록해 currentTarget 프롭퍼티를 사용하는 것이 일반적이다. 그렇게 하면 target 프롭퍼티가 상위 오브젝트를 참조하는 경우에도 currentTarget 프롭퍼티로 버튼을 참조할 수 있다.

currentTarget 프롭퍼티
currentTarget 프롭퍼티에는 해당 이벤트 오브젝트를 현재 처리하고 있는 표시 리스트 오브젝트로 참조할 수 있다. 조사하는 대상의 이벤트 오브젝트가 현재 어느 노드로 처리되고 있을지가 사전에 모른다는, 어떻게 보면 이상한 상황같이 들리지만 실제는 자주 일어나는 일이다. 왜냐하면 해당 이벤트 오브젝트의 이벤트 플로우에 포함되는 임의의 표시 오브젝트에 청취자 함수가 등록되어 있을 가능성이 있고 청취자 함수 자체가 임의의 장소에 배치될 가능성이 있기 때문이다. 게다가 1 depths 청취자 함수가 복수의 표시 오브젝트에 등록되어 있는 경우도 있을 수 있다. 프로젝트의 규모가 커져 복잡한 상황에 따라서 currentTarget 프롭퍼티의 유용성은 매우 높아진다.

parent_mc.child_mc.addEventListener(MouseEvent.CLICK, childClickHandler);
parent_mc.addEventListener(MouseEvent.CLICK, parentClickHandler);

parent_mc.child_mc.buttonMode = parent_mc.buttonMode = true;

function childClickHandler(evt:Event):void{
trace(evt.currentTarget.name +" is a child");
}
function parentClickHandler(evt:Event):void{
trace(evt.currentTarget.name +" is a parent");
}

출력 :
child_mc is a child
parent_mc is a parent



Event 클래스의 메소드
Event 클래스의 메소드는 다음의 3 종류로 구별할 수 있다.

유틸리티 메소드 : 이벤트 오브젝트의 카피를 작성하거나 스트링으로 변환한다.
이벤트 플로우 메소드 : 이벤트 오브젝트를 이벤트 플로우로부터 삭제한다.
디폴트 동작 메소드 : 디폴트 동작을 취소하거나 취소가 끝난 상태인지 어떤지를 확인한다.
 

Event 클래스의 유틸리티 메소드
Event 클래스에는 2 개의 유틸리티 메소드가 있다. clone() 메소드는 이벤트 오브젝트의 카피를 작성한다. toString() 메소드는 이벤트 오브젝트의 각종 프롭퍼티와 그러한 값을 나타내는 스트링을 생성한다. 어느 메소드도 이벤트 모델 시스템의 내부에서 사용되고 있는 것이지만 어플리케이션 개발자에게도 일반 용도 전용으로 공개되고 있다.

상급 개발자가 Event 클래스의 서브 클래스를 작성하는 경우에는 이벤트 서브 클래스를 정상적으로 기능시키기 위해서 양쪽 모두의 유틸리티 메소드를 오버라이드(override)하여 독자적인 버젼을 만들 필요가 있다.

Event 클래스의 이벤트 플로우 메소드

이벤트 오브젝트가 이벤트 플로우로 처리되는 것을 정지하려면 Event.stopPropogation() 메소드 또는 Event.stopImmediatePropogation() 메소드를 호출한다. 이것들 2 개의 메소드는 거의 같지만 현재의 노드에 등록되어 있는 나머지의 이벤트 청취자에 대해 실행을 허가할지 하지 않을지라는  점만이 다르다.

Event.stopPropogation() 메소드를 호출하면 해당 이벤트 오브젝트가 이벤트 플로우로 다음의 노드에 전달되는 것을 막을 수 있지만 현재의 노드에 등록되어 있는 이벤트 청취자는 모두 실행된다.
Event.stopImmediatePropogation() 메소드를 호출하면 해당 이벤트 오브젝트가 이벤트 플로우로 다음의 노드에 전달되는 것을 막아, 현재의 노드에 등록되어 있는 다른 이벤트 청취자의 실행도 막을 수 있다.
어느 메소드를 호출했을 경우도 이벤트에 관련되는 디폴트 동작이 실행할지 안할지에 영향을 주지 않는다. 디폴트 동작을 캔슬하려면 Event 클래스의 디폴트 동작 메소드를 별도로 사용할 필요가 있다.

Event 클래스의 디폴트 동작 메소드
디폴트 동작의 취소에 관해서는 preventDefault() 메소드와 isDefaultPrevented() 메소드의 2 개가 있다. preventDefault() 메소드를 사용하면 이벤트에 관련지을 수 있었던 디폴트 동작을 캔슬할 수 있다. 이미 preventDefault()를 호출했는지를 확인하려면 isDefaultPrevented() 메소드를 사용한다.호출이 끝난 경우는 반환값으로서 true를 보내고 아직 호출하지 않은 경우는 false를 돌려준다.

preventDefault() 메소드는 디폴트 동작의 캔슬이 가능한 이벤트에 대해서만 사용할 수 있다. 캔슬의 가부에 대해서는 API 문서로 해당하는 이벤트 타입의 항목을 참조하거나 ActionScript로 해당 이벤트 오브젝트의 cancelable 프롭퍼티를 확인해야 한다.

디폴트 동작을 캔슬해도 이벤트 플로우에 의한 이벤트 오브젝트 처리의 진행에는 영향을 주지 않는다. 이벤트 오브젝트를 이벤트 플로우로부터 없애려면 이벤트 플로우 메소드를 사용할 필요가 있다.

Event 클래스의 서브 클래스

많은 이벤트는 Event 클래스에 정의되고 있는 공통의 프롭퍼티 세트를 사용하면 충분히 표현할 수 있지만 Event 클래스의 프롭퍼티에서는 표현할 수 없는 독특한 성질을 가진 이벤트도 있다. 그러한 이벤트를 위해서 Flash Player API 에는 Event 클래스의 서브 클래스가 몇 개 정의되어 있다.

각 서브 클래스에는 그 이벤트의 카테고리에 특유의 프롭퍼티 및 이벤트 타입이 추가되어 있다. .예를 들어, 마우스의 입력에 관한 이벤트에는 Event 클래스에서 표현할 수 없는 독특한 성질이 있다. MouseEvent 클래스는 Event 클래스를 확장하여 마우스 이벤트의 발생 위치나 발생시에 특정의 키가 밀리고 있었는지등의 정보를 수반하는 프롭퍼티를 추가한 것이다.

또, Event 의 서브 클래스에는 해당 서브 클래스에 이벤트 타입을 나타내는 정수가 포함된다. 예를 들어 MouseEvent 클래스의 경우 마우스 관련의 이벤트 타입이다 click ,doubleClick ,mouseDown ,mouseUp 을 나타내는 정수가 각각 정의되어 있다.

    

설정

트랙백

댓글

[AS3] Flash Player 9 API 의 개요

Programming/ActionScript 3.0 2007. 6. 16. 17:24
ActionScript 3.0 의 Flash Player API 에는 오브젝트와 데이터를 낮은 레벨로 제어할 수 있는 다수의 새로운 클래스가 추가되었다. ActionScript 3.0 의 아키텍쳐는 기존의 ActionScript와는 달리 완전히 새롭고 보다 직관적이다. 예를 들어, Flash Player 9 API는 다음의 논리 패키지로 구성되어 있다. flash.display 패키지에는 Flash Player 의 비주얼 표시 리스트에 관한 모든 클래스가 포함되고 flash.media 패키지에는 오디오와 비디오를 처리하기 위한 클래스가 포함된다. 그리고 flash.text 에는 Flash Player 어플리케이션으로 텍스트를 처리하기 위한 클래스를 포함한다.

다음은 일반적으로 사용되는 클래스와 함수에 대해 각 패키지의 개요를 간단하게 보여준다.


flash.accessibility 패키지
flash.accessibility 패키지에는 Flash 컨텐츠 및 어플리케이션의 accessibility를 서포트하기 위한 클래스가 포함된다. Accessibility 클래스는 스크린 리더와의 통신을 관리한다. AccessibilityProperties 클래스를 사용하면 스크린 리더나 그 외의 accessibility 보조의 Flash 오브젝트의 제시 방법을 제어할 수 있다.

flash.display 패키지
flash.display 패키지에는 Flash Player에 의한 표시 리스트의 오브젝트를 제어하기 위해서 사용하는 코어 클래스가 포함되어 있다. Flash Player 어플리케이션의 모든 비주얼 엘리먼트가 포함된다.
ActionScript 2.0에서는 대부분의 비주얼 엘리먼트가 MovieClip 클래스에서 제어되어 Flash Player 에 의해서 내부에서 처리되고 있었다. 이 때문에 오브젝트의 저레벨 제어는 불가능했다. 하지만 ActionScript 3.0에서는 비주얼 엘리먼트를 제어할 수 있어서 기능과 사용 방법이 기존의 ActionScript보다 논리적으로 정의되고 있다. flash.display 패키지에는 다음의 클래스가 포함된다.
DisplayObject 클래스로부터 계승하는 기본적인 요소 DisplayObjectContainer ,Sprite 등 MovieClip 도 기본적인 요소이며 타임 라인을 필요로 하는 오브젝트에 사용한다. 다양한 버튼 상태를 나타내는 프롭퍼티 등, 버튼에 고유의 기능이 포함된 SimpleButton 클래스도 포함된다.

flash.errors 패키지
flash.errors 패키지에는 IOError (입출력 에러) , IllegalOperationError 등, Flash Player에 고유의 기능에 관련하는 에러 클래스가 포함된다. ActionScript 3.0에서 예외가 런타임 에러를 보고하는 주요한 메카니즘이다.

flash.events 패키지
flash.events 패키지에서는 새롭게 XML DOM (문서 오브젝트 모델) 이벤트 모델이 서포트되어EventDispatcher 기본 클래스가 포함된다. 이벤트에는 에러 이벤트도 포함되는데 에러 이벤트는 Loader.load() 메소드의 호출 등, 비동기 처리로 에러가 발생했을 때에 사용된다.

flash.external 패키지
flash.external 패키지에는 Flash Player8 그리고 fscommand() 함수를 대신하여 도입되었다. flash.external 패키지에는 ExternalInterface 클래스만이 포함된다. ExternalInterface 에 의해서 ActionScript와 Flash Player 컨테이너와의 통신이 가능하다.

flash.filters 패키지
flash.filters 패키지에는 Flash Player 8에서 도입된 비트맵 필터 효과의 클래스가 포함된다. 필터를 사용하면 풍부한 시각 효과를 표시 오브젝트에 적용할 수 있다. flash.filters 패키지의 클래스는 BevelFilter ,BlurFilter ,DisplacementMapFilter ,GlowFilter ,GradientBevelFilter , 및 GradientGlowFilter이다. 이 패키지에는 개별의 픽셀에 매트릭스를 적용하는 것으로 보다 복잡하고 광범위한 효과를 줄 수 있는 클래스가 포함되어 있다. 그것이 ColorMatrixFilter와 ConvolutionFilter이다.
 
flash.geom 패키지
flash.geom 패키지에는 Bitmap 클래스와 표시 오브젝트의 비트맵 캐쉬 프롭퍼티를 서포트한다. Point ,Rectangle ,Matrix 등의 geometry가 포함된다. 또, 칼라를 조작할 수 있는 Transform 및 ColorTransform 클래스도 포함된다.
 
flash.media 패키지
flash.media 패키지에는 클라이언트 컴퓨터로부터 흐르는 오디오 스트림 및 비디오 스트림을 처리하기 위한 클래스가 포함된다. Sound 클래스 및 이 클래스가 서포트하는 클래스를 사용하면 외부의 MP3 파일, 및 SWF 파일에 속한 스트리밍 사운드를 처리할 수 있다. Microphone 클래스를 사용하면 컴퓨터에 접속되고 있는 마이크로폰으로부터 오디오를 캡쳐 할 수 있다. Camera 및 Video 클래스를 사용하면 컴퓨터에 접속되고 있는 비디오 카메라로부터 비디오를 캡쳐 할 수 있다. 또, Video 클래스를 사용하면 외부 FLV 파일을 처리할 수 있다.
 
flash.net 패키지
flash.net 패키지에는 데이터의 송수신을 처리하는 다양한 클래스가 포함된다. Flash Player 9는 바이너리 데이터, XML , 텍스트,URL encode 된 변수, 업 로드 또는 다운로드할 수 있는 기능과 같이 많은 종류의 데이터를 처리할 수 있다. 데이터는 네트워크 서버와 Flash Player를 실행하고 있는 클라이언트 컴퓨터 사이에서 전송 할 수 있다.
이 패키지에는, navigateToURL()이나 sendToURL() 등, 서버와의 커뮤니케이션을 별로 필요로 하지 않는 단순한 조작에 사용할 수 있는 패키지 레벨의 함수도 포함되어 있다.

flash.printing 패키지

이 패키지에는 Flash 컨텐츠를 인쇄하기 위한 클래스가 포함된다.
 
flash.profiler 패키지
이 패키지에는 코드의 디버그에 도움을 주는 showRedrawRegions() 함수가 포함된다.
 
flash.system 패키지
flash.system 패키지에는 시스템 레벨의 기능을 제공하는 클래스와 Flash Player를 실행하고 있는 클라이언트 컴퓨터의 기능에 대해 제한된 특정 정보를 취득할 수 있는 클래스가 포함된다. Capabilities 및 IME 클래스를 사용하고 Flash Player를 실행하고 있는 컴퓨터의 특정의 하드웨어 및 소프트웨어 성능을 판단할 수 있다. 또한 Security ,SecurityDomain ,LoaderContext와 같은 시큐러티에 관련하는 클래스도 포함되어 있다.
flash.system 패키지에는 ApplicationDomain 클래스도 포함된다. 이 클래스를 사용하는 커스텀 클래스를 다른 어플리케이션 도메인에 분할해서 정의를 재이용할 수 있다.

flash.text 패키지
이 패키지에는 텍스트 필드, 텍스트의 포맷, 폰트, 에일리어징 제거, 텍스트의 스타일 시트, 및 레이아웃을 취급하는 클래스가 포함된다.

flash.ui 패키지
flash.ui 패키지에는 유저 인터페이스 (구체적으로 마우스 커서, 컴퓨터 키보드, context menu) 를 커스터마이즈하기 위한 클래스가 포함된다.

flash.utils 패키지
이 패키지에는 ByteArray , 지정한 타임 순서로 코드를 실행할 수 있다. Timer 클래스 등, 다양한 유틸리티 클래스가 포함된다. 또, ActionScript 코드를 실행하는 지연 시간이나 간격을 제어할 수 있는 패키지 레벨의 함수도 다수 포함된다.
 
flash.xml 패키지
flash.xml 패키지는 톱 레벨의 E4X 준거 XML 클래스가 도입되었기 때문에 ActionScript 1.0 및 2.0 XML 오브젝트와 호환성에 문제가 있을 수 있다. XML 관련 클래스는 flash.xml 패키지에 정리되었다.

    

설정

트랙백

댓글

[AS3] XML 처리의 새로운 어프로치

Programming/ActionScript 3.0 2007. 6. 16. 16:09
E4X:XML은 ActionScript 3.0 언어의 코어 기능의 베이스가 되고 있다. ActionScript 의 이전의 버젼 (Flash 5 의 ActionScript 1.0 및 그 이후) 에는 XML 데이터를 취급하는 클래스나 메소드가 있었지만 그것들은 ECMAScript 표준에 근거하는 것이 아니었다.

새롭게 설계된 ECMAScript for XML 사양에는 XML 데이터를 처리하기 위한 새로운 클래스군이나 기능이 정의되고 있다. 그것들은 총칭해 E4X로 불리고 있다. ActionScript 3.0은 E4X에 준거한 클래스로 XML , XMLList  ,QName , 및 Namespace 클래스를 갖추고 있다.

E4X 클래스의 메소드, 프롭퍼티, 연산자에 대한 책정 작업에서는 다음의 특징을 실현하는 것이 목표로 여겨졌다.

ActionScript 2.0 에 존재하고 있던 종래의 XML 클래스는 E4X 사양의 일부인 XML 클래스와 경합 하기 위해 ActionScript 3.0 XMLDocument 클래스명으로 변경되었다. XMLDocument ,XMLNode ,XMLParser ,XMLTag 의 각 클래스는 ActionScript 3.0의 XML을 컨트롤 하기 위해 필요한 새로운 클래스는 코어 클래스이므로 사용 시에 패키지를 읽어들 일 필요가 없다.
 
다음은 E4X를 사용한 데이터 처리의 예를 보여준다.

var myXML:XML =
    <order>
        <item id='1'>
            <menuName>burger</menuName>
            <price>3.95</price>
        </item>
        <item id='2'>
            <menuName>fries</menuName>
            <price>1.45</price>
        </item>
    </order>

XML 데이터는 실제의 어플리케이션에서는 Web 서비스나 RSS 피드등의 외부 소스로부터 로드하는 것이 일반적이지만 여기에서는 예를 단순하게 하기 위해서 XML 데이터를 리터럴로 할당했다.

다음의 코드에 나타내는 대로 E4X 에는 XML 의 프롭퍼티나 속성에의 액세스에 사용하는 닷 (.) 이나 속성 식별용의 접두사 (@) 등과 같이 알기 쉬운 연산자가 준비되어 있다.

trace(myXML.item[0].menuName);      // 출력 : burger
trace(myXML.item.(@id==2).menuName); // 출력 : fries
trace(myXML.item.(menuName=="burger").price); // 출력 : 3.95

XML의 노드에 새로운 노드를 할당하려면 다음과 같이 appendChild() 메소드를 사용한다.

var newItem:XML =
    <item id="3">
        <menuName>medium cola</menuName>
        <price>1.25</price>
    </item>

myXML.appendChild(newItem);
@ 및 . 연산자는 독해 뿐만이 아니라 다음과 같이 데이터의 할당에도 사용할 수 있다.

myXML.item[0].menuName="regular burger";
myXML.item[1].menuName="small fries";
myXML.item[2].menuName="medium cola";

myXML.item.(menuName=="regular burger").@quantity = "2";
myXML.item.(menuName=="small fries").@quantity = "2";
myXML.item.(menuName=="medium cola").@quantity = "2";
다음과 같이 for 루프를 사용하면 XML의 일련의 노드에 대한 반복 처리가 생긴다.

var total:Number = 0;
for each (var property:XML in myXML.item) {
var q:int = Number(property.@quantity);
var p:Number = Number(property.price);
var itemTotal:Number = q * p;
total += itemTotal;
trace(q + " " + property.menuName + " $" + itemTotal.toFixed(2))
}
trace ("Total: $", total.toFixed(2));
출력 :
2 regular burger $7.90
2 small fries $2.90
2 medium cola $2.50
Total: $ 13.30


외부 xml 파일을 로드 할 때

url.xml 파일 내용
<?xml version="1.0" encoding="euc-kr" ?>
<rss>
    <item id="1">
        <title>item 1</title>
        <img>img1</img>
        <target>_self</target>
    </item>
    <item id="2">
        <title>item 2</title>
        <img>img2</img>
        <target>_blank</target>
    </item>
    <item id="3">
        <title>item 3</title>
        <img>img3</img>
        <target>_parent</target>
    </item>
</rss>

var request:URLRequest = new URLRequest("url.xml");
var loader:URLLoader = new URLLoader();
loader.load(request);

loader.addEventListener(Event.COMPLETE, xmlLoaded);

function xmlLoaded(event:Event):void {
var myXML:XML = new XML(loader.data);
trace(myXML.item[0].title);
trace(myXML.item.(@id==2).title);
trace(myXML.item.(title == "item 1").title);
}
출력 :
item 1
item 2
item 1


    

설정

트랙백

댓글

[AS3] 배열의 카피

Programming/ActionScript 3.0 2007. 6. 16. 15:07
Array 클래스에는 배열의 카피를 작성하는 메소드는 준비되어 있지 않다. 배열의 "shallow copy" 는 concat() 또는 slice() 메소드를 파라미터 없이 호출하는 것으로 작성할 수 있다. shallow copy 에서는 오브젝트인 요소가 원래의 배열에 포함되어 있는 경우 카피한 배열내의 요소는 원래의 요소에 포함되고 있는 오브젝트에의 참조가 되어 참조하는 오브젝트는 카피되지 않는다. 따라서 원본 배열과 카피한 배열이 동일한 오브젝트를 참조하게 되어 한쪽으로부터 변경을 하면 이미 다른 한편에도 그 변경이 반영된다.

"deep copy"는 원의 배열내에서 참조되고 있는 오브젝트를 모두 카피하는 것이다. 그 경우 원본의 배열과 카피한 배열이 동일한 오브젝트를 참조하지 않는다. deep copy를 실행하려면 복수행의 코드를 기술할 필요가 있어 보통 특정한 함수를 작성하게 된다.

다음의 예에서는  deep copy를 실행하기 위해 actionscript에서는 clone() 함수를 정의하고 있다.아래 사용한 알고리즘은 Java 프로그래밍에서 일반적으로 사용되고 있는 방법이다. 우선 원래의 배열을 직렬화해서 ByteArray 클래스의 인스턴스를 작성하고 그것을 새로운 배열에 읽어들이는 것으로 카피를 실행하고 있다. 코드에 나타나고 있는 대로 이 함수는 오브젝트를 받아들이기 위해 인덱스 배열과 결합 배열의 양쪽 모두를 사용하고 있다.

import flash.utils.ByteArray;

function clone(source:Object):*{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}


    

설정

트랙백

댓글

[AS3] 타이머 간격의 제어

Programming/ActionScript 3.0 2007. 6. 16. 12:00
Flash authoring tool에 의한 어플리케이션 개발의 경우는 타임 라인을 사용해 어플리케이션의 진행을 프레임 단위로 확실히 제어할 수 있지만 ActionScript 만을 사용하는 프로젝트의 경우는 다른 타이밍 제어 메카니즘을 사용할 필요가 있다.

루프와 타이머의 차이
프로그램 언어에 따라서는 for문이나 do..while 등의 루프 스테이트먼트를 사용해 타이밍의 제어 방법을 독자적으로 궁리해야 하는 것이 있다.

일반적으로 루프 스테이트먼트는 동작환경이 되는 로컬 머신의 처리 속도에 따라 가능한 한 고속으로 실행되기 때문에 사용하는 시스템에 의해서 속도에 차이가 생긴다. 어플리케이션을 일정한 타이밍에 동작시키려면 어떠한 캘린더나 클럭에 의해서 생성되는 타이밍을 이용할 필요가 있다.게임, 애니메이션, 및 리얼타임 제어 등, 많은 어플리케이션은 어느 머신으로도 일관해서 이용할 수 있는 안정된 시간 베이스의 타이밍 메카니즘을 필요로 한다.

ActionScript 3.0 의 Timer 클래스에는 이러한 요구를 채우는 강력한 기능이 있다. Timer 클래스에서는 ActionScript 3.0 의 이벤트 모델을 사용해 지정된 시간 간격이 경과할 때 마다 타이머 이벤트를 송출한다.

Timer 클래스
타이밍 제어 기능의 취급에 대해서 ActionScript 3.0은 Timer 클래스 (flash.utils.Timer)라는 새로운 클래스를 통한 방법이 추천 되고 있다. 이 클래스를 사용하면 소정의 시간 간격이 경과할 때마다 이벤트를 송출할 수 있다.

타이머를 시작하려면 우선 Timer 클래스의 신규 인스턴스를 작성하고 그 인스턴스에 대해 타이머 이벤트를 생성하는 빈도 및 생성 종료까지의 송출 회수를 지정한다.

예를 들어, 다음의 코드에서는 1 초 마다의 이벤트 송출을 60 초간 계속하는 타이머 인스턴스를작성한 예다.

var oneMinuteTimer:Timer = new Timer(1000, 60);

타이머로는 소정의 시간 간격이 경과할 때마다 TimerEvent 오브젝트를 송출한다. TimerEvent 오브젝트의 이벤트형은 timer ( 정수 TimerEvent.TIMER 에 의해서 정의된다)이다. TimerEvent 오브젝트에는 표준의 Event 오브젝트와 같은 프롭퍼티가 포함되어 있다.

또 반복의 회수를 유한하게 설정한 타이머로는 마지막 시간 간격에 도달했을 때에 timerComplete 이벤트 ( 정수 TimerEvent.TIMER_COMPLETE 에 의해서 정의된다) 도 송출한다.

아래 짧은 소스를 보면 Timer 클래스의 실제의 동작이 어떻게 이루어 지는지 확인할 수가 있다.
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;

public class ShortTimer extends Sprite {
public function ShortTimer() {
// 5 초의 Timer를 신규 작성한다
var minuteTimer:Timer = new Timer(1000, 5);

// 시간 간격 이벤트 및 완료 이벤트용의 청취자를 지정한다
minuteTimer.addEventListener(TimerEvent.TIMER, onTick);
minuteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);

// 타이머의 카운트를 시작한다.
minuteTimer.start();
}

public function onTick(evt:TimerEvent):void {
// 현재의 카운트를 표시한다
// 이 이벤트의 target이며 Timer 인스턴스 자체를 나타낸다
trace("tick " + evt.target.currentCount);
}

public function onTimerComplete(evt:Event):void {
trace("Time's Up!");
}
}
}
이 예에서는 ShortTimer 클래스가 작성되었을 때, 1 초 마다의 카운트를 5 초간 계속한다. 일단Timer 인스턴스를 작성하고 이 타이머용의 청취자를 2 개 지정하였다. 1 개는 카운트 각 회의 이벤트를 받는 청취자이고(minuteTimer.addEventListener(TimerEvent.TIMER, onTick);) 다른 하나는  timerComplete 이벤트를 받는 청취자이다.( minuteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
)

타이머의 카운트를 시작하면 이후는 1 초간격으로 onTick() 메소드가 반복한다.
onTick() 메소드에서는 단지 현재의 카운트를 표시하고 있다. 5 초가 경과하면 onTimerComplete() 메소드가 호출되어 카운트가 종료한 것을 표시하게 된다.

이 샘플을 실행하면  트레이스 윈도우에 1 초 마다 다음의 행이 표시된다.

tick 1
tick 2
tick 3
tick 4
tick 5
Time's Up!


flash.utils 패키지에 포함되는 타이머 제어 함수
ActionScript 3.0 에는 ActionScript 2.0과 같은 타이머 제어 함수가 다수 준비되어 있다. 그것들은 패키지 레벨 함수로서 flash.utils 패키지에 포함되어 있어 ActionScript 2.0 의 경우와 같이 동작한다.

clearInterval(id:uint):void
setInterval() 호출을 취소한다.
 
clearTimeout(id:uint):void
setTimeout() 호출을 취소한다.
 
getTimer():uint
Flash Player가 초기화된 시점으로부터의 경과 밀리 세컨드수를 돌려준다.
 
setInterval(closure:Function, delay:Number, ... arguments):uint
밀리 세컨드 단위로 지정한 간격 마다 함수를 실행한다.
 
setTimeout(closure:Function, delay:Number, ... arguments):uint
밀리 세컨드 단위로 지정한 지연 시간의 경과 후에 지정한 함수를 실행한다.
 

이러한 함수는 이후 ActionScript 호환성을 유지하는 목적으로 ActionScript 3.0 에도 남아 있는 것이다. 앞으로 ActionScript 3.0 어플리케이션으로 사용하는 것에 기존의 호환성을 위해 남아 있는 메소드를 사용하는 것은 추천하지 않는다. 일반적으로 Timer 클래스를 사용하는 편이 효율적이다.

    

설정

트랙백

댓글

[AS3] 비디오의 조작

Programming/ActionScript 3.0 2007. 6. 15. 18:12
Video 클래스는 flash.display 패키지내에 없지만 DisplayObject 클래스의 서브 클래스다. 비디오를 Video 오브젝트에 관련지으려면 attachNetStream() 메소드 또는 attachCamera() 메소드를 사용할 필요가 있다.

다음은 넷스트림을 비디오에 관련 짓고, 비디오를 Sprite 표시 오브젝트 컨테이너에 추가하는 단순한 예를 보여준다.










import flash.display.Sprite;
import flash.net.*;
import flash.media.Video;

public class VideoTest extends Sprite {
private var videoUrl:String = "http://example.com/test.flv";

public function VideoTest() {

var connection:NetConnection = new NetConnection();
connection.connect(null);

var stream:NetStream = new NetStream(connection);
stream.publish(false);

var myVideo:Video = new Video(360, 240);
myVideo.attachNetStream(stream);
stream.play(videoUrl);

addChild(myVideo);
}
}


    

설정

트랙백

댓글

[AS3] SimpleButton 오브젝트의 조작

Programming/ActionScript 3.0 2007. 6. 15. 18:02
ActionScript 3.0에서는 SimpleButton 클래스를 사용해 버튼의 동작을 정의할 수 있다. SimpleButton에는 다음의 3 개 상태가 있다.
upState
downState
overState

이것들은 SimpleButton 오브젝트의 프롭퍼티로 각각 DisplayObject 오브젝트이다. 예를 들어, 다음의 클래스는 단순한 텍스트 버튼을 정의한다.







import flash.display.*;
import flash.events.*;
public class TextButton extends SimpleButton {
public var selected:Boolean = false;
public function TextButton(txt:String) {
upState = new TextButtonState(0xFFFFFF, txt);
downState = new TextButtonState(0xCCCCCC, txt);
hitTestState = upState;
overState = upState;
addEventListener(MouseEvent.CLICK, buttonClicked);
}
public function buttonClicked(e:Event) {
trace("Button clicked.");
}
}
SimpleButton 오브젝트의 hitTestState 프롭퍼티는 버튼의 마우스 이벤트에 응답하는 DisplayObject 인스턴스다. 이 예의 TextButton 클래스는 버튼 상태 ( 업, 다운, 또는 오버) 에 사용한다. DisplayObject를 정의하는 다음의 클래스를 참조.

import flash.display.*;
import flash.text.TextFormat;
import flash.text.TextField;
class TextButtonState extends Sprite {
public var label:TextField;
public function TextButtonState(color:uint, labelText:String) {
label = new TextField();
label.text = labelText;
label.x = 2;
var format:TextFormat = new TextFormat("Verdana");
label.setTextFormat(format);
var buttonWidth:Number = label.textWidth + 10;
var background:Shape = new Shape();
background.graphics.beginFill(color);
background.graphics.lineStyle(1, 0x000000);
background.graphics.drawRoundRect(0, 0, buttonWidth, 18, 4);
addChild(background);
addChild(label);
}
}

    

설정

트랙백

댓글

[AS3] 비트 맵의 작성과 조작

Programming/ActionScript 3.0 2007. 6. 15. 17:54
BitmapData 클래스를 사용하면 Bitmap 오브젝트의 픽셀을 조작할 수 있다. 조작할 수 있는 것은 파일로부터 로드한 비트 맵이나 BitmapData의 메소드로 만든 비트맵이다. Bitmap 오브젝트에는 BitmapData에서 사용할 수 있는 bitmapData 프롭퍼티가 있다.

BitmapData 오브젝트는 픽셀의 구형 배열을 나타낸다. 새로운 비트맵을 프로그램 처리에 의해서 작성할 수 있다. 다음의 예는 BitmapData constructor을 사용하여 지정한 색으로 구형을 작성할 수 있고 그 BitmapData 오브젝트를 새로운 Bitmap 오브젝트에 할당할 수 있는 것을 보여준다.






var bdWidth:Number = 100;
var bdHeight:Number = 100;
var bdTransparent:Boolean = true;
var bdFillColorARGB:uint = 0xFF007090;
var myBitmapData:BitmapData = new BitmapData(bdWidth,
bdHeight,
bdTransparent,
bdFillColorARGB);
var myBitmap:Bitmap = new Bitmap(myBitmapData);
addChild(myBitmap);


그러나 통상은 로드된 이미지 파일의 비트맵 데이터를 조작하기 위해 사용된다. 어느 경우도BitmapData 클래스에는 BitmapData를 조작해 변경하기 위한 메소드가 포함된다. 예를 들어, setPixel() 메소드를 사용하여 픽셀의 특정의 RGB 값으로 설정할 수 있다.

    

설정

트랙백

댓글

[AS3] 무비 클립의 제어

Programming/ActionScript 3.0 2007. 6. 15. 17:42
MovieClip 오브젝트에는 타임 라인의 재생 헤드를 제어할 수 있는 프레임 및 씬을 조작하기 위한 프롭퍼티와 메소드가 포함되어 있다.

ActionScript 1.0 및 2.0 의 MovieClip 클래스의 프롭퍼티 및 메소드의 상당수는 ActionScript 3.0의 MovieClip 클래스의 프롭퍼티 및 메소드를 제공되고 있다. 그 일부는 슈퍼 클래스로부터 계승된다. 예를 들어 DisplayObject 클래스의 x ,y , 및 blendMode 등의 프롭퍼티는 MovieClip 클래스에서 계승되기 때문에 사용할 수 있다. AS3의 MovieClip 클래스는 DisplayObject 클래스를 확장하기 때문이다. _x ,_y ,_root 등의 언더스코아 문자로 시작되는 이름의 프롭퍼티는 ActionScript 3.0 에서 언더 스코아 문자가 없는 이름으로 변경되었다. 또 _xmouse, _xscale, _ymouse , 및 _yscale 프롭퍼티의 이름은, mouseX ,scaleX ,mouseY , 및 scaleY로 변경되었다.

MovieClip 클래스에는 무비 클립을 제어하기 위한 메소드와 프롭퍼티가 포함된다. 그러한 프롭퍼티를 사용하면 무비 클립의 프레임과 씬의 총수, 및 현재의 재생 헤드 위치에 있는 프레임과 씬에 관한 정보를 감시할 수 있다. (currentFrame ,currentLabel ,currentLabels ,currentScene ,scenes , 및 totalFrames) 아래의 메소드를 사용하면 무비 클립의 재생 헤드를 제어할 수 있다. gotoAndPlay() ,gotoAndStop() ,nextFrame() ,nextScene() ,play() ,prevFrame() ,prevScene() , 및 stop()

예를 들어, 다음의 코드는 myMovie MovieClip 오브젝트의 현재의 씬의 선두 프레임에 재생 헤드를 이동한다.

myMovie.gotoAndPlay(0);

Stage 오브젝트의 frameRate 프롭퍼티를 사용하면 어플리케이션내의 모든 무비 클립의 frame rate를 설정할 수 있다. (Stage.frameRate = 30;)

ActionScript 1.0 및 2.0 과는 달리 ActionScript 3.0에서는 로드된 SWF파일은 MovieClip 오브젝트, AVM1Movie 오브젝트, 또는 Sprite 오브젝트로 사용할 수 있으나 ActionScript 3.0의 MovieClip 오브젝트의 타임 라인만을 제어할 수 있다. Sprite 및 AVM1Movie 오브젝트에는 타임 라인 관련의 메소드 및 프롭퍼티는 포함되지 않는다.
    

설정

트랙백

댓글

[AS3] 컨텐츠의 동적 로드 - Loader 클래스

Programming/ActionScript 3.0 2007. 6. 15. 17:30
Loader 클래스

Loader 오브젝트를 사용하여 어플리케이션에 SWF 파일 및 그래픽 파일을 로드 할 수 있다. Loader 클래스는 DisplayObjectContainer 클래스의 서브 클래스이므로 Loader 오브젝트에는 표시 리스트 표시 오브젝트를 사용할 수 있다. SWF 파일 또는 그래픽 파일을 나타내는 표시 오브젝트는 Loader로 작성된 인스턴스 1개당 1 개만 포함할 수 있다. 표시 리스트에 Loader 오브젝트를 추가할 때는 다음의 코드와 같이 표시 오브젝트의 로드가 완료하면 로드 된 표시 오브젝트도 표시 리스트에 추가해야 화면에서 확인이 가능하다







var pictLdr:Loader = new Loader();
var pictURL:String = "banana.jpg"
var pictURLReq:URLRequest = new URLRequest(pictURL);
pictLdr.load(pictURLReq);
this.addChild(pictLdr);
SWF 파일 또는 이미지가 로드 되면 로드 된 표시 오브젝트를 아래 코드처럼 container DisplayObjectContainer 오브젝트등의 다른 표시 오브젝트 컨테이너로 이동할 수 있다

import flash.display.*;
import flash.net.URLRequest;
import flash.events.Event;
var container:Sprite = new Sprite();
addChild(container);
var pictLdr:Loader = new Loader();
var pictURL:String = "banana.jpg"
var pictURLReq:URLRequest = new URLRequest(pictURL);
pictLdr.load(pictURLReq);
pictLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaded);
function imgLoaded(e:Event):void {
container.addChild(pictLdr.content);
}
LoaderInfo 클래스

파일이 로드 되면 LoaderInfo 오브젝트가 작성된다. 이 오브젝트는 Loader 오브젝트 및 로드 된 표시 오브젝트 양쪽 모두의 프롭퍼티다. 즉, LoaderInfo 오브젝트는 Loader 오브젝트의 contentLoaderInfo 프롭퍼티를 경유하는 Loader 오브젝트의 프롭퍼티이며 또, 표시 오브젝트의 loaderInfo 프롭퍼티도 로드된 표시 오브젝트의 프롭퍼티이다. 로드 된 표시 오브젝트의 loaderInfo 프롭퍼티는 Loader 오브젝트의 contentLoaderInfo 프롭퍼티와 같다. 즉, LoaderInfo 오브젝트는 로드 된 오브젝트와 로드하는 Loader 오브젝트간 ( 로드 되는 측과 로드하는 측) 공유하게 된다.

LoaderInfo 클래스는 로드의 진행 상황 로드하는 측과 로드 되는 측의 URL  미디어의 총바이트수, 미디어의 규격, 높이와 폭등의 정보를 제공한다. LoaderInfo 오브젝트는 로드의 진행 상황을 감시하기 위한 이벤트를 송출한다.

로드 된 컨텐츠의 프롭퍼티에 액세스 하려면 다음의 코드와 같이 LoaderInfo 오브젝트에 이벤트 청취자를 추가해야 한다.

import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;

var ldr:Loader = new Loader();
var urlReq:URLRequest = new URLRequest("eventDispatcher.swf");
ldr.load(urlReq);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded);
addChild(ldr);

function loaded(event:Event):void {
trace("loaded");
}

LoaderContext 클래스

Loader 클래스의 load() 또는 loadBytes() 메소드를 사용해 Flash Player 에 외부 파일을 로드하는 경우, context 파라미터를 지정할 수도 있다. 이 파라미터는 LoaderContext 오브젝트이다.

LoaderContext 클래스에는 로드 된 컨텐츠의 사용 방법의 문맥을 정의할 수 있는 다음과 같은 프롭퍼티가 포함되어 있다.

checkPolicyFile-- 이미지 파일을 로드하는 경우에게만 이 프롭퍼티를 사용한다. 이 프롭퍼티를 true로 설정하면 Loader 에 의해서 오리지날 서버로 크로스 도메인 폴리시 파일의 유무가 체크된다.  이것은 Loader 오브젝트를 포함하는 SWF가 있는 도메인 이외의 다른 도메인에 있는 컨텐츠를 로드할 경우에만 사용된다. 서버로부터 Loader 도메인에 액세스 허가가 주어지고 있는 경우라면 Loader 도메인 내의 SWF 파일의 ActionScript는 로드 된 이미지내의 데이터에 액세스 할 수 있다. 즉, BitmapData.draw() 커멘드를 사용하여 로드 된 이미지내의 데이터에 액세스 할 수 있다.
Loader 오브젝트의 도메인 이외의 다른 도메인에 SWF가 있을 경우에 Security.allowDomain()을 호출해 특정의 도메인을 허가할 수가 있다.

securityDomain - SWF 파일을 로드하는 경우에게만 이 프롭퍼티를 사용한다. Loader 오브젝트를 포함한 파일이 있는 도메인 이외의 도메인에 있는 SWF 파일에 대해서 이 프롭퍼티를 지정한다.이 옵션을 지정하면 Flash Player는 크로스 도메인 폴리시 파일이 존재할지를 체크하게 된다. 파일이 존재하는 경우는 크로스 도메인 폴리시 파일로 허가되고 있는 도메인의 SWF 파일은 로드된 SWF 컨텐츠를 크로스 스크립트 할 수 있다. 이 파라미터로서 flash.system.SecurityDomain.currentDomain을 지정할 수 있다.

다음은 다른 도메인으로부터 비트 맵을 로드할 때, 크로스 도메인 폴리시 파일의 유무를 체크하는 예를 나타낸다.

var loaderContext:LoaderContext = new LoaderContext();
loaderContext.checkPolicyFile = true;
var urlReq:URLRequest = new URLRequest("photo11.jpg");
var ldr:Loader = new Loader();
ldr.load(urlReq, loaderContext);
다음은 SWF 파일을 Loader 오브젝트와 같은 시큐러티 샌드 박스에 두기 위해서 다른 도메인으로부터 SWF 파일을 로드할 때 크로스 도메인 폴리시 파일의 유무를 체크하는 예를 나타낸다. 또, 이 코드는 로드된 SWF 파일의 클래스를 Loader 오브젝트와 같은 어플리케이션 도메인에 추가한다.

var loaderContext:LoaderContext = new LoaderContext();
loaderContext.securityDomain = SecurityDomain.currentDomain;
loaderContext.applicationDomain = ApplicationDomain.currentDomain;
var urlReq:URLRequest = new URLRequest("library.swf");
var ldr:Loader = new Loader();
ldr.load(urlReq, loaderContext);
    

설정

트랙백

댓글

[AS3] 텍스트의 조작

Programming/ActionScript 3.0 2007. 6. 15. 16:53
flash.text 패키지내에 있다. TextField 클래스를 사용하면 다이나믹 텍스트 필드 및 텍스트 입력 필드를 조작할 수 있다. flash.text 패키지에는 StaticText 클래스도 있지만 StaticText 오브젝트는 오로지 Flash authoring tool로 작성되기 때문에 ActionScript에서 인스턴스화할 수 없습니다.

다음의 예에 나타나듯이 TextFormat 오브젝트를 사용하여 TextField 전체 또는 임의의 범위의 텍스트의 포맷을 설정할 수 있다.








var tf:TextField = new TextField();
tf.text = "Hello Hello";

var format1:TextFormat = new TextFormat();
format1.color = 0xFF0000;

var format2:TextFormat = new TextFormat();
format2.font = "Courier";

tf.setTextFormat(format1);
var startRange:uint = 6;
tf.setTextFormat(format2, startRange);

addChild(tf);

Text 필드에는 plaintext 또는 HTML 형식의 텍스트의 어느쪽이든 포함할 수 있다. plaintext는 인스턴스의 text 프롭퍼티에 포함되어 HTML 텍스트는 htmlText 프롭퍼티에 포함된다.

다음 예와 같이 StyleSheet 오브젝트를 사용해 CSS 스타일 시트를 HTML 텍스트에 적용할 수 있다.

var style:StyleSheet = new StyleSheet();

var styleObj:Object = new Object();
styleObj.fontSize = "bold";
styleObj.color = "#FF0000";
style.setStyle(".darkRed", styleObj);

var tf:TextField = new TextField();
tf.text ="Hello Hello";
tf.styleSheet = style;
tf.htmlText = "<span class = 'darkRed'>Red</span> apple";

addChild(tf);


    

설정

트랙백

댓글

[AS3] 벡터 그래픽의 묘화

Programming/ActionScript 3.0 2007. 6. 15. 16:34
각각의 Shape, Sprite 및 MovieClip 오브젝트는 graphics 프롭퍼티를 갖고 있다. 각 오브젝트의 graphics 프롭퍼티는 Graphics 오브젝트로 Graphics 클래스에는 lines, fills, 셰이프를 묘화 해 조작하기 위한 프롭퍼티와 메소드가 포함된다.

예를 들어, 다음의 코드는 Shape 오브젝트로 오렌지를 묘화 한다.

import flash.display.*;
var circle:Shape = new Shape()
var xPos:Number = 100;
var yPos:Number = 100;
var radius:Number = 50;
circle.graphics.beginFill(0xFF8800);
circle.graphics.drawCircle(xPos, yPos, radius);
this.addChild(circle);
Graphics 클래스에는 단순한 셰이프를 간단하게 묘화하기 위한 다음의 메소드가 포함되어있다.
drawCircle()
drawEllipse()
drawRect()
drawRoundRect()
drawRoundRectComplex()

묘화 메소드를 호출하기 전에
linestyle()
lineGradientStyle()
beginFill()
beginGradientFill()
beginBitmapFill() 메소드를 호출하고  선스타일, fills, 또는 그 양쪽 모두를 정의하게 된다.

( 다른 표시 오브젝트를 포함한다) 표시 오브젝트 컨테이너이기도 하면서 타임 라인을 필요로 하지 않는 그래피컬 오브젝트를 작성하는 경우는 Sprite 클래스를 사용한다.

예를 들어, 다음의 Sprite 오브젝트에는 graphics 프롭퍼티로 묘화 한 circle의 아이 리스트내에 TextField 오브젝트가 있다.

var mySprite:Sprite = new Sprite();
mySprite.graphics.beginFill(0xFFCC00);
mySprite.graphics.drawCircle(30, 30, 30);
var label:TextField = new TextField();
label.text = "hello";
label.x = 20;
label.y = 20;
mySprite.addChild(label);
this.addChild(mySprite);
Sprite 또는 MovieClip 오브젝트의 그래픽 층은  항상 Sprite 또는 MovieClip의 아이 표시 오브젝트의 배후에 표시되지만 그래픽 층은 Sprite 또는 MovieClip의 아이 리스트에는 표시되지 않는다.

    

설정

트랙백

댓글

[AS3] 표시 리스트를 사용하는 어프로치의 이점

Programming/ActionScript 3.0 2007. 6. 15. 15:52
렌더링의 효율화와 파일 사이즈의 경량화

ActionScript 1.0 및 2.0에서는 MovieClip 오브젝트에서만 셰이프를 표현할 수 있었다. 하지만 ActionScript 3.0 에서는 셰이프를 표현 할 수 있는 간단한 표시 오브젝트 클래스가 있다. ActionScript 3.0 표시 오브젝트 클래스에는 MovieClip 오브젝트에 포함되는 메소드와 프롭퍼티가 모두 포함되지 않기 때문에 기존의 ActionScript(2.0 이하)보다 메모리 및 프로세서 자원에의 부담이 경감되었다.
예를 들어, 각 MovieClip 오브젝트에는 무비 클립의 타임 라인의 프롭퍼티가 포함됩니다만 Shape 오브젝트에는 포함되지 않는다. 타임 라인을 제어하기 위한 프롭퍼티는 대량의 메모리 및 프로세서 자원을 사용하는 경우가 있지만 ActionScript 3.0의 Shape 오브젝트를 사용하면 퍼포먼스가 향상된다. Shape 오브젝트는 복잡한 MovieClip 오브젝트보다 오버헤드가 적기 때문이다. Flash Player가 Shape에서는 MovieClip 프롭퍼티를 관리할 필요는 없기 때문에 스피드가 향상과 함께 오브젝트가 사용하는 메모리 용량을 줄일 수 있어 전제적으로는 CPU의 낭비를 줄일 수 있는 이점이 생겼다.


심도 관리의 향상

ActionScript 1.0 및 2.0에서의 depths는 직선적인 심도 관리 및 getNextHighestDepth() 등의 메소드를 사용해 관리되고 있었다. ActionScript 3.0에서는 표시 오브젝트의 심도를 관리하기 위해서 편리한 메소드 및 프롭퍼티가 포함된다. DisplayObjectContainer 클래스가 바로 그것이다.

ActionScript 3.0는 표시 오브젝트를 DisplayObjectContainer 인스턴스의 아이 리스트 내의 새로운 위치로 이동하면 표시 오브젝트 컨테이너 내의 다른 아이는 자동적으로 위치가 변경되어 표시 오브젝트 컨테이너내의 적절한 아이 인덱스 위치를 할당할 수 있다.

ActionScript 3.0는 항상 표시 오브젝트 컨테이너의 아이 오브젝트를 모두 찾아낼 수 있다. 어느 DisplayObjectContainer 인스턴스에도 표시 오브젝트 컨테이너의 아이의 수를 일람표시 할 수 있는 numChildren 프롭퍼티를 제공하고 있다. 또 표시 오브젝트 컨테이너의 아이 리스트는 항상 인덱스 리스트이기 위해 리스트내의 인덱스 위치 0으로부터 마지막 인덱스 위치 (numChildren - 1) 까지의 모든 오브젝트를 조사할 수 있다. 이것은 ActionScript 1.0 및 2.0 의 MovieClip 오브젝트의 메소드와 프롭퍼티에서는 불가능했던 점이다.

ActionScript 3.0는 표시 리스트 내를 순서로 이동하는 것은 간단하다. 왜냐하면 표시 오브젝트 컨테이너의 아이 리스트의 인덱스 번호에 결핍 번호가 없기 때문이다. 표시 리스트 내의 이동과 오브젝트의 depths 관리는 ActionScript 1.0 및 2.0 보다 간단하게 되었다. ActionScript 1.0 및 2.0에서는 무비 클립의 심도순서에 불연속인 결핍이 있는 오브젝트가 포함되어 있었기 때문에 오브젝트의 리스트 내를 이동하는 것이 곤란했지만 ActionScript 3.0에서는 표시 오브젝트 컨테이너의 각각의 아이 리스트가 1 개의 배열로서 내부에 캐쉬되므로 인덱스에 의한 룩업이 매우 고속으로 실행된다. 또한 표시 오브젝트 컨테이너의 모든 아이를 매우 고속으로 루프 할 수도 있게 되었다.


표시 리스트내의 자유로운 이동


ActionScript 1.0 및 2.0 에서는 벡터 셰이프나 Flash authoring tool로 묘화 된 오브젝트에는 액세스 할 수 없다. ActionScript 3.0에서는 그러한 표시 리스트상의 모든 오브젝트, 즉 ActionScript를 사용해 작성된 오브젝트 및 Flash authoring tool로 작성된 모든 표시 오브젝트에 액세스 할 수 있게 되었다.


    

설정

트랙백

댓글

[AS3] 정적 프롭퍼티와 스코프 체인

Programming/ActionScript 3.0 2007. 6. 15. 14:00
정적 프롭퍼티는 계승되지 않지만 그 프롭퍼티가 정의된 클래스 및 그 클래스의 서브 클래스에서는 스코프 체인내에 있다. 즉, 정적 프롭퍼티가 정의된 클래스 및 그 서브 클래스의 스코프 내로부터 직접 정적 프롭퍼티에 액세스 할 수가 있다.













package {
import flash.display.MovieClip;
public class StaticExample extends MovieClip {
public function StaticExample() {
var myExt:Extender = new Extender();
}
}
}

class Base {
public static var test:String = "static";
}

class Extender extends Base {
public function Extender () {
trace(test); //
}
}

출력 : static


인스턴스 프롭퍼티가 같은 클래스 또는 슈퍼 클래스내에서 정적 프롭퍼티와 같은 이름을 사용하고 있는 경우 인스턴스 프롭퍼티는 스코프 체인내에서 우선 순위가 높아진다. 이는 정적 프롭퍼티의 값이 아니라 인스턴스 프롭퍼티의 값이 사용되는 것을 의미한다.

package {
import flash.display.MovieClip;
public class StaticExample extends MovieClip {
public function StaticExample() {
var myExt:Extender = new Extender();
}
}
}

class Base {
public static var test:String = "static";
}

class Extender extends Base {
public var test:String = "instance";
public function Extender () {
trace(test); //
}
}

출력 : instance
다른 예로 parent_mc라는 무비클립에 포함된 child_mc라는 무비클립이 있을 때 두개의 무비클립에 CLICK 이벤트 적용하게 되면 결과는 아래와 같이 나오게 된다.

parent_mc.child_mc.addEventListener(MouseEvent.CLICK, childClickHandler);
parent_mc.addEventListener(MouseEvent.CLICK, parentClickHandler);

function childClickHandler(evt:Event):void{
trace(evt.target.name +" is a child");
}
function parentClickHandler(evt:Event):void{
trace(evt.target.name +" is a parent");
}
출력 :
child_mc is a child
child_mc is a parent
parentClickHandler에서 해당 이벤트가 적용된 무비클립에 접근하기 위해서는 아래와 같은 형태로 접근을 시도해야 한다.

trace(evt.target.parent.name +" is a parent");

    

설정

트랙백

댓글

[AS3] Bound methods

Programming/ActionScript 3.0 2007. 6. 15. 11:38
ActionScript 3.0는 오브젝트 인스턴스를 자동적으로 기억하는 Bound methods를 제공한다. 이 기능은 이벤트 처리에 도움을 줄 수 있는데 기존의 ActionScript 2.0에서는 Bound methods에 추출원의 오브젝트 인스턴스가 기억되지 않아서 Bound methods가 불려 갔을 때에 예기치 않은 동작이 발생했다. 이를 해결하기 위해서 mx.utils.Delegate 클래스를 사용하는 것이 일반적인 방법이었지만, ActionScript 3.0부터는 불필요한 과정이 되었다.









class ThisTest {
private var num:Number = 3;
function foo () { // 정의된 Bound methods
trace ("foo's this: " + this);
trace ("num: " + num);
}
function bar () {
return foo; // 돌려주는 Bound methods
}
}

var myTest:ThisTest = new ThisTest();
var myFunc:Function = myTest.bar();
trace(this);
myFunc();
출력 :
[object global]
foo's this:[object ThisTest]
num: 3

Bound methods foo() 의 this 참조가 그 직전의 행의 this 참조가 글로벌 오브젝트를 가리키고 있지만 여전히 ThisTest 클래스의 인스턴스를 가리키는 것을 나타내고 있다. 게다가 myFunc 변수에 속하고 있는 Bound methods는 계속 ThisTest 클래스의 멤버 변수에 액세스 할 수 있다. 이 같은 코드를 ActionScript 2.0에서 실행하면 this 참조가 일치하기 때문에 num 변수는 undefined 가 된다.

    

설정

트랙백

댓글

[AS3] 파일 내에 복수 클래스

Programming/ActionScript 3.0 2007. 6. 15. 04:11
ActionScript 2.0에서는 클래스 파일을 작성하는 경우 클래스와 같은 이름의 파일을 만들게 된다.  예를 들어 Rec이라는 클래스가 있을 때 클래스의 원시 코드는 "Rec.as" 와 같은 파일명으로 저장이 되어야 한다. "Rec.as" 파일에 존재할 수 있는 클래스는 Rec클래스만 가능한 일이었다.

하지만 ActionScript 3.0 에서는 1개의 파일 내에 복수의 클래스를 저장할 수 있도록 설계되었다. Flash 9 alpha 버전에서는 package{} 내에서도 internal class로 여러 개의 클래스가 package내에서 사용가능하도록 하였으나 CS3로 만들면서 이러한 기능은 제외되었다. 하지만 package 외에는 여러개의 클래스를 정의할 수가 있도록 되어 있다. 1 개의 원시 소스 파일에 복수의 클래스를 보존하는 것이 편리할 수도 있지만 남용하면 OOP형태의 언어에서 바람직하지 않은 문제를 양산할 우려가 있다. 문제는 다음과 같은 경우이다.

1.    복수의 클래스가 1 개의 소스파일에 보존되고 있는 경우, 각각의 클래스를 재이용하는 것이 곤란하게 된다.

2.    파일명과 클래스명이 대응하고 있지 않는 경우, 특정의 클래스의 원시 소스코드를 찾아내는 것이 곤란하다.

이러한 문제점으로 인하여 Adobe에서는 각각 하나의 클래스는 하나의 원시소스파일로 저장하는 것을 권장하고 있다. Alpha 버전에서 package 내에서 복수 클래스를 정의할 수 있었던 것을 제외시킨 이유 또한 이러한 문제점 때문일 것이라는 생각이다.

다시 생각해보면 기존 ActionScript 2.0에서 디렉토리 형태로만 패키지 영역을 정의했던 것을 벗어나 package에서 명시적으로 패키지 영역을 정의하고 그 영역 안에서 복수의 클래스를 정의할 수 있도록 하는 방향으로 검토하였으나 위와 같은 두가지 문제로 인하여 언어적 비판을 벗어나기 위해 CS3 제품에서 package 내 복수 클래스 정의 부분을 제외한 것이 아닌가 생각된다. 개념적 접근에서 실의[實義]를 추구했다고 보여진다.

    

설정

트랙백

댓글

[AS3] for each..in 문법

Programming/ActionScript 3.0 2007. 6. 15. 04:04
var myObj:Object = {x:20, y:30};
for each (var num in myObj) {
    trace (num);
}
//
출력 :
// 20
// 30


XML 또는 XMLList 오브젝트의 반복 처리를 실행.
var myXML:XML = <users>
                   <fname>Jane</fname>
                   <fname>Susan</fname>
                   <fname>John</fname>
                </users>;

for each (var item in myXML.fname) {
    trace(item);
}
/*
출력
Jane
Susan
John
*/


배열의 엘리먼트의 반복 처리를 실행할 수도 있음.
var myArray:Array = ["one", "two", "three"];
for each (var item in myArray) {
    trace (item);
}
//
출력 :
// one
// two
// three

    

설정

트랙백

댓글

[AS3] Object 형의 독립

Programming/ActionScript 3.0 2007. 6. 15. 03:24
ActionScript 2.0에서는 아래의 경우 1번과 2번은 같은 형으로 정의하게 되는데 이는 형을 지정하지 않은 변수의 경우는 Object 형으로 치환되기 때문이었다.

1.    var obj:Object;
2.    var obj;

하지만 ActionScript 3.0에서는 형을 지정되어 있지 않은 변수라고 하는 개념이 도입되었다. 이는 다음의 1, 2번과 같이 2 개의 방법으로 지정할 수 있다.

1.    var obj:*;
2.    var obj;
3.    var obj:Object;

형이 지정되어 있지 않은 1번과 2번은 3번의 Object 형태의 변수와 같지는 않다. 주된 차이는 형이 지정되어 있지 않은 변수는 특별한 값 undefined 를 담을 수 있지만 Object 형태의 변수는 그 값을 보관 유지할 수 없다는 것이다. 오직 null값만이 존재할 수 있다. 이를 다시 말하면 ActionScript 3.0에서는 더 이상 형을 지정하지 않은 변수는 Object형이 아니라는 것이다. 이는ActionScript 2.0보다 형 변환에 따른 엄격한 규칙을 적용하고 있다고 할 수 있겠다.

    

설정

트랙백

댓글

[AS3] Understanding garbage collection in Flash Player 9

Programming/ActionScript 3.0 2007. 6. 13. 11:17

I've been playing around with ActionScript 3.0 for a while now, and I'm really excited by its capabilities. The raw execution speed by itself provides so many possibilities. Toss in E4X, sockets, byte arrays, the new display list model, RegEx methods, a formalized event and error model, and a few dozen other features for flavor, and you have a pretty heady brew.

With great power comes great responsibility, and this is very true for ActionScript 3.0. A side effect of all this new control is that the garbage collector is no longer able to make as many assumptions about what it should automatically tidy up for you. This means that Flash developers moving to ActionScript 3.0 will need to develop a very strong understanding of how the garbage collector operates, and how to work with it effectively. Building even seemingly simple games or applications without this knowledge could result in SWFs that leak like a sieve, hogging all of a system's resources (CPU/RAM) and causing the user's system to hang—potentially even forcing them to hard reboot their computer.

To understand how to optimize your code for ActionScript 3.0, you'll first need an understanding of how the garbage collector works in Flash Player 9. Flash has two processes for finding objects that are not in active use and removing them. This article looks at both techniques and describes how they are relevant to your code.

At the end of this article you can find a simulation of the garbage collector in Flash Player 9 that visually demonstrates the concepts explained herein.

About the garbage collector

The garbage collector is a behind-the-scenes process that is responsible for deallocating the memory used by objects that are no longer in use by the application. An inactive object is one that no longer has any references to it from other active objects. In order to understand this, it is very important to realize that when working with non-primitive types (anything other than Boolean, String, Number, uint, int), you are always passing around a reference to the object, not the object itself. When you delete a variable you remove the reference, not the object itself.

This is easily demonstrated in the code below:

// create a new object, and put a reference to it in a:
var a:Object = {foo:"bar"}
// copy the reference to the object into b:
var b:Object = a;
// delete the reference to the object in a:
delete(a);
// check to see that the object is still referenced by b:
trace(b.foo); // traces "bar", so the object still exists.

If I were to update the code in the example above and delete "b" as well, it would leave my object with no active references and free it for garbage collection. The ActionScript 3.0 garbage collector uses two methods for locating objects with no active references: reference counting and mark sweeping.

Reference counting

Reference counting is one of the simplest methods for keeping track of active objects, and has been used in Flash since ActionScript 1.0. When you create a reference to an object, its reference count is incremented. When you delete a reference, its reference count is decremented. If the reference count of an object reaches zero, it is marked for deletion by the garbage collector.

Here's an example:

var a:Object = {foo:"bar"}
// the object now has a reference count of 1 (a)
var b:Object = a;
// now it has a reference count of 2 (a & b)
delete(a);
// back to 1 (b)
delete(b);
// the reference count down is now 0
// the object can now be deallocated by the garbage collector

Reference counting is simple, it doesn't carry a huge CPU overhead, and it works well in most situations. Unfortunately, the reference counting method for garbage collection is not optimal when it comes to circular referencing. Circular referencing is the situation when objects cross-reference each other (directly, or indirectly via other objects). Even if the application is no longer actively using the objects, their reference counts remain above zero, so the garbage collector never removes them. The code below illustrates how this works:

var a:Object = {}
// create a second object, and reference the first object:
var b:Object = {foo:a};
// make the first object reference the second as well:
a.foo = b;
// delete both active application references:
delete(a);
delete(b);

In the code shown above, both of the active application references have been deleted. I no longer have any way of accessing the two objects from my application, but the reference counts of both objects are 1 because they reference each other. This situation can become much more complex (a references c, which references b, which references a, etc.) and can be difficult to deal with in code. Flash Player 6 and 7 had issues relating to circular referencing in XML objects: each XML node referenced both its children and its parent, so they were never deallocated. Fortunately, Flash Player 8 added a new garbage collection technique called mark and sweep.

Mark sweeping

The second strategy employed by the ActionScript 3.0 (and Flash Player 8) garbage collector to find inactive objects is a method called mark and sweep. Flash Player starts at the root object of your application (which is conveniently called the "root" in ActionScript 3.0) and walks through every reference in it, marking each object it finds.

Next, Flash Player iterates through each of the marked objects. It continues this behavior recursively until it has traversed the entire object tree of your application, marking everything it can reach through an active reference. At the end of this process, Flash Player can safely assume that any objects in memory that are not marked no longer have any active references to them and can be safely deallocated. Figure 1 illustrates how this works: The green references were followed by Flash Player during marking, the green objects are marked, and the white objects will be deallocated.

Objects that no longer have active references are identified by Flash Player using the mark and sweep method

Figure 1. Objects that no longer have active references are identified by Flash Player using the mark and sweep method

Mark and sweep is very accurate. However, because Flash Player has to traverse your entire object structure, the process is costly in terms of CPU usage. Flash Player 9 reduces this cost by carrying out iterative mark and sweep—the process occurs over a number of frames, instead of all at once—and by running this process only occasionally.

Deferred garbage collector and indeterminacy

In Flash Player 9, the garbage collector's operations are deferred. This is a very important thing to understand. Your objects will not be removed immediately when all active references are deleted. Rather, they will be removed at some indeterminate time in the future (from a developer standpoint). The garbage collector uses a set of heuristics that look at the RAM allocation and the size of the memory stack, among other things, to determine when to run. As a developer, you must accept the fact that you will have no way of knowing when, or even if, your inactive objects will get deallocated. You must also be aware that inactive objects will continue to execute indefinitely, until the garbage collector deallocates them, so your code will keep running (enterFrame events will continue), sounds will keep playing, loads will keep happening, other events will keep firing, and so on.

It's very important to remember that you have no control over when the garbage collector in Flash Player will deallocate your objects. As a developer, you will want to make the objects in your games and applications as inert as possible when you are finished with them. Strategies to manage this process will be the focus of my companion article, Resource management strategies in Flash Player 9.

Notice the sawtooth pattern of the total memory in the following garbage collection simulation (click Figure 2 or the link below it). The dips are caused when the collector carries out a sweep. Click on the chart to focus it, then press Spacebar to pause or restart, and hold the up/down arrows to change the memory usage trend as it runs.

Garbage collection simulation

Figure 2. Garbage collection simulation

As shown in the following simulation (click Figure 3 or the link below it), drag out objects (round rectangles) and references to those objects. Then run reference counts or mark and sweep to see which objects would be collected. The number in an object indicates the number of references to that object.

Garbage collection simulation: mark and sweep

Figure 3. Garbage collection simulation: mark and sweep

Where to go from here

Understanding garbage collection is going to be one of the most important steps for writing optimized code that ensures that your Flash project runs with minimal impact on the user's computer. Read my companion article, Resource management strategies in Flash Player 9, and visit the Flash Developer Center and Flash Player Developer Center.

Also check out my blog at gskinner.com to read more about weak references and download helper classes that I've written.

About the author

Grant Skinner is the CEO and chief architect of gskinner.com, a Flash development and consulting company. He works with leading new media agencies and progressive corporate clients to create cutting-edge applications, games, and multimedia pieces. His expertise in fusing coding with interface design, usability, marketing, and business logic has garnered him international acclaim and resulted in a number of prestigious industry awards, including Best Canadian Developer at FITC 2005. Grant maintains an active blog at gskinner.com/blog/ and an exhibit of his experimental work at incomplet.org.


국문 : http://www.adobe.com/kr/devnet/flashplayer/articles/garbage_collection.html
    

설정

트랙백

댓글

[AS3] ActionScript 3 Tip of the Day

Programming/ActionScript 3.0 2007. 6. 13. 10:03
ActionScript 3 Tip of the Day

The release of Flex Builder 2 is around the corner and though the next version of Flash is still a ways away, ActionScript 3 will be a big part of Flex 2 and the impending release of Flash Player 9 (which arrives with Flex). ActionScript 3 is the next step forward and to help with the transition (for those of you deciding to make it), I thought, since I've been working with AS3 a bit lately, I'd make a new Tip of the Day thread for ActionScript 3.0 to help people prepare. So here we go:

ActionScript 3 Tips and Tricks:
  1. 06-19-06: Change the frame rate of your movie
  2. 06-20-06: Class scope is now bound to class methods
  3. 06-21-06: Graphics Object and the Drawing API
  4. 06-22-06: New Variable Types
  5. 06-23-06: Display Objects
  6. 06-24-06: New Import Directive
  7. 06-25-06: Type Casting and the as Operator
  8. 06-26-06: Unique Class Variables
  9. 06-27-06: New MouseMove Behavior
  10. 06-28-06: The delete Keyword and Class Members
  11. 06-29-06: The Dictionary Class
  12. 06-30-06: Label Statements
  13. 07-01-06: Detecting When the Mouse Leaves the Movie
  14. 07-02-06: SimpleButton Instances
  15. 07-03-06: Commas in Shorthand Array Definitions
  16. 07-04-06: Package Block
  17. 07-05-06: Same-file Helper Classes
  18. 07-06-06: Access Attributes
  19. 07-07-06: Abstract Classes
  20. 07-08-06: The override Keyword
  21. 07-09-06: Using prototype
  22. 07-10-06: Regular Expression (RegExp) Support
  23. 07-11-06: Approach to Depth Sorting
  24. 07-12-06: Deep Object Copies with ByteArray
  25. 07-13-06: Similarly Named Instance and Static Properties
  26. 07-14-06: EventDispatcher
  27. 07-15-06: Events and Event Types
  28. 07-16-06: Writing Inline XML
  29. 07-17-06: Determine Instance Class or Superclass
  30. 07-18-06: super() Placement (Now Anywhere)
  31. 07-19-06: Determining Current Frame Label
  32. 07-20-06: Multiple Arguments in trace()
  33. 07-21-06: Calling Event Handlers without Events
  34. 07-22-06: URLRequest for URL Strings
  35. 07-23-06: XML vs. XMLDocument
  36. 07-24-06: Loading Text and XML with URLLoader
  37. 07-25-06: is Operator (vs instanceof)
  38. 07-26-06: Flash 9: Timelines as Classes
  39. 07-27-06: RegExp: Email Validation
  40. 07-28-06: Render Event
  41. 07-29-06: XML: @ Operator for Attributes
  42. 07-30-06: Event Propagation Support
  43. 07-31-06: Get Sound Spectrum Information
  44. 08-01-06: Number() Conversion No Longer Interprets Octals
  45. 08-02-06: Garbage Collection: Reference Counting & Mark and Sweep
  46. 08-03-06: Weak References
  47. 08-04-06: Flash 9: BitmapData and Bitmaps from the Library
  48. 08-05-06: Changes in typeof
  49. 08-06-06: getBounds() vs getRect()
  50. 08-07-06: for..in and for each..in
  51. 08-08-06: Default Values for Function Parameters
  52. 08-09-06: Undetermined Number of Arguments With ...(rest)
  53. 08-10-06: arguments
  54. 08-11-06: Support for Namespaces
  55. 08-12-06: Namespaces: Name Qualifier Operator (::)
  56. 08-13-06: dynamic is Not Inherited
  57. 08-14-06: Creating a mouseWithin Event
  58. 08-15-06: Prevent Overriding and Subclassing with final
  59. 08-16-06: MXMLC: SWF Metadata Tag
  60. 08-17-06: Proxy Class
  61. 08-18-06: in Operator
  62. 08-19-06: Proxy: getProperty and setProperty
  63. 08-20-06: Flash 9: Display Object Variables and Instance Names
  64. 08-21-06: XML: XML and XMLList
  65. 08-22-06: Constants
  66. 08-23-06: duplicateMovieClip Replacement
  67. 08-24-06: Proxy: callProperty
  68. 08-25-06: Creating graphics Copies
  69. 08-26-06: TextField.appendText()
  70. 08-27-06: include Directive
  71. 08-28-06: Duplicate Variable Definitions
  72. 08-29-06: mouseEnabled and Event Blocking
  73. 08-30-06: mouseChildren with Event Propagation
  74. 08-31-06: rollOver and rollOut vs. mouseOver and mouseOut
  75. 09-01-06: DisplayObjectContainer contains()
  76. 09-02-06: Cleaning Up Event Listeners
  77. 09-03-06: Detecting Addition to or Removal from Stage
  78. 09-04-06: Event Phases and Event Capturing
  79. 09-05-06: Determining Event Phase
  80. 09-06-06: Preventing Event Propagation
  81. 09-07-06: Global Events
  82. 09-08-06: Detecting a mouseUp Outside
  83. 09-09-06: Flash 9: Document Class
  84. 09-10-06: Access to stage and root
  85. 09-11-06: Namespaces: use namespace Directive
  86. 09-12-06: No More Color Class; Use ColorTransform
  87. 09-13-06: Runtime Errors; Error Class
  88. 09-14-06: Errors: try..catch..finally and Exception Handling
  89. 09-15-06: Errors: Asynchronous Exception Handling
  90. 09-16-06: XML: Children (.) and Decendants (..)
  91. 09-17-06: Array.indexOf (Array.lastIndexOf())
  92. 09-18-06: asfunction: Now event:
  93. 09-19-06: Proxy: Property Enumeration (nextName(), nextValue(), and nextNameIndex())
  94. 09-20-06: Event Capturing and mouseEnabled
  95. 09-21-06: Flash 9: Strict Mode
  96. 09-22-06: System.totalMemory
  97. 09-23-06: Closing Net Connections
  98. 09-24-06: Timer Class
  99. 09-25-06: AVM2 (AS3) to AVM1 (AS2/AS1) Communication via LocalConnection
  100. 09-26-06: ByteArray Class


100 AS3 tips! After tip 100, no longer will they be added daily

    

설정

트랙백

댓글

[AS3] ActionScript 3.0 첫 프로그래밍

Programming/ActionScript 3.0 2007. 6. 13. 02:36
늦은 감이 없지 않지만 처음으로 AS3를 가지고 코딩을 해봤다. 간단한 결과물이지만 여러 가지로 사소한 것부터 이벤트 처리에 이르기까지 적지 않게 AS2에서 AS3으로 migration한 것을 볼 수가 있는데 이 결과물을 만들고 보니 참 재미있다는 생각이 든다. 플래시의 actionscirpt의 변천사를 보면 참으로 잘 짜여진 시나리오라는 생각과 동시에 엄청난 잔머리의 위대함이라는 생각도 들기 때문이다.

간단한 코딩이지만 직접 접하고 보니 이제야 비로소 정리가 되는 듯 하다. 기존에 호환성 문제로 인해서 불필요하게 사용되었던 군더더기가 많이 빠지고 깔끔해 졌다는 느낌이다. 형식적이고 자율적인 구조로 인해서 혼돈이 왔던 부분들은 간결한 형태로 변화되었고 그 형태 또한 만족스럽다.

하지만 그 동안 편리하게 사용되었던 기능들도 그러한 진화를 바탕으로 다소 불편한 부분도 없지 않다. 그러나 그 불편함 또한 개발자에게 동기와 목적을 확실하게 이미지화 하기 때문에 납득할 만한 변화라는 생각이다.

앞으로 플래시를 사용하는 모든 분야의 발 빠른 변화가 상당히 재미있어질 것 같다…

[Flash] http://jasu.tistory.com/attachment/cfile30.uf@222F35385880210F23FEAD.swf





// Rec.as
package{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;

public class Rec extends MovieClip{
public function Rec(){
trace(this.name +" is created");
this._mc.buttonMode = true;
this._mc.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
this._mc.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
this._mc.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
this._mc.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
this._mc.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
}
private function mouseDownHandler(event:MouseEvent):void{
trace(this.name + " : mouseDownHandler");
this.startDrag();
}
private function mouseOutHandler(event:MouseEvent):void{
trace(this.name + " : mouseOutHandler");
var myTween:Tween = new Tween(this, "scaleX", Elastic.easeInOut, this.scaleX, 1, 1, true);
var myTween2:Tween = new Tween(this, "scaleY", Elastic.easeInOut, this.scaleY, 1, 1, true);
}
private function mouseOverHandler(event:MouseEvent):void{
trace(this.name + " : mouseOverHandler");
var topPosition:uint = this.parent.numChildren - 1;
this.parent.setChildIndex(this, topPosition);
var myTween:Tween = new Tween(this, "scaleX", Elastic.easeInOut, this.scaleX, 1.4, 0.7, true);
var myTween2:Tween = new Tween(this, "scaleY", Elastic.easeInOut, this.scaleY, 1.4, 0.7, true);
}
private function mouseUpHandler(event:MouseEvent):void{
trace(this.name + " : mouseUpHandler");
this.stopDrag();
}
private function mouseWheelHandler(event:MouseEvent):void{
trace(this.name + " : mouseWheelHandler");
}
}
}

// RecDocumentClass

package{
import flash.display.Sprite;
import flash.display.MovieClip;
public class RecDocumentClass extends MovieClip{
private var rootChild:Sprite;
public function RecDocumentClass(){
rootChild = new Sprite();
addChild(rootChild);
init();
}
private function init():void{
var Rec1:Rec = new Rec();
Rec1.x = Rec1.y = 100;
rootChild.addChild(Rec1);

var Rec2:Rec = new Rec();
Rec2.x = Rec2.y = 200;
rootChild.addChild(Rec2);

}
}
}





    

설정

트랙백

댓글

크로스도메인 정책과 플래시의 bitmapData 문제

Programming/ActionScript 2.0 2007. 4. 30. 02:01
요즘 집에서 flickr api를 이용하여 이미지 갤러리를 만들고 있는데 한 가지 문제로 인하여 구현 하고자 하는 기능을 진행하지 못하는 상황이 발생했다.

문제는 로컬에서 load한 이미지(http://경로를 포함한 flickr의 이미지)를 bitmapData로 변환하면 제대로 작동하지만 이것은 개인 계정이나 flickr와 도메인 정책이 다른 웹에 올려놓고 이미지를 load한 후 그 load한 무비클립을 bitmapData로 변환 후 draw하게 되면 작동하지 않는다.

그 동안은 한 계정, 또는 플래시 라이브러리에 있는 이미지를 사용했기 때문에 이러한 문제를 확인하지 못하였으나 flickr를 이용하여 만들다 보니 서로 다른 도메인 계정에서 load한 이미지는 bitmapData로 만들 수 없다는 결론이다.

상식적으로는 도메인이 다르더라도 일단 무비클립에 이미지를 load한 상황이라면 화면에 보이는 무비클립을 비트맵데이터로 전환할 수 있을 것이라는 생각을 했었는데…

    

설정

트랙백

댓글

예의 바른 소프트웨어의 특성

Programming/Etc 2007. 4. 10. 23:54
요즘 전철을 오가며 읽고 있는 앨런 쿠퍼의 “정신병원에서 뛰쳐나온 디자인”을 보고 있는데 지옥철 2호선을 오가는 지라 하루에 10장 읽기도 어렵다. 그 본문 중에 예의 바른 소프트웨어의 특성에 관한 이야기가 나온다.

우리가 당연하게 받아들이고 있는 여러 가지 소프트웨어의 문제점들에 대한 이야기들이 나오는데 소프트웨어를 만든 사람으로서는 실용적이지 않은 귀찮은 질문들을 수없이 던지는 기능적인 요소들이 사용자에게 선택의 기회를 주었다고 생각하지만 사용자로서는 그다지 환영하지 않으며 선택의 여지들을 제공받는 것은 충복이 아니라 고문에 가깝다는 이야기가 나온다. 이러한 것들은 앨런 쿠퍼가 이야기 하는 무례한 소프트웨어다.

사실 이런 경험들은 무수히 많이 있다. 하루에도 수십 번씩 파일을 삭제할 것이냐, 프린트를 정말 할 것이냐, 창을 닫을 것이냐, 프로그램을 종료할 것이냐와 같은 메시지 창을 확인하게 되는데, 이러한 훈련 과정에는 대부분의 사람들은 자신의 어떤 행동에 대한 메시지로 인식하고 꼼꼼하게 읽고 확인하지 않는 듯 하다.

이런 바람직하지 않은 사용자의 훈련으로 그러한 소프트웨어의 무례한 행동에 대해 별로 거부감을 느끼지 않으며 그것이 잘못된 행동이든 잘 된 행동이든 무의식적으로 결정권을 컴퓨터에게 넘겨버린다.

물론 이러한 안내문이 없이 파일을 삭제하거나 덮어버릴 수 있는 여지도 다분히 있지만 안내창의 일련의 행동에 학습된 사용자가 과연 그것을 보고 삭제를 포기하거나 덮어쓰기를 취소하는 경우가 얼마나 있을까 하는 의구심이 든다.

예의 바른 소프트웨어의 특성
1.    나에게 관심을 갖는다.
2.    나에게 공손하다.
3.    사근사근하다.
4.    상식이 있다.
5.    내가 필요로 하는 것을 예측한다.
6.    빠르게 반응한다.
7.    자신의 개인적 문제에 대해 떠벌리지 않는다.
8.    정보에 밝다.
9.    통찰력이 있다.
10.    자신감을 갖고 있다.
11.    집중력을 유지한다.
12.    유연하게 대처한다.
13.    즉각적인 만족을 제공한다.
14.    신뢰할 수 있다.

책 에서도 이야기 했지만 이러한 무례한 소프트웨어의 행동들은 더 많은 문제점을 미리 예방하는 차원에서 행해지는 경우가 대부분일 듯 싶다. 나 또한 어떠한 기능적인 요소들에 대해서 작업을 진행할 때는 이보다 더 무례하고 돌이킬 수 없는 잘못을 사용자 탓으로 돌리기 위한 술책(?!)을 강구하는 편이다.

앞으로 어떠한 방향으로 소프트웨어가 변화해 갈지는 시대의 흐름에서 이미 밝혀진 것 같다. 하지만 그것을 구현하고 설계하는 것이 사람인 만큼 사람과 사람의 이해가 선행되지 않고서는 예의 바른 소프트웨어의 모든 요소들을 충족할 수 있는 소프트웨어는 나타날 수 없을 듯 싶다.
사용자 삽입 이미지
블로그에 추가한 사용자 방문 카운터



    

설정

트랙백

댓글

구글의 최종 목표는 인공지능 검색

Programming/Etc 2007. 4. 10. 00:46
구글을 위해 온갖 허드렛일을 마다하지 않을 사람을 꼽으라면 크레이그 실버스타인을 들 수 있을 것이다. 실버스타인은 구글의 핵심 멤버이자 기술 책임자이며 검색 분야에서 항상 “나쁜 짓은 하지 말라”는 구호를 외치는 사람으로 알려져 있다.

올해 31세인 실버스타인은 1998년에 스탠포드 대학에서 박사 과정을 밟던 중 서지 브린, 래리 페이지 등 학교 동창들과 함께 근처 차고에서 지금은 전세계적으로 유명해진 검색 엔진을 만들어냈다.

결국 이들의 노력은 성공을 거뒀다. 지금 이 검색 회사는 2000년 이래 IPO를 시행한 IT 업체들 중에서도 가장 큰 인기를 끌고 있으며 조만간 27억달러에 달하는 자금을 끌어모을 수 있을 것으로 기대되고 있다.

IPO 시행에 따라 엄청난 부도 챙기게 되겠지만 이와 별도로 실버스타인은 오랫동안 정말 열심히, 그리고 즐기면서 일한 것으로도 유명하다. 구글의 기술 책임자인 그는 검색이라는 비전을 가지고 사용자들이 실제로 정보에 접속하는 것은 도와주는 제품을 개발하는 임무를 수행중이다.

여기에는 구글 웹사이트를 각 개인에 맞춤화하는 새로운 기술과 무선 기기 활용 방안, 가격 비교 기능, 그리고 무료로 이메일을 1GB 용량까지 보내고 저장하고 관리할 수 있는 서비스 - 이것은 G메일이라고도 알려져 있다 - 등이 있다.

구글의 IPO 신청이 있기 이전에 가진 인터뷰에서 실버스타인은 사생활 옹호론자들의 G메일 반대 움직임과 구글의 문화적 변화, 그리고 페이지랭크(PageRank)에 대한 의존도가 변화하고 있는 현상에 대한 문제 등에 대해 얘기를 나눴다. 페이지랭크는 구글이 유명세를 떨치는데 크게 기여한 수학적 알고리즘이다. 최근 구글은 스탠포드 대학의 페이지랭크 라이선스를 2011년까지 연장한 바 있다.

검색 분야의 역사에 있어 구글이 한 역할에 대해 당신은 어떤 견해를 갖고 있는가?

구글은 사람들이 요구하는 딱 그 시점에 등장했다. 컴퓨터의 출현 이후 사람들은 점점 더 많은 정보를 가질 수 있게 됐다. 따라서 그 많은 정보들을 유용한 것으로 가공하는 우수한 기술을 필요로 했다. 그리고 바로 그때, 구글이 그 접점에 있었던 것이다.

당신은 그간 검색 엔진의 이상적인 모습을 스타트랙에 등장하는 스타쉽 엔터프라이즈가 갖고 있는 지적 능력이라든지 똑똑한 검색 애완동물들이 가득한 세상에 비유하곤 했다. 이에 대해 좀더 말해줄 수 있나?

좋다. 스타쉽 엔터프라이즈나 똑똑한 검색 애완동물에 이은 내 세 번째 생각은 컴퓨터가 도서관의 사서처럼 도움을 주는 것이다. 이것 또한 상당히 재미있다. 도서관 사서들은 검색하기 위해 물론 컴퓨터와 구글도 함께 사용하고 있지만 잘 보면 이들은 검색 작업에 컴퓨터만으로는 불가능한 어떤 지적인 요소를 집어넣고 있다.

결국 우리의 목표는 매우 영리한 컴퓨터를 만들어 상호 대화를 할 때 컴퓨터들로 하여금 실질적으로 더 좋은 검색 결과를 얻을 수 있도록 정보를 잘 활용할 수 있게 하는 것이다. 바로 이것이야말로 구글이 검색의 질을 향상시키기 위해 항상 생각하고 있는 부분이다.

설명한 것과 같은 인공지능적인 검색이 언제 가능해질 것이라고 생각하는가?

인공 지능의 마지막 미개척 분야는 언어 이해라고 본다. 이것이 이뤄진다면 컴퓨터와 대화를 나누는 것이 마치 도서관 사서와 얘기하는 것과 똑같은 경험이 될 것이다. 컴퓨터와 사서는 모두 우리가 살고 있는 이 세계와 우리 자신에 대해 매우 잘 알고 있다는 공통점을 갖게 되기 때문이다.

그러나 둘 간에는 큰 차이점이 있다. 바로 이 부분이 검색 애완동물이 필요한 지점인데 도서관 사서들은 컴퓨터가 완전히 이해할 수 없는 인간의 감정이나 다른 여러 상상속의 세계에 관한 정보들도 이해할 수 있다는 점이다.

언제 가능하냐고 묻는다면 나는 보통 200~300년이 걸릴 것이라고 말한다. 아마 300년보다는 더 짧아지지 않을까? 그러나 만약 200년이 걸리다 해도 어차피 나는 그 당시 살아잇지 않을 것이니까 아무도 나에게 뭐라고 말하진 못할 것이다.

정말 멋진 생각이다

좀 더 말해보자. 30년 내에 방금 언급한 것들이 이뤄질 것이라고 상정해보자. 사실 이런 문제들은 지난 60년대에 인공지능을 연구하던 사람들도 모두 생각했던 부분이다. 그렇다면 지금 우리가 사는 이 시대에 모든 문제가 다 해결됐어야 하지 않는가? 그러나 우리는 인공지능의 궁극적인 목표인 인간의 언어를 이해하기엔 아직 까마득한 수준이다.

몇몇 컴퓨터 연구가들은 페이지랭크가 이제 죽었다고 말한다. 인터넷 광고주들이 자사 사이트의 인기도를 허위로 만들어냄으로써 페이지랭크를 악용하고 있기 때문이라는 것이다. 사실인가? 그렇지 않다면 페이지랭크를 어떻게 수정한 것인가, 아니면 이젠 페이지랭크가 그리 큰 역할을 하지 않는 것인가?

페이지랭크가 죽었다는 주장은 우선 세계를 너무 정적으로 보기 때문에 나온 것이다. 페이지랭크는 언제나 순위 매김 방법 중 하나로 유효할 것이다.

그러나 시간이 가면서 우리가 순위를 매기는 방법에 대해 점점 더 새로운 아이디어를 개발해내고 기존 아이디어를 수정하거나 이 모든 것들을 함께 사용할 수 있는 새로운 방법을 생각해낼 것이기 때문에 우리가 사용하는 이런 모든 기술의 역할도 바뀔 수밖에 없다.

현재 구글에서 페이지링크보다 더 큰 역할을 하고 있는 알고리즘 기술이 있다면?

물론 우리는 현재 다른 기술도 사용하고 있다. 그러나 자세히 언급하는 것은 좀 곤란하다. 개괄적으로 말해보자면 우리는 약 2~3가지 종류의 기술을 사용하고 있다. 하나는 인간의 지능을 이해해 그것을 활용하는 종류다. 우리는 사람들이 어떤 한 페이지를 보고 있다가 다른 페이지로 넘어가기로 결정하는 것이라든지 아니면 그 텍스트가 어떤 것이라고 주석을 다는 행위에서 힌트를 찾아내고 있다.

현재 구글은 몇 대의 서버를 운영하고 있는가? 어떤 사람들은 10만대라고도 하고 어떤 사람들은 만대라고 추산하기도 한다.

몇몇 업계 관계자들은 구글의 컴퓨터 구성이야말로 일급비밀에 속하는 것이라고 하면서 그것만 잘 이용한다면 검색은 단지 한개의 애플리케이션에 불과하다고 말하기도 한다. 그러니까 G메일 같은 것이 가능하다는 것이다. 당신네들의 컴퓨터 구성이 바로 구글의 힘이라는 사람들의 평이 정당하다고 보는가?

재밌는 말이다. 검색의 역사는 실제로도 원래 검색을 위해 개발됐다기보다는 애플리케이션에 추가적으로 포함됐던 검색엔진의 역사에 그 궤를 같이 한다. 알타비스타와 같은 경우에도 원래는 알파 서버의 개념 증명(POC) 용도로 DEC에서 개발한 것이다.

구글에는 상업적 웹 검색 엔진 전용으로 1만대 이상의 컴퓨터를 갖고 있다. 그러나 이것은 물론 검색을 더 잘하기 위해 인프라스트럭처를 개발해온 결과다.

우리는 용이하게 확장시킬 수 있는 그 무언가를 원했다. 웹이 너무나 빨리 성장할 것이라는 사실을 이미 알고 있었기 때문이다. 우리는 컴퓨터만 추가시키면 코드를 새로 작성하지 않고 그 즉시 용량을 늘릴 수 있도록 확장성이 뛰어난 알고리즘을 개발해야만 했다.

이런 생각으로 시작했기 때문에 처음 회사를 설립했을 때는 지금보다 수천배나 작았던 것을 오늘날의 크기까지 키울 수 있었던 것이다.

여기에 우리는 이런 기술들이 많은 정보를 찾는 것과 같은 일상적인 업무에 상당히 유용하다는 것도 알게 됐다. G메일이 아주 좋은 예다. 게다가 이와 같은 정보들은 웹 자체만큼이나 클 수도 있으며 아니면 다 합쳤을 때 웹보다 더 클지도 모른다. 우리는 이런 종류의 정보도 다룰 수 있는 기술적 노하우를 갖고 있다.

현재 어떤 다른 애플리케이션을 개발하고 있는가?

자세히 말할 수는 없다. 일반적인 방향은 이미 위에서 언급한 것과 같다. 그러니까 사람들에게 좀더 많은 정보를 제공한다는 것이다. G메일은 사적인 정보를 검색할 수 있도록 하는 것으로 우리 노력의 첫 번째 실제 결과다.

사생활 옹호론자들부터 시작해 지금은 입법자들에 이르기까지 G메일에 부정적인 반응을 보이는 것을 보며 뭘 느꼈는가?

구글이 사람들의 생활에서 매우 중요한 역할을 하고 있으며 자극을 받는 것도 매우 가치 있다는 점들을 배웠다. 지난번에도 구글이 한 일에 대해 사람들이 흥분했던 것을 기억하고 있다.

바로 우리가 데자닷컴(Deja.com)으로부터 유즈넷(Usenet) 아카이브를 인수했을 때다. 이를 두고 유즈넷 공동체에서는 모두들 이제 유즈넷의 미래는 어떻게 되느냐면서 정보에 접속하는 문제에 대해 큰 우려를 표시했었다.

그러나 시간이 지나면서 상황에 익숙해지자 이들은 제품을 사용해보면서 정말로 좋다는 것을 알게 됐다. 그 사건은 지나갔지만 나는 이번에도 같은 일들이 일어날 것으로 보고 있다. 어떤 회사든지 모든 사람들에게 중요한 이슈로 간주되는 것에는 진지하게 임해야 한다. 나는 구글이 그런 회사라고 생각한다.

서비스는 어떻게 바뀔 것이라고 생각하는가?

어떤 변화가 생길 것이라고 추측하기엔 지금은 너무 이르다.

장기적으로 볼 때 하나의 거대한 검색 공간이 있는 것과 서로 다른 작은 검색 공간들, 그러니까 이 웹사이트에서는 이런 데이터베이스를 그리고 저 회사에서는 이메일 아카이브를 제공하는 식으로 존재하는 것 중 어떤 방식이 더 좋을 것 같은가?

사용자 입장에서는 한 개의 검색 공간을 가지고 싶어 할 것이다. 기술적인 면에서 나는 어느 것이나 상관없다. 나에게 중요한 것은 사용자들이 원하는 정보를 쉽게 얻을 수 있어야 한다는 것이다.

즉 한 공간에서 검색할 수 있어야 한다는 것이며 또한 그 단일한 검색 공간이 아주 영리해서 전세계 수억만 가지의 다른 정보 소스 중 어떤 결과가 적절한지 알아낼 수 있어야 한다는 것이다.

검색 기록이나 등록 데이터, 이메일 문서 등을 한 곳에 놓았을 때 사생활 보호 조치가 필요하다는 것에 대해서는 어떻게 생각하나?

정보를 만들어내고 정보를 소유하고 있는 사람들에게 정보 공개 방식에 대한 결정권이 있다는 것을 잘 알고 있다. 우리는 사람들이 구글을 통해 어떤 식으로 자기네 정보를 내보낼지 제어할 수 있도록 모든 종류의 방법을 제공하고 있다. 이것이 우리의 정책이 될 것이다.

구글의 알고리즘은 확장성이 있는가? 그러니까 예를 들어 당신네의 데이터베이스에 들어있는 데이터가 2배로 늘어나면 검색 결과를 보내주기 위해 단순히 컴퓨터만을 2배로 늘리면 되는 것인가?

우리 알고리즘은 물론 확장된다. 그리고 웹 크기가 2배로 늘어나면 컴퓨팅 기기도 물론 2배로 커져야할 것이다.

기계가 다운되는 특정한 경우가 있는가? 인위적으로 막대한 용량의 데이터를 입력시켜도 크게 상관이 없는가?

내가 아는 한도에서 볼 때 대용량 데이터가 인위적으로 들어와도 잘 돌아간다. 문제가 있을 수도 있겠지만 아직 실제로 그런 일이 일어나진 않았다.

검색 기능이 진보하려면 운영체제에 내장돼야 하며 MS가 개개인에 더 잘 맞는 툴을 만들어낼 수 있다고 생각하는가? 만약 그렇게 된다면 구글은 MS가 수집한 정보에 접속하기를 원하는가?

몇 년 전에 있었던 MS와 넷스케이프 간의 논쟁을 생각해보라. 당시에도 운영체제에 어떤 것이 들어가야 하는지, 들어가서는 안되는지 열띤 논쟁이 있었다. 주로 운영체제가 어떤 것이냐 하는 개념 정의에 관한 논쟁이었다.

사실 나에게 이런 것들은 그다지 흥미를 끌지 못한다. 나의 관심사는 사람들이 필요한 정보를 가능하면 가장 쉽게 얻어야 한다는 것이다.

MS 제품이 2006년도 이전에는 출시되지 않는다는 것을 상기해보자. MS가 검색 분야에서 이른바 FUD 전략을 사용하고 있다고 보는가?

그런 일에 별로 신경쓰지 않는다. MS는 검색이 사람들에게 매우 중요하다고 결론을 내렸고 공개적으로 표명한 적도 있다. 여기엔 우리도 확실하게 동의한다.

동영상이나 오디오 검색 엔진을 만드는데 있어 복잡성은 어느 정도인가?

텍스트가 아닌 정보를 어떻게 설명해야 하는지, 그리고 그런 정보들을 어떻게 활용할 것인지 등이 이런 복잡성에 속한다. 어찌 되든 간에 사람이 그것을 설명해야 하기 때문이다. 물론 쉬운 문제는 아니다. 그러나 오디오나 동영상에도 가능은 하다고 생각한다. 특히 학계에서 이 분야에 매우 큰 관심을 갖고 있다.

그러나 단기적인 문제점들은 그다지 기술적인 부분이 아니다. 이런 컨텐트를 갖고 있는 사람들은 공개를 꺼리고 사람들이 그것을 검색할 수 있도록 내놓으려 하지 않는다.

우리는 사람들의 의견을 존중한다. 언젠가 이런 정보를 웹상에서 검색할 수 있는 좋은 비즈니스 모델이 등장하거나 아무런 불편이 없는 어떤 방법이 나타날 때까지는 이와 관련한 기능을 제공하지 않을 작정이다.

현재 개인 맞춤화 툴들이 등장하고 있다. 아마존의 A9.com과 MSN에서는 각각 다른 기술로 개인화를 구현하고 있다.

구글의 툴은 이를테면 “우리에게 정보를 주면 검색을 도와주겠다”라는 식이다. 반면 다른 회사들은 “당신들의 방법을 배우고 싶다. 그런 이후에 당신을 돕겠다”라는 식이다. 구글의 접근 방식이 어떤 면에서 더 우월한지 설명해 달라.

후자의 경우에는 먼저 배우고 나서 방문자를 돕는다는 주의다. 컴퓨터는 2개의 다른 장소에서 각각 지적인 판단을 내려야한다. 이 방법이 나쁘다거나 전망이 없다는 것은 아니다. 그러나 이 방식을 사용하면 컴퓨터에 더 큰 부담을 준다. 컴퓨터에 당신의 관심사가 무엇인지 말하면 컴퓨터는 그 정보를 가지고 당신이 원하는 것을 찾아주는 정도만 수고하면 된다.

이 두가지 방법은 모두 사람들에게 개별적인 정보를 주자는 같은 목표를 가지고 있다. 다른 것은 단지 어떤 식으로 도달하느냐하는 것뿐이다. 미래에는 이런 검색이 더욱 더 흔해질 것이다.

당신은 구글의 첫번째 직원으로서 구글의 문화가 당신이 처음 시작했을 때와 비교해 어떻게 변했는지 말해줄 수 있는가?

분명히 많이 변했다. 과거에는 회사의 모든 사람들과 알고 지냈지만 지금은 그렇지 못하다는 것이 유감스럽다. 그러나 문화는 달라졌어도 구글의 기저를 이루는 기본 원칙들, 그러니까 제품에 있어서나 하나의 회사로서 내부 운영이 어떤 식으로 이뤄지느냐 하는 면에서는 시작할 때와 그다지 달라진 게 없다. 바로 이 점이 아직도 내가 감동하고 있으며 특히 아직도 구글에 있는 이유 중 하나다.

우리는 아직도 작업 분위기가 즐거워야 한다고 믿는다. 내가 처음에 시작했을 때처럼 지금도 이것은 지켜지고 있다. 구글 사무실에는 하루에도 몇 차례씩 마사지 치료사가 오는데 예전에는 한사람이 왔던 반면 지금은 몇 사람이 한번에 들어와서 마사지를 받고 싶어 하는 직원들에게 마사지를 해준다.

제품 면에서 구글은 매우 기술 중심적인 회사임과 동시에 사용자 경험에 매우 초점을 맞추고 있다. 물론 한 회사를 운영한다는 것은 어려운 일이다. 인터넷 회사로서 5년 반이라는 세월은 결코 짧지 않은 시간이다. 이런 저런 힘든 일이 있었음에도 불구하고 이렇게 늘 일관성 있게 운영되고 있다는 것은 대단한 일이다. 그리고 이 모든 것에 대해 나 자신은 감사하게 생각하고 있다.

출처 :  Stefanie Olsen ( ZDNet Korea )  

2004년 5월에 나온 기사인데 재미있는 내용들이 보이네요...^^

    

설정

트랙백

댓글

상황중심의 프로그래밍

Programming/Etc 2007. 3. 10. 20:54
스티븐 스필버그 감독은 영화 <뮌헨>을 발표한 후 알고 지내던 유태인 친구를 여러 명 잃었다고 고백했다. 영화 속에서 주인공은 이스라엘 정보기관 모사드의 도움을 받아 폭탄 제조, 문서 위조, 사건 뒤처리 등의 다양한 재주를 가진 6명의 요원으로 팀을 구성한 다음, 1972년 뮌헨 올림픽 선수촌에서 테러를 일으킨 검은 9월단의 배후 요원들을 한 명씩 살해한다.

하지만 시간이 흐르면서 주인공을 비롯한 요원들은 국가를 위한 복수와 비인도적인 살인 행위 사이에서 갈등을 겪게 되고 스스로의 생명마저 위협받자 깊은 회의에 빠져들게 된다. 스필버그 감독은 인간적인‘갈등’과‘회의’를 그렸을 뿐인데 열혈 유태인들은 그것조차 용납하기 어려웠던 모양이다.

아무튼 영화 속의 주인공은 복수의 대상 11명이 은거하고 있는 장소와 그밖에 필요한 정보를 얻기 위해서 일종의‘정보 브로커’와 거래를 한다. 그에게 거액의 돈을 주고 살해할 대상이 숨어 있는 장소에 대한 정보를 얻는 것이다. 재미있는 점은 주인공의 복수가 진행되는 동안 다른 나라의 정보조직에서도 똑같은 정보 브로커에게 접근해서 주인공과 동료들의 신원을 파악하려고 한다는 점이다. 이름도 없고, 얼굴도 없어서 어느 누구에게도 존재가 드러나지 않아야 하는 정보조직 세계의 요원들이 이렇게 ‘정보 브로커’라는 존재를 통해서 오히려 하나의 지점에서 만나는 현상이 벌어진다.


상황중심이란 개념 이해하기    

이렇게 다양한 독립적인 개체들이 자신의 목적을 위해서 공통적으로 통과할 수밖에 없는 지점, 혹은 수행할 수밖에 없는 행동을 상황중심 프로그래밍(Aspect Oriented Programming)에서는 접점(join point)라고 부른다.‘ 상황중심’이란 요즘 프로그래밍 세계에서 주목을 받고 있는 ‘Aspect Oriented’라는 표현을 나름대로 우리말로 옮겨본 것이다.‘ Aspect Oriented’라는 말이 국내에서는‘관점 지향’이라는 말로 표현되기도 하는데, 이것은 그 동안 ‘Object Oriented’를‘객체 지향’이라고 불러온 관성의 영향인 것으로 생각된다.

사실‘관점 지향’이라는 말은 의미가 분명하지 않을 뿐만 아니라 겉으로 드러나는 의미조차 정확하다고 보기 어렵다. ‘관점’을‘지향’한다니? 프로그래밍을 수행하는 사람이 자기 관점을 분명히 세우고 그것을 목표로 전진하라는 말인가?‘ 관점 지향’이라는 말이 국내 프로그래머 사이에서 일정한 합의를 이루고 있는 표현이라면 어쩔 수 없지만, 최소한 이 글에서는‘Aspect Object’를‘상황중심’으로 표현하고자 한다. 이렇게 해야 새로운 방법론이 전하고자 하는 의미가 분명하게 드러나기 때문이다.

상황중심 프로그래밍은 말 그대로 현재의 소프트웨어 코드가 처해 있는 특정한‘상황’에 초점을 맞추는 프로그래밍을 의미한다. 폭발적으로 늘어나는 수요를 감당하지 못해 심각한 위기를 맞이했던 소프트웨어 개발시장은‘모듈(module)’과‘객체(object)’라는 혁명적인 개념을 발견하면서 위기를 극복했다. 방대한 분량의 소프트웨어 코드를 모듈과 객체라는 작고 독립적인 부분으로 분리할 수 있었기 때문에 프로그래머들은 점점 더 복잡한 업무를 수행하는 코드를 만들어 낼 수 있었던 것이다. 하지만 독립적인 모듈과 객체의 수마저 기하급수적인 규모로 증가하면서 예전과는 전혀 다른 문제가 대두되었다.

모듈과 객체는 코드를 추상적이고 부분적인 캡슐로 분리해서 전체적인 코드에 대한 관리가 가능하도록 만들고 필요하면 재사용 할 수 있는 방법까지 제공했다. 즉 모듈과 객체는 코드의 부분을 떼어내서 추상화하는 방법을 제공한 것이다. 하지만 이러한 방법은 모듈과 객체를 가로지르며 존재하는 공통의 관심사(cross-cutting concern)를 효율적으로 추상화하는 방법은 제공하지 않았다. 공통의 관심사란 보안(security), 성능(performance), 기록(logging)과 같은 소프트웨어의 일반적인 속성에서부터 데이터 캐시(cache) 관리나 네트워크 프로토콜의 구현처럼 구체적인 기능에 이르기까지 다양하다.

이러한 공통의 관심사는 특정한 모듈이나 객체가 구현하는 기능에 국한되는 것이 아니라 소프트웨어 시스템 전체에 걸쳐 수평적으로 영향을 미친다. 잘 이해가 되지 않는 독자는 다음 예를 생각해 보면 도움이 될 것이다.


공통의 관심사    

인터넷 붐이 한창이던 90년대에 미국에서는‘수평적 시장(horizontal market)’과‘수직적 시장(vertical market)’이라는 표현이 자주 사용되었다. 수직적 시장이란 어떤 제품이 특정한 분야의 시장에 국한되는 경우를 의미한다. 예를 들어서 책, 의류, 자동차, 컴퓨터, 혹은 의료보험 시스템 등은 다른 분야와 겹치지 않는 자기 자신만의 시장을 형성한다.

이들은 모두 수직적 시장의 예이다. 하지만 웹브라우저와 같은 소프트웨어는 특정한 시장에 국한되지 않고 모든 수직적 시장들 사이에 공통적으로 존재하며 영향을 미친다. 그 자체로는 특정 품목에 대한 시장을 형성하지 않지만 여러 시장에서 동시에 존재하는‘공통의 관심사’가 되는 것이다.

영화 <뮌헨>에서 이스라엘의 모사드, 소련의 KGB, 미국의 CIA, 팔레스타인의 검은 9월단 등은 각자 겹치지 않는 고유의 영역을 구성하고 있지만, 그들이 어떤 인물의 은신처를‘검색’하기 위해서는 다양한 정보를 보유하고 있는‘정보 브로커’를 찾아가야만 했다. 각 국의 정보기관이 수직적 시장을 형성하고 있다면,‘ 정보 브로커’는 웹브라우저와 마찬가지로 수평적 시장을 형성하고 있는 셈이다. 이 경우에‘정보 브로커’는 여러 정보기관들을 가로지르며 공통적으로 존재하는‘공통의 관심사’로서의 역할을 담당한다.

오늘날의 프로그래밍 세계에서 수직적 시장을 구성하는 존재는 말할 것도 없이‘객체’들이다. 객체들은 저마다
주어진 일감을 구현하면서 일이 서로 겹치지 않도록 소프트웨어의 전체 영역을 분할한다. 이렇게 분할을 더욱 효율적으로 만들기 위해서 비슷한 일을 하는 객체를 한곳에 묶어서‘패키지(package)’라고 부르기도 한다. 지금까지 프로그래밍은 이러한 분할을 통해서 충분히 잘 이루어져 왔다.

하지만 이렇게 역할 분담을 통한 균형과 평화가 이루어진 상황에서도 여러 객체 사이에 존재하는‘공통의 관심사’는 존재하기 마련이다. 앞에서 예로 든 보안, 성능, 기록, 캐시, 프로토콜 등이 바로 그들이다. 이밖에 유닛테스트(unit test)나 테스트 자동화 등도 여기에 포함될 수 있을 것이다.

좀 더 이해를 돕기 위해서 하나의 구체적인 상황을 생각해보자. 소프트웨어의 사용자들이 항상 그렇듯이 개발자가 개발한 시스템을 이용하는 사용자 중에는 구체적인 데이터를 제시하지 않으면서 말로만“시스템이 느려 터졌다.

답답해서 못 쓰겠다.”라고 불평을 늘어놓는 사람이 있다. 소프트웨어를 제작하고 관리하는 입장에서는 이렇게 막연하게 불평만 늘어놓는 사용자처럼 속상한 존재가 없다.

구체적으로 어떤 기능을 사용할 때‘느린지’를 알아야 그가 겪고 있는 문제가 PC 하드웨어와 관련된 문제인지, 개발자가 만든 소프트웨어의 문제인지, 네트워크의 문제인지, 혹은 서버나 데이터베이스의 문제인지를 알 수 있고 그에 따른 해결책을 제시할 수 있기 때문이다(물론 사용자가 허락만 해준다면 그가 소프트웨어를 어떻게 사용하는지 직접 관찰할 수도 있을 것이다. 하지만 성격이 곱지 않은 월스트리트의 트레이더에게‘저는 소프트웨어를 제작한 사람인데요, 잠시 옆에서 PC를 사용하는 모습을 관찰해도 될 까요’라고 묻는 것은 자살 행위이다).

그렇지만 사용자가 데이터를 제공해 주지 않는다고 해서 손을 놓고 있을 수는 없으므로 우리는 필요한 데이터를 스스로 구해야 한다는 결론을 내리게 되었다. 그리하여 우리가 구현하기로 한 기능은 사용자가 소프트웨어에서 어떤 동작을 수행할 때마다 맨 처음 GUI의 이벤트 처리 메소드(event handler)에서 출발해서 서버와 데이터베이스에 이르는 과정에 존재하는 각 계층을 통과하는 데 걸린 시간을 측정한 다음 로그 파일과 같은 하나의 장소에 기록하는 것이었다.


스파이로그    

사용자가 GUI 화면에서 주식이나 채권 가격 같은 데이터를 입력하고 OK 버튼을 눌렀다고 해보자. 그러면 소프트웨어의 흐름은 GUI 계층, GUI 계층 아래에 존재하는 네트워크 계층, 실제 네트워크 전송, 서버에서 사용자의 요청을 받아들여서 적절한 컴포넌트( component)에게 전달하는 계층, 데이터베이스에 저장되어 있는 프로시저(stored procedure), 최종적인 데이터를 담고 있는 응답객체를 생성하는 계층, 응답 객체를 GUI 클라이언트에게 전송하는 계층, GUI가 서버의 응답을 받아서 처리하는 계층 등을 차례로 통과한다.

이 때 각 계층에서 소요된 시간을 측정해서 하나의 객체에 저장하는 것이다. 이렇게 처리시간이 기록된 객체는 각 계층을 통과할 때마다 다음 계층에게 전달되면서 값을 축적해 나간다. 필요한 처리 과정이 모두 끝나고 나면 이 객체에 저장된 값은 미리 지정된 포맷에 따라서 로그 파일에 기록되고 객체의 수명은 끝이 난다.

이제 사용자가 시스템의 성능에 대해서 밑도 끝도 없는 불평을 늘어놓으면 로그 파일에 저장되어 있는 데이터를 분석해서 실제로 성능에 문제가 있었는지, 만약 문제가 있었다면 어느 계층에서 문제가 있었는지를 파악할 수 있다.

이렇게 유용한 기능의 이름을‘스파이로그’라고 불러보자. 앞의 설명을 읽으면서‘흠 소프트웨어의 여러 계층을 관통하는 <공통의 관심사>를 설명하려고 애쓰고 있군’하고 생각하는 독자가 있다면 만점이다. ‘공통의 관심사(crosscutting concern)’라는 개념을 이해했다면 상황중심 프로그래밍의 98%를 거의 이해한 것과 다름이 없다.

이러한 스파이로그를 실제로 구현하는 방법은 어렵지 않다. 소프트웨어가 객체지향 기법에 따라서 계층별로 잘 분리되어 있다면 더욱 그러하다. 각 계층의 시작과 끝 부분에서 시간을 측정하는 데 필요한 동작을 수행하기만 하면 되기 때문이다. 하지만 그것이 가능하기 위해서는 최소한 두개의 전제 조건이 필요하다. 하나는 스파이로그를 구현하는 프로그래머가 각 계층의 입구와 출구를 정확하게 파악하고 있어야 한다는 점이고, 두 번째는 스파이로그를 구현하기 위해서는 입구와 출구에 해당하는 객체의 소스 파일이 수정되어야 한다는 점이다. 즉, 입구에 해당하는 위치에서는 앞의 계층에서 전달한 시간 측정용 객체를 받아들인 다음 들어온 시간(time stamp)을 찍고, 출구에 해당하는 위치에서는 같은 객체 위에 나가는 시간을 찍고 나서 뒤에 있는 계층에게 객체를 전달해 주는 것이다.

이런 방법은 기능적으로는 아무런 문제가 없지만 코드의 관리라는 측면에서 보면 문제가 많다. 한 가지만 예를 들자면 이런 식이다. 시스템에 A, B, C, D라는 네 개의 계층이 존재한다고 하자. 하나의 동작(operation)이 완성되려면 A, B, C, D, C, B, A라는 완성된 사이클이 그려져야하고, 스파이로그는 이러한 일곱 단계가 소비하는 시간을 각각 측정해서 기록한다.

그런데 나중에 누가 C 계층을 리팩토링해서 그것을 C1과 C2라는 두 개의 계층으로 분리했다고 가정해보자. 그리고 스파이로그의 존재를 의식하지 못한 그가 C1이 받아들인 객체를 C2에게 전달하는 것을 깜빡 잊었다고 하자. 이와 같은 본의 아닌‘실수’가 도입되는 순간 C1과 C2 사이의 고리가 끊어지면서 스파이로그의 기능은 동작을 멈출 수밖에 없다.

여러 계층이 공유하고 있는‘공통의 관심사’가 단지 한계층에서 발생한 실수 때문에 완전히 동작을 멈춘다는 것은 공정하게 들리지 않는다. 뿐만 아니라 스파이로그의 기능이 여러 소스 파일에 분산되면서 코드의 관리가 어려워진다는 단점도 존재한다. 이러한 상황은 서로 독립적으로 분할되어 있어야 하는‘객체’라는 존재를 중심으로 하는 프로그래밍 방법론으로는 명쾌하게 해결되기 어렵다.

객체는 본질적으로 다른 객체와 나란히 서 있도록 만들어진 존재이지, 다른 객체의 허리를 가로지르며 직교(orthogonal)하도록 만들어진 존재가 아니기 때문이다. 바로 이와 같이‘난처한 상황’에서 힘을 발휘하는 것이‘상황중심’의 프로그래밍이다.


제록스 팔로알토연구소에서 탄생    

상황중심 프로그래밍이라는 개념은 제록스 팔로알토 연구소에서 탄생한 것으로 알려져 있다. 현재 캐나다의 브리티시 콜롬비아 대학의 컴퓨터 사이언스 교수인 그레고르킥잘레스(Gregor Kiczales)는 팔로알토 연구소에서의 연구를 확장해서 현재 상황중심 프로그래밍 세계에서 대표적인 언어로 인정받고 있는 AspectJ를 설계했다. IBM에서도 HyperJ나 관심 변경 환경(Concern Manipulation Environment)과 같은 상황중심 프로그래밍 언어를 발표했지만, 현재 프로그래머 사이에서 널리 받아들여지고 있는 언어는 단연 AspectJ이다.

상황중심 프로그래밍에서 사용하는 개념은 크게 네 가지가 있다. 접점(pointcut), 안내(advice), 내부타입 선언(inter type declaration), 그리고 이들을 모두 묶어서 하나의 단위로 추상화하는 상황(aspect)이 그들이다. 상황중심 프로그래밍이나 이러한 개념들이 의미하는 바는 AspectJ의 홈페이지 등에서 쉽게 접할 수 있다. AspectJ에 대한 책도 이미 적지 않게 나와 있다. 여기에서 이들이 의미하는 바를 간단하게 살펴보자면 이렇다.

우선 접점(pointcut)은 공통의 관심사가 여러 개의 객체나 계층을 가로지를 때 그들과 만나게 되는 지점을 의미한다. 앞에서 살펴본 예에서는 각 계층의 입구와 출구가 접점에 해당하고, 더 앞에서 든 예에서는 모사드, CIA, KGB의 요원들이‘정보 브로커’와 만나는 상황 자체가 접점에 해당할 것이다. 접점은 상황중심 프로그래밍을 수행하는 프로그래머가 이미 존재하는 소프트웨어 시스템을 이해하고 있는 수준, 혹은 핵심을 짚어내는 안목에 따라 제대로 짚어질 수도 있고, 엉뚱한 곳이 접점으로 인식될 수도 있다. 어쨌든 프로그래머가 일단 접점을 골라냈으면 그 다음에 할 일은 그 곳에서 할 일을 정의하는 것이다.

그것이 안내(advice)이다. 상황중심 프로그래밍에서 안내는 객체지향 프로그래밍에서의 메소드에 해당한다고 생각하면 쉽다. 특정한 접점에 이르기 직전이나 혹은 직후에 어떤 일을 할 것인가를 정의하는 알고리즘이 안내의 내용을 이룬다.

내부 타입 정의(inter type declaration)는 약간 복잡하다. 이것은 자바 프로그래밍과 같은 기존의 프로그래밍 방식에 익숙한 사람들에게 개념적인 혼란을 초래하기 때문이다. 자바 언어를 예로 들자면, 어느 객체에게 새로운 인스턴스 변수(instance variable) 혹은 필드(field)를 추가하는 것은 언제나 소스 코드의 수정과 컴파일을 통해서 이루어진다.

프로그램이 실행되고 있는 도중에 새로운 필드를 내 마음대로 추가할 수는 없는 것이다. 자바 런타임(runtime) 내부에서 클래스 이름만 가지고 클래스의 인스턴스를 만들어내는 기능은 있지만 클래스에 이미 정의되어 있지 않은 필드를 더하는 기능은 없다.

그런데 상황중심 프로그램에서 사용하는‘내부 타입 정의’기능은 객체에게 새로운 필드를 동적으로 더하는 것을 가능하게 만든다. 이러한 기능이 필요한 이유는 이미 존재하는 다양한 객체와 계층을 가로지르면서 동작하는 알고 리즘을 작성하기 위해서는 주어진 객체의 정해진 틀을 뛰어넘는 능력이 필요하기 때문일 것으로 추측된다. 사실 필자 역시 상황중심 프로그래밍에 익숙하지 않기 때문에 섣불리 말하기는 어렵지만, 이러한 기능이 바람직한지에 대해서는 의문이 든다.

상황중심 프로그래밍을 구사하는 프로그래머가 어느 객체에게 내부 타입 정의 기능을 이용해서 동적으로 어떤 필드를 추가했다고 해보자. 그는 객체를 정의하고 있는 클래스에 새로운 필드를 사용하는 알고리즘을 추가할 수도 있다. ‘( 내부 타입 정의’기능을 통해서 추가한 필드가 퍼블릭으로 정의되어 있다면 기존의 자바 코드에서 접근하는 것이 가능하기 때문이다.)

이렇게 작성된 소스 코드를 나중에 읽는 다른 프로그래머는 (특히 그가 상황중심 프로그램의 존재를 인식하지 못하고 있다면) 도대체 이 코드가 사용하고 있는 필드가 어디에 정의되어 있는 것인지 알 길이 없다. 이런 식의 혼란은 미묘한 버그의 원인이 될 수 있다.

이런 측면에서 보자면 내부 타입 정의를 이용하는 것은 멀쩡한 객체에게 뼈를 깎고 살을 붙이는 성형수술을 시도하는 것, 혹은 객체의 유전자를 조작해서 없던 장기를 만들어 내는 것에 비유할 만하다. 수술이나 유전자 조작이 필요한 결과를 낳는다면 다행이지만, 잘못된 결과를 낳거나 그것이 남용된다면 차라리 하지 않느니만 못한 일이 될 것이다.

마지막으로, 객체지향 프로그래밍에서 클래스가 변수와 메소드를 한 곳에 묶어서 하나의 객체로 추상화하듯, 상황중심 프로그래밍에서 사용되는 접점, 안내, 내부 타입 정의를 한 곳에 묶어서 추상화하는 것은‘상황(aspect)’이다. 따라서 상황은 객체지향 프로그래밍에서 객체가 중심에 서있듯이 상황중심 프로그래밍에서 가장 중심에 서있는 개념이 된다(이것은 프로그래머들이 혐오하는‘중복’된 표현처럼 들린다. 하지만 달리 표현할 방법이 없다. 상황중심 프로그래밍에서 중심은 상황이기 때문이다).


출처 : 임백준(월스트리트 금융전문가) & 소프트웨어 산책외 다수 저자
    

설정

트랙백

댓글

trace 예찬론

Programming/Etc 2007. 3. 9. 00:48
action script를 코딩하다 보면 중간 중간 내가 작성하는 코드가 syntax error가 없는지 수시로 체크를 하게 되는데 그 단위는 코드 100줄을 넘지 못한다. 코딩을 하면서 중간에 딴 생각을 하다가 엉뚱한 방향으로 흐르는 경우도 있고 손가락의 강약 조절과 위치 파악을 제대로 하지 못한 손가락의 잘못도 있다.(결코 내 잘못 아니란다 쿠쿠)

대부분 syntax error로 수정이 가능한 것들이나 가끔은 overflow의 문제로 한참을 헤매는 경우도 종종 있다. Overflow의 경우는 컴파일러가 정확히 어느 위치에서 overflow가 발생했는지를 알려주지 않는 과계로 중간 체크를 하지 않고 코드를 길게 늘리다 보면 쉽게 문제가 되는 부분을 찾기가 어려울 경우가 있다.

더군다나 overflow가 발생했다는(플래시는 255번 이상 스택이 쌓이면 overflow가 발생한다.) 것을 output 패널 창에 보여주면 그나마 다행이지만 컴파일러가 한참을 계산하고서야 문제를 알려줄 때면 가뜩이나 바쁜 와중에 뒷골이 땡긴다.

이런 문제는 반복문에서의 조건문이 무한하거나 undefined일 경우 흔히 발생하게 된다. 가끔 사이트를 돌아다니다 보면 이런 문제로 브라우저를 종료해야 되는 경우가 종종 보이는데 외부에서 xml 데이터를 받아와서 처리해야하는 구문이 있다면 xml이 로드된 시점에서 처리해야 하는데 그것을 간과한 듯 하다.

이런 문제를 미연에 방지하기 위해서는 수시로 단위별로 체크를 해야 한다. 어느 언어나 기본적으로 특정 값을 확인 할 수 있도록 print 내장 메소드를 제공하는데 플래시도 trace라는 구문을 제공한다. 언제나 감사함을 느끼는 놈이다.

개인적으로 생각해 볼 때 논리적인 error를 잡아내는 데는 trace 하나면 충분하다. 중간 중간 확인을 하고 진행한 코드라고 했을 때 문제가 발생하지 않은 시점과 문제가 발생한 시점을 파악하고 그 문제가 발생했던 부분을 훑어봐도 어디가 문제인지를 모를 때는 최초 문제가 발생한 부분의 상위부터 단계별로 trace로 문제가 될만한 변수들을 확인하고 넘어가면 어느 시점에서는 문제의 변수를 잡아낼 수 있다.

가끔 프로그래밍에 발을 들여놓은 분들을 보면 이러한 확인 절차 없이 무턱대고 코드를 작성하고 한꺼번에 컴파일을 하는 경향이 있는데, 이럴 경우에는 문제가 발생할 만한 곳을 찾기란 쉽지가 않다. 문제가 없는 부분과 문제가 발생한 부분을 쉽게 파악하지 못하기 때문이다.

물론 oop 개념의 프로그래밍을 한다면 이러한 문제를 파악하는데도 많은 도움을 받게 된다. 하나의 독립된 class로 문제를 최대한 잘게 쪼개놓으면 문제가 된 class를 쉽게 알아 낼 수가 있기 때문이다. 플래시 액션스크립트도 2.0으로 넘어오면서 어느 정도 oop개념을 도입했지만 실무에서 완벽한 oop 프로그래밍을 하기에는 쉽지가 않다. Oop 개념을 완전하게 이해하지 못한 이유도 있지만 큰 프로젝트가 아닌 경우에는 사실 그러한 개발 노력보다 시간이 더 중요한 경우가 허다하게 발생하기 때문이기도 하다.

그래서 나 또한 실무에서는 oop반 막무가내 코드 반을 섞어서 사용하고 있고 개인적인 놀이나 작업을 할 때는 되도록 oop에 신경을 쓴다. 물론 개인적인 놀이에서 그러한 것을 하다 보면 실무의 실질적인 프로젝트에서도 기억을 되살려 사용하기도 하니 그러한 놀이를 통해서 점점 oop의 필요성과 유용성을 인정하게 된다.

이야기를 하다 보니 이야기가 엉뚱하게 흐르고 있다. 이쯤에서 trace 한번 찍어보자.

var 엉뚱한변수:String = “#@$#@$@#@$#”;
trace(“엉뚱하게 이야기가 흐른 변수 = ” + 엉뚱한변수);

액션 스크립트를 떠나 존재하는 모든 프로그래밍 언어에서 print 구문이 없었다면 아마도 지금도 어셈블리어로 코딩을 하고 있을지도 모르겠다. 생각해 보니 프로그래밍도 커뮤니케이션이다.

trace(“나 여깄어…너 거기있니”);
trace(“나 여기있고 너 거기있구나”);

trace를 사랑합시다. ^^
    

설정

트랙백

댓글

어도비, 모질라에 스크립트 코드 기증

Programming/Etc 2007. 3. 6. 23:32
어도비는 파이어 폭스 웹 브라우저에서 자바스크립트 프로그램들을 실행시키는데 사용될 소프트웨어를 모질라 재단에 기부할 것임을 밝혔다. 이는 모질라 재단 역사상 최대 규모의 기증이다.

어도비는 지난 화요일(미국 시간), 샌프란시스코에서 개최되는 웹 2.0 컨퍼런스에 발맞추어, 기부 내용을 발표할 예정이다. 이 코드는 어도비와 모질라의 개발자들에 의해 관리되고 운영될 ‘타마린’ 이라는 새로운 오픈 소스 프로젝트의 근간을 이룰 것이다.

어도비 또한 ‘액션 스크립트 버츄얼 머신’ 이라 불리는, 이와 똑같은 소프트웨어를 제공할 예정인데, 이것은 어도비 플래시 플레이어9에서 스크립트 코드를 실행시키는데 사용된다.

모질라 재단의 대표 프랭크 해커는 이 가상 머신이 2008년 1분기까지 파이어폭스 브라우저의 차세대 버전에 삽입될 것이라고 말했다.

어도비 플래시 플레이어 버츄얼 머신에서 사용될 스크립팅 언어는 액션 스크립트로 적힌 프로그램을 실행시키는데, 이는 ECMA 국제 표준인 ECMA 에디션4를 기반으로 하고 있다. 어도비의 소프트웨어 설계 부문 대표 케빈 린치는 MS의 제이스크립트와 기타 유명 자바 스크립트들도 이 표준을 적용하고 있다고 말했다.

그는 “플래시 플레이어9과 함께 지난 6월 선보여진 어도비 스크립트 ‘엔진’의 새로운 버전은 실시간 컴파일러를 사용하여 이전 버전보다 10배 빠른 속도로 프로그램을 실행한다”고 설명했다.

린치는 모질라와의 거래가 어도비에게는 오픈 소스 부문에서 진행한 가장 큰 거래였다고 밝혔다. 또한 이번 결정을 통해 개발자들이 에이젝 스타일의 웹 개발과 미디어와 애니메이션을 위한 플래시를 포함하여, 이러한 프로그램 기술들을 섞고 서로 조합할 수 있게끔 만들려는 어도비의 계획을 한 걸음 더 딛게 하는 계기를 만들었다고 덧붙였다.

“우리는 이러한 공통된 언어 사용을 통해 더욱 더 광범위한 HTML과 플래시 개발자 커뮤니티들을 한 데 모을 수 있다. 똑같은 언어 엔진을 사용한다는 것 자체가 매우 큰 진전이라고 할 수 있다.” (린치)

해커는 우수한 스크립트 엔진이 파이어폭스 브라우저나 썬더버드 이 메일 클라이언트 등을 포함한 오픈 소스 프로젝트들에게는 ‘매우 중요한’ 비중을 차지한다고 말했다. 그는 상당 부분의 파이어폭스와 확장자들이 자바 스크립트를 사용하고 있다고 말했다.

또, 타마린 프로젝트 코드는 파이어폭스 브라우저에 현존하는 자바 스크립트인 ‘스파이더 몽키’를 뒤이을 차세대 자바 스크립트의 근간이 될 것이라고 덧붙였다.

출처 : ZDNet Korea

기사가 나온지 오래된 내용이지만 익스플로러 vs 파이어폭스에서 어떤 브라우저가 우위를 차지할지 궁금해지는 기사다.
    

설정

트랙백

댓글

무결점에 도전하는 아름다운 사람들의 이야기

Programming/Etc 2007. 2. 27. 02:53
 지금의 고등학교에서는 문과와 이과를 구분하여 수업을 듣고 있는지 모르겠으나 나의 고등학교 시절에는 문과와 이과를 나누어 ‘가벼운 수학’과 ‘깊이 있는 수학’으로 구분하여 수업을 들었던 기억이다. 수학이 싫다는 단순한 생각에서 이과가 아닌 문과를 지망하게 되었지만 수학은 여전히 나의 기대에 부합하지 않고 문과에서 날 괴롭혔다.
 
 그러했던 나의 선택에 그나마 스스로에게 최선을 다 하겠다며 수학 시간에 학내 도서관에서 빌린 소설책을 선생님 몰래 보면서 스스로를 위한 하곤 했다…^^; 지금은 직장생활로 인해서 전문서적을 보는 것으로 책 읽기를 대신하고 있으니 평소에 소설을 책 한 권 접하기가 쉬운 일이 아니다.
 
 그래서 얼마동안 이 두 가지 토끼(전문 서적 & 에세이 & 소설)을 잡을 욕심으로 가벼운 프로그래밍 관련 서적을 구입하여 읽었다. 읽다 보니 임백준이라는 저자의 책들을 읽게 되었는데 그 중 4권을 소개해 볼까 한다.
 
 먼저 저자 임백준은 삼성 SDS와 미국 루슨트 테크놀로지에서 소프트웨어 엔지니어로 근무했으며 월간 마이크로소프트웨어에 컴퓨터 칼럼을 연재했고 인터넷 신문 “프레시안”에 시사 칼럼을 쓰고 있는 저자다.
 책은 초판발행일자 기준으로 정리 하였다.

1. 행복한 프로그래밍 – 컴퓨터 프로그래밍 미학 오디세이
사용자 삽입 이미지

: 책 제목에 ‘프로그래밍’이라는 말이 들어가면 사람들은 대개 기술적이거나 전문적인 내용을 다루는 책을 떠올리기 마련이다. 하지만 ‘행복한 프로그래밍’이라는 제목에서 필자가 중점을 둔 부분은 “프로그래밍”이라는 명사가 아니라 “행복한”이라는 형용사다. 다시 말해서 이 책은 특정한 기술이나 전공 지식을 담은 책이 아니라 컴퓨터 프로그래밍 속에 들어 있는 미학을 전달하려는 소프트한 얘기를 담고 있는 책이다. –서문중에서
해바라기 씨앗의 배열을 닮은 피보나치 수열은 매우 아름답지만, 그것을 컴퓨터 프로그램으로 옮기는 것이 별로 어려운 일이 아니라는 사실은 나중에야 알게 됐다. 그 때에는 화면에 나타나는 숫자들을 바라보는 것만으로도 황홀감을 느낄 지경이었다 – “영혼을 녹여서 만드는 아름다운 공식” 중에서…



2. 누워서 읽는 알고리즘 – 생각하는 방법을 알려주는 알고리즘 이야기
사용자 삽입 이미지
: 이 책은 어렵고 복잡한 알고리즘을 ‘쉽게 풀어서’ 설명한 책이 아니다. 오히려 맛있는 읽을거리를 만들기 위해서 알고리즘과 같은 기술적인 내용을 ‘동원한’ 책이다. 나는 새로운 알고리즘 이론을 소개하는 것도, 독자들에게 알고리즘을 ‘강의’ 하는 것도 아니다. 즉 ‘공부’와는 아무런 상관이 없다. 나는 실전 프로그래밍을 업으로 삼고 있는 사람들과 함께 가볍게 ‘수다’를 떨면서 우리가 매일 수행하는 ‘일’이 얼마나 재미있는지, 얼마나 아름다운지 그리고 얼마나 창조적인지 확인하고 싶었다 – 서문 중에서
짧은 시간이 흐르고, 화면에 나타나는 결과를 보았을 때 필자의 가슴은 그만 철렁 내려앉고 말았다. 화면에 나타난 것은 정상적인 페이지가 아니라 페이지 수가 이미 최대 값에 도달했으므로 더 이상의 페이지를 열 수 없다는 오류 메시지였다. 모든 경우에 대해서 완벽하게 동작하는 것처럼 보였던 알고리즘안에 조용히 숨어 있던 버그가 드디어 모습을 들어낸 순간이었다 – ‘재즈로 여는 아침의 향기’ 중에서



3. 나는 프로그래머다 – 무결점에 도전하는 아름다운 사람들의 이야기
사용자 삽입 이미지
: 인생에 있어서 도전이란 결코 입맛에 딱 맞는 방식으로 찾아오지 않는다. 그것은 언제나 두 발을 전부 땅에서 떼서 허공에 몸을 완전히 맡겨야 하는, 따라서 상당한 불편함과 두려움을 수반하는 방식으로 찾아온다. 어렵지만 마음에 쏙 드는 일자리를 만났을 때, 어렵지만 풀어 보고 싶은 문제를 만났을 때, 어렵지만 한 번 걸어 보고 싶은 길을 만났을 때, 어렵지만 한 번쯤 말을 꼭 걸어 보고 싶은 이성을 만났을 때, 필요한 것은 앞뒤를 재고 따지는 ‘계산’이 아니라 최선을 다해서 허공에 몸을 맡기는 ‘용기’다. – 서문 중에서
이 책은 IT 각 분야에서 종사하는 7분이 모여서 만든 책이다. 김용준, 김종호, 원은희, 유영창, 이춘식, 임백준, 허광남, 임백준을 제외한 분들은 책을 많이 써보지 않은 분들이라 그런지 문장이나 형식이 자연스럽지 못하다는 느낌이 많이 들었던 것 같다. 임백준의 글이 가장 읽기 편했다. (길들여 진 것일까..;;)





4. 임백준의 소프트웨어 산책 – 소프트웨어에 대한 새로운 시선 그리고 통찰력
사용자 삽입 이미지
: 이 책은 공부를 목적으로 하는 책이 아니다. 프로그래밍과 조금이라도 관련이 있는 사람이라면 이 책을 한 손에 들고 다른 한 속으로는 새우깡이라도 먹으면서 마치 소설책처럼 읽을 수 있기를 바라면서 글을 썼기 때문이다. 사실 이 책은 소설을 담고 있다는 점에서 실제로 ‘소설책’이기도 하다. 깊이와 짜임새를 향한 결심은 지켜내지 못했지만 독자들이 이 책을 재미있게 읽을 수 있기를 바라는 마음에서 아예 소설을 한 편 쓰기도 했다. 말하자면 프로그래머가 프로그래머를 위해서 프로그래밍을 주제로 쓴 소설인데, 책의 뒤에 실려 있다 – 서문중에서
“어려운 문제를 드디어 풀어냈다는 성급한 기대가 K씨의 심장을 빠르게 뛰게 만들었다. 사실 프로그래머가 이와 같은 ‘유레카’의 순간에 느끼는 순백의 열정은 사랑에 빠진 청춘의 감격과 별로 다를 것이 없다. 적어도 그 순간만큼은 세상의 모든 사물이 그 자리에서 동작을 멈추고 시간이 정지한다. – 프로그래머 K씨의 하루 중에서




 이렇게 4권의 책을 읽게 되었다. 임백준은 프로그래밍에 숨어 있는 미학을 발견하고 프로그래밍을 통해서 세상을 이해하려는 노력을 하고 있다. 현재는 뉴욕 월스트리트에서 금융 소프트웨어를 개발하고 있다고 한다. 책의 서문이나 내용을 보면 알 수 있겠으나 대부분의 책들은 프로그래밍이나 컴퓨터 언어에 대한 해박한 지식을 요구하거나 강요하지 않는다. 그렇다고 프로그래밍과 전혀 관련이 없는 사람들이 읽기에는 공감이 가는 성격의 글이 아니기에 권하고 싶은 마음은 없다.
 
 작년 Macromedia conference MAX 2005 KOREA에서 스피커로 나왔던 Jared Tarbell은  “프로그래밍은 시와 같다”, “프로그래밍은 아트다” 와 같은 이야기를 한 적이 있다. 임백준이 프로그래밍에서 발견한 미학이라는 것이 이런 의미에서의 아름다움이 아닐까 하는 생각이 든다. 나 자신도 구조적으로 잘 짜여진 짧지만 많은 의미를 담고, 아름다울 만큼 창의적인 결과를 표현하는 프로그램을 보면 ‘아름답다’라는 표현이 가장 적절하다는 생각이 든다.
 
 얼마 전에 모 출판사에서 나에게 책을 쓸 것을 권한 적이 있다. 판매금액의 10%를 받는 조건으로 책을 쓰면 어떻겠냐는 이야기였다. 금전적인 문제를 떠나 내가 쓴 책이 일반 서점에서 독자들에게 판매될 수 있다는 것을 생각하니 결정도 내리지 않은 시점인데도 흥분되는 일이 아닐 수 없었다.
 
 며칠 동안 고민하다가 일단 샘플을 하나 만들고 간단한 구조로 내용을 담아 보았다. 그런데 가만히 내가 만든 소스와 내가 쓴 글을 보고 있으니 책으로 세상에 내놓기에는 쓰레기 같아 보였다. 소스는 순전히 개인적인 습관과 입증되지 않은 구조와 알고리즘으로 낙서를 해놓은 것 같은 느낌이 들었다.
 
 임백준의 책 속에 이런 내용이 있다. “자신이 만든 프로그램으로 만든 전투기를 직접 자신이 조정할 수 있는 용기가 있는가” 결코 쉬운 일이 아닌 듯 싶다. 더군다나 인터넷이 아닌 인쇄물로 한번 세상에 내놓으면 수정할 수도, 업데이트 할 수도 없는 책을 출간한다면 잘못된 정보를 통해 위와 같은 질문에 ‘예’라고 대답한 사람들의 사고들을 내가 어찌 감당할 수 있겠는가 싶었다. 그래서 다음날 출판사 담당자에게 기회가 되면 다음에 쓰겠다고 정중히 거절을 했던 일이 있었다. 지금도 나는 그때의 결정을 잘 했다고 생각한다.
 
 프로그래밍이 아름다음을 갖으려면 그것을 만드는 사람의 흥미와 재미, 열정과 인내가 필요한 작업이 아닐까 싶다. 혹시나 나는 인내가 어려워 가벼운 흥미와 재미를 쫓고 그것을 열정이라 자찬하고 있는 것은 아닐런지...;
    

설정

트랙백

댓글

Iterator

Programming/Design Patterns 2007. 2. 21. 11:09









1 class DinerMenu{
2         public static var MAX_ITEMS = 6;
3         private var numberOfItems = 0;
4         private var menuItems:Array;
5
6         public function DinerMenu(){
7                 menuItems = new Array();
8
9                 addItem("채식주의자용 BLT", "통밀 위에(식물성) 베이컨, 상추, 토마토를 얹은 메뉴", true, 2.99);
10                 addItem("BLT", "통밀 위에 베이컨, 상추, 토마토를 얹은 메뉴", false, 2.99);
11                 addItem("오늘의 스프", "감자 샐러드를 곁들인 오늘의 스프", false, 3.29);
12                 addItem("핫도그", "사워크라우트, 갖은 양념, 양파, 치즈가 곁들여진 핫도그", false, 3.05);
13
14         }
15
16         public function addItem(name:String, description:String, vegetarian:Boolean, price:Number):Void{
17                 var menuItem:MenuItem = new MenuItem(name, description, vegetarian, price);
18                 if(numberOfItems >= MAX_ITEMS){
19                         trace("죄송합니다. 메뉴가 꽉 찼습니다. 더이상 추가할 수 없습니다.");
20                 }else{
21                         menuItems[numberOfItems] = menuItem;
22                         numberOfItems+=1;
23                 }
24         }
25         /* public function getMenuItems():Array{
26         return menuItems;
27 }*/

28         public function createIterator():Iterator{
29                 return new DinerMenuIterator(menuItems);
30         }
31
32 }

////////////////////////////////////////

 1 class DinerMenuIterator implements Iterator{
2         private var items:Array;
3         private var position:Number;
4
5         public function DinerMenuIterator(items:Array){
6                 this.items = items;
7                 this.position = 0;
8         }
9         public function next():Object{
10                 var menuItem:MenuItem = items[position];
11                 position += 1;
12                 return menuItem;
13         }
14         public function hasNext():Boolean{
15                 if(position>= items.length || items[position] == null){
16                         return false;
17                 }else{
18                         return true;
19                 }
20         }
21 }

///////////////////////////////////////////

 1 interface Iterator{
2         public function hasNext():Boolean;
3         public function next():Object;
4 }

///////////////////////////////////////////

 1 class MenuItem{
2         private var name;
3         private var description:String;
4         private var vegetarian:Boolean;
5         private var price:Number;
6
7         public function MenuItem(name:String, description:String, vegetarian:Boolean, price:Number){
8                 this.name = name;
9                 this.description = description;
10                 this.vegetarian = vegetarian;
11                 this.price = price;
12         }
13         public function getName():String{
14                 return name;
15         }
16         public function getDescription():String{
17                 return description;
18         }
19         public function getPrice():Number{
20                 return price;
21         }
22         public function isVegetarian():Boolean{
23                 return vegetarian;
24         }
25         public function toString():String{
26                 return name+" of MenuItem Object\n";
27         }
28 }

//////////////////////////////////////////

 1 class PancakeHouseMenu{
2         private var menuItems:Array;
3
4         public function PancakeHouseMenu(){
5                 menuItems = new Array();
6                 addItem("K&B 팬케이크 세트", "스크램블드 에그와 포스트가 곁들여진 팬케이크", true, 2.99);
7                 addItem("레귤러 팬케이크 세트", "달걀 후라이와 소시지가 곁들여진 팬케이크", false, 2.99);
8                 addItem("블루베리 팬케이크", "신선한 블루베리와 블루베리 시럽으로 만든 팬케이크", true, 3.49);
9                 addItem("와플", "와플, 취향에 따라 블루베리나 딸기를 얹을 수 있습니다.", true, 3,59);
10         }
11         public function addItem(name:String, description:String, vegetarian:Boolean, price:Number):Void{
12                 var menuItem:MenuItem = new MenuItem(name, description, vegetarian, price);
13                 menuItems.push(menuItem);
14         }
15         /* public function getMenuItems():Array{
16         return menuItems;
17 }*/

18         public function createIterator():Iterator{
19                 return new PancakeIterator(menuItems);
20         }
21 }

/////////////////////////////////////////////

1 class PancakeIterator implements Iterator{
2         private var items:Array;
3         private var position:Number;
4
5         public function PancakeIterator(items:Array){
6                 this.items = items;
7                 this.position = 0;
8         }
9         public function next():Object{
10                 var menuItem:MenuItem = items[position];
11                 position += 1;
12                 return menuItem;
13         }
14         public function hasNext():Boolean{
15                 if(position>= items.length || items[position] == null){
16                         return false;
17                 }else{
18                         return true;
19                 }
20         }
21 }

////////////////////////////////////////////////

 1 class Waitress{
2         private var pancakeHouseMenu:PancakeHouseMenu;
3         private var dinerMenu:DinerMenu;
4
5         public function Waitress(pancakeHouseMenu:PancakeHouseMenu, dinerMenu:DinerMenu){
6                 this.pancakeHouseMenu = pancakeHouseMenu;
7                 this.dinerMenu = dinerMenu;
8         }
9         public function printMenu():Void{
10                 var pancakeIterator:Iterator = pancakeHouseMenu.createIterator();
11                 var dinerIterator:Iterator = dinerMenu.createIterator();
12                 trace("메뉴 ----- \n 아침 메뉴");
13                 printMenuList(pancakeIterator);
14                 trace("\n점심 메뉴");
15                 printMenuList(dinerIterator);
16         }
17         private function printMenuList(iterator:Iterator):Void{
18                 while(iterator.hasNext()){
19                         var menuItem:MenuItem = MenuItem(iterator.next());
20                         trace(menuItem.getName()+", ");
21                         trace(menuItem.getPrice()+"--");
22                         trace(menuItem.getDescription());
23                 }
24
25         }
26 }

////////////////////////////////////////////

 1 class MenuTestDrive{
2         public function MenuTestDrive(){
3                 initialize();
4         }
5         private function initialize():Void{
6                 var pancakeHouseMenu:PancakeHouseMenu = new PancakeHouseMenu();
7                 var dinerMenu:DinerMenu = new DinerMenu();
8                 var waitress:Waitress = new Waitress(pancakeHouseMenu, dinerMenu);
9                 waitress.printMenu();
10         }
11 }
    

설정

트랙백

댓글

TemplateMethod

Programming/Design Patterns 2007. 2. 21. 11:09
 1 class CaffeineBeverage{
2         public function prepareRecipe():Void{
3                 boilWater();
4                 brew();
5                 pourInCup();
6                 if(hook()){
7                         addCondiments();
8                 }
9         }
10         public function brew():Void{
11
12         }
13         public function addCondiments():Void{
14
15         }
16         public function boilWater():Void{
17                 trace("물 끓이는 중");
18         }
19         public function pourInCup():Void{
20                 trace("컵에 따르는 중");
21         }
22         public function hook():Boolean{
23                 return true;
24         }
25 }

/////////////////////////////////////////////

 1 class Coffee extends CaffeineBeverage{
2         public function brew():Void{
3                 trace("필터로 커피를 우려내는 중");
4         }
5         public function addCondiments():Void{
6                 trace("설탕과 커피를 추가하는 중");
7         }
8         public function hook():Boolean{
9                 return false;
10         }
11 }

//////////////////////////////////////////////

 1 class Tea extends CaffeineBeverage{
2         public function brew():Void{
3                 trace("차를 우려내는 중");
4         }
5         public function addCondiments():Void{
6                 trace("레몬을 추가하는 중");
7         }
8 }

//////////////////////////////////////////////

 1 class TemplateTest{
2         public function TemplateTest(){
3                 init();
4         }
5         private function init():Void{
6                 var tea:CaffeineBeverage = new Tea();
7                 var coffee:CaffeineBeverage = new Coffee();
8
9                 trace("Tea Test..............");
10                 tea.prepareRecipe();
11
12                 trace("Coffee Test...........");
13                 coffee.prepareRecipe();
14         }
15 }
    

설정

트랙백

댓글