나는 Flex나 기타 무거운 프레임워크를 사용하지 않고 ActionScript 3.0 API 수준으로 개발을 한지 이제 겨우 1년이 넘은 것 같다. Flex로 개발할 것과 ActionScript로 개발해야할 것에 대한 구분은 항상 명확하다. 자주 새로 빠르게 로드되어야 하는 애플리케이션 제작은 무조건 ActionScript 기반으로 제작한다. 하지만 가끔 사용하며 Flex 컴포넌트를 잘 활용해야하는 애플리케이션이라면 Flex로 개발한다.

ActionScript 3.0기반으로 개발하고 완성하고 나서는 뭔가 꼬여있는듯한 느낌, 유지보수가 안될 것 같은 느낌을 항상 받아왔다. 또한 깨끗하지 못한 객체관리가 항상 걸렸고 너무 길어져서 지저분해지는 코드 또한 마음에 들지 않았다. 그리고 클래스간 역할 분담이 분명하지 않는다는 느낌을 받았다. 동작은 뭔가 석연치 않은 느낌을 계속 받았다. 어떤 개발의 스킬이나 전문적인 지식에 대해서 학습을 해보지 못해봤던 나로써는 설계때부터 항상 고민거리가 생긴다.

나는 근 한달동안 블로그 활동 및 외부 활동을 거의 안하면서 개발에만 매진하면서 지냈다. 바로 스타플의 타임라인 개발때문이였다. 타임라인이 궁금하시다면 아래 링크로 접속해보면 된다.

스타플 타임라인 업그레이드 및 앨범 기능 추가 소식


개발하면서 위에서 제시한 문제점을 어느정도 해소시킬 수 있는 몇가지 개념들이 있었다. 여기에 간단하게 적어두도록 하겠다.


1. 객체의 재사용 Object Pool
Flash 개발하면서 항상 걸리는 문제중에 하나가 메모리이다. Flash Player가 정확한 가비지 컬렉터(GC)를 가진다고 하지만 지금도 그다지 명확한 신뢰를 받지 못하고 있다. 하지만 분명 GC는 동작한다. 중요한 것은 Flash Player의 GC를 너무 맹신하지는 말자는 것이다.

new를 통한 객체 생성은 항상 지양하는 것이 가장 중요한 메모리 관리의 첫걸음이다. MyClass.Factory()와 같은 static 클래스를 통해 내부적으로 new를 사용하고 각종 처리는 factory가 담당하는 것이 각종 초기화 및 객체관리에 도움이 된다.

더불어 매우 자주 사용하다가 없어지는 객체를 계속 new를 통해 생성하고 GC객체화 시키는 것은 메모리 관리에 도움이 안될뿐 더러 퍼포먼스에도 문제가 있다. 실제로 비교적 큰 디스플레이 객체인 Sprite를 new를 자주하면 전체적인 퍼포먼스에 좋지 않은 영향을 줄 수 있다. 이런 경우에 퍼포먼스와 메모리를 동시에 해결할 수 있는 방법은 바로 Object Pool을 이용하는 것이다.

Using object pools : http://lab.polygonal.de/2008/06/18/using-object-pools/ 

위의 글은 Object Pool의 강력함을 시각적으로 말해주고 있다. 특히나 Object나 Point와 같은 작은 클래스가 아닌 Sprite와 같은 큰 클래스의 경우 new 연산자 사용보다 Object Pool의 사용은 큰 이점을 주고 있다는 것을 알 수 있다.

사용한 객체를 그냥 버리지 말자. 잘 보관했다가 다시 사용할 수 있게 만들고 사용하자... 특히나 시각객체(Sprite기반)이 자주 생성,소멸해야하는 경우라면 강력히 Object Pool을 사용하라고 주장한다.


