Creative Wrong Answer

Flash / Flex 에서 사용되는 이벤트는 종류도 많고 거의 필요한 모든 이벤트가 있다고 해도 과언이 아니다.
그런데 왜 커스텀 이벤트가 필요할까.

기본이벤트에서 제공하는 target 속성으로 이벤트를 발생시킨 객체의 정보를 가져올 수 있다고 하지만.. 그 객체의 속성이 아니라 다른 변수를 넘겨야 할 필요가 있다거나 하는 경우..
기본 이벤트가 발생했을때 그 이벤트를 멈추고 새로운 이벤트로 발생시켜서 상위의 객체로 통보하고 싶다거나 하는 경우등.
커스텀 이벤트를 사용하게 되면 이것 저것 편리한 작업들을 많이 할 수 있게 된다.

이번 포스트에서는 커스텀 이벤트를 만드는 방법에 대해서 살펴보자.

커스텀 이벤트는 Event 를 확장해서 만들어진다.

package csEvent
{
	import flash.events.Event;

	public class CustomEvent extends Event
	{
		public static var SEND_DATA:String = "sendData";
		public var csData:*;
		
		public function CustomEvent(type:String, csData:*, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
			this.csData = csData;
		}
		
		override public function clone():Event
		{
			return new CustomEvent(type, csData, bubbles, cancelable);
		}
		
		override public function toString():String
		{
			var str:String = "[CustomEvent type="+type+" bubbles="+bubbles+" cancelable="+cancelable
							+" eventPhase="+eventPhase+" csData 변수를 사용해서 넘어온 데이터를 사용하세요]";
			return str;
		}
	}
}


CustomEvent.SEND_DATA 형식으로 사용할 수 있도록 하기 위해서 static 으로 변수를 설정해준다.
이 이름은 편한대로 지어도 된다. string 값이 기존의 이벤트와 겹치지만 않으면 된다.

csData 변수로 이벤트에 데이터를 실어서 보내게 되는데. 데이터 전송 전용 이벤트 이기 때문에 받는 타입은 그냥 와일드카드(*)로 받도록 했다.
특별히 id 같은 string 값만을 전송한다면 타입을 지정해주는 것이 좋다.

csData 같은 경우 위의 예제에서는 public 으로 선언되어있지만 캡슐화를 위해서는 private 으로 선언하고 getter 를 구현해서 readonly로 사용하는 것이 정확하다.
외부에서 직접 변수를 엑세스 하는 경우에 특별한 경우가 아니면 public 보다는 private 으로 선언하고 getter/setter 로 엑세스 할수 있는 통로를 만드는 습관을 기르는 것이 좋다. (하지만.. 이게 귀차니즘 때문에 쉽지가 않다.. ㅠㅠ)

clone() 함수와 toString() 함수는 옵션이다. 둘다 오버라이드 해서 구현하지 않더라도 정상적으로 이벤트가 전파된다. 하지만 역시 구현해주는 것이 좋다.

