블로그 전문 “이글루스”에 오신 것을 환영합니다.

블로그 전문 “이글루스”에 오신 것을 환영합니다.
새로운 보금자리, 이것저것 어색한 것이 많으시죠?
포털블로그와는 다른, 이글루스만의 기능, 이글루스의 특징을 소개해드립니다.

이글루스는 블로그전문을 지향합니다.
2004년, 첫 발을 내디딘 이글루스는 국내 최초 트래백 을 도입하여 블로그전문 서비스로 입지를 다졌습니다. 관심사를 공유할 수 있는 ‘ 밸리’와 ‘마이’, 문화체험의 새로운 경험 ‘렛츠리뷰’, 국내 최고 메신저 네이트온 연동으로 더욱 새로운 블로깅, 독보적인 블로거가 되세요!

첫째, 공감하는 글이 있다면, 트랙백핑백을 이용하세요!
기존 포털 블로그에서 사용하던 스크랩기능 대신 트랙백과 핑백을 사용해보세요~
관심사가 비슷한 블로거를 만날 수 있는 방법입니다!

둘째, 일촌, 친구, 이웃 등 오프라인 인맥 위주의 ‘친구맺기’ 기능이 필요하시면!
이글루스에서 제공하는 이글루링크를 추천해드립니다.
이글루링크를 하시면, 해당 블로거의 새글 업데이트 소식을 실시간으로 받아볼 수 있습니다.

셋째, 카테고리별 공개/비공개 설정을 지원하지 않습니다.
이글루스는 자신이 작성한 글을 더 많은 블로거들과 나눌 수 있도록 참여와 공유를 지향합니다.
카테고리별 공개/비공개 기능은 현재 마련되어 있지 않으나 추후 필요성을 검토해보도록 하겠습니다.

넷째, 도움이 필요할 땐, EBC 와 이글루스도움말 을 찾아주세요.
이글루스를 이용하시다 발견되는 버그나 오류, 그리오 요청사항은 운영자 공식블로그 EBC 를, 이글루스의 기능과 운영정책을 알고 싶으시다면 이글루스 도움말을 방문하세요!

※ 공지사항을 지우고 싶은 경우, 포스트의 ‘삭제’를 클릭하면 지워집니다.
※ 삭제 버튼은 한 번만 누르세요. 여러 번 클릭 시 다른 글이 삭제될 수도 있습니다.

by 우듯 | 2009/02/19 15:39

Mustella - Flex Testing Engine

Flex SDK에는 Mustella라는 녀석이 있다.

이는 Flex Component GUI 테스트하기 위한 테스팅 엔진으로,
아직까지는 그 자세한 내용이 외부에 공개가 되지 않고 있다. (추후 공개 예정)

Mustella 특이할 점은, FlexUnit과는 다르게,
ant와 연동하여 빌드 테스트를 진행할 수 있다는 것이다.

이제 Flex에서도 Continuous Integration 가능하게 것으로 보인다.
(그런데, 아직 Async는 지원하고 있지 않다는 얘기가..)

아래는 현재 Flex 4 Gumbo에 사용되고 있는 테스트 스크립트


<<flex4test.mxml>>
<?xml version="1.0" encoding="utf-8"?>
<FxApplication xmlns="http://ns.adobe.com/mxml/2009"
    backgroundColor="white"
    width="800" height="600"
    initialize="initApp();">

        <Script>
                import flash.display.Sprite;
                import flash.text.engine.*;


                [Embed(source="BickhamScriptPro-Regular.otf", fontName="TestFont", mimeType="application/x-font", cff="true")]
                private var fontSymbol:Class;

                private var textLine:TextLine;

                private function initApp():void {
                        var fd:FontDescription = new FontDescription("TestFont");
                        fd.fontLookup = FontLookup.EMBEDDED_CFF;
                        var ef:ElementFormat = new ElementFormat(fd);
                        ef.fontSize = 32;
                        var te:TextElement = new TextElement("The quick brown fox", ef);
                        var tb:TextBlock = new TextBlock(te);
                        textLine = tb.createTextLine();
                        textLine.x = 100;
                        textLine.y = 100;
                        panel.addChild(textLine);
                }
        </Script>

    <layout>
        <VerticalLayout/>
    </layout>

    <states>
        <State name="normal" />
        <State name="altered" />
    </states>

    <FxContainer width="100%">
        <FxCheckBox label="Enabled" id="buttonEnabler" selected="true" />
        <FxButton id="testButton" label="Hello" label.altered="World" enabled="{buttonEnabler.selected}" click="testLabel.text = 'This is a test'" />
        <FxButton id="testButton2" label="Button with a long label" enabled="{buttonEnabler.selected}" excludeFrom="altered" />
        <FxButton id="stateTestButton" includeIn="altered" />
        <FxCheckBox id="testCheckBox" label="Check Box 1" enabled="{buttonEnabler.selected}" />
        <FxCheckBox label="Check Box 2" enabled="{buttonEnabler.selected}" />
        <FxRadioButton label="Radio Button" enabled="{buttonEnabler.selected}" />
        <Label id="testLabel" text=" " />
    </FxContainer>

    <FxContainer width="100%">
        <CheckBox id="enabler" selected="true" label="Enabled"/>
        <FxVScrollBar id="testVScrollBar" minimum="0" maximum="100" enabled="{enabler.selected}" />
        <FxHScrollBar id="testHScrollBar" minimum="0" maximum="100" enabled="{enabler.selected}"/>        
    </FxContainer>
    
    <FxContainer width="100%" id="panel">
    
    </FxContainer>

        <FxContainer id="deferredContent" creationPolicy="none">
                <FxButton label="Button 1" />
                <FxButton label="Button 2" />
        </FxContainer>
