Adobe Flex에서 Visual Component에 스타일을 입히기 위해 MXML형태의 <mx:Style></mx:Style>을 자주 사용할 것이다.

 

<mx:Style>을 이해하기 앞서 먼저 Flex의 컴파일 과정에 대해서 언급하겠다. 알다시피 Flex의 결과물은 Flash 컨텐츠인 SWF파일이다. Flex로 만들어진 결과물은 컴파일 단계에서 모두 ActionScript 3.0으로 변환(Generate)되고 변환된 ActionScript 3.0 파일을 가지고 SWF가 만들어진다. 즉, Flex에서 유용하게 사용되는 MXML은 UI 디자인의 편의성을 제공하기 위해 사용되는 것이지 실제 컴파일 단계에서는 직접적으로 사용되지 않는 언어이다. 

 

<mx:Style> 변환에 대한 이해

 

MXML에서 <mx:Style>로 싸여진 것도 ActionScript 3.0 으로 변환한다는 것을 이제 짐작할 수 있을 것이다. 실제로 어떻게 ActionScript 3.0으로 변환되는지 확인하기 위해 Flex Builder에서 Flex Project를 만들고 생성된 프로젝트의 컴파일러 옵션에 –keep-generated-actionscript를 넣어주자. 이 옵션은 Flex 컴파일시 사용되는 mxmlc에 지정하는 옵션이다. 더 많은 옵션은 “About the application compiler options”를 참고하면 되겠다.

 

 

 

위 옵션대로 넣어주면 프로젝트의 src폴더에 generated 폴더가 생성된다.

 

 

 

generated 폴더를 살펴보면 아래 그림처럼 ActionScript 3.0 파일이 생성된 것을 확인할 수 있다.

 

 

 

아래 코드 처럼 Application에 어떤 visual component도 삽입하지 않은 상태에서 GenerateCSSTest-generated.as 파일을 살펴보자. (프로젝트명을 GenerateCSSTest로 했기 대문에 GenerateCSSTest-generated.as 가 된 것이다.)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
</mx:Application>

 

아래 코드는 MXML로 만들어진 Application을 ActionScript 3.0으로 변환된 GenerateCSSTest 클래스이다.(GenerateCSSTest-generated.as). 우리가 집중적으로 살펴보아야 할 부분은 <mx:Style>이 어떻게 사용되는가 알아내는 것이므로 코드상에서 _GenerateCSSTest_StylesInit() 부분에서 관련성을 찾아낼 수 있을 것이다. 이 애플리케이션이 실행하게 되면 GenerateCSSTest 생성자에서 _GenerateCSSTest_StylesInit()를 호출하므로 <mx:Style>에서 적용한 CSS가 여기서 적용될 것이다라는 것을 예측할 수 있다.

public class GenerateCSSTest
    extends mx.core.Application
{

    //    instance variables

    //    type-import dummies

    //    Container document descriptor
private var _documentDescriptor_ : mx.core.UIComponentDescriptor =
new mx.core.UIComponentDescriptor({
  type: mx.core.Application
})

    //    constructor (Flex display object)
    /**
     * @private
     **/
    public function GenerateCSSTest()
    {
        super();

        mx_internal::_document = this;

        //    our style settings

        //    ambient styles
        mx_internal::_GenerateCSSTest_StylesInit();

        //    properties
        this.layout = "vertical";

        //    events

    }

    //    initialize()
    /**
     * @private
     **/
    override public function initialize():void
    {
         mx_internal::setDocumentDescriptor(_documentDescriptor_);

        super.initialize();
    }

    //    scripts
    //    end scripts

    //    supporting function definitions for properties, events, styles, effects

    //    initialize style defs for GenerateCSSTest

    mx_internal static var _GenerateCSSTest_StylesInit_done:Boolean = false;

    mx_internal function _GenerateCSSTest_StylesInit():void
    {
        //    only add our style defs to the StyleManager once
        if (mx_internal::_GenerateCSSTest_StylesInit_done)
            return;
        else
            mx_internal::_GenerateCSSTest_StylesInit_done = true;

        var style:CSSStyleDeclaration;
        var effects:Array;

        StyleManager.mx_internal::initProtoChainRoots();
    }

    //    embed carrier vars
    //    end embed carrier vars

//    end class def
}

 

이제 아래 코드처럼 Application안에 Button과 TextArea 컴포넌트를 삽입하고 각각에 대해서 Type Selector와 Class Selector로 CSS를 <mx:Style> 태그안에 적용해보자.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
    <mx:Button label="버튼1"/>
    <mx:TextArea text="Flex가 쪼아~" styleName="myTextArea"/>
    <mx:Style>
        Button
        {
            fontSize:12pt;
        }
        .myTextArea
        {
            fontSize:14pt;
            color:red;
        }
    </mx:Style>
</mx:Application>

 

아래코드는 위처럼 Application에 2가지 컴포넌트와 스타일을 적용했을 때 만들어진 GenerateCSSText 클래스 ActionScript 3.0 코드이다. 파란색 부분은 아무것도 안넣을 때와 비교할 때 추가된 부분이다. MXML로 컴포넌트를 삽입하면 상단 파란색 부분처럼 UIComponentDescriptor의 인스턴스인 _documentDescriptor_에 자동으로 등록시켜준다. 각 컴포넌트에 설정된 속성인 label, text, styleName도 추가되어 있는 것을 볼 수 있다. _documentDescriptor_는 initialize()함수 실행시 적용된다.

 

또한 그 아래로 가보면 우리가 관심을 가지고 있는 <mx:Style>에 작성된 CSS가 어떻게 적용되었나 알 수 있다. 

 

여기 있는 코드는 2개의 CSS Selector를 등록하고 있다.

 

첫번째로 Class Selector인 “.myTextArea” 이다. StyleManager.getStyleDeclaration()을 통해 기존에 “.myTextArea”가 등록되어 있는지 조사한다. 만약 등록이 안되어 있다면 StyleManager.setStyleDeclaration()을 통해 CSSStyleDeclaration의 인스턴스형으로 “.myTextArea”를 등록한다. 그런 다음 <mx:Style>에 지정한 fontSize와 color를 적용하기 위해 CSSStyleDeclaration의 factory함수를 정의한다. 이렇게 해두면 자동적으로 StyleManager에 등록된 Class Selector인 “.myTextArea”를 생성하게 되며 StyleManager는 styleName이 “.myTextArea”로 적용된 컴포넌트는 전부 찾아 적용해준다.

 

같은 방법으로 Type Selector인 “Button”을 등록한다. StyleManager은 Button 컴포넌트로 만들어진 인스턴스를 찾아 fontSize:12pt를 적용해준다.

이처럼 <mx:Style></mx:Style>안에 적용된 CSS는 ActionScript 3.0으로 만들어져 StyleManager 클래스가 담당하도록 Flex 컴파일러가 변경시켜준다. 이것이 핵심이다.

public class GenerateCSSTest
    extends mx.core.Application
{

    //    instance variables

    //    type-import dummies

    //    Container document descriptor
private var _documentDescriptor_ : mx.core.UIComponentDescriptor =
new mx.core.UIComponentDescriptor({
  type: mx.core.Application
  ,
  propertiesFactory: function():Object { return {
    childDescriptors: [
      new mx.core.UIComponentDescriptor({
        type: mx.controls.Button
        ,
        propertiesFactory: function():Object { return {
          label: "버튼1"
        }}
      })
    ,
      new mx.core.UIComponentDescriptor({
        type: mx.controls.TextArea
        ,
        propertiesFactory: function():Object { return {
          text: "Flex가 쪼아~",
          styleName: "myTextArea"
        }}
      })
    ]
  }}
})

    //    constructor (Flex display object)
    /**
     * @private
     **/
    public function GenerateCSSTest()
    {
        super();

        mx_internal::_document = this;

        //    our style settings

        //    ambient styles
        mx_internal::_GenerateCSSTest_StylesInit();

        //    properties
        this.layout = "vertical";

        //    events

    }

    //    initialize()
    /**
     * @private
     **/
    override public function initialize():void
    {
         mx_internal::setDocumentDescriptor(_documentDescriptor_);

        super.initialize();
    }

    //    scripts
    //    end scripts

    //    supporting function definitions for properties, events, styles, effects

    //    initialize style defs for GenerateCSSTest

    mx_internal static var _GenerateCSSTest_StylesInit_done:Boolean = false;

    mx_internal function _GenerateCSSTest_StylesInit():void
    {
        //    only add our style defs to the StyleManager once
        if (mx_internal::_GenerateCSSTest_StylesInit_done)
            return;
        else
            mx_internal::_GenerateCSSTest_StylesInit_done = true;

        var style:CSSStyleDeclaration;
        var effects:Array;

        // myTextArea
        style = StyleManager.getStyleDeclaration(".myTextArea");
        if (!style)
        {
            style = new CSSStyleDeclaration();
            StyleManager.setStyleDeclaration(".myTextArea", style, false);
        }
        if (style.factory == null)
        {
            style.factory = function():void
            {
                this.color = 0xFF0000;
                this.fontSize = 14;
            };
        }
        // Button
        style = StyleManager.getStyleDeclaration("Button");
        if (!style)
        {
            style = new CSSStyleDeclaration();
            StyleManager.setStyleDeclaration("Button", style, false);
        }
        if (style.factory == null)
        {
            style.factory = function():void
            {
                this.fontSize = 12;
            };
        }

        StyleManager.mx_internal::initProtoChainRoots();
    }

    //    embed carrier vars
    //    end embed carrier vars

//    end class def
}

 

본문에서는 StyleManager 자체의 구조를 설명하는 것은 너무 방대할 것이므로 생략한다. 개인적으로 Flex의 스타일 적용 방식은 매우 유연하고 사용하기 편하다고 생각한다. 그만큼 Flex SDK에 있는 StyleManager가 잘 만들어져 있다는 것을 의미하기도 한다. 시간이 허락된다면 StyleManager를 분석해서 배치된 Visual Component에 어떻게 스타일이 적용되는지 알아보는 것도 흥미롭고 유익한 일일 것이다.

 

컴파일러 옵션인 –keep-generated-actionscript은 MXML을 ActionScript 3.0으로 변환한 코드를 가시적으로 볼 수 있게 함으로써 Flex가 어떻게 동작하는가 아는데 중요한 가이드 역할을 하고 있는 셈이다.

 

컴포넌트의 기본 스타일은 어떻게 적용되는가?

 

이쯤되면 궁금한 점이 또 생긴다.

 

<mx:Style>로 적용하지 않은 컴포넌트들은 어떻게 CSS가 먹히는 것일까? 본인은 처음에 해당 컴포넌트 클래스에 StyleManager를 이용하여 CSS를 만들었을 것이라 생각했다. 하지만 그게 아니였다. Flex SDK에 있는 Button.as를 살펴보길 바란다.(Window XP에 Flex Builder 3 Professonal을 설치한 경우에는 C:\Program Files\Adobe\Flex Builder 3\sdks\3.2.0\frameworks\projects\framework\src\mx\controls에 Button.as 가 있다.) 직접 보면 알겠지만 Button.as안에는 StyleManager에 관련된 내용이 전혀 존재하지 않는다. 그럼 Flex 컴포넌트들의 기본 스타일은 도대체 어떻게 적용되는 것인가?

답은 generated 폴더 안에 있다.

 

generated 폴더 내부에는 Button에 기본 스타일을 적용을 정의한 _ButtonStyle.as 뿐 아니라 _gloabalStyle.as, _ApplicationStyle.as, _dateGridStylesStyle.as 등이 있다.

아래는 _ButtonStyle.as이다. Button의 스킨인 mx.skins.halo.ButtonSkin이 여기서 적용된다. 또한 textAlign도 여기서 적용되는 것을 볼 수 있다. 즉 사용한 컴포넌트에 CSS를 적용하지 않더라도 기본 스타일이 이들 코드를 통해 적용됨을 알 수 있다.

 

앞선 예제에서 Application에서 <mx:Style>에 “Button” Type Selector로 fontSize=12pt가 적용되었으므로 이 로직이 실행이 되고 난 다음에 fontSize=12pt가 적용됨을 감각적으로 알 수 있을 것이다.

public class _ButtonStyle
{

    public static function init(fbs:IFlexModuleFactory):void
    {
        var style:CSSStyleDeclaration = StyleManager.getStyleDeclaration("Button");
        if (!style)
        {
            style = new CSSStyleDeclaration();
            StyleManager.setStyleDeclaration("Button", style, false);
        }
        if (style.defaultFactory == null)
        {
            style.defaultFactory = function():void
            {
                this.paddingTop = 2;
                this.textAlign = "center";
                this.skin = mx.skins.halo.ButtonSkin;
                this.paddingLeft = 10;
                this.fontWeight = "bold";
                this.cornerRadius = 4;
                this.paddingRight = 10;
                this.verticalGap = 2;
                this.horizontalGap = 2;
                this.paddingBottom = 2;
            };
        }
    }
}

 

방금 언급한 Style관련 ActionScript 3.0 코드들(_ButtonStyle.as, _gloabalStyle.as, _ApplicationStyle.as, _dateGridStylesStyle.as 등)은 Flex SDK의 SystemManager 클래스에 등록되어 사용된다. generated 폴더를 살펴보면 SystemManager 클래스를 확장한 _GenerateCSSTest_mx_managers_SystemManager 클래스의 ActionScript 3.0 코드가 존재한다. 아래 코드를 살펴보자.

public class _GenerateCSSTest_mx_managers_SystemManager
    extends mx.managers.SystemManager
    implements IFlexModuleFactory
{
    public function _GenerateCSSTest_mx_managers_SystemManager()
    {

        super();
    }

    override     public function create(… params):Object
    {
        if (params.length > 0 && !(params[0] is String))
            return super.create.apply(this, params);

        var mainClassName:String = params.length == 0 ? "GenerateCSSTest" : String(params[0]);
        var mainClass:Class = Class(getDefinitionByName(mainClassName));
        if (!mainClass)
            return null;

        var instance:Object = new mainClass();
        if (instance is IFlexModule)
            (IFlexModule(instance)).moduleFactory = this;
        return instance;
    }

    override    public function info():Object
    {
        return {
            compiledLocales: [ "en_US" ],
            compiledResourceBundleNames: [ "containers", "core", "effects", "skins", "styles" ],
            currentDomain: ApplicationDomain.currentDomain,
            layout: "vertical",
            mainClassName: "GenerateCSSTest",
            mixins: [ "_GenerateCSSTest_FlexInit", "_alertButtonStyleStyle", "_ScrollBarStyle", "_activeTabStyleStyle", "_textAreaHScrollBarStyleStyle", "_ToolTipStyle", "_advancedDataGridStylesStyle", "_comboDropdownStyle", "_ContainerStyle", "_textAreaVScrollBarStyleStyle", "_linkButtonStyleStyle", "_globalStyle", "_windowStatusStyle", "_windowStylesStyle", "_activeButtonStyleStyle", "_errorTipStyle", "_richTextEditorTextAreaStyleStyle", "_CursorManagerStyle", "_todayStyleStyle", "_dateFieldPopupStyle", "_plainStyle", "_dataGridStylesStyle", "_ApplicationStyle", "_headerDateTextStyle", "_ButtonStyle", "_popUpMenuStyle", "_swatchPanelTextFieldStyle", "_opaquePanelStyle", "_weekDayStyleStyle", "_headerDragProxyStyleStyle" ]

        }
    }
}

info() 메소드를 override해서 mixins에 CSS를 적용한 클래스의 이름들을 전부 Array형태로 담고 있다. SystemManger는 이 mixins에 등록된 클래스들을 전부 스캔하며 CSS를 적용한다.

 

아래코드는 StyleManager 내부의 일부 코드이다. 앞서 설명한 SystemManager를 확장한_GenerateCSSTest_mx_managers_SystemManager 클래스는 info()를 override했기 때문에 해당 mixins값을 전부 얻어올 수 있다. 이 값의 길이만큼 loop를 돌면서 getDefinitionByName()메소드를 통해 해당 클래스 정의되어 있는지 알아내어 그 클래스의 init()함수를 호출한다. _ButtonStyle.as에 init()메소드에 StyleManager를 가지고 Button의 Type Selector를 등록했다는 것을 확인할 수 있었다. 결국 StyleManager로 Style을 적용한 클래스들의 init()함수를 모두 호출함으로써 기본 CSS가 애플리케이션에 적용되는 것이다.

        var mixinList:Array = info()["mixins"];
        if (mixinList && mixinList.length > 0)
        {
            var n:int = mixinList.length;
            for (var i:int = 0; i < n; ++i)
            {
                // trace("initializing mixin " + mixinList[i]);
                var c:Class = Class(getDefinitionByName(mixinList[i]));
                c["init"](this);
            }
        }

 

 

상속되는 CSS 속성은 어떻게 적용될까?

 

