개발자라면 모두 자기 만의 프로젝트관리 방법이 있을 거라 생각합니다. 이번에 다룰 주제는 하나의 어플리케이션을 개발하기 위해 어떻게 준비하고 진행해야 하는가? 에 대한 내용입니다. 개인적인 경험을 정리한 것이므로 절대적인 기준 같은걸 설명 드리거나 일반론을 말씀 드리는 건 아닙니다. 단지 어떻게 하는 게 효율적이고 안정적인 어플리케이션 작성에 도움이 되었다 라는 저의 요령 같은 걸 공개한다고 생각해주시면 되겠습니다. 꼭 제 글이 아니라도 보다 쾌적하고 생산성 높은 작업을 위해 한번 쯤 프로젝트의 실질적인 프로세스를 생각해보시는 건 언제나 큰 도움이 될 듯합니다.
단지 실무적인 내용을 정리하는 글이다 보니 다른 글처럼 초보자에 대한 깊은 배려는 없을지도 모릅니다 ^^;
1단계. 설계단계 – AS3 격리 수준을 이용한 설계
프로젝트를 진행하기에 앞서 먼저 AS3에 대한 아주 기본적인 지식이 필요합니다. 아니 정확하게는 OOP 언어로 무언가를 설계 시에 기본적으로 고려해야 하는 지식일 수도 있습니다. 바로 격리단계에 대한 이야기입니다.
AS3는 언어적인 수준에서 3가지 격리단계를 지원합니다. 즉 ApplicationDomain(이하AD), namespace(이하 NS), package 라는 겁니다. 하나의 어플은 여러 개의 클래스로 구성하는데 이러한 클래스 설계 시에 반드시 저 세 가지의 카테고리를 모두 고려하여 분배하는 습관을 가져야 합니다.
언제나 처럼 게임으로 예를 들며 생각해보겠습니다.
ApplicationDomain 수준에 대해
- stage2에서 사용될 배경과 적에 대한 처리를 담당하는 Cstage2 라는 클래스가 있다고 합시다.
- 그럼 우선적으로 이 클래스는 Main AD소속이 아닐 가능성이 높습니다. Main.swf 에 소속된 클래스가 아니라 stage2.swf 에 소속된 클래스일 가능성이 높죠.
- 따라서 이미 AD 상 본체와 분리시킬 생각을 한다면 Cstage2클래스 내부에서는 MainAD에 선언된 클래스나 여러 가지 참조를 사용할 생각을 하면 안됩니다. 바로 AD 수준의 격리 로직을 고려해야만 하는 상황이죠.
- 하지만 게임이 운영되는 시점에 MainAD에 있는 것들과 전혀 객체통신을 하지 않는다는 것은 말이 안됩니다. 결국 이러한 문제는 MainAD, 공유AD, stage2AD 라는 3가지 영역이 이미 필요하다는 사실을 암시합니다.
- AD를 구별짓는 격리화 수준은 클래스의 모든 로직에 관여하므로 나중에 아무렇게나 swf로 빼내서 로딩할 문제가 아닙니다. 만약 이러한 고려가 없이 설계된 클래스들이라면 그저 런타임 시엔 MainAD로 로딩되거나 MainAD를 상속받은 AD를 사용할 수 밖에 없고, 이는 GC도 안되고 덮어쓰기도 안된다는 얘기입니다.
- 이와 관련되어 보다 자세한 AD의 얘기는 여기서 다루고 있습니다.
Namespace 수준에 대해
- NS는 컴파일타임에 격리를 확인해주는 커스텀 격리 장치로 이해할 수 있습니다. 왜냐면 이는 반드시 코드 상의 구상을 하면 회피할 수 있는 것으로 사용 못하게 강제할 수는 없는 장치이기 때문입니다.
- 즉 NS가 public인 경우는 다른 클래스가 구상해버리면 그만이고 internal이나 private로 NS를 선언하면 이미 저 한정자 수준으로는 외부의 클래스가 접근 할 수 없으므로 구지 NS를 사용하지 않아도 되는 문제가 됩니다. 콜린옹의 책에서는 무려 NS를 동적으로 생성 할당하는 식으로 NS의 의미를 찾아 보실라 하는데 제가 보기엔 미친 삽질..=.=;(절대 여러분은 그런 짓 하시면 안됩니다..) 따라서 요점은 NS는 일종의 안내용 마커라는 겁니다. 정확하게는 개발자가 코딩하는 시점에서 주의를 환기시켜주는 효과가 있는 마커입니다.
- 그럼 NS가 격리화 수준에서의 뭐냐구요? 어쩌면 템플릿메쏘드 패턴과 유사합니다. 개발시 코딩 스타일을 강제하는 효과가 있습니다. 이 로직을 사용하고 싶으면 반드시 이 NS를 사용하여 이 스타일로 정의해라 라는 코딩 시의 규격을 표현할 수 있습니다. 개발자가 다른 개발자를 강제하는 컴파일타임에 검사가 되는 코딩 규칙 같은 걸로 바라보는 편이 정확하겠죠. 물론 내부적으로는 여러 가지 역활을 수행하고 있습니다. 대표적으로 as1, as2와 호환하기 위해 같은 이름을 갖는 Math등의 시스템 클래스를 각 as버전에 따라 분리 사용하는 역활로 AS3라는 NS를 사용하는 등의 목적으로 사용됩니다. 하지만 실제 개발할 때는 글쎄요..거의 쓸모는 없는 셈입니다.
Package 수준에 대해
- 패키지는 자바를 비롯한 파생언어에서 격리화의 기준이 되는 매우 강력한 추상화 도구입니다. 패키지는 물리적인 위치를 분리해내는데 사용되기도 하지만 그보다 더 중요한 기능은 다수의 클래스를 묶어 하나의 의미로 표현하는 매우 강력한 추상화 도구라는 점입니다.
- 이러한 패키지를 사람들이 주로 시스템내장 패키지부터 공부하는 경향이 있어 크게 오해하는 경우가 많습니다. 즉 flash.display.* 소속의 클래스들은 display라는 패키지의 소속이긴 하지만 거의 모든 클래스가 노출되어있습니다. 이는 제가 방금 설명한 display패키지가 하나의 의미로 표현되는 예라고 볼 수 없죠.
- 즉 Sprite는 Sprite고, Bitmap은 Bitmap이지 둘이 합쳐져서 Display라는 어떠한 의미를 생성하지 않는다는 뜻입니다. 대부분의 언어에서 시스템 패키지는 이러한 형태로 단지 의미론적으로 구별 짓는 카테고리 역할만 합니다. 그도 그럴게 시스템이 제공하는 클래스는 이미 클래스 수준에서 시스템의 기능을 대신하기 때문에 하나하나의 클래스가 더 이상 추상화하거나 묶어서 표현할 필요 없이 단일객체로 완전한 상태의 클래스인 경우가 대부분이기 때문입니다. 따라서 단지 그러한 완성된 의미체계로서의 클래스를 대략 묶어주기만 하면 되는거죠. 덕분에 DisplayObject의 상속과 전혀 무관하게 media라던가 text에 그 자식들이 들어가 있는걸 볼 수 있습니다. DisplayObject가 추상클래스인걸 생각해보면 참 이례적인 패키징이라 할 수 있습니다.
- 하지만 여러분이 작성하실 클래스는 절대로 이러한 시스템패키지의 예를 따라 하시면 안됩니다. 패키지 단위의 설계를 반드시 실천해야 합니다. 패키지단위의 설계란 패키지 하나가 완전히 하나의 의미 체계를 가져야 한다 는 것으로 클래스 단일 책임의 확장판이라 생각하시면 됩니다. 즉 game.player 라는 패키지가 있다고 생각해봅시다. 이 패키지 안에는 CsinglePlayer, CnpcPlayer, CnetworkPlayer 등이 있을 수 있습니다. 하지만 이 패키지는 단일한 의미로 게임상에서 액션을 취하는 플레이어라는 거죠. 단지 그 상황이나 조건에 따라 어떤 상세 플레이어로직을 구현한 클래스가 선택될 것인가만 패키지내부에서 결정되는 식입니다. 따라서 이를 도와줄 클래스와 이 플레이어라는 의미 체게를 도와줄 클래스만 이 패키지 안에 존재해야 합니다.
- CsinglePlayer, CnpcPlayer, CnetworkPlayer – 경우에 따라 로직을 따로 구현한 Player 서브 클래스
- Iplayer – game.player 패키지의 의미 : 클래스의 의미는 외부에 인터페이스로 표현됩니다.
- CplayerFactory – game.player패키지가 외부에 공개하는 생성용 API
- 위의 예에서 결국 player서브클래스는 전부 internal 클래스이고, Iplayer와 CplayerFactory만 public이 되며 CplayerFactory.getPlayer()의 경우 반환을 Iplayer로 하게 됩니다. 즉 game.player패키지 자체가 완전히 player라는 단일 역할을 외부에는 인터페이스만 공개하고 패키지 내부에는 그를 도와줄 서브 클래싱으로 처리된거죠. 실제로 여러분의 솔루션에서도 반드시 패키지는 저러한 의미로서 사용되어야 합니다. 만물상패키지가 되어 그 안에 수많은 public클래스가 존재하는 것 자체가 패키지라는 격리체계를 전혀 사용하지 못하고 있다고 볼 수 있습니다.
이상의 기본적인 격리 수준을 완전히 이해하고 클래스 설계 시나 세부 알고리즘 구상 시에도 항상 염두 하여 패키지 넘어서의 참조에 조심하고 AD넘어서의 객체통신을 조심해야만 합니다. package에 추가적인 글은 여기에 있습니다.
2단계. 개발도구선택 – CS4와 빌더
저는 이 글을 읽는 분은 개발자라고 생각합니다. 개발자 분들은 모두 빌더만 사용하세요. CS4를 사용해야 하는 경우는 전혀 없습니다. 만약 있다면 그것은 디자인작업이 결부되어있는 경우이고, 그러한 경우 본인이 스스로 디자인이 결부된 부분만 따로 정리하여 cs4에서 swf를 생성하고 개발은 빌더에서 진행하여 그러한 swf를 에셋으로 처리하게 분리해주세요. 즉 cs4가 에셋을 생성하기 위해 부분적으로, 혹은 협업하는 디자이너가, 혹은 디자이너작업을 할 때의 자기 자신(분신?)이 사용하는 건 전혀 문제없습니다만, 개발이란 영역에서는 언제나 빌더를 사용하세요. 모든 cs4의 결과는 swf로 요약되고 그 swf는 반드시 빌더에서 embed나 loader로 연동할 수 있습니다. 왜라고 물어보시겠죠?
- 이클립스 통합환경의 사용이 가능합니다. 수많은 개발을 위한 플러그인의 도움으로 IDE에서의 개발과는 비교가 되지 않을 정도로 안정적이고 생산성 높은 진행이 가능합니다.
- 컴파일을 CS4로 하면 이클립스의 통합 개발 프로세스에서 많은 부분이 수동으로 할 수 밖에 없게 되고 이는 최종 생산물이 잘못될 가능성이 높아지게 됩니다. 따라서 컴파일까지도 완전히 빌더에서 처리해야합니다.
- FLA파일은 악의 근원입니다. 이러한 통합파일은 항상 위험성을 내포합니다. 즉 라이브러리의 이미지가 바뀌어도 FLA를 열어서 업데이트하고 컴파일을 수동으로 하는 모든 과정이 위험합니다. 만약 빌더 환경이라면 공유폴더에 약속된 이름으로 그 이미지가 존재하고 디자이너가 그 이름만 지켜 네트웍드라이브로 카피해주고 개발자에게 알려주면 개발자는 어떠한 파일도 건드리지 않고 컴파일만 다시 하게 됩니다. 즉 어떠한 기존의 소스파일이나 프로젝트 관련파일도 건드리지 않는다는 것이죠.
- 원격저장소 및 백업파일에 대한 완전한 지원이 가능해야만 복원, 복구 등이 자유롭습니다. CS4에서 개발한다는 건 내일을 보지 않고 오늘 지구가 멸망할거라 생각하는 것과 별 다를 바 없습니다(물론 디자인관련 작업 말고 개발 시에요 ^^;)
- 수많은 다른 개발 툴이 있습니다. 강력히 권해드리는데 절대로 빌더를 사용하세요. FDT도 쓰지 마시고, 디벨로퍼도 쓰지 마시고, 기타 제가 잘 모르는 툴도 쓰지 마세요. 오피셜한 툴을 쓰시고 그 툴과 함께 어도비본사의 업그레이드 정책에 맞게 개발해 가시고 부족한 기능은 이클립스로 매꾸세요. 다른 툴이 무슨 묘기를 하던 별로 생산성과 상관없습니다. 그런 묘기가 많이 필요하다는 것 자체가 잘못된 설계 클래스를 개떡칠로 만들고 있다는 신호일 가능성이 농후합니다. 대부분의 리펙토링 책들은 메쏘드가 10줄이 넘어가면 경계하라고 하고 메쏘드의 수가 5개가 넘어가는 클래스를 경계하라고 가르칩니다.
- 빌더의 설치는 절대로 플러그인으로 하세요. 현재 플래시빌더베타까지 해서 모든 빌더가 지원하는 이클립스 최대버전은 아쉽게도 3.4까지입니다. 가니메데를 설치하시고 플러그인으로 설치하세요. 그래야만 이클립스의 모든 플러그인을 제한없이 사용할 수 있기 때문입니다.
- 이클립스와 플러그인의 설치에 대해서는 여기를 참고하세요.
3단계. 프로젝트의 셋팅
실무적인 프로젝트 셋팅은 길게 설명할 필요 없는 매우 실무적인 내용이라 간단간단히 항목으로 설명하겠습니다.
- SVN서버 섭외 – 일단 코드를 올릴 레포지토리를 확보합니다.
- 반드시 하나의 프로젝트가 하나의 레포지토리를 확보하도록 섭외한다.(가장 좋게는 각자의 URI를 갖는 것이다)
- /trunk/src/ 의 구조를 갖도록 생성한다.
- 이클립스에서 레포지토리 프로젝트를 시작하여 세팅한 후 위자드를 통해 as프로젝트나 flex lib 프로젝트로 설정한다.
- 다음과 같은 폴더 구조를 생성한다.
- /lib/ – swc를 모아둔다.
- /doc/ – asdoc의 결과를 저장한다.
- /swf/ – 릴리즈 된 swf를 버전별로 백업한다.
- /src/embed/ – 엠베딩 에셋을 모아둔다.
- /src/remote/ – 원격지에서 런타임 로딩할 자원을 모아둔다.
- 최초 개발 단계의 작업 시엔 사내 라이브러리의 경우 swc보다는 패스에 라이브러리 폴더를 잡아준다. 프로젝트가 진행되면서 기존의 라이브러리가 기능이 추가되거나 버그가 수정되는 일은 매우 흔한 일이므로 이렇게 진행하는 편이 훨씬 효율적이다.
- 프로젝트가 완료된 후 반드시 현재 상태의 참조 라이브러리들의 그때 상태로 swc를 생성하여 lib에 카피한 후 패스를 전부 삭제하고 swc folder를 lib로 지정하여 컴파일이 문제없는지 확인한다.
- 레포지토리에 반드시 관련된 swc도 같이 넣어서 이후 라이브러리가 변경되어도 그 때 상태 그대로 언제나 컴파일이 가능하게 보존한다.
- remote에 저장된 런타임로딩용 자원들은 실서버로 대체될 때 코드상에서도 일괄 반영할 수 있도록 각 로더의 경로를 처음부터 ROOT_PATH+’/image/menu1.jpg’ 라는 식으로 생성하여 전역변수 한 개를 수정하여 처리할 수 있게 작성한다. 이러한 방식을 통해 개발 시에는 로컬에서 런타임로딩 테스트를 진행하고 완료 후엔 서버 상에서 자연스럽게 테스트를 진행할 수 있다.
또한 위의 프로젝트는 하나의 어플에 대해 하나만 생성하는 것이 아닙니다. 위에서 설명한 AD격리단계에 따라 격리된 AD수만큼 생성하는 것이 바람직합니다. 개발 시부터 근본적으로 AD넘어 호출이 불가능하도록 완전히 격리된 상태로 개발을 하는 것이죠. 하지만 프로젝트에 따라서는 어플리케이션 클래스를 여러 개 만들어서 관리하는 방법도 있습니다. 각 프로젝트의 특성에 맞게 선택하면 될 문제긴 하지만 실제 진행해보면 하나의 프로젝트 안에 여러 개의 어플리케이션클래스가 존재하는 경우 디플로이 위치문제나 AD건너 호출이 쉽다는 요인들이 항상 안좋게 작용한다는 게 일반적인 제 경험담입니다.
4단계. 컴파일 및 디버깅하기
일단 여러분들의 코딩스타일이나 진행에 대해서는 제가 무슨 의견을 드릴 필요는 없다고 생각하기 때문에 곧장 컴파일 및 디버깅 단계로 점프해보겠습니다. 최종적으로 코딩이 끝나고 컴파일 단계의 흐름은 다음과 같은 단계로 진행 하는 걸 추천해 드립니다.
- 코딩이 끝나면 디버그를 통해 로컬에서 디버그 버전 swf를 컴파일하여 디버깅 모드로 테스트를 진행한다.
- 1번의 안정성이 확인되면 이를 디플로이서버에 디버그 버전인 상태로 업로드하여 디버거와 연결하여 테스트한다.
- 2번의 안정성이 확인되면 로컬에서 릴리즈버전을 컴파일하고 이를 디플로이한다.
- 3번의 안정성이 확인되면 디플로이한 swf를 날짜이름과 버전을 붙여 위에 설명한 swf폴더에 백업해둔다.
- 이후 변경 사항이 생기면 1~4번까지의 과정을 다시 진행한다.
일단 원격지의 swf를 빌더에 연결하여 디버깅 하는 방법은 여기에 적어 두었습니다. 간단합니다 ^^; 원격디버깅을 제대로 하지 않아 로컬에서 잘 돌던게 디플로이 후 어딘가 에러가 생기고 어디가 에러인지도 로그로 파악하기 힘든 경우가 많습니다. 하지만 원격디버깅을 도입하면 브레이크포인트까지 완전히 먹기 때문에 완전한 서비스 환경에서도 디버깅을 진행할 수 있습니다. 대략 넘어가지 마시고 반드시 원격디버깅도 진행하시는 습관을 갖도록 하세요.
디버그버전의 컴파일과 릴리즈버전은 일단 용량에서만 70%정도로 릴리즈버전이 작아집니다. 성능이나 속도 또한 눈에 확 띌 정도로 릴리즈버전이 우수하므로 절대로 디버그 버전으로 서비스되게 하지 마세요.
5단계. 디플로이 자동화
거창한 건 아니라도 디플로이를 자동화하지 않는 건 항상 위험을 내포하고 있습니다(언제나 사람이 깜빡하는게 문제죠) 따라서 ANT라도 한 줄 짜두면 알 FTP로 사람이 손으로 일하는 위험을 최소화 시킬 수 있습니다. 근데! 제 블로그에 이것과 관련된 블로깅을 한적이 없어서 링크를 걸어드릴 게 없네요 ^^; 포스트 단일 책임의 원칙에 따라 이 글에 앤트 ftp사용법을 기술할 수 없기 때문에 지인의 포스트를 여기에 링크 겁니다. 참조하시라고 하고 싶으나 대략 셋팅만 설명하고 태스크 샘플을 안올려두셨네요. 나중에 궁금하시면 물어보시라는.. ant던 marvin이든 하다못해 deploy.bat 파일이라도 만드세요. 사람이 매번 손으로 그런 짓을 하게 두면 안됩니다. 사소한 조작오류가 큰 위험을 야기 합니다 ^^;
'0.일반개발' 카테고리의 다른 글
화면 속성 : 설정 , 가로 : 세로 회전 onCreate(). onDestroy() : 고정 (0) | 2010.09.14 |
---|---|
EditText 입력 글자수 제한 / InputFilter (0) | 2010.09.13 |
네이버 Flash 2010 04 (0) | 2010.09.13 |
안드로이드 3차원 좌표계 (0) | 2010.09.13 |
안드로이드 리스트뷰 이미지 웹 다운로드 (0) | 2010.09.12 |