</FxApplication>

<<flex4test_testScript.mxml>>
<?xml version="1.0" encoding="utf-8"?>
<UnitTester xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" testSWF="main.mxml">

        <!-- this set of lines form a template that must be in each unit test -->
        <mx:Script>
        <![CDATA[
        public static function init(o:DisplayObject):void
        {
        }
        ]]>
        </mx:Script>
        <mx:Metadata>
        <![CDATA[
                [Mixin]
        ]]>
        </mx:Metadata>
        <!-- end of set of lines that must be in each unit test -->

        <mx:Script>
        <![CDATA[
        ]]>
        </mx:Script>

        <testCases>
                <!-- controls -->
                <TestCase testID="ButtonTest1">
                        <body>
                                <DispatchMouseEvent target="testButton" type="mouseOver" localX="10" localY="10" />
                                <DispatchMouseClickEvent target="testButton" localX="10" localY="10" />
                                <AssertPropertyValue target="testLabel" propertyName="text" value="This is a test" />
                        </body>
                </TestCase>
                <TestCase testID="CheckBoxTest1">
                        <body>
                                <DispatchMouseEvent target="testCheckBox" type="mouseOver" localX="10" localY="10" />
                                <DispatchMouseClickEvent target="testCheckBox" localX="10" localY="10" />
                                <AssertPropertyValue target="testCheckBox" propertyName="selected" value="true" />
                        </body>
                </TestCase>
                <TestCase testID="EnabledTest1">
                        <body>
                                <DispatchMouseEvent target="buttonEnabler" type="mouseOver" localX="10" localY="10" />
                                <DispatchMouseClickEvent target="buttonEnabler" localX="10" localY="10" />
                                <AssertPropertyValue target="testButton" propertyName="enabled" value="false" />
                                <AssertPropertyValue target="testCheckBox" propertyName="enabled" value="false" />
                        </body>
                </TestCase>
                <TestCase testID="VScrollBarTest1">
                        <body>
                                <DispatchMouseEvent target="testVScrollBar" type="mouseDown" localX="3" localY="60" />
                                <DispatchMouseEvent target="testVScrollBar" type="mouseDown" localX="3" localY="60" />
                                <AssertPropertyValue target="testVScrollBar" propertyName="value" value="40" />
                        </body>
                </TestCase>

                <!-- states -->
                <TestCase testID="StatesTest1">
                        <body>
                    <SetProperty target="" propertyName="currentState" value="altered" waitTarget="" waitEvent="currentStateChange" />
                                <AssertPropertyValue target="testButton" propertyName="label" value="World" />
                                <AssertPropertyValue target="stateTestButton" propertyName="visible" value="true" />
                                <AssertPropertyValue target="testButton2" propertyName="parent" value="null" />
                        </body>
                </TestCase>
                <TestCase testID="StatesTest2">
                        <body>
                    <SetProperty target="" propertyName="currentState" value="normal" waitTarget="" waitEvent="currentStateChange" />
                                <AssertPropertyValue target="testButton" propertyName="label" value="Hello" />
                                <AssertPropertyValue target="stateTestButton" propertyName="parent" value="null" />
                        </body>
                </TestCase>


                <!-- cff -->
                <TestCase testID="CFF_width_height">
                        <body>
                                <AssertPropertyValue target="panel.getChildAt(0)" propertyName="width" value="163.65" />
                                <AssertPropertyValue target="panel.getChildAt(0)" propertyName="height" value="32.05" />
                        </body>
                </TestCase>

                <!-- deferred instantiation -->
                <TestCase testID="DeferredInstantiation1">
                        <setup>
                                <RunCode code="application.deferredContent.createDeferredContent()
                                                 waitTarget="deferredContent" waitEvent="contentCreationComplete" />
                        </setup>
                        <body>
                                <AssertPropertyValue target="deferredContent" propertyName="numItems" value="2" />
                        </body>
                </TestCase>
        </testCases>
