ZF.js 개발기 #2
가끔 돌이켜 생각해보면 내가 생각해도 무모한 작업을 행했던 적이 몇 번 있었다. 여기서 무모함이란 당장의 이득이나 누구의 하청이 아닌 그냥 내가 만들어야겠다 생각해서 도전한 프로젝트들을 말한다.
첫 번째 무모한 도전은 PHP를 배운 지 얼마 되지 않아 게시판 설루션을 만들었던 때다. 당시(2003) 나는 사이트를 만들 때마다 제로보드 (나랑 상관없음;; 현재로 비유하면 워드프레스 같은 설루션)를 이용할 수밖에 없었던 그냥 웹디자이너였다. 다른 페이지에 아무리 신경을 써도 게시판만큼은 내 마음대로 디자인할 수 없음이 너무 답답했다. 그래서 PHP를 배우기 시작했고 기본 문법을 겨우 마친 상태임에 불구하고 자동 설치부터 데이터베이스 생성, 관리부터 디자인의 관리 및 확장 기능까지. 뭘 믿고 그리 용감했는지 시간이 지나서 당시 코드를 봐도 참 무모했구나 싶을 정도였다.
두 번째 무모한 도전은 Flash ActionScript2.0 때 어느 날 윈도 화면을 보다가 보이는 컴포넌트들을 모두 만들어봐야겠다 생각이 들었다. 물론 플래시 자체 내장 컴포넌트들이 해당 기능들을 제공하긴 하지만, 그냥 내 맘대로 만질 수 있는 새로운 컴포넌트들이 만들고 싶어 졌었다. 단순 Scrollbar, Button, Input, TextArea 등 기본 컴포넌트부터 Panel, Window, Browser 등 복합 컴포넌트들까지 당시 윈도를 이용하면서 볼 수 있는 컴포넌트들은 모두 만들어봤다.
세 번째 무모한 도전은 ActionsScript가 2.0에서 3.0으로 버전업을 했을 때였다. 이전 글에서도 얼핏 말했지만 Javascript를 베이스로 했던 2.0에서 Java 베이스로 바뀐 3.0에 적응하는 것도 꽤나 어려웠던 시기였다. 하지만 너무 만족스러웠던 건 2.0이나 자바스크립트에서 날 괴롭혀왔던 Callback이나 Scope문제 등이 3.0에선 완전히 없어졌고 보다 정형적인 클래스 구조체나 이벤트 모델 등 많은 장점에 완전히 매료돼 있을 때였다. 하지만 문제는 내가 3.0을 쓰고 싶다고 해도 기존에 프로젝트들이나 업계에선 신기술을 반영하기 어렵다는 문제들 때문에 2.0에서 3.0의 문법으로 개발할 수 있는 프레임웍을 개발했던 것이다;;;
각각의 고생들의 포인트를 일일이 열거하긴 힘들지만 중요한 점은 그 삽질들이 나에게는 뼈가 되고 살이 되는 좋은 경험들이 되었다는 것이다. 왜냐하면 기존에 만든 ZF.js가 모태가 된 것이 세 번째 도전에서의 프레임웍이었고 당시의 2.0의 문제들을 3.0 방식으로 우회하는 루틴에 대해서 학습이 되지 않았더라면 만들 엄두도 내지 못했기 때문이다.
ZF.js의 시작 동기는 AS3.0에서 사용하던 PureMVC 같은 프레임웍을 자바스크립트에서 사용하고 싶었다. 또한 콜백 방식이 아닌 이벤트 방식의 서비스 빌딩을 진행하고 싶었기 때문에 이 두 가지를 혼합해서 간단히 하나 만들어야겠다는 생각과 과거의 경험들이 혼합돼서 ZF.js 초안을 완성하고 활용할 수 있게 되었다.
하지만 간단히 만들어서 그런지 갈증이 나는 부분들이 발견되었고, 벼루고 벼르다 결국 새로운 무모한 도전을 시작하게 되었다. 기존 ZF.js가 util개념의 간단한 프레임웍이었다면 이번에는 자바스크립트 환경에서 내가 불만족스럽거나 필요한 환경을 제대로 구축하자는 취지다.
기존의 ZF.js가 이벤트 모델 및 기반 프레임웍에 집중했다면 신규 ZF.js에서는 기본적인 문법, 구조체부터 빌딩 작업에 전반적인 영역에서 안정적 코딩을 할 수 있는 환경을 만들겠다는 것이 목표이다. 가장 먼저 명확한 상속 구조체가 필요했다. 자바스크립트에서는 아직은 Class문법이 없기 때문에 명확한 클래스를 정의하기도 힘들고 방식도 다양하며 만들어진 인스턴스를 동적 생성, 변경이 가능한 점이 상당히 불안한 구석이었다.
$ZF.extends( 부모 클래스, 대상 클래스, [prototype], [getter [setter]] );
$ZF.super( this, [SuperClassInitParams], [InterfaceClass] );
조금 생소한 방법 일순 있겠지만, $ZF Core를 통해서 상속 체인을 선언한다. 일반적인 객체지향 언어처럼 단일 상속 체인을 형성하며 부모 클래스가 다른 클래스를 상속 중이라면 최상위 객체인 ZObj부터 순차적으로 상속받게 된다.
TestExtends -> ZEventDispatcher -> ZObj
자바스크립트는 접근 제한자가 없기에 별도의 방법으로 private을 구현하거나 우회를 하여야 하는데 매번 private 속성이나 읽기 전용 속성을 코드로 작성하기에 복잡한 구조를 해결하기 위해 상속 체인 결성 시에 옵션을 통해서 해당 부분들을 처리하였다. [prototype]을 통해서 선언하는 값 중 Class Option인 Final, Once, Limit을 통해서 더 이상 상속을 받지 못하게 막는다거나 Singleton 객체처럼 한 번만 생성되도록 하거나, Limit을 통해서 정해진 개수만큼만 생성할 수 있도록 제약할 수 있다. 물론 작업자가 망가트리려면 얼마든지 망가질 순 있겠지만, 모든 구조가 $ZF Core와 ZObj 기반으로 돌아가기 때문에 전체가 가동되지 않는 한이 있어도, 일부를 공격하기 힘들게 구조를 정의했다.
자바스크립에서도 읽기 전용 속성 설정은 가능하다, 하지만 선언하는 구조가 간결하지 않고, 많은 수의 읽기 전용 속성을 설정하기엔 코드가 지저 분해기에, [getter [setter]] 옵션을 통해서 조금은 쉽게 Get/Set Method 선언을 구현했다. 또한 $ZF.super를 통해서 부모 클래스 초기화를 하면서 Parameter를 넘기거나 가상 인터페이스 격으로 다중 상속을 처리하는 구조도 간결하게 정의했다.
위의 이미지에 오른쪽 콘솔 창에서 보는 것처럼, $ZF 프레임웍은 클래스의 정의, 관리, 데이터 타입에 대한 비교 등 ‘동적 함수형 프로그래밍’이 아닌 ‘정적 클래스형 프로그래밍'을 지향점으로 서비스가 러닝 중에 값이나 처리가 꼬이지 않도록 명확한 정의를 할 수 있게 하는 쪽으로 집중하고 있다. 현재까지 ZF.js 코어와 ZF-MVC.js 모듈을 완성한 상태이고 이를 기반으로 ZF-Component.js ZF-Graphic.js 등 패키지 단위의 확장 모듈들을 추가해 나갈 생각이다.
아마도 이번 무모한 도전은 이 프레임웍을 통해서 두세 번의 프로젝트를 빌딩 하며 검증이 끝나면 GitHub 등을 통해 오픈소스로 배포해야 일단락이 될 것 같다. 내일부터는 이 ZF.js와 함께 신규 프로젝트를 시작하게 되어 설레는 밤이다.