CSS 속성중에는 상속되는 것과 상속되지 않는 것이 있다. 가령 fontSize, color, fontFamily 등은 상속이 된다. 한 예로 아래코드처럼 Application에 color를 blue로 지정해보자. color는 상속되는 CSS속성이기 때문에 Button에 color가 지정되어 있지 않음에도 불구하고 파란색 글자색이 적용된다.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
    <mx:Button label="버튼1"/>
    <mx:TextArea text="Flex가 쪼아~" styleName="myTextArea"/>
    <mx:Style>
        Application
        {
            color:blue;
        }

        Button
        {
            fontSize:12pt;
        }
        .myTextArea
        {
            fontSize:14pt;
            color:red;
        }
    </mx:Style>
</mx:Application>

 

 

Button에는 파란색이 적용된 반면 TextArea에는 그대로 빨간색이 적용된 이유는 CSS적용 우선순위 때문이다. 부모(Application)에 적용한 CSS속성값에 자식(TextArea)에서 다시 적용하면 부모에서 적용한 것은 무시된다. 다른 이야기지만 이러한 일을 전부 StyleManager에서 하고 있다는게 대단해보인다. Flex SDK의 강력함이 엿보인다. 만약 Flex SDK를 사용하지 않고 순수하게 ActionScript 3.0으로 코딩해야하는 경우에 CSS를 적용해야한다면… 앞이 깜깜할 뿐이다. 다 만들어야하니 말이다. ^^;

 

이처럼 Flex의 CSS는 상속이 되는 속성들이 있는데 이들 속성도 generated 폴더에 살펴보면 어떻게 등록되어 사용되는지 살펴볼 수 있다. _GenerateCSSTest_FlexInit.as를 살펴보자.

public class _GenerateCSSTest_FlexInit
{
   public function _GenerateCSSTest_FlexInit()
   {
       super();
   }
   public static function init(fbs:IFlexModuleFactory):void
   {
      EffectManager.mx_internal::registerEffectTrigger("addedEffect", "added");
      EffectManager.mx_internal::registerEffectTrigger("creationCompleteEffect", "creationComplete");
      EffectManager.mx_internal::registerEffectTrigger("focusInEffect", "focusIn");
      EffectManager.mx_internal::registerEffectTrigger("focusOutEffect", "focusOut");
      EffectManager.mx_internal::registerEffectTrigger("hideEffect", "hide");
      EffectManager.mx_internal::registerEffectTrigger("mouseDownEffect", "mouseDown");
      EffectManager.mx_internal::registerEffectTrigger("mouseUpEffect", "mouseUp");
      EffectManager.mx_internal::registerEffectTrigger("moveEffect", "move");
      EffectManager.mx_internal::registerEffectTrigger("removedEffect", "removed");
      EffectManager.mx_internal::registerEffectTrigger("resizeEffect", "resize");
      EffectManager.mx_internal::registerEffectTrigger("rollOutEffect", "rollOut");
      EffectManager.mx_internal::registerEffectTrigger("rollOverEffect", "rollOver");
      EffectManager.mx_internal::registerEffectTrigger("showEffect", "show");
      var styleNames:Array = ["fontWeight", "modalTransparencyBlur", "textRollOverColor", "backgroundDisabledColor", "textIndent", "barColor", "fontSize", "kerning", "textAlign", "fontStyle", "modalTransparencyDuration", "textSelectedColor", "modalTransparency", "fontGridFitType", "disabledColor", "fontAntiAliasType", "modalTransparencyColor", "leading", "dropShadowColor", "themeColor", "letterSpacing", "fontFamily", "color", "fontThickness", "errorColor", "fontSharpness", "textDecoration"];

      import mx.styles.StyleManager;

      for (var i:int = 0; i < styleNames.length; i++)
      {
         StyleManager.registerInheritingStyle(styleNames[i]);
      }
   }
}  // FlexInit

앞의 코드에서 볼 수 있듯이 상속되는 Style속성들은 StyleManager의 registerInheritingStyle() 메소드를 통해 등록된다. 아하! 라고 외쳤다면 여러분도 Flex SDK의 StyleManager의 강력함에 찬사를 보내고 있는 것일지도 모르겠다. ^^

참고로 _GenerateCSSTest_FlexInit 클래스는 _GenerateCSSTest_mx_managers_SystemManager의 info() 메소드의 mixins에 등록되어 있어서 SystemManager에서 _GenerateCSSTest_FlexInit 클래스의 info() 메소드를 자동으로 호출하게 된다.

 

 

나만의 Visual Component에 기본 CSS는 어떻게 적용할까?

 

Flex SDK에서 제공하는 Button이나 CheckBox와 같은 컴포넌트는 컴파일시 기본 CSS를 만들어주는 것을 앞서 확인할 수 있었다. 그럼 UIComponent를 확장해서 만든 Visual Component는 어떻게 기본 CSS를 적용할 수 있을까? 생각보다 어렵지 않다. 다음 코드를 보자.

package
{
import com.jidolstar.ui.frames.skins.FrameSkin;
import mx.core.UIComponent;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;

[Style(name="frameSkin", type="Class", inherit="no")]
[Style(name="backgroundColor",type="Number",format="Color",inherit="no")]
[Style(name="backgroundAlpha",type="Number",inherit="no")]
[Style(name="borderColor",type="Number",format="Color",inherit="no")]
[Style(name="borderAlpha",type="Number",inherit="no")]
[Style(name="borderThickness",type="Number",nherit="no")]
[Style(name="paddingLeft",type="Number",nherit="no")]
[Style(name="paddingRight",type="Number",nherit="no")]
[Style(name="paddingTop",type="Number",nherit="no")]
[Style(name="paddingBottom",type="Number",nherit="no")]
[Style(name="cornerRadius",type="Number",format="Color",inherit="no")]

public class MyComponent extends UIComponent
{
    private static var classConstructed:Boolean = classConstruct();
    private static function classConstruct():Boolean
    {
        // 기존에 TagBar이름의 type selector
        // 스타일 선언에 대한 인스턴스를 가져온다.
        var styleDeclaration:CSSStyleDeclaration
            = StyleManager.getStyleDeclaration("MyComponent ");

        // 이전에 스타일 선언이 되어있지 않은 경우라면
        // 스타일선언 인스턴스를 새로 하나 만든다.
        if (!styleDeclaration)
            styleDeclaration = new CSSStyleDeclaration();

        // defaultFactory를 이용해 스타일을 정의한다.
        styleDeclaration.defaultFactory = function ():void
        {
            this.frameSkin = FrameSkin;
            this.backgroundColor = 0xcccccc;
            this.backgroundAlpha = 1;
            this.borderColor = 0×009999;
            this.borderAlpha = 1;
            this.borderThickness = 4;
            this.paddingLeft = 10;
            this.paddingRight = 10;
            this.paddingTop = 10;
            this.paddingBottom = 10;
            this.cornerRadius = 10;
        }

        //선언된 스타일을 적용시킨다.
        StyleManager.setStyleDeclaration("MyComponent",
                  styleDeclaration, false);
        return true;
    }

    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged( styleProp );
        invalidateProperties();
        invalidateDisplayList();
    }
}
}

 

위 코드는 구동되지 않는다. 하지만 어떻게 기본 CSS를 줄 수 있을지 해답을 제공하고 있다. 앞서 설명한 _ButtonStyle.as 에서 적용한 방법대로 private static 코드를 위처럼 만들면 된다. UIComponent를 확장한 MyComponent의 static 값인 classConstructed:Boolean = classConstruct() 부분이 처음 MyComponent가 엑세스 될 때 실행되므로 딱 한번만 CSS적용하는 static으로 정의된 classConstruct() 메소드가 실행된다. 이런 방법으로 기본 CSS를 컴포넌트에 적용시킬 수 있다. 이보다 더 좋은 방법이나 다른 방법이 있다면 소개해주길 바란다.

 

정리하며

 

지금까지 <mx:Style>에 적용한 CSS가 어떻게 ActionScript 3.0으로 변환되어 적용되는가 알아보았다. 여기서는 <mx:Style>만 짚고 넘어갔지만 Flex가 전체적으로 어떻게 돌아가는가 알기 위해서 generated 폴더에 변환된 ActionScript 3.0 파일을 전부 살펴보면서 분석해 봐야 한다. 중요하게 이해하고 넘어가야 하는 것은 Flex의 MXML은 쉽고 빠른 설계를 위해 사용되는 언어라는 점과 MXML은 모두 ActionScript 3.0으로 변환되어 컴파일 된다는 점이다. 그러므로 Flex는 MXML을 통해 ActionScript 3.0의 불편한 하드 코딩을 줄여주고 쉽게 스타일링, 데이터바인딩, 구조설계 등을 할 수 있게 해준 일종의 프레임워크로 이해해야 한다. C나 C++, Java등을 하고 Flex를 처음 접하는 사람들은 MXML과 ActionScript 3.0의 차이점을 알고 어떤 방식으로 Flex 애플리케이션이 돌아가는지 이해하는 과정이 필요한 시점이 반드시 올 것이다. Visual Component들이 어떻게 CSS가 적용되고 어떤 방식으로 Application이 구동되는지 어느 정도 이해해야 한 단계 높은 Flex 프로그래밍을 할 수 있다. 이것이 제대로 된 Flex Component를 설계하기 위한 필요조건이 아닐까?

 

참고글

 

 

 

 

천문노트(Astronote) 대표로 2009년 세계 천문의 해 선포식 행사에 참가하게 되었다.

 

이 행사는 2009년 올해가 갈릴레오 갈릴레이 자신의 망원경으로 태양의 흑점과 목성의 4대 위성을 발견한 400주년을 된 것을 기념하는 행사이다. 2009년 내내 천문학계 이슈가 많이 일어날 것이다. 이런 영광적인 자리에 참석할 수 있게 되어 기쁘다.

 