clone()을 오버라이드 해서 구현 해야 하는 이유를 아래처럼 설명하고 있다.
Why do you need to override clone? Well, the clone method creates a copy of your event (or object - whatever object has the clone event; this isn't limited to Event objects). The default clone method inherited by the Event class or whatever class your custom class extends, will return an event object of the type of that class, not your custom event subclass. In the situations where a clone is needed, it is needed to be of the same type of your class, not the class it extends.

-Flex PMD event Rule


toString() 같은 경우는 나중을 위해서나 다른 사람과의 협업을 위해서라도 해당 이벤트가 하는 일이나 넘어오는 변수의 타입등이 지정되어있다면 그 데이터를 보여주도록 만들어놓는 편이 좋다.
커스텀 컴포넌트를 만들때에는 항상 toString 을 구현해놓는 습관을 들이는 것이 좋을것이다.

dispatchEvent(new CustomEvent(CustomEvent.SEND_DATA, "http://rinn.kr", true));


이벤트를 디스패치 할때 두번째 옵션인 csData 파라미터에 원하는 데이터를 실어서 보내면 된다.
이벤트 리스너에서 CustomEvent 가 캐치 되면 아래의 함수에서 처럼 데이터를 확인 할수 있다.

import csEvent.CustomEvent;

private function init():void
{
	this.addEventListener(CustomEvent.SEND_DATA, csEventHandler);
}

private function csEventHandler(e:CustomEvent):void
{
	trace(e.toString());
	trace(e.csData);
}

// trace ----------------
// [CustomEvent type=sendData bubbles=true cancelable=false eventPhase=3 csData 변수를 사용해서 넘어온 데이터를 사용하세요]
// http://rinn.kr


e.csData 형식으로 넘어온 데이터를 확인 할수 있다. 어떤 형식도 가능하고 여러개 보내는 것도 가능하다.

커스텀 이벤트를 만들어서 팝업으로 뜬 오브젝트에 데이터를 넘겨주고 닫힐때 변경된 내용을 메인 어플리케이션쪽으로 보내주고 하는 등의 작업이 가능하다.
이렇게 이벤트를 만들어서 사용하게 되면 컴포넌트를 만들어서 사용할때에 parent.publicFunction 형식으로 직접 접속해서 뭔가 하지 않아도 되기 때문에 독립적인 컴포넌트를 만들 수 있다.

보통은 컴포넌트를 만들때 해당 컴포넌트의 이벤트를 정리해서 한꺼번에 만드는 경우가 많다.

as3 에서 이벤트가 중요한 개념이듯이 이벤트를 본격적으로 사용하기 위해서는 커스텀 이벤트가 중요한 개념이라 하겠다.
이벤트를 잘 사용해서 프로젝트를 효율적으로 끝내보자!!
저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +4

  • clone() 메소드의 경우, 이벤트 버블링이나, 타 컴포넌트에서 받은 이벤트를 릴레이 해줄 때 꼭 필요했던 것으로 기억하고 있어요.
    오래되서 자세히는 기억이 안 나지만, clone()을 제대로 구현하지 않으면 에러가 나는 상황이 있었던 것 같네요. 가물가물..

    • 처음에는 clone()을 구현을 해서 사용했었는데.
      완료되지 않은 작업중에 clone() 없이 그냥 테스트 하다가.. 동작에 이상이 없어서 그냥 놔둬버린 케이스가 있었지요.

      일단 수정은 해놔야 할것 같군요.. 아 습관이 중요한듯.. 귀차니즘을 이길수 있는건 좋은 습관뿐인거같아요..
      귀찮다 생각할 겨를도 없이 코딩이 자동으로 되버리는.. 그런 습관을 기르고 싶군요 ㅎㅎ

  • 뭐가 더 좋을 지는 저도 잘 모르겠어요.
    깨진 창문은 물론 피하는 것이 맞지만, 모든 창문을 항상 반짝이게 닦아놓는 것은, 때로는 도움이되고, 때로는 그렇지 않기도 하니까요. :')
    늘 상황에 맞춰서 그때 그때.. ㅎㅎ 다만, 미리 알아두는 것은 도움이 되겠지요. ㅎㅎ

    • 심오하군요..
      깨진 창문 이론.. 그건가요 ㅎㅎ
      사용하지 않더라도 일단은 알아두는것이 좋다는거에는 백프로 동감이에요~

Flex Event 기본 설명

Flex2010.02.05 19:46
나는 디자이너 출신이기 때문에 프로그래밍에 대한 심오한 지식이 없다.
대학에서 윈도우 프로그래밍이나 자바, C 관련 언어에 대한 강의를 들었지만 디자인에 더 관심이 많았기 때문에 별로 주의깊에 듣지 않았었고... 그걸 지금 와서 엄청 후회하는 중이다.

Flash2 때 처음 Flash를 접하게 되었고 3 버전부터 사용을 하다가.. 4,5 를 넘어오면서 actionscript가 timeline 보다 점점 벽으로 다가왔지만.. 그때까지도 할만 했다.
하지만 2.0이 나오면서 부터 기존에 onClick 형식으로 타임라인에 스크립트를 입력하던 방식에 한계가 오고 내입장에서는 듣도보도 못한 addEventListener 라는놈이 나오기 시작하면서.. "아.. 개발자의 영역으로 가버리는구나" 생각하고 디자인에만 매진하게 되었다.

역시 이것도 지금은 후회하는 중이다.. 지금 개발자로 전향할줄 알았다면 그때 좀 힘들어도 포기하지 않았을텐데 -ㅅ-
지금도 이벤트가 정확하게 동작하기 위해서 trace로 확인하는 테스트 과정을 거쳐야 원하는 대로 결과가 나오는등.. 언제나 조금 복잡한것은 삽질의 연속이다.

역시 이 글도 [2010/02/02 - [as3] - Flex, Flash 가비지 컬랙션 방법과 메모리 관리] 요넘 처럼 정리 차원에서 쓰게 되었고. 글을 쓰면서 사용하게될 예제들도 사용하기위해서 테스트 하던 소스들이 될것이다.


AS3 는 이벤트를 기반으로 동작하도록 되어있어서 모든 행위들이 이벤트를 발생하게 된다.
이벤트를 이해 하고 있어야 복잡한 동작들을 원하는 시점에서 원하는 방식으로 정확하게 동작할 수 있도록 구현이 가능하다.

이벤트를 사용하면서 얻는 이점

이벤트를 사용하면 특정 개체에 종속적이지 않은 프로그램을 만들 수 있다.
이전의 프로그래밍은 특정 행위가 발생했을때 콜백함수를 호출하는 방식이었다.
이런 방식은 해당 컴포넌트가 상위의 컴포넌트에 종속되는 결과를 가져온다. 상위 컴포넌트에 정의되어있는 함수를 호출하게 되기 때문에 다른 컴포넌트에서 사용할수가 없게 되고 사용하기 위해서는 같은 이름의 콜백함수를 등록해야 한다.
이런 방식은 각 컴포넌트들간의 결합도를 강하게 만든다.

이벤트를 사용하게 되면.. 하위컴포넌트가 발생시킨 이벤트를 상위 컴포넌트가 받을수 있고 하위 컴포넌트 입장에서는 이벤트만 발생하면 땡이다.. 상위에서 받아서 쓰던지 말던지 신경쓰지 않아도 되는것이다.
누가 받는지.. 어디서 받아서 무슨일을 하는지 전혀 신경쓰지 않아도 되기 때문에 여러곳에서 해당이벤트를 받아서 사용할수도 있고 다른 컴포넌트에 추가 되더라도 어차피 이벤트만 발생시키는 것이기 때문에 사용하는데 전혀 무리가 없다.

공용으로 사용할 수 있는 독립적인 컴포넌트를 만들 수 있게 되는것이다.

이벤트는 비동기적이다.
따라서 어떤 작업을 실행시켰을때 화면이 멈추지 않고 다른 작업을 진행할 수 있다.
이벤트가 완료되고 실행되는 핸들러에서 완료되는 시점에 해야 할일을 정의 해놓으면 되는 것이다.
이 방법은 반대로 불편하게 느껴지기도 하는데.. 순차적으로 처리 해야 하는 일이나.. 모든것보다 우선해서 뭔가를 처리 해야 할때 기존의 방식대로 처리 하다가 에러를 만나게 되는 경우가 많다.
하지만 제대로 사용한다면 자유로운 세계를 만나게 될 것이다.

AS3 에서 이벤트는 EventDispatcher 라는놈이 관리 하게 되고 이벤트 디스패쳐를 상속해서 만들어진 컴포넌트 들은 이벤트를 발생시키거나 받을 수 있다.
플렉스의 기본이 되는 UIComponent 도 이벤트 디스패처를 상속하고 있기 때문에 모든 컴포넌트들이 이벤트를 주고받을 수 있는것이다.

개요는 이정도로 마무리 지어도 될것 같고..

이후에 포스트들에서는



등에 대해서 알아 볼것이다.

저작자 표시 비영리 동일 조건 변경 허락
신고

Comment 0