'Action Script'에 해당되는 글 4건

  1. 2010/01/29 kineticroad Naver OpenAPI 쇼핑 검색
  2. 2009/12/30 kineticroad Class란 무엇인가요?
  3. 2009/09/25 kineticroad Interface 클래스의 존재 이유
  4. 2009/09/05 kineticroad ActionScript의 대기코드?
Team:FP(Flash Quickly Progress)를 운영한지 4주차가 되어가는데
ActionScript 3.0을 처음 접하는 녀석들을 데리고서 열심히 가르쳐서

1. Class 구조 보기, Class 만들기
2. Event 이해하기, Event 만들기
3. 통신, Naver OpenAPI에서 데이터 갖고 오기
4. XML, XML 파싱하기

이렇게 진행했다.

그래서 이번에 과제를 낼겸 해서 네이버 OpenAPI를 이용한 쇼핑검색을 만들었는데
반나절만에 만든거라 영 안좋다 ㅎ
좀더 손봐서 잘 좀 쓸 수 있게 해야겠다.

 

2010/01/29 19:57 2010/01/29 19:57

요새 스터디를 시작하게 되었다.
누군가를 가르친다는게 상당한 부담이기도 하고 나도 내 앞가림하기 바쁘다고 생각했기때문에
사실 오래전부터 고민해 왔었다.
정식으로 전산과를 나온것도 아니고 맨날 그림만 그리다가 이길로 진입하게된 나로써는 깊이있는 내용을
전달해주지 못할 것 같다는 생각때문이었다.
그런데 IT에 처음 와서 Flash를 처음 만지고 ActionScript를 처음 접하는 친구들이 고생하는걸 보니
전에 다니던 회사시절이 생각났다. 그래서 결심을 했다. 스터디를 시작하게되었다.

TEAM : FP(Flash Quickly Progress)

내가 잘 할 수 있는건 빨리 배우게 하는 밑거름을 만들어 배우는 시간을 단축시키는거다.
모든 과정이 그렇듯 기본이 되어있으면 빨리 배울 수 있게된다.
하지만 이 과정은 굉장히 지루하고 인내가 필요하다. 그래서 내가 가르쳤던 대부분의 사람들은 금새 나가 떨어졌었다.
이번에 내 교육방침은. "내가 뭘하는지 몰랐는데 정신을 차려보니 뭔가를 만들고 있었다"는게 기본적인 방침이다.
그래야 덜 지루하게 수업을 진행할 수 있지 않을까 하고 생각했기 때문.
어찌 되었든 간에 수업의 첫시간은 Class에 대한 이야기로 시작하려고 한다.

사실 Class라는 말 자체가 풍기는 뉘앙스로 봐서는 뭐가 들어가 있긴 있는데 도무지 무슨일을 하는 녀석인지 당최 이해하기가 어렵다.

보통 Class를 설명할때 책에서는 "교실"을 예를 들어 설명하는 경우가 많은데 가장 적절한 예라고 생각은 하지만 이해가 쉬워지진 않는다.

ActionScript에서 Class를 정의하자면 대충 이렇다.

"클래스는 프로그램을 구성하는 기능성을 갖춘 객체의 집합"

정도로 설명할 수 있는데 이 설명을 이해하려면 "객체지향"이라는 말을 먼저 이해해야한다.

객체지향프로그래밍이라는게 나오면서 클래스라는 개념들이 등장하기 시작했는데 사람 몸에 비유해서 사람 몸을 구성하는데 있어서 부위별로 나눠보면 머리 팔 2개 다리 2개 몸통. 5군데로 나눠볼 수 있다.

각 부위를 클래스로 이해하면 간편하다.

사용자 삽입 이미지

각각의 부위는 그에 해당하는 역할을 지닌 클래스로 분리할 수 있고 그 기능들이 유기적으로 결합되어있어 있다.
팔이나 다리가 없어진다 하더라도 신체라는 큰 프로그램이 "죽지는" 않고 나름대로의 기능을 유지할 수 있도록 설계되어 있다.
객체지향프로그램은 각각의 모듈들이 각기 다른 기능들을 갖고 있어서 어떤 물건을 조립하듯 프로그램을 만들어가는 것이라고 이해하면 "일단" 객체지향에 대해서 첫번째 관문은 통과했다고 보면 된다.