2. Linked List 와 Dictionary
컴퓨터를 전공한 사람이라면(본인은 아님) 자료구조를 배우면서 Linked List는 반드시 이해해야할 필수 항목이다. 나는 이번 타임라인을 제작하면서 Linked List를 활용해 중간중간에 얻어진 시간순서 데이터를 엮어주는데 요긴하게 사용했다. 일반적인 Array형태의 데이터는 중간에 데이터 삽입하는 것은 효율적이지 못하지만 Linked List는 연결하고자 하는 지점의 연결부의를 끊고 그 중간에 삽입하여 앞뒤로 연결만 하면 되기 때문에 훨씬 효율적이다.

Data Structures example : linked lists http://lab.polygonal.de/2007/08/13/data-structures-example-linked-lists/

또한 특정 key의 자료검색에 Dictionary를 사용했다. Dictionary를 직접 사용하는 것보다는 한번 감싸서 클래스를 만들어 추가/삭제/편집/데이터접근등을 처리하기 쉽게 하면 정말 요긴해진다. 나는 Linked List와 더불어 Dictionary를 통해 key값을 통한 데이터 검색에 사용했다. 이것을 이용하면 아무래도 index 순으로 찾는 것보다 훨씬 빠른 검색을 할 수 있다.


3. MVC
개발자라면 Model-View-Controller에 대한 개념을 잘 알고 있을 것이다. 이러한 개념은 Flex 수준의 개발이라면 Flex가 어느정도 지원해주는 편이기 때문에 그나마 괜찮지만 ActionScript 수준에서 개발하려면 이 점을 고려하는 것이 좋다. 기본적으로 Model의 데이터 변화는 View에 영향을 미치고 View의 변화는 Controller에 영향을 준다. Controller는 View와 Model을 통제하며 서로의 상호작용에 조절한다. 그리고 View가 Model을 절대 변경하지 않는다. 이런 약속으로 MVC 구조를 설계하면 View와 View관계도 명확해지고 아직 로드되지 않는 View(모듈)에게도 도움이 된다.

타임라인의 경우 최초 구동될때 달력과 보기설정은 아에 모듈로 만들어 버린다. 그리고 보여달라고 요청할때만 모듈을 로드해 시각화시킨다. 이때 모듈은 부모 애플리케이션에 Model에 있는 데이터를 사용한다. 이 데이터는 View(모듈)의 존재를 모르기 때문에 어떤 상황이 되든 사용할 수 있다. 또 달력과 보기설정은 같이 보여질 수 없다. 각각 show()와 hide()함수가 있는데 달력이 show하면 보기설정은 hide가 호출되어야하는 식이다. 그런데 View에서 이런것을 컨트롤해버리면 View간에 상호 간섭이 생긴다. 이런 경우 Controller가 중재하도록 하면 훨씬 쉽게 이런 문제를 해결할 수 있다.


4. 인자객체를 이용하자.
TextField를 이용해서 객체를 생성해본적이 있을 것이다. 1개 Text를 출력하기 위해서 얼마나 많은 설정을 해야하고 또한 수십줄이 넘는 코딩을 해야하는가? 타임라인의 달력 기능에는 한개 한개가 다 TextField 객체들이다. 물론 반복적으로 생성해주면 되지만 이 마저도 마우스오버,클릭,선택등과 같은 동작에 대응해야하기 때문에 단 몇줄 코드로는 이런 기능을 구현하기가 어렵다.

나는 이러한 문제를 인자객체를 이용해 해결했다.
이에 대해서는 더이상 말이 필요없다. 다음 글을 보자.
인자객체 : http://diebuster.com/flash/?s=인자객체


5. Helper 수준의 프레임워크
이번 타임라인을 제작하면서 가장 도움이 되었다고 생각하는 사람은 hika님이다. 물론 같은 회사도 아니고 자주 만나본 것도 아니지만 hika님의 블로그에 정리해놓은 내용은 나에게 큰 자극제가 되었다. 그중에 hika님이 만들어놓은 ActionScript 3.0 프레임워크는 나에게 큰 도움이 되었다. 이는 흔히 말하는 무거운 프레임워크 아니다. 정확히 말하자면 Helper 수준이다. Helper 수준이라는 것은 Flex처럼 Button, Label, DataGrid와 같은 컴포넌트를 가지는 것이 아니라 Sprite, Shape, TextField, Loader등의 기본 ActionScript 3.0 기반의 클래스를 더욱 효율적으로 사용하게 하기 위한 것이라는 것이다.

