ActionScript 3.0은 객체지향언어이다. 객체 지향의 일반적인 특징은 캡슐화, 상속, 다형성일 것이다.

 

Flex/AIR가 MXML이라는 특수한 XML형태의 언어를 사용하는 것은 순수한 ActionScript 3.0 프로그래밍보다 더 쉽게 개발 하기 위한 일종의 도구인 것이다. Flex 컴파일러는 MXML을 ActionScript 3.0로 변환한뒤 컴파일한다. 컴파일 옵션으로 -keep-generated-actionscript를 입력하면 generated폴더에 MXML이 ActionScript 3.0으로 변환된 것을 확인할 수 있다. 결국 필연적으로 Flex 또는 AIR를 제대로 개발하려면 ActionScript 3.0을 이해해야한다.

 

ActionScript 3.0는 객체지향언어이므로 객체지향을 얼마나 잘 이해하고 활용하느냐에 따라 프로그램의 설계에 큰 영향을 미치게 된다. 덧붙여 Flex와 AIR의 Data Binding 이라는 데이터-UI의 연동을 아주 쉽게 해주는 기능이 있어서 객체지향으로만은 느끼지 못하는 또 다른 새로운 감동을 준다.

 

결론적으로 Flex,AIR로 개발할 때는 ActionScript 3.0의 객체지향 방식을 잘 활용하고 Flex,AIR만의 데이터 바인딩과 같은 유용한 점을 잘 활용하여 개발해야 개발의 능률이 오르고 훨씬 보기 좋은 코드와 UI을 만들어 낼 수 있다.

 

여기서는 두가지 개념을 가지고 이야기 한다. 객체지향 개념중 하나인 다형성, 그리고 Data Binding(데이터 바인딩)이다.

 

다형성이라는 것은 여러형태로 쓸 수 있다는 말인데 이를 지원하는 대표적인 것인 바로 인터페이스(Interface)이다. 인터페이스는 매우 유용한 도구로 이것을 잘 사용하느냐 안하느냐에 따라 설계가 엉터리가 되느냐 안되느냐를 결정할 정도로 중요한 개념이다.

 

인터페이스가 다형성을 지원한다는 것은 인터페이스 하나를 만들어 그 인터페이스를 구현한 클래스를 여러개 접근이 가능해진다는데 있다. 가령, IShape라는 인터페이스가 있다고 하자. IShape는 Rectangle, Triangle, Circle등의 클래스로 구현되어 질 수 있다. 이들 클래스는 IShape를 사용하는 MyCanvas에 사용할 수 있는데 MyCanvas는 IShape덕분에 Rectangle, Triangle, Circle에 대해서 알지 못해도 IShape만 가지고 사용이 가능한 것이다.

 

다형성은 인터페이스로부터 출발해서 추상클래스, 구현클래스로 확장하지만 ActionScript 3.0에서는 Java와 같이 추상클래스 개념이 없다. 그러므로 필요하다면 구현클래스를 가지고 추상클래스처럼 사용하는 경우도 있게 된다. 만약 ActionScript 3.0에도 추상클래스와 private 생성자를 지원해준다면 프로그램 디자인 하는데 꽤 유용해질 것이라 생각이 든다.

 

또 한가지 논할 것은 데이터 바인딩(Data Binding)이다. 데이터 바인딩은 말그대로 데이터를 묶어준다는 의미이다. 무엇과 묶는 것인가? 보통 데이터와 그 데이터 결과를 출력하는 화면(View)과 묶어주는 것이다. 그래서 데이터가 변하면 자동적으로 화면이 능동적으로 변하도록 하는 것이다. 만약 데이터 바인딩 기술을 사용하지 않는다면 데이터 변하는 시점을 따로 알아야 하고 그 시점에 화면(View)에 출력하는 코드가 따로 작성되어야 한다. Flex는 [Bindable] 메타데이터나 <mx:Binding>과 같은 훌륭한 클래스들을 만들어놔서 데이터 바인딩을 쉽고 간편하게 할 수 있도록 지원해주고 있다. 만약 ActionScript 3.0으로만 엔터프라이즈급 프로젝트를 수행해야 하는데 데이터 바인딩 기술이 없다면 참 답답할 것이다. 이 말은 Flex/AIR 설계 및 개발시에 반드시 데이터 바인딩을 고려해야한다는 것을 의미한다.

 

이렇게 ActionScript 3.0의 객체지향의 다형성과 Flex/AIR의 데이터 바인딩 기술은 매우 유용하고 필수적으로 이해하고 응용할 줄 알아야 한다.

 

그럼 결국 오늘 언급하고자 하는게 뭐냐?! ㅋㅋ

 

그건 인터페이스에서 데이터 바인딩이다.


아래 ISimpeModel 이름을 가진 인터페이스와 그것을 구현한 SimpeModle 클래스가 있다.