이때 각각의 모듈들은 클래스의 집합으로 이뤄져 있고 클래스는 모듈을 만들어 내기 위한 기능을 구현해낸다.
클래스는 큰 프로그램을 만들기 위한 모듈을 구성하는 하나의 집합이라고 생각하면 일단 거시적인 관점에서는 맞다고 볼 수 있다.

그렇다면 각각의 Property와 Method들이 Class를 이루고 있다면 Property와 Method들이 Program을 이루고 있는 최소단위인가? 라는 의구심이 들 수도 있겠지만 대답은 "아니다"라고 단정지어 말할 수 있다.

왜냐하면 Property는 그 자체가 개개의 클래스이기 때문이고 Method 또한 Property를 이용해 구현하고자 하는 기능을 실행하는 방아쇠 역할이기 때문이다.
클래스는 단지 클래스일 뿐이고 뭔가를 구현하고 구성하기 위한 하나의 부품 역할을 한다.

그렇기 때문에 하나의 클래스를 정상적으로 작동하게 하기 위해서는 클래스간 유기적인 결합이 필요하다.

간단한 예를 들어 코드를 살펴보도록 해보자.

package
{

// 만들고자 하는 클래스를 시작하기전 클래스에서 사용되는 클래스들을 미리 포함시킨다.
import flash.display.Graphics;
import flash.display.Sprite;

// 클래스의 시작. extends는 Sprite 클래스를 상속받아 사용한다는 뜻.(상속의 개념은 제 1강 상속(클래스에도 족보가 있다) 편을 읽어볼 것)
public class TestSample extends Sprite
{
    /**
     *  Constructor.
     *  생성자. 클래스를 생성하게 될 때 실행되는 메서드(?)정도로 이해하면 된다.
     *  생성하는 방법은 아래와 같다.
     *  
     *  var test:TestSample = new TestSample();
     */
    public function TestSample()
    {
        // super 클래스인 Sprite를 생성한다.
        // (무슨의미인지 알려고 해봤자 지금 단계에서 설명해도 이해하기 어려울 터. 그냥 그렇다고 생각해라)
        super();

        drawReadRectangle();
    }

    /**
     *  @private
     *  속이 빨간 네모를 만드는 메서드로 Sprite 속성 중 graphics 속성을 이용해 빨간 네모를 코드로 그려낸다.
     */
    private function drawReadRectangle():void
    {
        var thisGraphics:Graphics = this.graphics;
        graphics.clear();
        graphics.beginFill(0xFF0000, 1);
        graphics.drawRect(0, 0, 100, 100);
        graphics.endFill();
    }
}
}

샘플코드를 잘 보면 3.0 코드를 처음으로 보는거라 이해하기 어려울지 모르겠지만 그냥 일단 빨강색으로 표시해둔 부분을 설명하는 것으로 Class가 뭔가요 챕터를 마치도록 하겠다.

var 이란 명령어는 2.0코드에도 비일비재하게 나타나는 거라 별 설명없이 넘어가도록 하고.
thisGraphics라는 변수를 선언해 놓고 뒤에 ":Graphics" 라고 적어놨다. 이는 "thisGraphics라는 녀석은 Graphics클래스 객체입니다!"라고 컴퓨터한테 이야기 해준거다.
그렇다면 thisGraphics라는 녀석은 Graphics 클래스 외에는 다른 정보를 담을 수 없다. 이를 지키지 않으면 컴파일(Flash에서는 Import라고 하나요?) 중에 오류가 발생하게 된다.

그렇다면 this.graphics라는 건 뭐지?

위에서 말했듯 위의 클래스는 Sprite라는 놈을 상속받아서 쓴다고 했고 상속은 "제 1강 상속(클래스에도 족보가 있다)"편에서 설명하겠다고 했다.

단순히 설명하자면 위의 클래스는 Sprite에 있는 모든 기능을 사용할 수 있다고 미리 정해둔거라고 보면 된다.

그리고 Sprite 내부에는 graphics라는 변수가 있다.