나는 이 프레임워크를 이용해서 시각객체관리, 레이어관리, Embed자원관리, 원격자원관리, 이벤트관리, 데이터관리등 전반적으로 큰 도움이 되었다. 나는 hika님이 만들어놓은 프레임워크를 분석하면서 큰 구조의 변경없이 나만의 프레임워크로 변경하고 이번 타임라인 개발에 적극적으로 사용했다. 만약 프레임워크의 도움이 아니였다면 역시나 어려운 코딩을 감당해야할지도 모르겠다.


6. EnterFrame 수준의 동작 관리
MouseMove 이벤트를 시각객체를 이동하는데 사용하지 말자. 대신 EnterFrame 이벤트시에 stage.mouseX, stage.mouseY등을 사용해서 시각객체를 이동시키자. 실제로 MouseMove 이벤트는 그 동작이 매우 느리다. 그러나 EnterFrame 이벤트는 최소한 stage.frameRate에 지정된 수준에서 발생하기 때문에 느린 마우스 동작에 걱정하지 않아도 된다.

나는 타임라인을 마우스로 움직일 때 이 방법을 사용했다.

마우스 이벤트 최적화 : http://diebuster.com/flash/category/algorithm/io


7. Event 사용의 최소화
나는 Event 사용을 최소화 하려고 많이 노력했다. 정말 필요한 곳에만 사용해도 개발에 무리가 없었다. 시각객체를 통한 이벤트 전파는 생각보다 매우 느린 편이기 때문에 되도록이면 사용을 지양해야한다. 이것도 정말 필요하고 요긴하다고 판단할때만 사용하는 것이 옳다. 사용한 이벤트는 반드시 remove시키는 것이 현명하다. useWeakReference는 정말 필요할때만 사용하는 것이 좋다. 되도록이면 명시적으로 remove 시키는 것이 메모리 관리에 도움이 된다.


8. arguments.callee 활용
arguments.callee는 함수 자신을 말한다. 이는 꽤 유용한데 특히나 이벤트 리스너 함수에서 자신을 호출한 이벤트를 삭제할때 사용될 수 있다.

스스로 삭제되는 이벤트 리스너 : http://diebuster.com/flash/110


9. BitmapData.clone() 사용 지양
BitmapData 클래스는 비트맵 데이터를 저장하는 클래스이다. 이 데이터를 시각화 하기 위해 사용하는 클래스는 Bitmap이다. new Bitmap( bitmapData ) 시에 첫번째 인자가 BitmapData 객체이다.  같은 bitmapData가 자주 사용되어져야 하는 경우에 bitmapData.clone() 을 통해 계속 생성하지 말고 그냥 원본 bitmapData를 이용해 Bitmap객체를 생성해서 시각화 처리하자.

나는 타임라인에 들어가는 각종 비트맵 객체에서 bitmapData를 뽑아내어 static으로 참조해 계속 사용하도록 했고 Bitmap 또한 Object Pool 관리를 통해 최소한의 객체 생성을 유도시켜 메모리 관리를 하도록 했다.


10. mouseChildren, mouseEnabled, tabChildren과 같은 속성은 왠만하면 false로 지정하자.
이러한 속성들이 필요없는 곳에 사용되면 오히려 퍼포먼스에 악영향을 준다. 정말 필요한곳에만 사용하는 것이 좋다. 이들 속성의 의미를 파악해두는 것이 중요하다.


11. cacheAsBitmap은 이동에만 사용하자.
cacheAsBitmap은 확대,축소,회전,Alpha값 변경되는 곳에는 사용하지 않는 편이 좋다.
다음 글을 참고하자.

왜 cacheAsBitmap은 나쁜가? http://www.bytearray.org/?p=290