//ISimpleModle.as
package
{
	public interface ISimpleModel 
	{
		function get name():String;
		function set name(value:String):void;
		function get age():int;
		function set age(value:int):void;
	}
}
//SimpleModel.as
package 
{
	public class SimpleModel implements ISimpleModel 
	{
		private var _name:String = "";
		private var _age:int = 0;

		public function SimpleModel() 
		{
		}

		public function get name():String 
		{ 
			return _name; 
		}
		public function set name(value:String):void 
		{
	  		_name = value;
		}

		public function get age():int
		{
			return _age;
		}

		public function set age(value:int):void
		{
			_age = value;
		}		
	}
}

 


위 클래스를 사용하는 Flex Main Application은 아래와 같다.
<!—- Main Application -->
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()">
	<mx:Script>
		<![CDATA[
			[Bindable]
			private var model:ISimpleModel;
			
			private function init():void
			{
				model = new SimpleModel();
				model.name = "지돌스타";
				model.age = 30;
			}
		]]>
	</mx:Script>
	<mx:TextInput text="{model.name}"/>
	<mx:TextInput text="{model.age}"/>
</mx:Application>

 

Case 1.

위 코드를 바로 실행하면 아래와 같은 경고 문구가 나올 것이다.

Data binding will not be able to detect assignments to "age".

Data binding will not be able to detect assignments to "name".

Flex 컴파일러는 데이터 바인딩이 될 수 없는 곳에 데이터 바인딩 처럼 사용했다고 해서 경고를 띄울 것이다. 프로그램은 정상적으로 실행되긴 하지만 TextInput에 “지돌스타”와 “30”이 표시가 되어지지 않는다. 즉 SimpeModel의 속성인 name, age자체가 데이터 바인딩 처리가 안되었기 때문에 이들 데이터가 바뀌어도 TextInput에 적용되지 않는 것이다.

 

Case 2.

보니깐 우리는 model로 ISimpleModel 인터페이스를 사용했다. 그러므로 데이터 바인딩은 여기서 처리해야할 듯 싶다. 그래서 ISimpleModel에 선언된 getter에 함수 위에 [Bindable] Metadata tag를 붙여본다.

 

그러나 아래와 같은 에러가 뜬다. 경고도 아니다.

[Bindable] not allowed on global or package-level functions.

Case 3.

조금 어이없어 보인다. 그래서 ISimpleModel에 붙은 [Bindable] Metadata tag를 떼고 SimpleModel.as의 getter 함수에 같은 방법으로 [Bindable]을 붙여준다. 첫번째와 동일하게 아래와 같이 데이터 바인딩할 수 없다고 나온다.

Data binding will not be able to detect assignments to "age".

Data binding will not be able to detect assignments to "name".

Case 4.

결국 인터페이스인 ISimpleModel에서 해결해야한다.

이번에는 SimpleModel에 붙인 [Metadata]는 그대로 두고 ISimpleModel의 클래스 위에 [Metadata]를 붙여본다. 경고문구는 없어지고 프로그램은 정상적으로 “지돌스타”, “30”을 TextInput에 출력해준다. 음 됐다… ㅡㅡ;

 

Case 5.

이번에는 ISimpleModel의 [Bindable]을 그대로 둔채, SimpleModel의 getter위에 붙은 [Bindable]을 떼어보자.  에러,경고 모두 없지만 실행해보면 “지돌스타”, “30”을 TextInput에 출력하지 못한다. 컴파일러가 여기까지 미치지 못하는구나. ^^;;;

 

Case 6.

지금까지 결과를 놓고 보자면 SimpleModel의 클래스 이름 위나 getter 함수에 Bindable을 붙여주고 ISimpleModel에는 Classs 이름 위에만 붙여야 하는 것이다.

희한하다… 왜 인터페이스의 getter 함수 위에는 붙일 수 없는 것일까?

이번에는 ISimpleModel의 클래스 이름위에 [Bindable]은 떼어내고 getter에 [Bindable(event=”propertyChange”)]을 붙여보자.

그리고 컴파일하고 실행해보자!

잘된다… ㅡㅡ;

 

정리

 

정리하자면, 인터페이스 바인딩을 위해서 구현체인 SimpleModel의 클래스 이름 위 또는 getter 함수 위에 [Bindable]을 붙인다. 그리고 그의 인터페이스인 ISimpleModel의 클래스 이름 위에는 [Bindable] 또는 getter 함수위에는 [Bindable(event="propertyChange")]를 붙이면 데이터 바인딩이 잘되는 것이다. ^^;

 

사실 [Bindable(event="propertyChange")]은 [Bindable]과 동일한 표현이다. event="propertyChange"를 생략한 [Bindable]만 있어도 Flex는 propertyChange이벤트에 대응하는 데이터 바인딩이 된다. 하지만 Flex 컴파일러 버그인가? 인터페이스의 getter위에는 [Bindable]이 붙일 수 없다. 버그인지 아닌지 모르겠지만 해결방법은 알았으니 됐다. Flex 4부터는 이 문제를 해결하겠지?

 

좋은 글

+ Recent posts