이 graphics라는 변수는 Graphics라는 클래스 형태로 지정되어있다. 참고로 이야기 하자면 graphics라는 놈에 대해서 미리 알려고 하지말 것. 혼란만 가중될거니까. ㅋ(미리 알아봐도 나쁘지는 않겠지만)

그렇다면 방금 만든 TestSample이라는 클래스는 Sprite를 상속받았고 TestSample은 Sprite의 기능을 모두 쓸 수 있다고 앞에서 미리 말했다. 그러니 graphics라는 변수도 사용할 수 있다는 의미다.

thisGraphics는 Graphics 클래스 이므로 Graphics의 기능중 drawRect를 이용해 사각형을 만든다.

위의 예제는 Class안에서 다른 Class 객체를 이용해 필요한 기능을 구현하는 방법을 아주 간단하게 표현한 것으로 어떤 기능을 만들어 내기 위해 또다른 클래스와 유기적으로 결합해 사용한 것이다.

Class라는 것에 대해 너무 완벽한 이해를 할 필요는 없다.
단지 Class는 하나의 프로그램을 만들기 위한 최소 단위이며 Class들간 유기적인 결합으로 하나의 모듈을 만들어 내고 모듈들은 커다란 프로그램을 만들어 내기 위한 하나의 구성요소라는 것만 이해하면 된다.
2009/12/30 13:18 2009/12/30 13:18
ActionScript 3.0을 시작한지 벌써 1년 9개월이 됐다.
3.0이 라이터로 불을 붙이는 거라면 2.0은 부싯돌로 불을 붙이는 것과 같은 효과라고 생각한다.
(물론 모바일에 들어가는 FlashLite는 다른 이야기다.)

3.0으로 OOP 개념을 공부하며 궁금했던 것은 인터페이스 클래스다.

인터페이스 클래스가 왜 필요하지?

요새 프로젝트를 진행하다 보니 나도 모르게 인터페이스 클래스를 사용하고 있었다.
그도 그럴 것이 어떤 구조체가 대입되어 들어오게 되던 커스텀된 컨포넌트에 전달되어야하는 필수 조건들이 있기 때문이었다.
그래서 반드시 구현되어야 하는 프로퍼티, 메서드들이 필요했다.
그렇지 않으면 필수요소를 전달받지 못해 프로그램이 오작동 할 수 있기 때문이었다.
그래서 인터페이스 클래스를 기본적으로 정의한 후 그 클래스 형이 아니면 인자로 받지 못하게끔 제동장치를 걸어놓았다.


package classes.core
{
public interface IListItem
{
function set location(value:String):void
function get location():String

function set dataObj(value:Object):void
function get dataObj():Object
}
}

위와 같이 인터페이스 클래스를 만들어 놓으면 아래와 같이 구현한다.


package classes.controls
{
import classes.core.IListItem;

import mx.core.UIComponent;

public class MyControl extends UIComponent implements IListItem
{
public function MyControl():void
{
super();
}

//-------------------------------
// interface 구현
//-------------------------------
private var _location:String = null;

public function set location(value:String):void
{
_location = value;
}

public function get location():String
{
reuturn _location;
}

private var _dataObj:Object;

public function set dataObj(value:Object):void
{
_dataObj = value;
}

public function get dataObj():Object
{
return _dataObj;
}
}
}

위와 같이 인터페이스를 구현해 놓게 되면 클래스 사용자는 위와 같은 프로퍼티를 기본적으로 갖고 있게 된다.
물론 클래스를 이용하기 위한 필수 조건을 반드시 포함하기 때문에 실수할 염려와 디버깅 횟수를 줄일 수 있다는 장점이 있지만 이것 만으로는 약간 모자란 감이 있다.
실수는 누구나 하는 것이지만 조금만 신경을 쓴다면 이런건 문제가 아닐 수 있기 때문이다.
(물론 클래스 개체가 늘어나고 코드가 한없이 복잡해 진다면 당연히 문제가 되긴 하겠지만.)