12. 동적언어의 장점을 충분히 살리자.
동적언어와 정적언어의 차이점은 메모리를 사용하는 차이점에서 비롯된다. 실행하는 시점에 초기에 메모리를 확보해서 사용하는 언어는 정적이다라고 하며 거대한 메모리를 먼저 잡아놓고 실행하는 시점에 메모리를 자유롭게 사용하는 것은 동적언어이다. ActionScript 는 동적언어이기 때문에 중간중간에 실행도중 클래스 정의, 함수를 추가/수정/삭제가 가능하다. 이에서 나온 개념이 클로저라는 것인데 이 개념을 잘 이용하면 코딩이 훨씬 간편하고 편리해질 경우가 많다. Flex의 대부분 코딩 방법은 정적언어처럼 되어 있는데 사실 ActionScript는 동적언어이므로 이를 더 잘 사용해서 만들어져야 한다고 생각한다. 

Closure에 대해 : http://diebuster.com/flash/82


추가사항

13. package 격리원칙
클래스 격리에 대해서는 들어봤을 것이다. 클래스내 함수에 public, private를 적절하게 잘 사용해서 외부에 노출되는 메소드는 3~4개정도로 하고 내부 동작방식을 몰라도 클래스를 쉽게 이해할 수 있도록 하는데 필요한 개념이다. 이는 사용하는 관점도 그렇고 상속받는 관점에서도 마찬가지로 적용되도록 한다.

패키지 격리라는 것은 internal을 적극활용한다는 의미이다. 아마도 많은 개발자들이 internal의 강력함을 잘 인지하지 못할것이다. 이에 대해서는 내가 굳이 설명할 필요 없다. 다음글을 보자.

플래시 애플리케이션 개발하기 : http://diebuster.com/flash/86


14. 적절한 코딩규칙
개발하는데 코딩규칙은 무엇보다 중요하다. 가령 클래스 private 변수에는 _을 붙힌다던지 const값은 대문자로 표시한다던지 그런것 말이다. ActionScript 3.0에서 코딩규칙은 더욱 상세화 되면 좋다. 왜냐하면 워낙 동적인데다가 다른 언어에 비해서 명확한 컴파일 단계의 문법체크가 약하기 때문이다.

hika님의 2009년도 코딩 규칙을 잠깐 보자. http://diebuster.com/flash/3 

나는 처음에 클래스에 C, 정적클래스에 CS를 붙이는 의도에 대해서 잘 이해할 수 없었다. 하지만 이에 대한 강력함은 개발해보면 안다. 나는 클래스에 C, 정적클래스에 S, 인자객체는 A, internal 클래스는 앞에 _, 어떤 클래스의 Part라면 클래스명뒤에 _파트명 이런식으로 클래스 이름 규칙을 정했다. 실제로 이렇게 관리하면 클래스가 정확히 어떤 역할을 하는지 눈에 팍 들어온다. 함수를 인자로 받아야하는 경우 FN_intNumberString_Boolean:Function 과 같이 쓰면 이 인자로 들어올 함수는 반드시 function( a:int, b:Number, c:String):Boolean 형태로 만들어야 된다. 이런 규칙은 코딩시 코드힌트기능에도 표시되기 때문에 사용하면 정말 편리하다.

반복구문에 대해 : http://diebuster.com/flash/?s=%EB%B0%98%EB%B3%B5%EA%B5%AC%EB%AC%B8&submit=

결국 코딩규칙을 사용하는 명확한 의미는 한눈에 코드를 파악하고자 하는 의도에서 찾아야 한다.


정리하며
앞서 말했지만 타임라인 개발하는데 많은 도움을 주신 분을 꼽자면 hika님이다. 부족하지만 이 분의 도움으로 나는 스킬업을 할 수 있었다. 사실 hika님 입장에서는 이런 외부활동과 저술활동이 없어도 부족함이 없어보인다. 하지만 그의 공유정신 때문에 개발에 입문하는 많은 사람들에게 큰 도움이 되는 것은 사실이다. 이 글을 통해 감사하다고 전하고 싶다.

글쓴이 : 지돌스타(http://blog.jidolstar.com/661)

+ Recent posts