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() 없이 그냥 테스트 하다가.. 동작에 이상이 없어서 그냥 놔둬버린 케이스가 있었지요.

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

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

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