하지만 예를 들어 위의 IListItem 인터페이스 클래스를 구현한 서로 다른 클래스가 있다고 가정해보자.
위에 있는 MyControl라는 클래스와 별개의 클래스인 MyControl2라는 클래스가 있고 MyComponent2 라는 클래스는 Sprite를 확장해 만들었다고 가정하면 그 둘의 공통점은 서로 같은 인터페이스를 구현한것 밖에 안된다. 하지만 아래와 같은 예제에서 그 인터페이스가 유용하게 사용된다는 점을 알 수 있다.


package classes.data
{
import classes.core.IListItem;
import classes.controls. MyControl;
import classes.controls. MyControl2;

import mx.core.UIComponent;

public class ExampleClass extends UIComponent
{
public function ExampleClass()
{
super();
}

private var myControl:MyControl = new MyControl();
private var myControl2:MyControl2 = new MyControl2();

public function sampleMethod(control:IListItem):void
{
trace(control.location);
}

private function callSampleMethod():void
{
sampleMethod(myControl);
sampleMethod(myControl2);

trace(IListItem(myControl).location);
trace(IListItem(myControl2).location);
}
}
}



위와 같이 IListItem을 인터페이스 클래스로 구현된 클래스들은 아무리 서로 다른 클래스라도 IListItem 인터페이스 클래스로 캐스팅이 가능하다. 이 이야기는 IListItem 클래스가 구현된 모든 클래스 및 자식 클래스들도 모두 IListItem으로 캐스팅 할 수 있으며 여기에서 발생하는 장점은 좀더 유연한 코드를 작성 할 수 있다는 것이다.
(확장성이 더 좋다고 표현하는게 맞을지 모르겠지만 적어도 "액션스크립트 3.0 디자인패턴"이라는 책에서는 그렇게 설명하고 있다;;)

커스텀 컨포넌트를 만들다 보면 항상 고민하는 것이 사용자가 어떤 클래스를 넣어서 사용할지 모르는 불확실성에 대응하는 코드를 구성하는 것이었다. 이런 인터페이스 클래스를 이용함으로써 커스텀 컨포넌트를 만드는데 조금 더 유연한 코드를 갖출 수 있다면 더 효율적으로 코딩할 수 있을 거라고 생각한다.
2009/09/25 13:05 2009/09/25 13:05
ActionScript 를 처음 만지는 사람들은 간혹 이런 질문을 할 때가 많다.

순차적으로 실행하지 않아서 통신해서 뭔가 불러올때 대기하지 않고 바로 다음 코드를 실행해서 오류가 난다. 해결 방법이 없을까?

사실 나는 ActionScript 만 만져왔기 때문에 처음엔 이게 무슨 질문인가...  하고 이해를 하지 못했다. 그런데 알고 봤더니 이런 식으로 코딩을 하고 난 뒤에 발생하는 오류였더라

package
{
import mx.rpc.http.HTTPService;
import mx.events.ResultEvent;

public class DataConnection extends HTTPService
{
/**
* Constructor.
*/
public function DataConnection()
{
// super class Constructor.
super();
eventConfiguration();
send("http://www.test.com/callData.php");
}

public var totalDataLength:int = -1;

private function eventConfiguration():void
{
addEventListener(ResultEvent.RESULT, resultHandler);
}
public function getTotalDataLength():int
{
return totalDataLength;
}

private function resultHandler(event:ResultEvent):void
{
totalDataLength = event.result.totalDataLength;
}
}
}

이런식으로 통신클래스를 만들어 두고 아래와 같이 사용하는것이 "왜 오류가 나느냐"는게 질문의 골자였다.


private function test():void
{
var connection:DataConnection = new DataConnection();
var i:int = connection.getTotalDataLength();
trace(i);
}

물론 "오류"는 나지 않겠지만 너무나 당연하게도 trace 에서 i의 값은 -1 이 나오게 될거다.
근데 보통은 저렇게 원격지에 있는 데이터를 불러오게 되면 대기하고 있다가 아래있는 코드를 실행시켜 준다는 이야기를 들은 순간....."사실 난 이해할 수가 없었다."

나에게 질문했던 사람들에게 정말로 미안하게도 사실 나는 ActionScript 외에 다른 언어는 깊숙하게 만져본적도 없었을 뿐더러 (Visual C++, Java, php 등등..) Event Driven 방식외에 다른 코딩방식이 있는 줄도 몰랐다.
"당연히 이벤트 방식으로 처리해줘야하는 것인데 왜 저렇게 코딩들을 하셨지?" 라고 밖에 생각이 안되었던 것이다.