</UnitTester>


by 우듯 | 2008/10/14 04:03 | Flex 4 Gumbo Preview | 트랙백 | 덧글(0)

메모리 누수의 해결.

Flex나 AIR로 개발을 하다보면,
코딩 실수로 인한 메모리 누수가 자주 발생한다.

그리고, 덩치가 커질대로 커진 어플리케이션에서
뒤늦게 발견한 메모리 누수를 해결하려면, 
엄청난 시간과 노력을 소모해야 한다.

물론 Flex 3 Builder Pro에서는 프로파일러를 제공하긴 하지만,
역시 작은 단위 어플리케이션일 때에나 해결이 가능하다.

그렇다고, 코딩의 실수를 100% 막을 수도 없다.

이에 대한 답은 단 하나뿐이다.

항상 어플리케이션을 기능별로 잘게 분할해두어,
언제든지 나누어서 테스트할 수 있도록 하는 것이다.

모래사장에서 바늘을 찾기란 매우 어려운일이지만,
한 줌의 모래 속에서라면 다르다.

by 우듯 | 2008/10/13 14:33 | Flex | 트랙백 | 덧글(0)

Gumbo의 Skinning - Part 1

Flex 4 Gumbo에서는 Skin 기능이 상당히 달라진다.
간단히 설명하자면, View와 Logic의 분리가 보다 수월해지는데,
사실 기존의 Flex 아키텍처에서 View와 Logic를 분리를 연구하는데에 
많은 시간과 노력을 들인 나로서는, 그 노력이 다소 무색해지는 것 같아 조금 아쉽기도 하다.

어쨌든 본론으로 들어가서,
Gumbo의 비쥬얼 컴포넌트는 Content를 가지고 있는 ItemsComponent와
그 Content를 시각적으로 어떻게 표현할 것인지를 결정하는 Skin으로 나뉜다.

아래 예는 ItemsComponent의 하위 컴포넌트인 Panel을 시각적으로 표현하기위한
MyPanelSkin이라는 간단한 Skin 컴포넌트이다.

com/chanik/skin/MyPanelSkin.mxml
<?xml version="1.0" encoding="utf-8"?>
<Skin xmlns="http://ns.adobe.com/mxml/2009">
<Metadata>
[HostComponent("flex.component.Panel")]
</Metadata>
<states>
<State name="normal"/>
<State name="disabled"/>
</states>
<!-- Border -->
<Rect left="0" right="0" top="0" bottom="0" radiusX="3" radiusY="3">
<stroke>
<SolidColorStroke color="0x000000" color.disabled="0xC0C0C0" />
</stroke>
<fill>
<SolidColor color="0xAAAAFF"/>
</fill>
</Rect>
<!-- Content Box Fill -->
<Rect left="5" right="5" top="25" bottom="5">
<stroke>
<SolidColorStroke color="0xC000C0" color.disabled="0xC0C0C0" />
</stroke>
<fill>
<SolidColor color="0xFFFFFF"/>
</fill>
</Rect>
<!-- Title -->
<TextBox id="headerGroup" left="10" right="10" top="5" bottom="0" height="20"
text="{hostComponent.header}"/>
<!-- Content -->
<Group id="contentGroup" left="10" right="10" top="25" bottom="10" color.disabled="gray"
content="{hostComponent.content}"/>
</Skin>

위에서부터 설명을 하자면, 일단 Skin 컴포넌트는 메타데이터로 HostComponent를 가지고 있다.
즉, 자신이 표현할 컴포넌트를 미리 지정해놓는 것이다. 이곳에서는 Panel을 표현할 것이므로, flex.component.Skin을 지정하였다.

또한 <state> 부분을 보면, Panel이 가질 수 있는 상태, normal과 disabled를 정의하고 있는데,
normal은 평소때의 상태, disabled는 Panel.enabled = false 로 설정되었을 때의 상태이다.

그 아래에는 Border와 Content Box를 그리는 부분이 들어가있다.
여기서 주의해서 볼 것은 color.disabled 와 같이 표현된 property이다.
이는 위의 states에서 설정한 특별한 상태가 되었을 때, 해당 값을 적용한다는 뜻인데,
위에서처럼 color.disabled="0xC0C0C0" 일때는 상태가 disabled가 되었을 때, 0xC0C0C0값에 해당하는 값을 color에 넣어준다는 뜻이다.

