scaleform.minarto.com

애드온 ui 에 대한 고찰 - 1 본문

Scaleform Etc

애드온 ui 에 대한 고찰 - 1

미나토 2013. 1. 14. 19:07



2013/01/02 - [Scaleform Etc] - 스케일폼을 위한 작은 변명


2013/01/14 - [Scaleform Etc] - 애드온 ui 에 대한 고찰 - 0




1. 애드온 ui 를 위한 준비



앞선 글에서 언급한 적이 있지만 다시 한번 필요한 요소를 말해보겠습니다



1. 클라이언트와 스케일폼 간의 격리되어 있는 구조


2. 클라이언트와 스케일폼 간의 간단한 통신 인터페이스


3. 애드온 개발자들을 위한 라이브러리 및 샘플 배포



첫번째 언급한 클라이언트와 스케일폼과의 격리된 구조는 단순히 둘 사이의 격리를 말하는 것만은 아닙니다. 스케일폼의 각 UI 위젯마다의 격리된 것도 필요합니다



첫번째와 두번째 요소를 해결하기 위한 방법으로 제가 바인딩 클래스를 언급했었습니다



기존의 CLIK 데모는 보통 다음과 같은 것을 보여주고 있습니다.


1. 위젯의 로드

2. 로드된 해당 위젯 객체 포인터를 클라이언트에게 알림

3. 해당 포인터를 이용하여 인보크 함수나 다이렉트 액세스 사용



스케일폼에서 제공한 데모이다 보니 많이들 따라할 텐데, 사실 이 방식에는 다음과 같은 문제가 있습니다


1. 인보크 함수가 미리 약속되어 있어야 하며, 바뀌면 오류 발생

2. 다이렉트 액세스를 사용할 객체명을 알고 있어야 하며, 바뀌면 오류 발생

3. 로드하여 포인터를 날리기 전에 인보크 함수나 다이렉트 액세스를 하면 오류 발생



프로그램은 한번 개발하고 나면 끝나는 것이 아닙니다. 지인의 말을 빌리자면 프로그램은 살아있습니다.


개발을 하다보면 함수명도 자주 빠뀌게 되고, 인자 또한 바뀌게 되며 객체의 네이밍도 바뀌는 것이 현실입니다. 현재 서비스를 하고 있는 중이라도 말이죠...


그때마다 오류를 뿜어내는 방식으로 개발하는 것은 개발자 스스로 이 방법론에 의문을 가져야 합니다




게다가 위젯을 로드하는 것은 스케일폼인데 로드 완료는 다시 클라이언트가 알아야 한다니... 무언가 비효율 적이지 않나요?




2. 바인딩을 사용하자



예를 들어 캐릭터의 체력이 바뀌어야 한다고 해보겠습니다.


MMORPG 의 보편적인 UI를 생각할 때, 화면 좌측 상단의 캐릭터의 초상화와 체력바와 마나바가 있는 위젯을 MCPortrait 라고 해보죠


그런데 여기만이 아닙니다. 캐릭터의 장비나 스탯이 나와있는 정보창도 있죠...(MCInfo 라고 하겠습니다) 여기도 체력수치가 있으니 바꿔줘야 합니다.



기존의 방법으로는


1. "MCPortrait.swf" 파일 로드


2. "MCInfo.swf" 파일 로드


3. MCPortrait 파일이 로드된 객체를 enableInitCallback 옵션으로 클라이언트에게 객체 포인터를 알리거나, 클라이언트가 root 에서부터 "root.MCPortrait" 이런 식으로 찾아감 - 클라이언트와의 통신 발생 (각 위젯마다 한번씩)


4. MCInfo 파일이 로드된 객체를 enableInitCallback 옵션으로 클라이언트에게 객체 포인터를 알리거나, 클라이언트가 root 에서부터 "root.MCPortrait" 이런 식으로 찾아감 - 클라이언트와의 통신 발생 (각 위젯마다 한번씩)


5. 클라이언트가 위의 포인터에서 MCPortrait 객체의 체력 수치를 바꿔주는 setHP($n:Number) 인보크 함수 실행 - 클라이언트와의 통신 발생


6. 클라이언트가 위의 포인터에서 MCInfo 객체의 체력 수치를 바꿔주는 setHP($n:Number) 인보크 함수 실행 - 클라이언트와의 통신 발생



위에서 보다시피 캐릭터의 체력이라는 한가지의 수치가 바뀌는데 최소 네번의 통신이 필요하게 됩니다.