그래서 찬찬히 조사해본 결과 충격적인 사실은 ActionScript 외 다른 언어에서는 대기하고 있다가 값이 들어오면 값을 리턴해준다는 거였다;;(나에게만 충격적인 사실임;)

그럼 왜 ActionScript에서는 다른 코드와는 다르게 대기 하지않고 그냥 다음코드를 실행해버리는 걸까.

여러 지인들의 의견과 조사해본 결과에 의하면 크게 두가지 이유가 있는데

1. ECMAScript 기반 코드이기 때문이다.
ActionScript 코드 자체가 ECMAScript 기반 코드로 만들어졌기 때문이다.(ECMAScript의 스팩을 따라간다.) ActionScript가 사실 JavaScript 코드의 형태와 유사하게 만들어진 이유이기도 하다. 어쨌거나 태생적으로 기반이 되는 코드가 ECMAScript라면 개발자의 의도와는 상관없이 바로 다음코드를 실행 할 수밖에 없단다;;

2. FlashPlayer는 싱글쓰레드이기 때문이다.
사실 나는 아직 쓰레드 개념이 없어서(이유는 저위 써놓은대로 쓰레드를 관리 할 수 있을 정도의 로우레벨 언어를 접해보지 못했기 때문이다.) 적당히 통밥으로 얻어 들은 바에 의하면 멀티 쓰레드를 관리할 수 있다면 대기할 수 있도록 조치를 취할 수 있다고 들었다. 그런데 이게 문제가 코드적인 부분이 아니라 산출물인 swf 파일을 실행하는 런타임에 문제가 있다. FlashPlayer다. 물론 AIR 도 AIR 런타임이라고 런타임이 따로 있지만 어찌되었거나 이 둘은 "싱글 쓰레드"로 동작하게 되어있다. 그래서 멀티 쓰레드를 통한 코드의 대기상태 조절이라던가 하는 부분은 물건너 갔다고 보는게 맞을 듯.


위와 같은 이유로 결국 Event-Driven 방식의 코드를 고수할 수 밖에 없다는 결론이 나왔다;
그렇다면 여기에 대한 대안은 없는걸까.
우리는 순차코딩을 하고 싶단 말이다!

물론 순차코딩을 할 수 있다. 하지만 ActionScript의 특성상 외부의 데이터를 갖고 오거나 컨포넌트가 생성된다거나 하는 시점이 규칙적이지 않고 "지멋대로 언제 되는지 알 방법이 없다"는 문제가
순차코딩방식에 빨간불을 켰다.

하나의 메서드만 봤을 때는 물론 순차적으로 진행되는 듯이 보이지만 계속해서 덩치가 커지는 어플리케이션에게 순차적인 방식으로 코드가 진행될 거라고 보장할 수가 없기 때문이다.
게다가 그렇게 덩치가 커지는 어플리케이션에게 순차코딩방식을 고수하라 한다면 결국 클래스들의 참조관계가 너무 강하게 엮이게 되어 "프로젝트 한개밖에 사용할 수 밖에 없는" 재활용이 불가능한
쓰레기 코드가 되어버린다.
예를 들어서 부모 객체에 있는 메서드를 실행하기 위해서 이벤트가 아니라 자식 객체가 직접 실행하려면 결국 그 클래스는 한정된 부모 객체를 갖을 수 밖에 없다. 한정된 부모 객체만 갖을 수 밖에 없는 자식 객체는 살아있는 코드가 아닌 "죽은 코드"가 된다.

위와같은 이유 때문에 Event-Driven 방식의 코드를 만들어야 하는데 이를 위해서는 하나의 목적 클래스 주위로 Event Class를 만들어 보조해주게끔 해야한다.(물론 flash 패키지나 mx 패키지에 있는 이벤트 클래스를 사용해도 되지만.) 그래서 클래스 하나 하나를 만들때마다 충분히 고민하고 설계를 해야 효율적인 코딩을 할 수 있을 것이다.
2009/09/05 12:52 2009/09/05 12:52