그 밑에서는, 실제 Panel의 내용을 표현하는 방법을 지시하고 있다.

Title 부분에서는, Text로 입력이 된 컴포넌트의 header값(Panel의 title은 header값에 저장된다)을 TextBox로 보여주고 있다.
hostComponent는 [HostComponent] 메타데이터 태그에서 지정한, 자신이 표현할 데이터를 가진 컴포넌트를 가리킨다. 

Content 부분에서도 역시 마찬가지로 hostComponent.content를 사용한다.
그런데 여기서 조금 주의할 것은, id값이 contentGroup으로 설정이 되어있다는 것이다.
contentGroup이란 Gumbo Flex 4의 skinPart라는 기능에서 사용하는 부분인데,
간단히 설명하자면, Panel의 Super Class인 ItemsComponent는 contentGroup에 자신의 content를 집어넣는다.
그렇기에, ItemsComponent의 skin은 무조건 이 contentGroup을 가지고 있어야하며,
Panel의 skin 역시 마찬가지로, 위와 같이 자신의 내용을 표현할 부분을 id="contentGroup"으로 하여,
이 안에 Panel의 content 부분이 들어가도록 한다. (contentGroup이 없으면 에러가 난다.)
이에 대한 자세한 내용은 나중에 다시 다루기로 하겠다.

그럼 이제 위의 Skin을 적용한 간단한 Application을 보자.


<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://ns.adobe.com/mxml/2009"
layout="{new flex.layout.HorizontalLayout()}">
<Style>
Panel {
skinZZ: ClassReference("com.chanik.skin.MyPanelSkin");
}
</Style>
<Panel title="제목 부분입니다" width="200" height="200">
<content>
<TextBox width="100%" height="100%">
내용 부분 입니다.
</TextBox>
</content>
</Panel>
<Panel title="역시 제목 부분입니다" width="200" height="200" enabled="false">
<content>
<TextBox width="100%" height="100%">
내용 부분 입니다. 컴포넌트는 enabled = false 설정되어있습니다.
</TextBox>
</content>
</Panel>
</Application>


그다지 특별한 부분은 없다.
state가 적용된 부분을 보기 위해, enabled='false'로 설정된 Panel을 하나 더 넣었다.

스타일 부분을 보면 skinZZ라는 스타일을 사용하고 있는데, 
이는 해당 컴포넌트의 스킨을 지정하는 값이다.
현재는 임시 이름으로 skinZZ를 사용하고 있으며, 추후 skinClass로 변경될 예정이다.
(현재 버전인 v4.0.0.3466에는 아직 적용이 되지 않았다.)

실행을 해보면 아래와 같은 화면을 볼 수 있다.



참고로, 위의 MyPanelSkin은, 예제용으로 만든 스킨이며, 실제로 쓰기엔 부적절하다.
예를 들어, 다수의 컴포넌트가 들어가거나, Title의 Font-Size나 길이가 바뀌면, 부적절하게 표현된다.
간단히 맛보기라고 생각하고, 참고만 하자.


by 우듯 | 2008/10/04 02:41 | Flex 4 Gumbo Preview | 트랙백 | 덧글(0)

[Gumbo] Two Way Binding

Flex 4 Gumbo에서는 Two-way Binding이 새로 생긴다.

Two Way Binding이란 : 
Flex 2,3에서는 Data Binding을 하면, source 값이 변하면 destination의 값이 함께 변하지만,
destination의 값이 변할때는 source의 값이 변하지 않았다.
또한, 이를 구현하면 코드가 다소 복잡해지는 경향이 있었는데,
Flex 4에 도입되는 Two Way Binding은,
source, destination을 가리지 않고, 둘 중 어떤 한 값이 변하면, 다른 한 값도 같이 변하게 되는 것이다.

이를 적용하는 방법은 아래와 같다.


1.  @{property} 와 같이 사용하는 방법
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://ns.adobe.com/mxml/2009">
<layout>
<VerticalLayout/>
</layout>
<TextInput id="input" />
<TextInput id="output" text="@{input.text}" enabled="false"/>
</Application>


2. <Binding> 태그를 이용하여 twoWay 값을 true로 지정하는 방법.

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://ns.adobe.com/mxml/2009">
<layout>
<VerticalLayout/>
</layout>

<Binding source="input.text" destination="output.text" twoWay="true"/>
<TextInput id="input" />
<TextInput id="output" enabled="false"/>
</Application>


현재 버전(4.0.0.3466)의 Flex 4 SDK에도 적용이 되어있다.



by 우듯 | 2008/10/04 01:32 | Flex 4 Gumbo Preview | 트랙백 | 덧글(0)

◀ 이전 페이지다음 페이지 ▶