천문노트(http://astronote.org)는 2001년 본인과 이형철(http://lucid.astronote.org/)군과 함께 천문프로그램 보급 배포와 천문학 저변 확대를 위해 만들어진 비영리민간단체이다. 일반인들도 쉽게 천문학에 대해 알아갈 수 있도록 많은 행사를 진행해왔다. 앞으로 한국 천문학 발전을 위해 노력하는 단체가 되도록 노력할 것이다.

 

개인적으로는 천문노트를 통해 지금의 위콘(http://weconize.com)에 입사해서 천문프로그래밍 분야를 맡아 스타플(http://starpl.com)서비스를 개발하고 있다.

 

아래는 세계 천문의 해에 대한 자세한 내용이다. 참고하면 좋겠다.

 

 

 

국제천문연맹(IAU, International Astronomical Union)은 2009년을 ‘세계 천문의 해(IYA2009, International Year of Astronomy 2009)’로 정했다. 갈릴레오 갈릴레이가 고급스런 놀잇감으로 여겨졌던 망원경의 성능을 개량해 만든 20배율 망원경으로 달의 표면과 태양 흑점, 목성의 4개 위성 등을 처음 발견한 것을 기념하고 지난 400년 동안 발전한 인류의 천문 지식을 펼쳐 보고 나누려는 행사다. 그리고 2009년은 아폴로 우주선이 달에 착륙한 지 40돌 되는 때이다. 그리고 미국 천문학자 에드윈 허블이 ‘우주가 팽창하고 있다’는 사실을 발견한 지 80돌 되는 해이기도 하다.

 

2009년에는 몇 가지 큰 천문현상이 있다. 2009년 7월 22일의 개기일식. 21세기에 일어나는 일식 가운데 가장 지속시간이 길며 인도, 방글라데시, 중국을 지나는 좁은 경로를 따라 6분 39초간 이어진다. 11월 중순에는 전에 없이 화려한 유성우가 기다리고 있다. 2009년 사자자리 유성우는 시간당 최고 500개의 별똥별을 뿌릴 것으로 예측되고 있다. 또 10월 중순 초저녁, 북반구 하늘에는 목성의 밝기가 가장 밝게 변하는 ‘충’ 에 들어선다. 목성을 육안으로 관측할 수 있는 절호의 기회다. 아마추어천문가들이 사용하는 작은 망원경으로도 목성의 위성까지 감상할 수 있다고 한다.

 

이제는 상식이 되어버린 태초의 ‘빅뱅’과 넓혀져 가고 있는 우주의 나이는 137억년정도이다. 빅뱅이전에는 어떤 시간들이 있었는지는 영원한 신비로 남아 있을지도 모른다. 태양계를 축소해 책에 인쇄하려면 지구를 동전만하게 표현해도 화성과 지구의 거리는 2.5Km정도 떨어지게 된다고 한다. 30년전 발사돼 지금까지 미약한 전파를 주고 받으며 기약없는 우주항해를 하고 있는 보이저호도 명왕성을 지났지만 태양계의 끝자락에는 한참 못미치고 있다. 70년대 초반까지의 관측으로는 북두칠성의 국자부분 정도에 담겨 있는 은하계의 수가 약400개 정도 였는데 허블 망원경의 관측 결과는 부분에만 1억 9천만개 정도의 은하계가 있다고 한다. 은하계마다 1,000억개정도의 행성을 가지고 있다니 규모를 생각하면 현기증이 인다. 어디서 왔고 시작되었는지 알 수 없고 그 끝을 알 수 없는 우주의 시간과 크기를 머릿속에 그리다 보면 일상의 소소한 고민들은 그저 사소하게 여겨지게 된다.

 

우주는 호기심의 원천이었다. 우주선에 대한 이야기부터 빅뱅이야기까지 우주는 세상에 대한 호기심을 잃지 않게 하는 샘물 같은 존재다. 인류의 과학으로 밝혀낸 우주의 이야기는 UFO, 외계인등 ‘유사과학’에 대한 호기심과의 균형감각을 유지 시켜준다. 인류가 이룩한 과학을 기념하고 향연들이 펼쳐지는 2009년이 기쁘게 열렸다.

 

한국 세계천문의 해 공식 홈페이지 : http://www.astronomy2009.kr/

 

텍스트큐브(TextCube)를 쓰다가 워드프레스(wordpress)로 옮기고 나서 제일 불편한 점은 글쓰기였다. 익숙하지 않은 것도 있겠지만 실제로 파일/사진등을 문서에 첨부하기 위해 너무 많은 노력이 필요했다. 나름 깔끔하고 잘 만들어져 보였지만 텍스트큐브보다는 불편한 건 어쩔 수 없는 것 같다.

 

그래서 워드프레스에서 글쓰기를 좀 쉽게 할 수 없을까 고민하다가 찾은 것이 Windows Live Writer(이하 WLW)이다. WLW은 윈도우에 설치하는 편집기로 자신의 블로그에 글을 작성해서 올리거나 편집할 수 있도록 도와준다. 이러한 것이 가능한 것은 XML-RPC 표준 프로토콜을 이용하기 때문인 것으로 생각된다.(아직 자세히 모름) 표준 프로토콜이기 때문에 워드프레스뿐만 아니라 다른 블로깅 툴인 TextCube, Tistory등에서도 WLW을 이용해 글을 작성하는 것이 가능하다.

 

웹에서 사용하는 편집기는 이미지를 서버에 올리고 나서 붙여야하고 별도의 이미지 편집기 설치없이는 이미지 편집이 어렵다. 이미지 뿐만은 아닐것이다. 글을 쓸때도 이상하게 답답함을 누구나 겪었을 것이다. 글쓰다가 HTML을 수정해야하는 경우도 빈번이 있으니깐 말이다. 그렇다고 한글과 같은 프로그램으로 글을 쓰고 복사하면 폰트가 깨지고 이미지를 다시 올려야하는 불편함이 있기 때문에 웹에 올리는 글은 여간해서 적지 않은 노력이 들어감이 사실이다.

 

WLW는 이런 불편함을 매우 많이 해소시켜준다. 작성한 글을 자기 컴퓨터에도 백업해둘 수 있으니 이것 또한 WLW를 쓰는 이유이기도 하겠다.

글 많이 써본 사람은 알겠지만 글 쓰는 거… 이거 매우 큰 에너지가 필요한 작업이다. WLW을 이용하면 좀 더 적은 노력으로 글을 수 있으니 나 같은 사람에게는 정말 고마운 툴이다.

Window Live Writer를 설치해보자.

 

WLW은 공짜다!
그렇기 때문에 웹에서 쉽게 다운로드 받아 설치할 수 있겠다. 아래 링크로 가서 다운로드 받아 설치하기 바란다.

 

http://download.live.com/writer

 

참고로 설치중간에 아래화면처럼 Writer만 선택하고 설치하면 되겠다.

 

설치후 [시작]->[프로그램]->[Windows Live]에 들어가보면 WLW가 있는 것을 확인할 수 있다. 편의성을 위해 바탕화면에 바로가기를 만드는 것도 좋겠다.

 

WLW를 실행하기 전에 먼저 해야할 일이 있다. 자신의 블로그 관리자로 들어가 외부에서 블로그에 글을 등록이 가능하도록 설정해줘야 한다. 워드프레스의 경우 [설정]->[쓰기]로 들어가면 아래 화면과 같은 설정화면이 나온다. 외부에서 글을 올리기 위한 지원사항으로 Atom, XML-RPC, 이메일 등을 사용할 수 있다는 것을 확인할 수 있다. 본인은 XML-RPC를 선택했다. 참고로 Tistory나 TextCube의 경우에도 관리자화면에서 [설정]->[글작성]으로 들어가면 “MetaWeblog API나 Blogger API를 이용하여 글을 작성할 수 있도록 합니다.”이라는 문구를 체크하면 똑같이 외부에서 글을 작성하도록 할 수 있다.

 

 

외부에서 블로그에 글을 등록할 수 있도록 설정했으니 이제 WLW을 본격적으로 실행해보자.

 

실행해보면 사용하는 블로그를 선택하도록 아래와 같은 화면이 나온다. 이 화면은 처음 실행할 때만 나오며 사용할 블로그를 등록하기 위함이다. 필요하다면 나중에 여러개의 블로그를 등록해서 관리할 수도 있다.

 

맨 마지막의 기타 블로그 서비스를 선택하고 다음 화면으로 넘어간다.

 

 

 

아래 화면이 나오면 아래와 같이 블로그 계정을 등록하면 된다.

 

 

다음단계로 넘어가면 아래와 같이 내 블로그 계정에 접속해서 필요한 정보를 얻어온다.

 

 

 

위와 같은 화면이 안나온 경우는 실패한 것이므로 블로그 주소, 아이디, 비밀번호등과 외부에서 블로그에 글을 작성할 수 있게 잘 설정했는지 확인하길 바란다.

 

Windows Live Writer를 사용해보자.

 

아래 화면은 WLW를 이용해 블로그 글 작성하고 있는 모습이다. 이 글도 WLW에서 작성했다. 한글판이 버그가 있어서 영문판을 설치했는데 별탈없으면 한글판사용하길 바란다.(내 컴퓨터만 이상한 것 같다. 회사에선 안그랬는데…)

 

 

블로그에 있는 글을 가져와서 작성하고 싶으면 열기(Open) 버튼을 선택하고 아래 화면처럼 자신이 등록한 블로그를 선택하여 해당 블로그에 올린 글의 리스트를 볼 수 있다. 여기서 글을 선택하면 편집기로 불러온다. 진짜 편리한 기능이다. 아래 메뉴에 Drafts, Recently posted가 있는데 이것은 미완성글과 최근작성한 글을 말한다. 실제로 글을 작성할때 미완성된 글로 블로그에 일단 올릴 수 있고 때로는 내 컴퓨터에 저장할 수도 있다. 웹에도 올리고 원본글을 내 블로그에도 가지고 있을 수 있으니 정말 좋지 않은가?

 

 

WLW의 오른쪽 화면을 보면 아래와 같이 화면이 나오는데 맨 위의 블로그 제목 아래 Dashboard를 통해 관리자 화면으로 직접 접속할 수 있다. 또한 현재까지 작성한 글과 작성하다가 미룬 글도 전부 열어서 편집할 수 있다. 또한 로컬 이미지를 올려 편집하거나 테이블 작성등이 웹에서 할 때보다 훨씬 편하다. +Add a plug-in 메뉴는 앞으로 더 기능을 추가할 여지를 남겨놓은 것 같다. 그렇지 않아도 WLW은 직접화면을 캡쳐해서 붙인다거나 이미지 이외에 로컬파일을 올리는 것은 제한되어 있어 이 부분은 약간 불편하긴 하다. 또한 수학공식과 같은 것도 쉽게 넣을 수 있는 플러그인이 제공된다면 더할 나위 없을 것 같다.

 

 

WLW의 재미있는 점은 내 블로그에 작성하고 있는 글을 미리 올려 볼 수 있다는 점이다.

 

 

또한 아래 화면처럼 작성된 글의 HTML 소스를 직접 볼 수 있고 편집도 가능하다. HTML코드가 이쁘게 작성되어 있어서 손수 편집하기도 편하다.

 

WLW의 아래 부분을 살펴보면 아래 화면처럼 카테고리를 선택할 수 있고 필요하다면 만들 수도 있다. 또한 태그도 입력할 수 있다. 이거 직접 블로그에서 작성하는 것과 같은 느낌이다.

 

 

이미지 올리기 쉽게 하자.

 

아무래도 글을 쓸때 가장 많이 하는 행위가 바로 이미지 올리는 것이다. WLW의 단점은 화면캡쳐 기능이 없다는 것이다. 그래서 보조로 쓸 수 있는 프로그램을 설치해서 사용하면 유용하다.

 

PicPick - http://picpick.wiziple.net/

 

PicPick도 무료이다.


하지만 매우 강력하다. 캡쳐기능 뿐이니라 간단한 편집 기능 및 화이트보드, 컬러 픽커등의 기능도 포함한다. 한번 설치하면 여러모로 좋은 프로그램이라고 생각한다. 다운로드 받은 후에는 별도의 설치없이 압축만 원하는 곳에 풀어놓고 실행만 하면 된다. 한국어도 지원되고 기본설정으로 윈도우 실행시 자동 실행하게 하면 여러모로 편리하다.

PicPick을 가지고 WLW에 유용하게 사용하기 위해 화면캡쳐후 클립보드에 저장했다가 Ctrl+V만으로 WLW의 편집기에 붙일 수 있도록 할 수 있다. 그렇게 하기 위해 실행후 실행된 PicPick의 트레이 아이콘을 선택해서 메뉴가 뜨면 [캡쳐환경설정]->[캡쳐방식]->[클립보드에 복사]를 선택하면 되겠다.

 

 

 

아래처럼 PicPick의 다양한 캡쳐 방법을 선택할 수 있으니 이것또한 매우 유용하다.

 

 

때로는 그냥 Print Screen 키를 눌러 클립보드에 복사후 WLW에 Ctrl+V로 복사한 다음 복사한 이미지를 선택해 WLW의 잘라내기 기능으로 아래 화면처럼 원하는 화면만 잘라낼 수도 있다.

 

 

 

이제 블로깅을 하기 위해 블로그의 글쓰기 에디터를 사용하지 말자!
WLW만 가지고도 충분히 편리하게 글을 쓸 수 있다.

즐거운 블로깅을 하는데 도움되는 글이 되었으면 한다.

참고사이트

Prototype 디자인 패턴GoF의 23가지 디자인 패턴중 생성관점에서 바라보는 패턴중에 하나이다. 생성관점에서 바라보는 이유는 복사를 해서 새로운 객체(인스턴스,instance)를 만든다는 개념을 가지고 있기 때문이다.

Prototype의 용어가 “원형“이라는 뜻을 알아둘 필요가 있다.

Prototype 디자인 패턴은 “원형”이 되는 클래스의 객체와 똑같은 것을 복제해서 사용할 수 있게 하는 것이다.

 

왜 Prototype 디자인 패턴을 사용하는가?

일반적으로 Something 클래스를 이용하여 객체를 만들때 new Something()과 같이 new 연산자를 이용해서 생성하게 된다. 이 경우 10개 만들면 new연산자를 10개 써야한다. 하지만 Prototype 디자인 패턴을 이용하면 new 연산자를 사용하지 않는다. 대신 복사(복제)하는 방법을 이용한다. 이 패턴은 어떤 클래스의 객체를 생성하는 것이 자원과 시간을 많이 잡아먹거나 복잡한 경우에 유용하게 쓰일 수 있다. 또한 객체를 생성하는 부분이 필요한 상황일때, 생성하려는 객체의 종류정보가 컴파일 시간이 아닌 실행시간에 정해지는 경우에도 필요하다.

Yuki Hiroshi가 지은 “Java 언어로 배우는 디자인 패턴 입문”에서 다음 경우에는 기존의 객체를 가지고 복사(복제,clone생성)해서 사용하는 경우가 유용할 수 있다고 한다.

 

1. 취급하는 객체의 종류가 너무 많아 다수의 소스파일을 작성하는 일이 빗어질때

마음만 먹으면 얼마든지 많은 객체를 다루게 될 수 있다. 이러한 경우 복사해서 사용하는 경우가 유용할 수 있다.

 

2. 클래스로부터 인스턴스를 생성하기가 복잡할 때

가령, 마우스를 사용해서 조작하는 도형 에디터와 같은 애플리케이션에서 도형을 나타내는 객체와 똑같은 것을 만드는 경우 클래스를 이용해 new 연산자로 객체를 생성하는 것보다 인스턴스를 복사해서 만드는 방법이 더 간단할 수 있다.

 

3. 프레임워크와 생성할 인스턴스를 분리하고 싶을 때

프레임워크의 기본은 클래스간에 결합도를 줄여주고 확장성을 높여주는 것이 중요하다. 이것은 프레임워크가 특정 클래스에 의존적이지 않게 한다는 의미이다.  가령, 진열장이 프레임워크라고 하자. 진열장안에는 각종 물건이 있다. 진열장에는 어떤 물건이든 들어올 수 있다.  진열장에 있는 물건은 구입자가 그 물건을 사기위한 원본이 된다. 이 원본에는 이름이 있고 구입자가 이 물건을 구입할때 진열장에 있는 물건을 바로 구입하는 것이 아니라 물건과 똑같은 물건이 구입자 손으로 넘어온다. 여기서 중요하게 짚고 넘어갈 것은 진열장(프레임워크)는 어떤 물건(객체)이 들어있는지 알 수 없으나 그 물건이 선택되면 그와 똑같은 물건을 반환해준다.

 

Prototype 디자인 패턴에서 객체를 복사해서 사용하는 이유에 대해 3가지를 언급했지만 감이 잘 안올것이다. 사실 제대로 이해하기 위해서는 직접 코딩해보고 유용함을 몸소 깨달아야한다. 본인도 new연산자를 사용하는 것과 복사해서 사용하는 것에 대한 장단점을 가려내는데 많이 힘들었지만 하다보니 객체를 복사해서 사용하는 것이 더욱 깔끔한 설계를 이끌어 내는데 도움이 되는 것을 느낄 수 있었다.

 

깊은 복사와 얕은 복사

여기서 한가지 짚고 넘어갈 것은 “복사”라는 용어이다. 복사에는 “얕은 복사(Shallow Copy)”와 “깊은 복사(Deep Copy)”가 있다. 얕은 복사는 일종의 참조이다.  ActionScript 3.0의 복사는 대부분 얕은 복사이다.

 

 

상단 코드의 결과는 어떻게 나올까?

 

1,2,4

1,2,3

 

이라고 생각했다면 아직도 당신은 ActionScript 3.0이 깊은 복사로 되는줄로 착각하고 있는 것이다.

 

답은

 

1,2,4

1,2,4

 

이다.

 

앞서 설명했지만 일반적인 복사의 형태는 참조복사의 형태이다. 즉, 얕은 복사이다. 참조한다는 것은 메모리를 공유하고 있다는 것을 뜻한다. 위 코드에서 단순히 var b:Array = a를 통해 b에 a를 복사했기 때문에 a와 b가 전혀 다른 객체를 참고하고 있다는 것을 뜻하지 않는다. 실제로는 a에서 참조하고 있는 데이타를 b도 참고한다는 것을 의미한다. 그러므로 a의 요소가 수정되면 b의 요소도 바뀌는 것이다.

 

 

이 글에서 다뤄지는 Prototype 디자인 패턴의 복사는 깊은 복사이다.

 

즉, 앞선 코드에서 a와 b가 있다고 할 때 a와 b의 데이터의 값은 완전히 같지만 서로 다른 메모리의 주소를 참고하도록 한다는 것이다. 일반적으로 일란성 쌍둥이를 생각하면 된다. 모든 유전자정보가 같은 일란성 쌍둥이지만 엄연히 완벽히 다른 2개의 객체인 것이다. Prototype 디자인 패턴에서 객체를 복사한다는 의미는 이러한 의미에서 깊은 복사를 뜻한다.

 

위 코드에서 깊은 복사의 형태로 바꿔지기 위해서는 다음과 같은 작업이 필요하다.

 

createClone() 메소드를 통해서 위 코드를 실행하면

결과는 아래와 같다.

 

1,2,4

1,2,3

 

깊은 복사가 제대로 실행된 것을 볼 수 있다.

 

createClone() 메소드에 사용된 ByteArray를 통해 객체를 생성하는 것을 유심히 살펴보자.

 

Java의 경우 Cloneable인터페이스와 java.lang.Object에 clone()이 정의되어 있어서 객체복사(깊은복사)를 매우 쉽게 할 수 있다. 하지만 ActionScript 3.0의 경우 그런 메소드가 존재하지 않는다. 그래서 이와 같이 조금 어려운 객체 복사를 해야한다. 이 또한 클래스의 객체를 완벽하게 복사하기 위해서 쓰기에는 완벽하지 않다. 아래처럼 조금 더 수정될 필요가 있다.

 

 

위 코드는 createClone() 메소드를 통해 클래스 객체도 완벽히 복사할 수 있도록 만들었다.

 

메소드내 추가된 코드는 객체을 복사할때 원본 객체의 클래스 유형을 유지하기 위한 부분이다. 기존에 클래스가 등록된 경우에는 getClassByAlias()로 Class가 반환되지만 등록되어 있지 않은 경우 ReferenceError를 발생시킨다. 에러 발생시 registerClassAlias()을 이용해 원본객체의 클래스 유형을 유지시킨다. 이 코드를 넣지 않으면 이 함수를 통해 만들어진 복사된 객체가 Object가 되어 원하는 Class의 원형을 갖추지 못하게 된다. 이 말은 registerClassAlias()를 사용하지 않으면 var a:MyClass = createClone( b ) as MyClass로 사용할 수 없고 var a:Object = createClone( b ) 로 밖에 사용할 수 밖에 없다는 것을 뜻한다. 아래 코드는 이에 대해서 이해하기 위한 예제이다.

 

 

위 코드에서 registerClassAlias()를 빼면 trace() 결과가 false로 나온다. 이와 관련된 자세한 내용은 “getClassByAlias()와 registerClassAlias() 설명서“를 참고하길 바란다.

 

Prototype 디자인 패턴을 적용한 UML과 ActionScript 3.0 코드

 

위 그림은 Prototype의 기본 디자인 패턴에 대한 클래스 다이어그램이다. 사용자인 Client 클래스는 인터페이스 Prototype을 구체적으로 구현한 ConcretePrototype1, ConcretePrototype2…. 를 사용한다. Client 클래스는 ConcretePrototype1, ConcretePrototype2의 존재를 알필요 없이 clone()만 알고 있으면 된다. 이 clone() 메소드가 바로 깊은 복사를 통해서 자신을 복사해주는 역할을 하는 것이다.

 

 

위 다이어그램은 이제부터 선보일 Prototype 디자인패턴을 적용시킨 클래스들의 관계를 설명하고 있다. 아래 이미지는 다이어그램에 따라서 만들어진 ActionScript 3.0 프로젝트의 Package구조를 보여주고 있다.

 

 

간단히 설명하자면

framework 패키지와 car 패키지로 구분되어 있는데 이렇게 구분한 것은 Prototype 디자인패턴이 적용된 framework 패키지 안에 클래스를 이용하여 계속 확장할 수 있음을 뜻한다. 가령, car 뿐아니라 boat, television, radio 어떤 것이든 상관 없다는 것이다.

Prototype의 핵심 인터페이스인 IPrototype을 확장한 Product를 또 Engine과 Wheel 클래스로 확장했다. 또한 IPrototypeClient 인터페이스를 확장해 ProductManager를 framework에 만들고 이것을 확장한 CarPartManager 클래스를 볼 수 있다.  CarPartManager 클래스에 Engine, Wheel의 객체를 등록하면 CarPartManager의 create()메소드를 통해 Engine과 Wheel의 객체의 새로운 객체를 복제할 수 있다.

이해를 돕기 위해 사용예를 보자.

 

CarPartManager의 객체에 2개의 Wheel 객체와 2개의 Engine 객체를 등록하고 create() 메소드를 통해 새로운 객체를 생성하고 있다. 결과는 다음과 같이 나온다.

 

This is a wheel A
This is a wheel B
This is a engine 1
This is a engine 2

 

중요하게 체크해야할 사실은 등록할때 외에는 Wheel과 Engine의 객체 복사를 new를 통해하지 않는다는 것이다. 단지 처음에 Wheel과 Engine를 CarPartManager에 register()메소드의 첫번째 인자값만 가지고 등록된 객체를 복사해낸다. Prototype 디자인 패턴은 이렇게 new를 사용하지 않고 등록시 사용한 별칭(wheel1, wheel2, engine1, engine2)만 가지고 똑같은 객체를 복사생성하기 때문에 new를 통한 생성의 복잡함(설정이 매우 많은 경우)이 있는 경우 크게 도움이 될 수  있다.

각각의 클래스 코드를 살펴보자.

 

먼저 인터페이스이다.

 

IPrototype은 매우 단순하다. clone() 메소드를 통해서 복사만 가능하도록 구현할 수 있으면 된다.

 

 

IPrototypeClinet는 복사가 가능한 인터페이스(IPrototype)를 가지는 객체를 특별히 지정된 이름으로 등록할 수 있고 등록된 객체로 부터 지정된 이름으로 생성할 수 있도록 하는 것이 목적이다.

 

위 2개의 핵심 인터페이스를 구현한 프레임워크내 2개의 핵심 클래스를 살펴보자.

 

위 클래스는 IPrototype을 구현한 Product클래스이다. 앞서 소개했던 CloneMachine클래스를 확장해서 만들어졌다. clone()메소드를 구현한 부분을 살펴보면 CloneMachine 클래스에 정의된 createClone()메소드를 이용하여 자기 자신을 복제하여 넘겨주는 것을 확인할 수 있다. Product클래스는 일종의 생산품의 부모라고 생각하면 된다. 이 생산품을 설명해주는 description get/set 메소드도 추가되어 있는 것을 확인하자. 이 클래스는 단독으로 쓰이지 않으며 반드시 확장해서 사용한다. 일종의 추상클래스라 생각하면 된다. ActionScript 3.0에서는 추상클래스로 지정하기 위해 Java의 abstact와 같은 키워드가 없으므로 별도의 설정은 하지 않았다.

 

 

위 클래스는 IPrototypeClient 인터페이스를 확장한 ProductManager 클래스이다. 이 클래스는 등록(register)와 복제(create)를 구현하고 있다. 코드는 그리 어렵지 않다. create()메소드에 등록된 객체를 찾아 clone()메소드로 복사하는 것을 꼭 확인하기 바란다.

 

프레임워크 부분은 모두 설명했다. 이제 활용 예제로 만든 car 패키지 부분을 살펴보자.

 

IPrototype을 구현한 Product를 확장해 Wheel과 Engine 클래스를 만들었다. 자동차 부속품인 바퀴휠과 엔진을 의미한다. 단순히 생성자만 새로 만들었을뿐 별 다른 구현은 하지 않았지만 필요하다면 다른 구현을 해도 무방하다.

 

 

IPrototypeClinet를 구현한 ProductManager를 확장해 CarPartManager를 만들었다. 더이상 다른 정의를 하지 않았고 ProductManager가 구현한 것을 그대로 쓰고 있지만 원하는데로 확장해서 사용해도 문제없다. 의미적으로는 자동차 부속품을 관리하는 관리자 클래스라고 생각하면 되겠다.

 

다시 한번 이 클래스를 사용하는 예제를 보자.

 

 

이제 어렵지 않게 해석할 수 있을것이다.

 

이것만은 꼭 기억하자. Prototype 디자인 패턴은 객체를 원하는데로 복사(깊은복사)해서 사용할 수 있게 만든 패턴이다. Prototype 패턴을 이용해 Flex/AIR/Flash/ActionScript 3.0 프로그램 설계에 도움이 되길 바란다.

 

참고자료

ActionScript 3.0 Prototype Design Pattern: A Minimalist Example

ActionScript 3.0 Clone: A Prelude to the Prototype Design Pattern

getClassByAlias()와 registerClassAlias() 설명서

소스

-> 무료 UML 툴인 StarUML을 다운로드 받아 보실 수 있습니다.

-> Flex Builder 3 에서 Import 해 사용하세요.

 

추가내용

Flex에 관련된 컴포넌트는 여기서 소개된  Prototype 방식으로 clone()을 생성하면 에러가 생성될 가능성이 많다. 특히 UIComponent 계열은 Flex SDK 프레임워크 종속적인 클래스이다. 이 것으로 만들어진 객체를 clone()으로 깊은 복사에 성공하더라도 프레임워크 자체에서 UIComponent 객체들을 관리하기 때문에 단순한 clone() 메소드로는 Flex 자체에서 동작하도록 만들 수 없다. 그러므로 프레임워크와는 상관없는 Sprite, Shape등을 이용해서 만들도록 하자.

추가내용 2 (2009.12.9)

히카님과 대화하면서 새롭게 안 사실입니다. 위에서 객체 복사를 위한 부분에 대해서 실제로 메서드, 변수정의는 모두 되지만 ByteArray, Vector, Array, Dictionary, Object 값외에 다른 값의 복사는 되지 않는다고 합니다. 그래서 결국 이 방법으로 복사하는 것은 잘못된 것이네요. 참고하세요.

무료 UML 제작 프로그램으로 StarUML이 있다. 무료이지만 꽤 쓸만한 UML툴이다. 이게 원래 국산이였다. 사업이 잘 안되서 그런지 OpenSource로 전향된 이래로 국내외에서 매우 잘 활용되어 있는듯하다.

이 프로그램에서는 기본적으로 클래스 다이어그램을 Java,C#,C++언어로 변환할 수 있는 기능을 제공한다. 하지만 ActionScript 3.0으로 산출해줄 수 있는 기능이 없던 것이 개인적으로 아쉬웠다.

그런데 웹서핑도중 UML을 ActionScript 3.0으로 만들 수 있는 템플릿이 있는 것을 찾게되었다.

여기서는 설치방법과 간단히 사용하는 방법을 소개하도록 하겠다.

 

설치

 

1. StarUML_ActionScript3_Export.zip 을 다운로드 받는다.

2. C:Program FilesStarUMLmodulesstaruml-generatortemplates 에 압축을 푼다.

3. 정상적으로 설치하면 다음과 같은 경로에 파일이 존재해야한다.

C:Program FilesStarUMLmodulesstaruml-generatortemplatesActionScript 3.0template description.tdf
C:Program FilesStarUMLmodulesstaruml-generatortemplatesActionScript 3.0template.cot

StarUML이 실행한 도중이라도 다시 재실행할 필요 없이 사용할 수 있다.

 

사용법

 

1. 클래스 다이어 그램을 제작한다. 아래는 예제이다.

 

 

 

위 파일을 다운로드받아 StarUML에서 Open하면 위 그림의 다이어그램을 바로 실행해 볼 수 있다.

 

2. 메뉴에서 Tools > StarUML Generator… 를 선택하면 아래와 같은 창이 나온다. 여기서 ActionScript 3.0 템플릿을 선택하고 Next 버튼을 누른다.

Opt.에 …버튼을 누르면 템플릿 속성도 임의로 지정할 수 있다. 가령 생성자를 기본적으로 만들것인지 아닌지, Event에 toString()함수를 만들것인지 아닌지 check가 가능하다. 참 잘만들었다.

 

 

 

3. ActionScript 3.0으로 산출된 결과물을 저장할 경로를 지정한다.

 

 

4. 모든 준비가 완료되었다. Generate 버튼을 누르면 지정된 폴더에 만든 클래스 다이어그램을 바탕으로 ActionScript 3.0 코드가 만들어진다.

 

 

5. 아래는 만들어진 ActionScript 3.0 결과물이다. 문법상 문제없이 잘 만들어진것을 확인할 수 있다.

 

 

ActionScript 3.0에는 Event, 예외처리등도 필요하다. 우리가 사용한 ActionScript 3.0 템플릿을 이용하면 이 모든게 지원이 된다.

 

http://www.senocular.com/flash/tutorials/starumltoas3/ 로 가보면 몇가지 설정방법과 클래스 다이어그램이 어떻게 변환되는지 알 수 있다.

 

참고사이트

ActionScript 3.0 Generator 공식페이지 : http://www.senocular.com/flash/tutorials/starumltoas3/

StarUML 공식 페이지 : http://staruml.sourceforge.net/ko/

 

 

 

매우 유용한 자료를 발견했다.

GoF의 디자인 패턴을 포스트 형태로 만들어놓은 것이다.

아래와 같은 형태로 보여주고 있다.

Page 1.

Page 2.

아래 링크로 PDF파일을 다운로드 받을 수 있다.

designpatternscard.pdf

자료출처 : http://www.mcdonaldland.info/2007/11/28/40/

글쓴이 : 지돌스타(http://blog.jidolstar.com)

사용자 삽입 이미지


Collinder목록 399번(Cr 399)으로 등록되어 있는 산개성단, 일명 옷걸이 성단입니다.
모양을 봐도 금방 알 수 있듯이 옷걸이처럼 생겼습니다.
이 성단은 여름철 별자리인 작은여우자리에 위치했습니다.
본인도 망원경으로 이것을 자주 봤었죠.

스타플(http://starpl.com) 별지도에서 찾아보겠습니다.
작은여우 자리에 있다고 했으니깐 일단 작은여우자리로 가보겠습니다.


사용자 삽입 이미지

지금 3단계 확대한건데 아직 잘 안보입니다. 더 확대해볼께요.


사용자 삽입 이미지

5단계 까지 확대해봤습니다.. 옷걸이가 보이나요? ㅋㅋ


사용자 삽입 이미지


예~~~ 작은여우 앞발에 있었군요. ㅎㅎ
정말 옷걸이 처럼 생겼네요. ㅎㅎ

큰사진 및 더욱 다양한 정보는 아래 링크를 참고하세요.

http://antwrp.gsfc.nasa.gov/apod/ap081223.html
http://www.seds.org/messier/xtra/ngc/brocchi.html

스타플은 실제별을 기반으로 만들었습니다. ^^

글쓴이 : 지돌스타(http://starpl.com/422)

예전부터 Flex4 프로젝트의 일환인 Gumbo를 다운로드를 받았지만 쓸 기회가 없어서 안쓰다가 Flash Player 10에서 3D 회전 예제가 있어서 한번 해봤다.

Flex Builder 3에서 작업을 하기 위해 수행해야할 일은 다음과 같다.

1. Gumbo 최신버전을 다운받는다. [다운로드 받으러가기]

2. 다운로드 받는 Flex 4 SDK를 Flex Builder 설치폴더안에 sdks 폴더에 압축하여 풀어준다.

3. Flex Builder 3를 실행해서 메뉴에 Windows->Preperences...에 들어가면 창이 뜬다. 창 왼쪽에 Flex->Installed Flex SDKs를 선택한 다음 아까 압축을 푼 SDK폴더를 등록한다.

4. File->New->ActionScript Project를 선택하면 창이 뜬다. 창 아래부분에 Use a specific SDK를 선택한다음 Flex 4를 선택하고 프로젝트 명을 CubeRotationExample로 프로젝트를 만든다.

5. 아래 소스를 복사해서 메인 소스에 덮어쓴다.

 

package{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
 
	public class CubeRotationExample extends Sprite {
		
		private static const EDGE	:Number = 40;		//edge length
		private var mtxWorld		:Matrix3D;			//world transform matrix
		private var vCube			:Vector.<Number>;	//cube points
		private var vFlatCube		:Vector.<Number>;	//projected cube points
		private var vUVT			:Vector.<Number>;	//uvt data
		private var vIndicies		:Vector.<int>;		//triangle indicies
		private var sprCube			:Sprite;			//canvas object
		
		public function CubeRotationExample(){
			// setup and initialize
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.quality = StageQuality.BEST;			
			
			mtxWorld = new Matrix3D();
			vCube = Vector.<Number>([	EDGE,EDGE,-EDGE,
				 						EDGE,-EDGE,-EDGE, 
										-EDGE,-EDGE,-EDGE,
										-EDGE,EDGE,-EDGE, 
										EDGE,EDGE,EDGE,
										EDGE,-EDGE,EDGE,
										-EDGE,-EDGE,EDGE,
										-EDGE,EDGE,EDGE
										]);
			vFlatCube = new Vector.<Number>(16);
			vUVT = new Vector.<Number>(24);
			vIndicies = Vector.<int>([0,1,2, 2,3,0, 4,7,6, 6,5,4, 0,4,5, 5,1,0, 1,5,6, 6,2,1, 2,6,7, 7,3,2, 4,0,3, 3,7,4]);
			
			sprCube = new Sprite();
			addChild(sprCube);

			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function onEnterFrame(eo:Event):void {
			// center the cube
			sprCube.x = stage.stageWidth/2;
			sprCube.y = stage.stageHeight/2;
			
			// rotate the transform matrix
			mtxWorld.appendRotation(2, new Vector3D(0,1,0));
			mtxWorld.appendRotation(2, new Vector3D(0,0,1));
			mtxWorld.appendRotation(2, new Vector3D(1,0,0));
			
			// project 3D data to 2D plane
			Utils3D.projectVectors(mtxWorld, vCube, vFlatCube, vUVT);
			
			// draw the cube using cube data
			sprCube.graphics.clear();
			sprCube.graphics.beginFill(0xFF00FF);
			sprCube.graphics.lineStyle(1,0xFF0000,1);
			sprCube.graphics.drawTriangles(vFlatCube, vIndicies, null, TriangleCulling.POSITIVE);
			sprCube.graphics.endFill();
		}
	} 
}

 

6. 저장하면 에러가 날거다. Flash Player 10에서 작동하므로 그에 따른 설정을 해주어야 한다. 메뉴에서 Project->Properties 로 들어가면 창이 뜬다. 왼쪽메뉴에 ActionScript Compiler를 선택하고 오른쪽 아래 Require Flash Player version을 10.0.0으로 맞춰준다.

7. 실행한다.(단 Flash Player 10이 설치되어 있어야 한다.)


[실행화면]


다시한번 언급하지만 Flash Player 10 환경에서만 된다.

위의 소스를 보면 예전 ActionScript 3.0에서 볼 수 없었던 것들이 보인다.
Vector, Matrix3D, Util3D등이다. Papervision3D와 같은 것을 쓰지않아도 쉽게 네이티브 코드로 3D를 구현할 수 있게 한 Flash Player 10. 아직 다양한 표현을 위한 많은 API를 가지고 있지 않지만 더욱 발전될 가능성이 크다고 생각한다. 기대해보겠다.

[소스출처]
http://dispatchevent.org/calebjohnston/flash-player-10-3d-example/

글쓴이 : 지돌스타(http://blog.jidolstar.com/421)

제가 직접 참여해서 만든 사이트 홍보입니다. ^^

Flex/Flash로 개발을 담당했고요~~

스타플에서 홍보이벤트 중입니다.

1등 문화상품권(10만원)+스타플 카드지갑 입니다.

여러분도 도전해보심이 어떨까요?


Starpl. 밤하늘의 별을 당신에게 드립니다.

밤하늘의 별을 주는 재미있는 서비스가 있어 소개합니다.

스타플은 실제 별 관측 데이터를 이용해서, 정말 존재하는 별 중에 하나를 나에게 준답니다.
나의 별에다가 나의 이야기를 담고, 우주를 여행하며 사람들도 만나는 흥미로운 서비스에요.

별찾기 성향테스트

나만의 별을 찾아라!

회원가입을 누르면, 성향 테스트를 거쳐 나만의 별을 받게 됩니다.
그림으로 푸는 성향테스트가 독특하고 재미있어요.

예시 별 1. 예시 별1의 타임라인

나를 담는 별

별을 방문한 모습입니다. 별 위에 보이는 바가 타임라인이라고 하는 건데,
타임라인에 추억과 일상, 생각 들을 기록할 수 있습니다. 글을 쓸 때 시간을 설정하거나, 첨부사진의
촬영시간을 적용하면 그 때 그 시간의 타임라인에 글이 쓰여져 내 인생의 히스토리를 만들 수 있어요.
블로그를 가지고 있다면, 블로그를 타임라인에 등록하여 새 글이 자동으로 타임라인에 담기게 할 수도 있어요.

예시 별 2. 예시 별3.

나의 취향대로 꾸미는 나만의 별

여러 별들의 모습입니다. 스타플에는 나만의 별을 꾸밀 수 있도록 다양하고 예쁜 아이템과 위젯들이 많습니다.
아이템은 별가루로 구입할 수 있는데, 별가루는 처음에 가입하면 왕창 주는데,
다 써 버려도 스타플 사용하다보면 저절로 계속 쌓이더라구요. ^^

스타플 별지도

다른 별들을 만날 수 있는 공간, 별지도

별지도에 가보면 많은 별들이 있습니다. 저 별들에도 다 사람들이 살고 있다고 생각하니 신기하네요.
별지도 위의 상단메뉴를 클릭하면
다른 별들이 남긴 기록들을 볼 수가 있는데요, 말풍선을 클릭하니 그 별로 방문이 되는군요.

똑똑한 소식 배달부 알림이

별지도 왼쪽에 알림이를 통해 나의 별친구들의 새 기록과 댓글, 생일 등의 소식들을
바로 바로 알려줘서 알림이에서 손을 땔 수가 없더라구요.
또, 관심 가는 별이 있으면 관심별로 등록해 알림이로 쉽게 받아 볼 수 도 있답니다.

너무 너무 이쁘고 개성 넘치는 스타플!
나만의 별을 받고 싶으신 분들, 나의 이야기를 담을 특별한 공간을 찾으신 분들께
꼭 추천해드리고 싶은 서비스입니다.

별증서

나의 별임을 인증하는 별증서 이벤트도 진행 중이니, 한번 방문해 보세요.

스타플 방문하기

Adobe Flex를 접할때 어려워하는 부분중에 하나가 Event입니다.
깊숙히 이해하려고 할때 잘 이해가 안되는 부분이 많은게 이벤트죠.

기본에 충실해야한다!
프로젝트(http://starpl.com)를 하면서 많이 느꼈습니다.
처음 Flex 접했을때 가장 어려움을 겪었던 것은 기본이 탄탄하지 못한 것으로부터 였습니다.
그래서 Flex와 함께 ActionScript 3.0의 기본 문법 및 대략적 내용을 이해해야한다고 생각합니다.
단순한 문법뿐 아니라 분석/설계에도 관심을 가지고 공부해서 명확하고 깨끗한 프로그램을 만들 수 있도록 노력해야겠구요.

아래는 Event에 대한 질문을 걸어놓고 스스로 답변까지 해두었습니다.
이것으로 Event 전부를 설명할 수 없지만 몇가지 궁금한 사항을 이해하는데는 도움이 될겁니다.
그냥 읽고 지식만 얻어가지 마시고 없는 질문이 있다면 스스로 질문/답변을 댓글로 달아주시면 더욱 고맙겠습니다. 잘못된 내용이나 추가해야한다는 것도 포함합니다.


1. ActionScript 3.0 이벤트(Event)

1.1 ActionScript 2.0과 3.0에서 이벤트가 바뀐점은?

  • ActionScript 2.0에서는 이벤트 리스너를 추가하는 경우 상황에 따라 addListener() 또는 addEventListener()를 사용하지만 ActionScript 3.0에서는 항상 addEventListener()를 사용합니다.
  • ActionScript 2.0에는 이벤트 흐름이 없으므로 이벤트를 브로드캐스팅하는 객체에서만 addListener() 메서드를 호출할 수 있지만 ActionScript 3.0에서는 이벤트 흐름에 포함된 모든 객체에서 addEventListener() 메서드를 호출할 수 있습니다.
  • ActionScript 2.0에서는 함수, 메서드 또는 객체를 이벤트 리스너로 사용할 수 있지만 ActionScript 3.0에서는 함수 또는 메서드만 이벤트 리스너로 사용할 수 있습니다.
  • on(event) 구문은 이제 ActionScript 3.0에서 지원되지 않으므로 ActionScript 이벤트 코드를 무비 클립에 첨부할 수 없습니다. 이벤트 리스너를 추가할 때는 addEventListener()만 사용할 수 있습니다.


1.2 Event를 사용해야하는 이유? 2가지 이상

  • 객체간 강한 결합 해결 : 애플리케이션 설계시 Callback함수를 사용하는 등의 강한결합을 이용하는 경우 유지보수 및 확장이 어려워지는 경우가 크다. 이벤트는 객체간 느슨한 결합을 해주는데 큰 힘을 발휘할 수 있다.
  • 작업에 대한 일관성 없는 응답 : 동기적 방식과 비동기적 방식에 대한 응답에 대한 처리를 이벤트를 사용하지 않는 경우 서로 다른 방법을 선택해서 사용해야한다. 이벤트는 1가지 방법으로 응답처리를 가능하게 해준다.


2. Event의 구성요소 3가지는 무엇이고 의미를 설명하라.

  • 이벤트 객체(Event Object)
    flash.net.Event의 객체나 이를 확장한 이벤트 객체를 의미한다. 이벤트 객체에는 이벤트에 대한 정보가 들어가있다. 이벤트의 종류(Type)과 이벤트를 발생한 객체(target)에 대한 정보가 포함된다.
  • 이벤트 발생자(Event Dispatcher)
    이벤트를 발생(broadcast)하는 객체이다. 이벤트 객체에 target으로 이벤트 발생자 정보가 담긴다. flash.net.EventDispatcher를 확장한 모든 객체는 이벤트 발생자가 될 수 있다. EventDispatcher의 dispatchEvent() 메소드에 이벤트 객체를 담아 실행하면 이벤트가 발생하게 된다.
  • 이벤트 청취자(Event Listener)
    일종의 메소드 또는 함수이다. 발생한 이벤트를 듣는 역할을 한다. EventDispatcher클래스를 확장한 클래스의 객체에서 addEventListener()을 이용해 이벤트 청취자를 등록할 수 있다. addEventListener()을 이용하면 청취할 이벤트의 종류(type)을 결정할 수 있으며 청취할 이벤트 흐름(capture,target,bubbling) 및 우선순위등을 선택할 수 있다.


3. Event Listener를 등록/삭제하는 방법을 기술하라.

  • 등록
    EventDispatcher의 addEventListener() 메소드를 이용한다.
    예)
    var button:Button = new Button();
    button.addEventListener( MouseEvent.CLICK, onClick, false );
    public function onClick( event:MouseEvent )
    {
      trace( event.type, event.target  );
    }
  • 삭제
    EventDispathcer의 removeEventListener() 메소드를 이용한다.
    예)
    button.removeEventListener( MouseEvent.CLICK, onClick, false );
    3개의 인자가 addEventListener()를 사용할때와 같아야 정상적으로 이벤트 청취자 등록이 삭제된다.
    참고로 맨 마지막 인자는 useCapture이다.


4. Event 전파단계의 종류 3가지가 무엇이며 각각에 대한 설명

  • 이벤트 전파단계의 종류 : 캡쳐(capture) 단계, 타겟(target) 단계, 버블(bubble)단계
  • 이벤트 전파 순서 : 캡쳐->타겟->버블
  • 캡쳐 단계
    루트(root) 디스플레이 객체서부터 이벤트를 발생한 객체(target)까지 디스플레이 객체 리스트(display Object List)를 따라 검색해나가는 단계이다. 즉, 부모->자식으로 이벤트를 전파한다. 이 캡쳐 단계에 이벤트를 청취하기 위해서는 addEventListener()의 3번째 인자인 useCapture가 반드시 true로 되어야 한다. false로 되어 있다면 캡쳐단계가 아닌 타겟과 버블 단계에서 이벤트 청취를 한다.
    캡쳐단계 청취하는 목적은 다양할 수 있다. 가령 중간에 이벤트 전파를 중지시킬때 필요할 수 있다. 이해가 안될 수 있지만 실제 프로젝트를 하면 이런 경우가 다분하다.
    사용 예 )
    button.addEventListener( MouseEvent.CLICK, onClick, true );
  • 타겟 단계
    갭쳐 단계 이후 타겟단계에 도달한다. 타겟 단계는 이벤트를 발생시킨 객체까지 도달했을때 이뤄진다.
  • 버블 단계
    타겟 단계 이후 다시 루트(root) 디스플레이 객체로 이벤트가 전파되는 단계이다. 버블버블 물망울이 수면위로 다시 올라가는 것을 연상하면 되겠다. 캡쳐와 반대로 자식->부모로 이벤트가 전파되는 단계이다.
    이벤트가 버블 단계로 전파되기 위한 조건은 이벤트 송출시 Event의 생성자 인자값중 bubble값을 true로 설정되어 있어야 한다. MouseEvent같은 경우 이 bubble값이 true로 설정되어 있다.
    타겟단계와 버블단계에 이벤트 청취자를 등록하기 위해 addEventListener()의 3번째 인자 useCapture가 false로 되어야 한다. useCapture를 설정하지 않으면 기본값이 false이다.
  • 이벤트 객체가 전파되는 기능이 굳이 필요한 이유
    부모-자식1-자식2....-자식100 의 형태로 디스플레이 객체 리스트가 형성되어있다고 가정하자 자식50에서 자식 100을 마우스 클릭했을때 이벤트를 받고 싶다고 하자. 자식50은 자식100의 존재유무를 모른다(알 수 있지만 알게되면 강한결합이 일어난다.) 이런 경우 이벤트 객체가 전파되는 기능은 매우 유용하게 쓰일 수 있다. 캡쳐나 버블 단계에서 자식50은 자식100에서 발생된 이벤트를 받을 수 있다.
  • flash.display.DisplayObject 클래스는 EventDispatcher를 확장해서 만들어졌다는 것에 주목하자.


5. 4번의 Event 전파는 어떤 환경에서 가능한가?

  • 반드시 디스플레이 객체 리스트(Display Object List) 상에 존재하는 디스플레이 객체(Display Object)여야 이벤트 전파가 가능하다. 그 외의 이벤트 전파는 타겟 단계밖에 없다. 가령, HTTPService나 URLLoader에서 이벤트가 발생하는 경우 이들은 디스플레이 객체가 아니다.
  • 이벤트 전파의 조건
    1. 디스플레이 객체여야 한다.(flash.display.DisplayObject를 확장한 클래스의 객체)
    2. 디스플레이 객체는 디스플레이 객체 리스트에 존재해야 한다. 즉, stage로 부터 addChild되어 있어야 한다.

6. 이벤트 전파시 target과 currentTarget의 차이점은 무엇인가? 예를 들어 설명하라.

  • target은 이벤트를 발생한 객체이고 currentTarget은 이벤트를 청취하는 객체이다.
  • 예시)
    var p:Sprite = new Sprite(); //parent
    var c:Sprite = new Sprite(); //child
    addChild( p );
    p.addChild( c ); //c가 p의 자식인 것에 주목
    p.addEventListener( MouseEvent.CLICK, onClick ); //이벤트 청취를 p가 하는 것에 주목!
    public function onClick( event:MouseEvent )
    {
    trace( event.target, event.currentTarget ); //c를 클릭했을 경우 c, p가 나오고 p를 클릭했을 경우 p,p가 나온다.
    }


7. Event 우선순위에 대해서 간단한 예제를 들어 설명하라.

  • 이벤트 우선순위는 구체적으로 이벤트 청취 우선순위라고 할 수 있다.
  • 이벤트 청취 우선순위는 addEventListener()의 4번째 인자인 priority를 이용한다. 이 값이 클 수록 청취 우선순위가 높아지며 addEventListener()의 등록 순서에 상관없이 우선순위에 따라 이벤트 리스너가 호출된다.
  • 이벤트 청취 우선순위가 유효한 조건
    1. 같은 객체에서 청취한다.
    2. 같은 이벤트 종류(type)을 청취한다.
    3. 같은 useCapure 값을 가진다.
  • ex)
    a.addEventListener(MouseEvent.CLICK, aHandler, false, 3);
    a.addEventListener(MouseEvent.CLICK, bHandler, false, 1);
    a.addEventListener(MouseEvent.CLICK, cHandler, false, 100);

    a객체에 MouseEvent.CLICK 이벤트가 발생시 등록순서에 상관없이 priority값이 가장큰 cHandler가 먼저 호출되고 다음으로 aHandler, bHandler가 호출된다.

8. Event 전파를 중단하는 메소드 2개가 무엇이며 간단한 예제를 들어 각각의 차이점을 설명하라.

  • Event 클래스의 stopPropogation()와 stopImmediatePropogation() 메소드이다.
  • 차이점
    - stopPropogation()
      이벤트 전파를 중단하되 같은 노드의 이벤트를 청취까지는 허락한다.
    - stopImmediatePropogation()
      이벤트 전파를 즉시 중단한다.
  • 예제
    back이 배경 canvas이고 button1이 back에 포함된 button일때
    back.addEventListener(MouseEvent.CLICK, event1Handler);
    back.button.addEventListener(MouseEvent.CLICK, event2Handler);
    back.button.addEventListener(MouseEvent.CLICK, event3Handler);
    back.button.addEventListener(MouseEvent.MOUSE_OUT, outHandler);

    private function event1Handler(e:MouseEvent):void
    {
           trace('back');
    }
    private function event2Handler(e:MouseEvent):void
    {
           trace('button');
           e.stopPropagation();
           e.stopImmediatePropagation();
    }
    private function event3Handler(e:MouseEvent):void
    {
           trace('button2');
    }
    private function event1Handler(e:MouseEvent):void
    {
           trace('out');
    }

    e.stopPropagation(); e.stopImmediatePropagation(); 두가지 다 없을경우
            button
            button2
            back
            out
    e.stopPropagation(); 만 실행
            button
            button2
            out
    e.stopImmediatePropagation(); 만 실행
            button
            out
     


9. addEventListener의  useCapture 인자는 무엇을 의미하는가? 간단한 예제를 들어 설명하라.

  • 이벤트 전파를 청취할때 캡처단계를 청취할지 타겟 및 버블 단계를 청취할지 결정하는 인자이다.
  • 모든 전파 단계에서 청취하기 위해서는 useCapture가 다른 2개의 addEventListener()를 사용해야한다.
  • 예제 생략


10. Sprite, Shape와 같은 클래스에서 어떻게 하면 이벤트를 송출할 수 있는가?

  • dispatchEvent() 메소드를 호출하면 된다.


11. Sprite, Shape와 같이 이벤트 송출할 수 있는 클래스는 근본적으로 어떤 클래스를 상속받았기 때문에 가능한가?

  • Sprite와 Shape는 궁극적으로 DisplayObject를 확장해서 만들어졌으며 DisplayObject는 EventDispatcher를 확장했다. 그러므로 Sprite와 Shape와 같은 클래스는 EventDispatcher의 메소드를 전부 사용할 수있다. 이중에 dispatchEvent()도 사용할 수 있다.


12. IEventDispatcher는 무엇이며 어떤 경우에 이것을 사용해야할까?

  • EventDispatcher의 인터페이스이다.
  • IEventDispatcher를 활용하는 것은 다중상속이 불가능한 AS3에서 유용하다.
    가령, 어떤 클래스가 ProxyObject를 확장해서 만들어져야한다. 그런데 이 클래스는 이벤트도 발생시켜야 하므로 EventDispatcher클래스도 확장해야한다. ActionScript 3.0은 다중상속을 지원하지 않는다.(다중상속은 이점도 있지만 단점도 있다.) 그러므로 이러한 경우에는 주가 되는 클래스인 ProxyObject를 is-a 확장을 하고 EventDispatcher를 has-a 확장을 감행한다음 만들어진 클래스가 EventDispatcher의 기능을 수행한다는 것을 명시적으로 외부에 알려주고 내부적으로 구현시켜주기 위해 IEventDispatcher 인터페이스를 implements 해준다. 이렇게 하면 원하는 기능인 ProxyObject와 EventDispatcher의 기능을 전부 수행하면서도 다중상속의 문제를 극복할 수 있다.
  • ex)
    public class MyProxyObject extends ProxyObject implements IEventDispatcher
    {
      var evnetDispatcher:EventDispatcher = new EventDispatcher();
     
      //내부적으로 IEventDispatcher에 선언한 메소드를 구현한다.  가령...
      public function dispatchEvent( event:Event ):Boolean
      {
         return  eventDispatcher.dispatchEvent( event );
      }
    }


13. preventDefault()와 stopPropagation(), stopImmediatePropagation()의 근본적 차이점은 무엇인가?

  • preventDefault()는 기본 동작(dafault behaviors)를 취소하는데 쓰이는 메소드인 반면 stopPropagation(), stopImmediatePropagation()는 이벤트 전파에만 영향을 준다.
  • preventDefault()가 사용 가능한지는 isDefaultPrevented() 메소드로 알 수 있다.

14. preventDefault()를 호출해서 실행을 가능하게 하기 위한 조건은 무엇인가?

  • 이벤트 객체를 생성시 cancelable속성이 true로 설정되어 있어야 한다.


15. 커스텀 이벤트를 만들어야하는 어떤 경우이며 어떻게 만드는가?

  • 커스텀 이벤트는 기본 이벤트 클래스(flash.events.Event) 또는 그 상위 이벤트 클래스를 확장하는 경우를 의미한다.
  • 이벤트를 확장해야하는 경우는 이벤트 송출시에 필요한 정보를 담아내기 위함이다.
  • 만드는 방법
    class MyEvent extends Event
    {
      public static const MY_EVENT:String = "myevent";
      public var value:String;
      public function MyEvent( type:String, value:String ):void
      {
         super( type, false, false );
         this.value = value;
      }
      overide public function clone():Event
      {
        return new MyEvent( type, value );
      }
    }



16. 커스텀 이벤트가 bubbling이 가능하기 위해 어떤 조건이 필요한가?

  • Event의 생성자의 2번째 인자인 bubble값을 true로 설정한다.

17. 커스텀 컴포넌트 만들때 clone()함수를 override해야하는 이유는 무엇인가?

  • clone()메소드는 기존과 신규 properties들을 clone 내로 설정해 이벤트 객체의 복사본을 돌려준다.
    clone() 메소드를 Event 클래스 확장시 오버라이드 해야하는 이유는 이벤트를 다시 재전달해야하는 경우 묵시적으로 복사해서 재전달할 필요가 있을때 필요하기 때문이다.
  • 참고로 toString()도 확장해서 사용하는 것이 좋다. 이벤트에 대한 명세서가 될 수 있기 때문이다.

18. 약참조에 대해서 GC(가비지 콜렉션)과 관련되어 설명하라.

  • addEventListener()함수로 이벤트 청취자를 등록할때 5번째 인자로 useWeakReference 인자가 있다. 이것을 true로 설정하면 이벤트 청취자가 이벤트 청취를 약참조를 하겠다는 의미이다. 반대로 false(기본)이면 강참조이다.
  • 약참조, 강참조를 설명하기 전에 가비지 콜렉션(GC, Garbage Collection)에 대해서 먼저 알아야한다.
    만들어졌던 객체가 더이상 쓸모가 없어졌을때 GC라고 한다. 쓸모가 없어졌다는 것은 참조의 고리가 끊어졌다는 것을 의미한다. 메모리에 상주해 있지만 조만간 메모리에서 없애야할 대상인 것이다. Flash Player는 GC로 선정된 객체들을 메모리에서 삭제하는 시점을 내부적으로 구현해놓고 있다.(많은 분들이 Flash Player GC처리를 못한다고 하지만 실제로는 문제없이 잘하고 있다. 단지 효율적으로 GC처리를 하는지는 의문이지만...)
    Flash Player GC 대상을 찾아내기 위한 방법은 2가지가 있다. 그것은 레퍼런스 카운팅(reference counting)과 마크 앤 스윕(Mark and Sweep)이다. 레퍼런스 카운팅은 생성된 객체가 참조할때마다 참조 카운트를 1씩 더해준다. 또 참조에서 끊어지는 경우 1씩 감소시켜준다. 만약 레퍼런스 카운팅 값이 0이되는 경우 바로 GC 대상이 되는 것이다. 마크 앤 스윕은 레퍼런스 카운팅 만으로 찾을 수 없는 GC대상을 찾아준다. 가령, 두개 이상의 객체가 서로 다른 객체를 참조하고 있다고 가정한다.(순환참조) 그럼 이들 레퍼런스 카운팅 값은 1 이상이다. 그러므로 레퍼런스 카운팅 방법으로는 GC대상을 만들 수 없다. 마크 앤 스윕은  이들 객체가 최상위 부모와 연결되어 있는지 검사하는 방법이다. 부모로 부터 꼬리에 꼬리를 물고 객체가 참조되어 있는 것인지 조사해나가는 방법으로 GC대상을 검색한다.
    레퍼런스 카운팅과 마크앤 스윕 방법으로 찾아낸 GC대상은 메모리에 상주되지만 Flash Player의 GC 삭제방법 로직에 의해 어느 순간 삭제된다.(이 시점은 프로그래머가 어찌할 수 없다. AIR 또는 Flash Player Debug버전의 경우에만 System.gc()를 이용해 강제적으로 GC를 메모리에서 삭제할 수 있긴 하다.)
  • addEventListener()의 useWeakReference를 true로 설정하면 약참조가 되어 레퍼런스 카운팅을 증가시키지 않는다. 강참조의 경우 이벤트 대상(target)의 참조를 지웠다고 해도 addEventListener로 등록한 청취자 메소드가 GC대상이 아니라면 이벤트 대상의 레퍼런스 카운팅 값은 0이 될 수 없다. 결국 프로그래머의 뜻과 다르게 메모리를 낭비하는 일을 초래할 수 있다. 물론 이벤트 대상이 사라지는 시점에 removeEventListener() 사용하면 되겠지만 때로는 그 시점을 모르는 경우도 발생한다. 이러한 경우 useWeakReference를 true로 설정해서 메모리 낭비를 없앨 수 있겠다.
  • Flex에서 List 계열의 컴포넌트를 살펴보면 dataProvider()에 ArrayCollection 객체를 받을때 ArrayCollection의 변화를 살펴보기 위해 addEventListener()를 사용한다. 그런데 ArrayCollection 객체는 언제 어떻게 될지 List 계열 컴포넌트는 알 수 없을 것이다. 이때 유용하게 사용하는 것이 바로 useWeakReference=true로 설정해서 필요없어진 ArrayCollection이 메모리 남는 것을 방지할 수 있다. 참고 : http://blog.jidolstar.com/375



19. 이벤트가 전파되는 중간에 전파를 멈추게 하기 위해 stopPropagation()을 사용하지 않고removeEventListener() 를 사용하면 안되는 이유를 설명하라. (힌트, ActionScript 3.0의 Native 메커니즘에 입각한다. http://bixworld.egloos.com/2149717)

  • 이벤트 송출을 시작하면 flash player는 이벤트가 송출될 디스플레이 객체 리스트를 전부 조사해 미리 이벤트 객체를 복사해두기 때문이다. 이미 전파할 대상이 모두 정해져있고 전파가 시행중인 경우에는 중간에 removeEventLisener를 사용하더라도 일단 송출된 이벤트는 끝까지 전파된다. 다음 시점 이벤트 송출시에는 removeEventLisener()가 적용되어 있는 상태가 된다.


20. willTrigger()와 hasEventListener()의 의미를 설명하고와 두 메소드의 차이점을 보여줄 수 있는 대한 예를 들어보자.

  • 공통점
    hasEventListener()이나 willTrigger() 모두 이벤트 청취자가 있는지 검사한다.
  • 차이점
    hasEventListener() : 지정한 객체에(만) 이벤트 청취자가 있는지 조사한다. 이벤트 흐름과는 무관하다.
    willTrigger() : 지정한 객체를 포함하는 디스플레이 객체 리스트에 해당 이벤트가 청취자가 있는지 조사한다. 그러므로 이벤트 흐름과 관련 있다.
  • 예제
    var button:Sprite = new Sprite();
    addChild( button );
    this.addEventListener( MouseEvent.CLICK, onClick );
    trace( button.willTrigger( MouseEvent.CLICK ) ); //true
    trace( button.hasEventListener( MouseEvent.CLICK ) ); //false ->왜 false가 되는가 아는게 중요!
    trace( this.willTrigger( MouseEvent.CLICK ) ); //true
    trace( this.hasEventListener( MouseEvent.CLICK ) ); //true
  • 이 두개의 함수를 잘 활용하면 쓸데없이 이벤트를 송출하는 경우를 방지할 수 있다.

21. ActionScript 3.0 이벤트에 대해 참고할 만한 문헌 및 자료를 조사하자.
Introduction to event handling in ActionScript 3.0
Jasu님의 ActionScript 3.0 이벤트 오브젝트
Event 한글 문서
EventDispatcher 한글 문서


글쓴이 : 지돌스타(http://blog.jidolstar.com/415)

재사용/유지보수를 극대화를 위해 다형성, 추상화 개념이 들어간 객체지향프로그래밍을 이용한다.


객체지향프로그래밍(OOP) 5대 원칙도 마찬가지입니다. 결국 재사용/유지보수를 위해서 필요한 원칙입니다. 이런 원칙을 잘 지키는 것은 초보 개발자에게 무척 어려운 일이기도 합니다. 왜냐하면 이해와 설계과정이 함께 들어가는 것이기 때문입니다. 하지만 지속적으로 적용하고 몸에 베면 그리 어려운것만은 아닙니다.


[공부]

http://muticd.com/lec/director/viewBody.php?t_Name=Lec_drbook2

11, 12 동영상을 학습한다.



[과제]


1. 인터페이스(Interface), 추상 클래스(Abstract Class), 구상 클래스(Concrete Class)

1.1 인터페이스란 무엇인가?  

1.2 추상클래스란 무엇인가? 추상클래스의 역할을 정확히 언급하라. 인터페이스와의 차이점을 언급하라.

1.3 구상클래스란 무엇인가?

1.4 AS3에는 추상 클래스의 키워드로 abstract가 없다. 그러나 실제 설계시에는 추상클래스 역할을 하는 클래스가 필요한 경우가 많다. 이런 경우에 대한 적절한 예제를 들고 Class Diagram을 작성하라. (단,추상클래스는 직접 사용할 수 없도록 해야한다.)

1.5 1.4에서 만든 추상클래스를 가지고 구상클래스를 3가지 이상 예제를 들고 Class Diagram을 작성하라.

1.6 1.4, 1.5에서 만든 추상클래스와 구상클래스를 가지고 문제없이 사용할 수 있다. 하지만 다중상송의 경우 문제가 발생할 수 있다. 이런경우 예를 들고 왜 인터페이스-추상클래스-구상클래스를 셋트로 설계하는게 좋은지 설명하라.



2. Open-Close 원칙 (OCP, 개방-폐쇄의 원칙)

2.1 OCP원칙에 의하면 확장 상속(is-a)에 관해서 어떻게 하나?

2.2 OCP원칙에 의하면 합성 상속(has-a)에 관해서 어떻게 하나?

2.3 OCP원칙에 따르기 위해 Class를 어떻게 설계해야하는가?

2.4 OCP 원칙에 맞지 않는 예를 Class Diagram으로 표현하라.

2.5. OCP 원칙에 대한 적절한 예를 Class Diagram으로 표현하라.



3. The Liskov Substitution 원칙(LSP, 리스코프 치환 원칙)

3.1 LSP 원칙에 대해 설명하라

3.2 LSP 원칙에 맞지 않는 적절한 예를 Class Diagram으로 설명하라.

3.3 LSP 원칙에 맞는 적절한 예를 Class Diagram으로 설명하라.



4. The Dependency Inversion 원칙(DIP, 의존 관계 역전 원칙)

4.1 DIP 원칙에 대해서 간단하게 설명하라.

4.2 DIP 원칙에 맞지 않는 예제를 Class Diagram으로 설명하라.

4.3 DIP 원칙에 맞는 예즈를 Class Diagram으로 설명하라.



5. The Interface Segregation 원칙(ISP, 인터페이스 격리 원칙)

5.1 ISP에 대해서 간단히 설명하라.

5.2 ISP에 맞지 않는 예제를 Class Diagram으로 설명하라

5.3 ISP에 맞는 예제를 Class Diagram으로 설명하라.



6. The Single Responsibility 원칙(SRP, 단일 책임의 원칙)

6.1 SRP에 대해서 간단히 설명하라.

6.2 SRP에 맞지 않는 예제를 Class Diagram으로 설명하라.

6.3. SRP에 맞는 예제를 Class Diagram으로 설명하라.



[참고서적]

Flex/AIR Bible (대림, 윤훈남저)

액션스크립트 3.0 디자인 패턴(에이콘, 조이로트.대니 패터슨 저)



이들에 대해서 학습을 완료하면 재사용/유지보수를 위해 아래와 같은 작업을 해야할 것을 느낄겁니다.


1. 인터페이스 또는 추상클래스로 설계한다.

2. 참조시 인터페이스 및 추상클래스를 참조해야한다.(의존성을 줄임)

3. 인터페이스나 추상클래스는 확실한 자기 역할을 부여해라.(유지보수,확장성 향상)


OOP 5대 원리 및 다양성, 추상화 과정에 대해서 이해하고 계속 적용할려고 노력하는 것은 개발의 삽질을 줄여주는데 반드시 필요한 부분입니다. 처음에는 머리 아플지 모르지만 예전보다 이쁘게 만들어진 자신의 프로그램을 보며 웃을날이 분명 올것입니다. ^^


객체기반프로그래밍(OBP, object based programming)이 아닌 객체지향프로그래밍(OOP, object oriented programming)을 하시기 바랍니다.


댓글이 곧 달리겠죠? ^^

글쓴이: 지돌스타(http://blog.jidolstar.com/419)

많은 프로그래머들이 클래스 관계 및 설계에 대해서 명확히 이해하지 않고 손가는데로 프로그램을 만들다가 나중에 유지보수에 어려움을 겪는다.(본인도 예외가 아님) 이러한 문제를 극복하는 취지에서 이번 학습이 필요하다고 생각한다. 물론 Flex의 경우 Flex자체의 내부구조를 이해하고 효율적인 사용이 필요하다. 이 부분은 따로 학습해야할 것이다.


[공부할 것]

클래스들 간에 관계설정

출처:http://cafe.naver.com/javasolution/26


윤훈남의 Flex강의중 10.객체지향프로그래밍-클래스 다이어그램 : http://muticd.com/lec/director/viewBody.php?t_Name=Lec_drbook2


[숙제]

1. 클래스의 관계에서 is a, use a, has a 에 대해서 예시와 함께 설명하라.(예시는 3가지 이상)


2. UML에서 클래스 관계

2.1 "의존관계"의 영문, 의미, UML 표기법 설명, AS3 예시

2.2 "연관관계"의 영문, 의미와 2가지 종류에 대한 설명과 UML 표기법 설명, AS3 예시

2.3 "일반화관계"의 영문, 의미와 UML 표기법 설명, AS3 예시

2.3 "실체화관계"의 영문, 의미와 UML 표기법 설명, AS3 예시

2.4 위 관계에 대해 UML을 작성해보자

  (http://amateras.sourceforge.jp/cgi-bin/fswiki_en/wiki.cgi?page=AmaterasUML 에서 다운받에 Flex Builder에 설치하고 다 만든 결과물을 스크린샷해서 붙인다)


3. 합성과 상속

3.1 의미를 설명하고 AS3로 예시를 들어라.

3.2 각각의 장단점을 설명하고 예시를 들어라.


4. 인터페이스

4.1 인터페이스의 의미와 AS3에서 일반적으로 통용되는 인터페이스 명명규칙

4.2 AS3는 다중상속을 할 수 없다. 하지만 인터페이스를 이용하면 다중상속의 문제점을 해소시키면서 클래스를 만들 수 있다. 예를 들어 설명하라.

4.3 인터페이스는 클래스간에 결합도를 줄여준다. 예를들어 설명하라.

4.4 ActionScript 3.0에서 부모SWF에서 자식SWF를 로드하여 자식 SWF안에 있는 클래스를 사용할 수 있다. 인터페이스를 이용하면 부모와 자식간에 클래스 공유의 결합도를 줄여줄 수 있는데 그 예를 들어보자.



5. 추상화 클래스(AS3는 이런 개념이 없지만 충분히 활용할 수 있다.)

5.1 추상화 클래스의 의미.

5.2 추상화 클래스를 사용해야하는 이유

5.3 인터페이스를 이용해서 추상화 클래스를 만들고 이 추상화 클래스를 이용한 구체화된 클래스에 대한 예제를 만들라(AS3, UML)


6. 캡슐화(은닉화)

6.1 캡슐화의 의미

6.2 캡슐화가 적절하게 된 클래스와 아닌 클래스에 대한 예시를 들어라.(Array 활용)


7. 다형성

7.1 다형성의 의미

7.2 다형성의 의미를 대변할 수 있는 예시(코드/UML)를 들어라.


8. 절차지향 방식과 객체지향 방식의 차이점(장,단점 포함)을 설명하라.


답은 언제 달릴까요? ^^

글쓴이: 지돌스타(http://blog.jidolstar.com)


국제천문연맹(IAU, International Astronomical Union)은 2009년을 '세계 천문의 해(IYA2009, International Year of Astronomy 2009)'로 정했습니다. 2009년은 갈릴레오 갈릴레이가 처음으로 망원경을 통해 천체를 관측한지 400년이 되는 해입니다.

잠깐 "2009 세계 천문의 해" 동영상을 감상해볼까요?


스타플(http://starpl.com)도 나름대로 천문을 바탕으로 만들어졌습니다.
일반인들이 쉽게 다가갈 수 있게 별을 소재로 만들어진 스타플....
우연치 않게 2009년은 세계 천문의 해라고 하니...
이렇게 생각도 드네요.

2008년은 스타플 결실의 해라고 한다면
2009년은 스타플 도약의 해라고 생각되네요.

앞으로 스타플은 어떤 모습이 될까요?
별은 이제 과학자들만의 대상이 아닌
우리 일반인들에게도 소중한 대상이 될 것 입니다.
꿈과 희망을 주는 멋진 스타플이 되길 희망합니다.


2009 세계 천문의 해 공식홈페이지

영문 : http://www.astronomy2009.org/
한국 : http://www.astronomy2009.kr/main.aspx

글쓴이 : 지돌스타(http://blog.jidolstar.com/417)

제 나름대로 따져본 스타플(http://starpl.com)에서 이쁜 별 모음입니다.


"지돌스타"의 별. 역쉬 이쁘군요. ^^


"ckdan"님의 별. 스타플 별 스킨과 아이템등을 그리는 분이시죠?


"별이"님의 별. 독특한 배경, 기울어진 별... 다들 떨어질 것 같네요. ㅎㅎ



"위콘"별. 스타플을 만든 회사의 별이죠? 만든 사람들의 친구링크위젯이 있네요.


"아리아스"님의 별. 이번에 새로 나온 크리스마스 테마를 이용했네요. 담달에 결혼한다죠? ^^


"아이"별. 산소가 모락모락 나올 것 같은 별이예요. 저기 안에서는 왠지 공기가 쾌적할 것 같다는...


"싸늘한레몬향"별. 요리를 좋아하는 분인만큼 별이 레스토랑이예요~~

일전에 위콘에 쿠키도 보내줬죠? 넘 맛있게 먹었어요


"addLayer"의 별. 보통 별들보다 작네요~~

별을 뚫고 깜찍한 조카사진이 일품이군요. ^^


"allriv"의 별. 이쁜집을 꿈꾸는 듯한 별이네요~~  


"mkyoon"님의 별.

뭔가 이국적 느낌이 나는 별이네요.


"joykim"의 별.

제가 생각하는 가장 이쁜 별입니다.

배치도 참 이쁘고, 사진도 이쁘고... 어쨌든 이쁩니다.

기준은 제 마음입니다.



당신만의 이쁜 별을 꾸며봐요.

http://starpl.com


Flex나 Flash로 개발 결과물안에 폰트를 포함시켜야하는 경우를 많이 경험해봤으리라 생각한다.

폰트를 포함(Embed)한다는 것은 시스템 폰트를 사용하지 않고 프로그램안에 폰트를 내장해서 좀더 세밀하게 폰트를 제어할 수 있게 하기 위함이다. 가령, 폰트의 안티알리어싱, 회전, 투명도 조정 등을 위해서는 반드시 프로그램안에 해당 폰트를 내장해야한다.

폰트를 포함할때 가장 큰 문제점은 프로그램 용량이 너무 커진다는 것이다.
이럴때 보통 동적으로 로딩하는 방법을 통해 프로그램 자체 크기 용량을 줄일 수 있다.

그럼, 쓰여질 폰트가 제한적일때는 어떻게 할까?
가령, 폰트안에 숫자만 사용할 것이라면 그것만 뽑아내서 사용할 수 있을 것이다.
사용할 폰트가 제한적이라면 프로그램 크기를 줄이기 위해서라도 반드시 수행해야할 것이다.

Flash에서는 이것을 아주 쉽게 할 수 있다.
하지만 Flex에서 이런 작업을 하기에 여간 불편한것이 아니다.
왜 그런지 살펴보자.

Flex에서 폰트를 포함하기 위해서 CSS의 @font-face 또는 ActionScript3에서 Embed 메타데이타 태그를 이용하면 된다.

즉,

@font-face
{
src:systemFont("돋움");
fontFamily: myFontFamily;
advancedAntiAliasing: true;
unicodeRange : U+c0ac,U+c790,U+cc98; /*변환후 사용하면 됩니다.*/
}

또는


[Embed(source="../assets/돋움.ttf",fontName='MyFont',
mimeType='application/x-font', unicodeRange='U+c0ac,U+c790,U+cc98')]
private var font1:Class;

이다.

상단은 시스템 폰트를 포함 방법, 아래는 지정된 폰트를 포함하는 방법을 사용하고 있지만 어쨌든 둘다 어렵지 않게 사용할 수 있다.

둘다 unicodeRange 속성을 가지고 있다. 여기에 입력된 값은  특정문자에 대한 유니코드(unicode)값이다.
숫자면 숫자, 문자면 문자에 대한 유니코드값을 이곳에 넣어주어야 지정된 폰트만 프로그램안에 포함할 수 있는 것이다.

저 유니코드 값을 넣어주어야하는데 당신은 저걸 다 외우고 있는가?
"안녕하세요" 만 쓴다고 하자.
그럼 이것에 대한 유니코드값은 "U+c548,U+b155,U+d558,U+c138,U+c694,U+2e"이다.
이 값을 모른다면 Flex에서 유니코드 넣기란 여간 어려운 것이 아닐 것이다.

본인도 이것때문에 어떻게 할까 고민하다가 폰트 유니코드 변환기를 만들어서 사용하면 되겠다 싶어서 하나 만들었다.

사용자 삽입 이미지



이 프로그램의 핵심 함수는 다음과 같다. 의외로 간단하다. ^^;;;

private function encodeUnicode( fonts:String ):String

{

       var fontUnicodes:String = "";

       var length:int = fonts.length;

       for( var i:int = 0; i < length; i++ )

       {

             var char:String = fonts.substr( i, 1 );

             fontUnicodes += "U+"+char.charCodeAt(0).toString(16)+",";

       }           

       return fontUnicodes;      

}     

우측 스타플 "내별위젯"도 그렇게 만들었다.
회사에 Flasher가 없어서... 전부 ActionScript3로 만들었는데... 사용할 폰트가 제한적이라 이 프로그램을 유용하게 사용했다.

왜 Flex로 하지? 어렵게 ActionScript 3로 했는가? 라고 반문하실 수 있겠다. 사실 Flex는 쓰기 편하지만 덩치가 크다. 위젯과 같은 작은 프로그램을 만들기 위해 덩치큰 Flex를 사용하는 것은 별로 바람직하지 못할때가 많다. 왜냐하면 결과물의 용량이 커지기 때문이다. 위젯의 경우 Flash를 할 수 있다면 Flash로 제작하자. Enterprise급 프로그램이라면 Flex로 만들면 되겠다.

 



Flex 하시는 분들도 이제 폰트 Embed 범위지정 쉽게 해요.

관련내용

Setting character ranges
[Flex, AIR] 프로그램 크기를 줄여보자 2 - 폰트(font) 동적로드 또는 문자범위지정
[Flex, Flash] 폰트(font) Embed의 이점과 제한점
[Flex] 폰트를 런타임(run time)시 동적으로 불러와 적용하는 방법


밤하늘에 당신의 유일한 별을 찾아가세요. 스타플 http://starpl.com


글쓴이 : 지돌스타(http://blog.jidolstar.com/414)

2008년 11월 30일 오후 1시 13분 KST
새로운 스타플(http://starpl.com)을 드디어 오픈했다.

사용자 삽입 이미지

새로 오픈한 스타플(starpl.com)의 메인화면



몇달간 밤샘작업하면서 만든 결과물을 이제 오픈했다고 하니 감회가 새로웠다.
아래 동영상은 스타플을 사용하는 모습을 일부 담았다.




새롭게 리뉴얼된 스타플은 SNS를 더욱 잘 표현하기 위해 업그레이드 했다. 또한 개인 컨텐츠 생산 활성화를 위해 몇가지 기능을 더욱 추가했으며, 더욱 미려한 디자인 도입으로 사용자로 하여금 하고 내 별을 가지고 싶다는 느낌을 주려고 많이 노력을 했다. 기존 초대제로만 운영했던 방식에서 누구나 가입할 수 있도록 했다.

이제 스타플에서 추가되고 발전된 기능에 대해서 소개하겠다.
본인은 스타플의 개발자중 한명이기 때문에 본인이 관여한 부분이 중심이 되어 스타플을 소개할 것이다.



별지도 (star map) - 메타센터로서의 별지도  

스타플에서 사용된 가장 큰 메타포(metaphor,상징)는 바로 별(star, 恒星)이다.

스타플은 가상의 별이 아닌 실제 관측을 통해 만들어진 천체목록에 등록되어 있는 별을 사용하고 있으며 이 별을 사람들에게 나눠준다는데서 출발한다. 거기에 감성을 더하여 자신이 이 별을 소유했고 별을 꾸밀 수 있다는 개념을 도입했으며 별에 자신의 인생을 담는다는 의미를 주기 위해 타임라인을 도입했다. 또한 별과 별을 친구로 맺게 해주고 관심별에 찾아갈 수 있게 하는 SNS(Social Network Service) 개념을 도입시켰다.

별은 우주 공간에 있다. 그렇기 때문에 Text위주의 사이트로는 별을 표현하기에 역부족이다. 그래서 도입한 것이 바로 별지도(star map, 星圖)이다. 스타플의 별지도는 2차원 공간에 별을 그려주고 일반 지도와 비슷하게 이동 및 확대/축소가 가능하게 만들어졌다. 별지도의 이러한 표현이 가능하게 하기 위해 Adobe Flash/Flex 기술을 도입했다. Adobe 기술을 도입된데는 단순히 UI 표현만을 위한 것을 뜻하지 않는다. 수억개의 별을 별지도에 표현하기 위해 데이타 베이스 작업이 필요하며 그 데이터를 별지도에 전송하고 별지도는 그 데이터를 가지고 렌더링(그림을 그려줌)해준다. 서버-클라이언트 간에 통신의 최적화를 위해 Adobe Flash/Flex 기술은 크게 도움이 되었다고 생각한다.

별지도는 외관상 전과 달라진 점은 많이 없다. 하지만 내부적 재설계를 통해 확대/축소등을 할때 예전 보다 더욱 사실감 있게 보여질 수 있도록 했으며 별자리 그림을 추가하여 좀 더 감성적으로 보여지도록 했다.

사용자 삽입 이미지

새롭게 리뉴얼된 별지도 http://starpl.com/meta


별지도에는 가입한 사람들의 별을 볼 수 있다. 사용자별(가입을 통해 받은 별)은 활동량, 분야에 따라서 별 주변의 후광의 크기와 색, 그리고 노출빈도에 영향을 준다. 새롭게 도입된 것은 바로 개인 글의 분야에 따라서 후광색이 달라진다는 점이다. 스타플은 이번 리뉴얼을 통해 RSS 발행 및 스타플 메타 센터에 글을 발행하여 공개할 수 있는 시스템을 도입했다. 그래서 전체검색등을 통해 자신의 별에 방문 유입이 가능하도록 제작되었다.


사용자 삽입 이미지

글쓰기후 분야별로 발행할 수 있다.



사용자 삽입 이미지

활동량, 분야에 따른 사용자 별지도에서 별의 후광 표현방법



사용자 삽입 이미지

발행한 글은 검색에 노출되며 별지도 상에 말풍선의 형태로 표현된다



발행된 개인 글은 스타플의 별지도의 메타센터에 노출된다. 인기글 및 추천글 등이 메인에도 노출되지만 위 화면처럼 별지도상에 보여질 수 있다. 기존 와글댓글도 별지도에 나타낼 수 있게 한 것이 이번 스타플 별지도에 변화된 점이다.

앞으로 별지도의 메타센터는 좀 더 쉽게 사용성을 높이기 위한 UI작업을 수행할 것이다. 또한 연관된 기록을 찾아갈 수 있는 기능도 추가될 예정이다.



타임라인(Time Line) - 더욱 쉬워진 인터페이스


스타플은 국내 최초로 SNS서비스에 타임라인을 도입했다. 하지만 사용하기에 불필요한 기능이 있었고 단추형태로 되어 있는 UI로 사용자의 컨텐츠가 직접 노출이 안된다는 단점이 존재했다. 이러한 단점을 극복하고 사용자에게 더욱 친숙한 타임라인을 다시 제작하게 되었다.

사용자 삽입 이미지

스타플의 새로운 타임라인



위 화면처럼 타임라인은 개인 컨텐츠가 바로 노출될 수 있도록 UI를 개편했다. 또한 카테고리 별로 자신의 컨텐츠를 볼 수 있도록 만들어 편의성을 더욱 강화시켰다.

사용자 삽입 이미지

스타플 타임라인은 스킨을 변경할 수 있다.


스타플 타임라인에서 크게 달라진 또 한가지는 바로 타임라인에 스킨를 적용할 수 있도록 한 것이다. 타임라인의 상단에 보면 원하는 색으로 입혀진 타임라인으로 자신의 별과 어울리게 스킨을 정할 수 있도록 만들었다.

타임라인도 별지도와 함께 Adobe Flex를 이용해 개발했다. 스킨기능 및 각종 데이터 통신의 편의성을 위해 Flex 기술의 도입은 디자인 적용 및 개발에 도움이 되었다.


별꾸미기 - 나만의 별을 꾸며봐요.


별꾸미기의 겉모습은 기존과 달라진 점이 많이 없다. 하지만 더욱 빨라지고 사용성을 증대시켰다.
기존에는 꾸미기 상단 패널은 Javascript, 꾸미기 영역은 Flex로 개발했지만 이번에는 전체 Adobe Flex로 개발하여 더욱 세밀해지고 확장가능한 꾸미기가 가능해지도록 제작되었다.

사용자 삽입 이미지

꾸며진 내 별의 모습



사용자 삽입 이미지

스타플에서 내 별 꾸미기하는 장면


이번 리뉴얼을 통해 또 한가지 크게 달라진 점은 별을 아이템화 했다는 것이다. 즉, 기존에는 별의 크기와 회전, 레이어 변경등을 할 수 없었지만 이번에는 위치 조정을 빼놓고 모두 가능해지도록 만들었다. 결국 더욱 다양한 방식으로 별을 꾸밀 수 있게 되었다.



별마트 - 더욱 다양해지고 이뻐진 아이템들


웹사이트는 아무리 기술이 좋고 전문적이다 하더라도 세련되고 이쁜 디자인이 없다면 사용자들에게 외면당하기 쉽다. 이번에 새롭게 추가 것중에 하나가 바로 테마별이다.

사용자 삽입 이미지

스타플에서 제공하는 다양한 테마별



별마트(http://starpl.com/mart/main) 에 방문해 "테마" 메뉴에 보면 위와 같이 다양한 테마별을 볼 수 있다. 테마별은 별스킨과 함께 아이템을 일부만 구입하거나 한꺼번에 구입할 수 있다. 스타플에서는 테마별을 별가루라는 가상의 화폐 시스템을 이용해 구입할 수 있다. 참고로 별가루는 스타플 활동량으로 벌어들일 수 있다.


사용자 삽입 이미지

테마별 중 하나




알림이 - 친구들과 관심별의 소식을 알려줘요


기존 스타플부터 유지해온 알림이 서비스이다. 알림이 서비스는 자신의 친구별 및 관심별의 소식을 보는데 유용하게 쓰여질 수 있다.

사용자 삽입 이미지

스타플 알림이 서비스

이번 리뉴얼을 통해 동작이 더욱 부드러워졌으며 데이타 베이스 개편으로 로딩속도를 향상시켰다. 이번 알림이 서비스에서 가장 주요하게 추가된 점은 관심별 이다. 관심별은 관심법으로 다루는 별인가? ㅎㅎ 그런것은 아니고 별친구는 아니지만 개인적으로 유용한 자료가 많거나 관심 분야를 가진 별이 있을때 지속적으로 방문하고 싶은 별을 관심별이라고 한다. 블로그 RSS 구독을 하는 것처럼 관심별을 등록하여 그 별의 소식을 알림이를 통해 볼 수 있다.

알림이 서비스는 친구들의 소식 뿐아니라 자신의 포스트에 쓰여진 댓글, 방명록 글등을 거의 실시간으로 알려준다.
앞으로 알림이 서비스는 데스크탑 영역으로 확장되어질 수 있으며 메신저 서비스와도 연동되어 질 수 있다고 생각한다.


내별위젯(My Star Widget) - 자신의 블로그에 내별위젯을 달아봐요.




위 위젯이 바로 내별위젯이다. object, embed 태그로 구성되어 있기 때문에 HTML 형태로 붙일 수 있는 게시판이나 자신의 블로그에 얼마든지 붙힐 수 있다. 본인 블로그 우측에도 내별위젯을 붙였다.

내별위젯은 실제 별지도 위에 내별의 위치, 별을 받은 날을 보여주고 자신의 별에 바로 갈 수 있도록 만들어졌다. 첫번째 버전이기 때문에 별 기능은 없지만 개인적으로 디자인이 이뻐서 마음에 든다.

내별위젯은 스타플에 가입한 사람에게만 유효하며 http://starpl.com/main/banner/down 에서 직접 복사해서 사용할 수 있다.

사용자 삽입 이미지

Starpl 배너 페이지. 여기서 스타플 위젯과 Link 배너를 다운로드 받을 수 있다.



외부 블로그 등록 기능 - 자신의 블로그를 스타플 타임라인에 담아봐요.

스타플 리뉴얼에서 추가된 유용한 기능중 하나가 바로 기존에 사용하고 있는 자신의 블로그의 RSS를 타임라인에 담을 수 있는 것이다. 컨텐츠를 스타플에 직접 유입한다기보다 타임라인을 통해 자신의 블로그에 방문을 유도할 수 있도록 하며, 스타플 메타센터에 노출될 수 있게 하는데 유용하게 쓰일 수 있는 기능이다.


사용자 삽입 이미지

메인화면의 블로그 등록하기 버튼


스타플 메인화면(http://starpl.com/)에서 좌측부분을 보면 블로그 등록하기 버튼이 있다. 로그인후 이 버튼을 눌러보면 아래와 같은 화면이 나온다.

사용자 삽입 이미지

타임라인에 내 블로그 등록하기


본인은 타임라인에 지돌스타 블로그라는 카테고리를 등록하여 여기에 RSS를 등록했다.

사용자 삽입 이미지

등록된 블로그가 타임라인에 들어간 모습

[Blog]단추에 붙은 제목을 클릭하면 아래와 같은 화면이 뜬다.

사용자 삽입 이미지

타임라인을 통해 자신의 블로그로 이동한 모습. 아래에 추천 버튼이 있다.



스타플 메타센터에 추천이 들어가기 때문에 추천이 많이 된 블로그 포스트는 방문유입을 유도할 수 있다.



정리하며...

스타플은 이제 시작하는 것과 같다. 개인적으로 스타플에서 보여줄 수 있는 것중 10%도 안보여줬다고 생각한다. 스타플은 앞으로 국외서비스를 위해서 한발짝 다가갈 것이다. 우주를 배경으로 시작했다는 것, 별은 국내뿐 아니라 국외에도 통용될 수 있다는 점은 스타플의 가장 큰 경쟁력이다. 한국 SNS 서비스의 파워를 스타플을 통해 보여주고 싶다.

사용자 삽입 이미지




관련 사이트 및 글

스타플(http://starpl.com)
실제 별을 이용한 위치기반 감성 SNS, 스타플
스타플(starpl.com)에 사용된 Adobe Flex 기술
지돌스타의 별


글쓴이 : 지돌스타(http://blog.jidolstar.com/413)
사용자 삽입 이미지

오늘 드디어 새로운 스타플(http://starpl.com)을 선보입니다.
기존 초대제 방식에서 누구나 가입해서 별을 받을 수 있는 시스템으로 전환했습니다.

스타플은 실제 별을 가입하는 사람에게 주고 그 별을 꾸미고 별친구를 사귈 수 있도록 한 SNS(Social Network Service)입니다. 밤하늘을 연상케 하는 별지도와 자신의 인생을 담은 타임라인, 친구와 관심분야에 쉽게 다가갈 수 있도록 한 알림이, 그리고 나의 별을 꾸밀 수 있는 기능들이 마련되어 있습니다.

별지도 
 - 메타센터(검색기능)가 도입되어 스타플내 다양한 별들의 기록을 별지도상에서 볼 수 있습니다.(계속 기능이 추가될 예정입니다.)
 - 더욱 빨라지고 미려해진 에니메이션을 보여줍니다.

타임라인
 - 기존과는 UI가 완전히 달라졌습니다. 자신의 기록을 타임라인에 담을 수 있습니다.
 - 스킨을 설정할 수 있도록 수정되었습니다.

내 블로그 담기
 - 기존 블로그에서 발행한 RSS를 자신의 타임라인에 담을 수 있습니다.
 - 타임라인에 담근 블로그 글은 별지도의 메타센터 및 검색에 노출되어 더욱 많은 사람이 자신의 별 및 블로그에 올 수 있도록 할 수 있습니다.

나의 별 꾸미기
 - 기존 평면적인 별을 꾸몄다면 공간느낌이 더해진 나만의 별을 꾸밀 수 있도록 만들어졌습니다.
 - 기존 꾸미기보다 더욱 빨라지고 편하게 꾸밀 수 있습니다.

별마트
 - 더욱 풍성해진 이쁜 아이템을 구입할 수 있습니다. 별마트에서 판매되는 아이템은 현재까지는 자신의 활동량에 따라 쌓여지는 별가루로 구입할 수 있습니다. 열심히 쓰시는 만큼 더욱 예쁜 별을 꾸밀 수 있답니다. 한번 도전해보세요. ^^

나의 별 위젯
 - 외부 블로그 및 개인홈페이지에 나의 별을 보여주는 예쁜 위젯을 달 수 있습니다. 앞으로 스타플은 서비스내에서 제공하는 모든 컨텐츠에 대해 위젯화 하여 더욱 풍성한 서비스를 제공하도록 노력할 것입니다.

알림이
 - 스타플의 또하나의 특징은 나의 친구별와 관심별의 새로운 기록, 이벤트등을 알림이를 통해 한번에 볼 수 있다는 것입니다. 더욱 빨라지고 쓰기 편해진 알림이로 친구들과 더욱 친해지고 관심분야 사람들을 많이 만나보세요. ^^

스타플에 놀러오세요~~~
http://starpl.com


글쓴이 : 지돌스타(http://blog.jidolstar.com/412)

POST방식으로 MultiPart 컨텐츠 타입으로 지정하여 데이타를 서버에 올리는 경우가 종종 있다.
가령, 이미지를 BitmapData로 캡쳐해서 ByteArray형태로 만든다음 서버에 전송하기 위해서는 URLLoader를 이용해 URLRequest의 contentType을 "multipart/form-data;"으로 지정해서 전송할 수 있다. 이와 관련되서는 예전에
"[Flex/AIR]BitmapData를 PNG나 JPG로 변환하여 ByteArray로 서버에 전송하는 방법" 제목으로 글을 올린적 있으니 참고바란다.

하지만 Flash Player 10부터 이러한 과정에서 보안이슈에 걸린다. 아래는 Flash Player 10 기준 ActionScript 3.0 메뉴얼에서 URLLoader의 load()에 설명되어 있는 글이다.  

Flash Player 10 이상에서는 multipart Content-Type(예: "multipart/form-data")을 사용하고 POST 본문 내 "content-disposition" 헤더에 "filename" 매개 변수를 지정하여 업로드를 처리하는 경우 POST 작업이 업로드에 적용되는 보안 규칙의 영향을 받을 수 있습니다.

  • POST 작업은 마우스 클릭이나 키 누르기 같은 사용자 동작에 대한 응답으로 수행됩니다.
  • POST 작업이 크로스 도메인인 경우, 즉 POST 대상이 POST 요청을 보내는 SWF 파일과 같은 서버에 없는 경우 대상 서버는 크로스 도메인 액세스를 허용하는 URL 정책 파일을 제공해야 합니다.

또한 multipart Content-Type의 경우 구문이 RFC2046 표준에 따라 유효해야 합니다. 구문이 유효하지 않은 경우 POST 작업은 업로드에 적용되는 보안 규칙의 영향을 받을 수 있습니다.


마우스 클릭이나 키 누르기 같은 사용자 동작에 대한 응답이 있은 직후에 하지 않고 이 기능을 사용하게 되면 "SecurityError: Error #2176 Certain actions, such as those that display a pop-up window, may only be invoked upon user interaction, for example by a mouse click or button press." 에러가 발생한다. 이 메시지는 자바스크립트(Flash가 아닌 외부)에서 Flash 컨텐츠의 FileReference browse() 메소드를 같은 이유의 보안 문제로 호출할 수 없을때와 동일하다. 이와 관련되어서는 다음 글을 참고한다.

[Flash Player 10]FileReference의 변경된 보안정책과 새롭게 추가된 기능에 대한 나의 생각

아무튼, Flash Player 10 으로 업그레이드 되면서 보안문제때문에 걸리는게 한두개가 아니다. 이와 관련되서 명확히 이해할 수 있으면 좋겠다.

글쓴이 : 지돌스타(http://blog.jidolstar.com/)

Flash Player 10에 맞게 제작된 ActionScript 3.0 한글문서 입니다.
참조하세요. ^^

http://help.adobe.com/ko_KR/AS3LCR/Flash_10.0/
http://help.adobe.com/ko_KR/ActionScript/3.0_ProgrammingAS3/


글쓴이 : 지돌스타(http://blog.jidolstar.com/410)



Adobe Flex 공식사이트
에 소개된 "스타플"(http://starpl.com) 입니다.

"스타플"의 별지도, 별꾸미기, 타임라인, 위젯, 이미지 에디터는 Flex라는 프로그램 기술을 이용했습니다. 그래서 Flex 공식 사이트에 소개된겁니다. ^^

조금 아쉬운 것은 요즘 사이트 리뉴얼 작업을 하고 있는데 리뉴얼 끝나고 소개를 했으면 더욱 좋았다 싶네요. 몇일내로 더욱 빨라진 별지도와 함께 새로운 스타플을 볼 수 있을겁니다. ^^

글쓴이 : 지돌스타(http://blog.jidolstar.com/409)

1997년 봄은 제게 잊지 못할 추억거리를 남긴 때였던 것 같아요.  그 때에는 별보는것과 별사진 찍는 것에 푹빠졌었는데요. 왜냐하면 당시에 헤일-밥(Hale-Bopp) 혜성이 왔거든요.

혜성의 이름이 헤일-밥인 이유는 1995년 7월 22일 미국의 아마추어 천문가인 Alan Hale과 Thomas Bopp이 M70 구상성단을 관측하던 중 그 옆에 있던 10.5등급의 천체를 발견했고, 후에 이 혜성이 새로 발견된 혜성이라 판명되어 발견자의 이름을 붙혀주었기 때문입니다. 학명으로는 1995O1로 명명되었습니다.

이 혜성은 20C 최대 혜성이였습니다. 헤일밥 혜성은 주기가 약 3000년 쯤 된다고 합니다. 즉, 3000년 뒤에나 이 혜성을 다시 볼 수 있다는 이야기입니다. 1997년 당시 밝기가 1등급 이상으로 일반인 들도 잘 알고 있는 핼리혜성보다 100이상 밝았으며 핵의 지름은 40km로 핼리혜성의 핵(15km) 크기의 2배가 넘습니다. 1997년 3월 31일 근일점(태양에서 가장 가까운 거리)을 통과하였습니다.

아참... 혜성과 유성(별똥별) 의 차이를 잘 모르시는 분들을 위해서 간단히 소개하자면.... 혜성은 지구 대기권 밖... 즉 우주에 있는 천체입니다. 반면에 유성은 지구 대기권밖에 있는 작은 바위 덩어리(유성체; meteoriod)가 지구에 떨어지면서 지구의 대기권과 마찰하여 발광하는 것입니다.

혜성의 구성물질은 먼지와 얼음이 섞여 있습니다. 그래서 태양 근처로 지나가면 태양풍에 의해 증발하면서 꼬리가 생깁니다. 지구에서 보면 길게 꼬리가 보이고요, 거의 정지되어 있는 것처럼 보입니다.  실제는 엄청난 속도로 움직이죠. 하지만 너무 멀리 떨어져 있기 때문에 정지된 것처럼 보이는 것 뿐입니다.  실제로 하루하루 관측해보면 별 사이로 움직이는 것을 볼 수 있지요. 망원경으로 몇분간 혜성을 보면서 별들사이로 움직이는 혜성을 본적이 있는데요. 참 재미있는 추억거리였던것 같습니다. 아직도 눈에 아른아른... ㅋ

뭐... 헤일-밥 혜성에 대한 소개는 이 정도로 마치고요.

별사진 찍는 법에 대해 잠깐 소개할께요.
천체사진을 찍는 방법은 크게 두가지로 나누는데요. 바로 고정촬영법과 가이드촬영법입니다. 고정촬영법은 말그대로 카메라를 고정시켜놓고서 찍는 방법이고요. 가이드촬영법은 지구의 자전에 의해 흘러가는 별을 추적하면서 찍는 방법입니다. 가이드촬영법이 고정촬영법보다 더 어렵고 비싼 장비가 요구된 다는 느낌이 오지 않나요? 1997년도 당시는 제가 이제 막 대학생이 되었을 때라 가이드촬영할 수 있는 장비를 마련할 경제적 능력이 되지 않았습니다. 그래서 고정촬영을 했고요. 아래 소개하는 사진들이 다 고정촬영법으로 찍은 사진들입니다.

당시 DSLR은 없었기 때문에 필름사진기를 이용해서 찍었습니다. 아래와 같은 사진은 일반 자동카메라로는 찍을 수 없습니다. 왜냐하면 별이 매우 어둡기 때문에 1초도 안되는 짧은 노출로는 어두운 별을 찍을 수 없답니다. 이러한 사진은 B셔터(노출을 무한대로 줄 수 있는 셔터)가 달린 수동카메라를 이용해 찍게 됩니다. 그 외에도 튼튼한 삼각대, 감도가 높은 필름(ISO 400이상:숫자는 필름의 감도를 뜻합니다. 숫자가 클 수록 높은 감도를 가진 필름입니다.), 그리고 릴리즈(셔터를 카메라에서 직접 누르지 않고 간접적으로 누를 수 있게 해주는 악세서리)가 필요합니다. 이 정도 장비면 충분히 별사진을 찍을 수 있지요. 한 20~30만원정도면 이러한 장비들을 구할 수 있겠군요.


그럼 본격적으로 제가 1997년 2월~4월에 찍은 혜일-밥 혜성의 모습을 보여드리겠습니다. 

Comet Hale-Bopp , Yong-Ho, Ji1997.02.17 5시 AM, 충남시 천안시 직산읍 군서리. 노출시간:20초, 필름감도 :1600


짜잔~~ ㅋㅋ 위 사진은 제가 생전 처음으로 찍은 헤일밥 혜성사진입니다. 동쪽에서 떠오르는 혜성이 보이시나요? 꼬리도 보입니다. 그때는 혜성의 꼬리가 겨우 보였는데요. 이 때부터 혜성의 밝기는 상당히 밝아지기 시작하더군요.



Comet Hale-Bopp , Yong-Ho, Ji1997.02.21 5h AM 충난 천안시 천안공업전문대학교(현재 공주대)


위 사진은 400의 감도를 가진 흑백 필름으로 찍은 것으로 기억합니다. 맨 위에 밝은 별이 직녀성(Vega)입니다. 백조자리 부근을 지나가는 혜성의 모습입니다.


Comet Hale-Bopp , Yong-Ho, Ji1997.03.04 5:47 AM, 충남시 천안시 직산읍 군서리. 노출시간:3분, 필름감도 :400(?)


위 사진은 3분정도 노출한 사진입니다. 혜성 위에 밝은 별은 백조자리의 데네브(Deneb)라는 별입니다. 이 별이 2등성 정도 되니깐 혜성이 2등성보다 더 밝다는 의미겠지요. 눈으로도 잘 보였죠.

Comet Hale-Bopp , Yong-Ho, Ji1997.03.11 새벽, 필름감도:400, 노출시간:20초(?)


Comet Hale-Bopp , Yong-Ho, Ji1997.03.11 새벽, 필름감도:400, 노출시간:20초(?)


Comet Hale-Bopp , Yong-Ho, Ji1997.03.11 새벽, 필름감도:400, 노출시간:20초(?)



위의 3개 사진은 1997년 3월 11일 새벽에 찍은 사진입니다. 혜성이 앞의 사진들보다 더 커보인다는 것을 확인할 수 있습니다. 또한 꼬리가 2개가 보입니다. 잘보이는 흰 꼬리는 먼지꼬리라고 하고요. 파랗게 보이는 꼬리는 이온꼬리라고 해요. 잘 안보이신다고요? 그럼 아래사진을 한번 보시죠.

사용자 삽입 이미지찍은분:박대영, 장소:경기도양평한치고개,일시:1997.03.08 05:15, 8분노출, 자동가이드


바로 위 사진은 제 대학교 선배인 박대영님이 찍은 사진인데요. 제 사진과는 다르게 멋지게 찍었네요 ㅎㅎ 제가 찍은 방식은 고정촬영이고 이 사진은 아까 별을 쫗아가면서 찍는 방법인 가이드촬영법을 이용한 것입니다. 아까 말씀드렸던 먼지꼬리와 이온꼬리가 눈으로 아주 잘보입니다. 혜성이 꼬리가 2개가 생기는 이유는 http://blog.daum.net/rhdejrwn4101/10301884 에 찾아가 보시면 아실 수 있겠습니다.
위 사진의 출처는 http://cafe.naver.com/ngc7000/104 입니다.


Comet Hale-Bopp , Yong-Ho, Ji1997.04.05 새벽, 충남천안직산군서



Comet Hale-Bopp , Yong-Ho, Ji1997.04.05 새벽, 충남천안직산군서

위 사진들 역시 새벽에 찍은 사진입니다. 혜성의 꼬리가 확연히 잘 보입니다. 정말 멋진 모습을 보여주고 있죠? 당시 눈으로 볼때도 장관이였습니다. 바로 위 사진은 카시오페이아 별자리와 같이 찍은 겁니다. 혜성 옆에 W자가 보이시나요? ^^  이날 혜성사진 찍다가 삼각대가 부러지는 사고가 있었죠. 그래서 찍다가 못찍었는데요. 삼각대만 안뿌러졌다면 진짜 멋진 사진을 많이 찍었을텐데 라는 아쉬움이 많이 남았습니다.

Comet Hale-Bopp , Yong-Ho, Ji1997.04.11 저녁 충남 천안 직산 군서, 필름:1600슬라이드,노출:30초?


Comet Hale-Bopp , Yong-Ho, Ji1997.04.11 저녁 충남 천안 직산 군서, 필름:1600슬라이드,노출:30초?


위 사진은 특별한 필름을 사용했습니다. 보통 쓰는 필름은 네거티브필름이라고 하는데요. 이 사진에 사용한 필름은 슬라이드 필름, 즉 포지티브필름입니다. 감도는 1600로 꾀 높은 걸 썼죠. 이 날 사진 찍을려고 산으로 올라가는데 가시나무가 너무 많아서 다 못올라가고 무덤에서 찍었습니다. ㅋ 혜성이 페르세우스 자리에 있고요. 아래 사진 왼쪽 에는 조그만하게 플라이아데스 산개성단도 보이는 군요. 아~.... 사진에 휙~ 하고 길게 찍힌 건... 찍는 동안 비행기가 지나가서 그런겁니다. ㅎㅎㅎ 아쉽군요.


Comet Hale-Bopp , Yong-Ho, Ji충남 천안시 직산면 수헐리 1997년 4월 12일 저녁 한사랑감리교회 앞



Comet Hale-Bopp , Yong-Ho, Ji충남 천안시 직산면 수헐리 1997년 4월 12일 저녁 한사랑감리교회 앞



Comet Hale-Bopp , Yong-Ho, Ji충남 천안시 직산면 수헐리 1997년 4월 12일 저녁 한사랑감리교회 앞


위의 3개 사진이 제가 마지막으로 찍은 헤일-밥 혜성입니다. 교회 십자가에 붉게 물든 나무와 지붕이 혜성과 잘 어울리는 듯합니다.

벌써 10년 전이군요. 그때는 정말 밤하늘을 보고 사진찍는것이 행복했던 시절이였습니다.
지금은 사는게 바빠서 그런지 하늘을 볼 기회가 많지 않군요. 좀더 여유를 가지고 시골로 나가서 별을 보고 싶습니다.

사용자 삽입 이미지이올린 추천글 : 사진 분야에 추천되었습니다. 잘찍은 것도 아닌데 ㅎㅎㅎ



글쓴이 : 지돌스타(http://blog.jidolstar.com)

함께 만드는 최고의 천문학 사이트 천문노트(http://astronote.org) 에 놀러오세요.

위 사진을 상업적인 용도로 사용하는 것을 금지합니다. 스크랩을 하실경우 출처를 꼭 밝히시기 바래요.

+ Recent posts