잦은 통신만이 문제가 아닙니다. 모든 것은 동기화가 되어야 진행이 됩니다. 1, 2, 3, 4... 이 순서가 하나라도 바뀐다면 게임은 null 오류를 뿜어내게 되는 것이죠.



위의 방법에서 만약 체력 수치가 반영되지 않는다면, 다음과 같은 것들을 테스트 해봐야 합니다.


1. 클라이언트에게 MCPortrait 객체 포인터를 잘 넘겨줬는지

2. 클라이언트는 MCInfo 객체 포인터를 잘 받았는지

3. setHP 인보크 함수가 MCPortrait 위젯 안에 존재하는지

4. setHP 인보크 함수가 MCInfo 위젯 안에 존재하는지

5. 클라이언트가 MCPortrait.setHP 라는 인보크 함수에 제대로된 인자를 던져줬는지

6. 클라이언트가 MCInfo.setHP 라는 인보크 함수에 제대로된 인자를 던져줬는지

7. MCPortrait.setHP 라는 함수의 정상 동작 여부

8. MCInfo.setHP 라는 함수의 정상 동작 여부



수치 하나 바꾸는데 이 많은 과정이 필요하게 되는겁니다.



이는 바인딩을 사용하면 다음과 같이 바뀌게 됩니다.


as2 : http://code.google.com/p/minarto-scaleform4/source/browse/trunk/as2/src/com/minarto/data/Binding.as

as3 : http://code.google.com/p/minarto-scaleform4/source/browse/trunk/as3/src/com/minarto/data/Binding.as



각 위젯의 confitUI 부분에 다음과 같이 추가


Binding.addBind("mc.hp", setHP);



그럼 다음과 같은 순서에 따라 체력 수치를 반영하게 됩니다


1. Binding.init 함수를 통해 클라이언트에게 Binding 객체포인터를 알려준다 클라이언트와의 통신 발생(전체 딱 한번만 실행)


2. 클라이언트가 Binding.setValue("mc.hp, 134) 함수를 통해 체력 수치 설정 클라이언트와의 통신 발생



이와 같이 최소 두번의 통신으로 모든게 끝납니다.

(여기서 제 자랑을 하자면...스케일폼에서 제공하는 DataBinding 조차 바인딩된 횟수만큼의 통신 횟수가 필요합니다 ㅡㅡb )


그리고 앞선 방식과 달리 로드되고 초기화되는 순서를 지킬 필요가 전혀 없습니다.



바인딩 방식에서는 바인딩 객체가 내부적으로 해당하는 캐시값을 가지고 있고, 그 캐시값을 활용하기에 특정 위젯이 로드되고 안되고는 전혀 영향을 주지 않습니다.

클라이언트는 바인딩 객체하고만 통신을 하게 되는거죠.


바인딩 방식에서의 테스트는 어떤 것이 필요할까요.


1. MCPortrait 위젯의 Binding.addBind("mc.hp", setHP) 키 값이 맞는지

2. MCInfo 위젯의 Binding.addBind("mc.hp", setHP) 키 값이 맞는지

3. 클라이언트가 Binding.setValue("mc.hp, 134) 제대로된 인자를 던져줬는지

4. MCPortrait.setHP 라는 함수의 정상 동작 여부

5. MCInfo.setHP 라는 함수의 정상 동작 여부 



클라이언트는 setValue 함수 하나만 사용하게 되니, 특정 인보크 함수를 사용하지 않습니다. 서로 API 를 테스트할 것 자체가 없어지는 셈입니다.

서로 맞추어봐야 하는 것은 "mc.hp" 이런 키값 뿐이죠.



오류가 안나게 조심 조심 프로그래밍 하는 것이 아니라, 아예 테스트할 것 자체가 없어지는 방식이란 겁니다.






3. 또 다른 장점



UI의 로드와 초기화를 클라이언트가 알 필요가 없다는 것은 단순히 null 오류를 피하는 것만이 아닙니다.



1. 서로간의 객체를 참조하지 않으니, 로드 / 언로드가 쉬워(아예 상관이 없으므로) 메모리 해제가 자유로워진다.


2. 위젯의 로드를 기다리지 않고 처음에 캐릭터의 정보를 모두 설정할 수 있으니, 초기 실행 속도가 빨라진다


3. 테스트 과정이 대폭 줄게 되어 개발이 빨라진다


4. 다양하게 커스터마이징 된 UI 개발이 쉬워진다



다음 글에서는 4번에 언급한 커스터마이징 UI 에 대해서 말해보도록 하죠