WinJS

하이브리드 앱 개발 on Visual Studio #4

WinJS 앱을 살펴보도록 하자.

index.html

index.html에는 WinJS 컨트롤을 사용하고 있다.

image

data-win-control과 data-win-bind는 WinJS에서 컨트롤을 사용할 때 사용하는 확장 속성들이다. data-win-control은 컨트롤로 동작하게 할 때 사용하며, data-win-bind는 바인딩 기능을 이용해서 특정 변수 값과 요소의 속성을 연결시켜 준다.

처음에 div 태그에 WinJS.Binding.Template이 data-win-control에 지정되었는데, 이 부분이 추후에 템플릿으로 사용됨을 알 수 있다. 또한, input 태그에는 data-win-bind에 value: text가 적용되어서, 해당 컨텍스트(바인딩에서 사용하는 데이터 오브젝트)의 text 값을 value 속성에 바인딩 시키고 있다.

image

이 부분은 실제 앱의 UI 부분이다. 할일 내용을 넣는 부분에는 onchange 이벤트에 Xplat.datasource.addToDo(event.target) 함수가 핸들러로 지정되어 있다.

또한, main 섹션의 div 요소는 WinJS.UI.ListView로 선언되었다. data-win-options 속성을 통해 ListView 생성에 필요한 설정들을 전달한다. 여기에는 itemDataSource(리스트 데이터), itemTemplate(앞서 정의한 각 항목을 담는 템플릿 코드), layout(GridLayout과 ListLayout 중에 선택) 등이 포함되어야 한다.

index.ts

그럼 계속 index.ts 파일을 살펴보자. TypeScript를 사용하고 있기 때문에 JS에서 몇 가지 확장 키워드들이 사용되고 있다.

image

module은 코드를 모듈화 하는데 사용되는 키워드이며, 재사용성을 높여주고 네임스페이스를 만든다. export 명령을 통해 해당 네임스페이스에서 사용 가능한 클래스와 변수 등을 정의할 수 있다.

여기서는 Xplat.app 변수를 XplatApplication 형으로 선언하고, Xplat.XplatApplication 클래스를 정의하고 있다. TypeScript는 JS와 달리 클래스 정의를 위해 class 키워드와 멤버 관련 문법을 제공한다.

image

계속해서 Xplat.ApplicationEvents를 정의하고, Codova로 받는 이벤트를 처리할 핸들러 들을 포함하고 있다. 앞서 만든 app에는 XplatApplication의 인스턴스의 참조를 저장한다.

그리고, app.initialize()를 실행하고 initialize()의 this.bindEvents()를 통해 Codova의 deviceready에 onDeviceReady와 여러 가지 앱 이벤트들을 등록하여 초기화한다. dataSource.refresh()하여 데이터를 새로 가져오고, WinJS.UI.processAll()을 실행하여 현재 페이지의 WinJS 컨트롤들의 바인딩이 처리되도록 한다.

todo.ts

dataSource는 todo.ts 파일에 정의가 되어 있다.

image

index.ts와는 같은 Xplat 네임스페이스를 공유하고 있다. dataSource는 ToDo 클래스 인스턴스 참조를 저장하기 위한 변수로 선언되어 있으며, 아래 부분에 ToDo 클래스를 정의하고 있다.

ToDo 클래스는 this._items에 WinJS.Binding.List 인스턴스를 생성하여 참조하고 있고, 앞서 index.ts에서 호출된 dataSource.refresh()도 여기 정의되어 있는 것을 확인할 수 있는데, Storage.getAllToDoItems()를 비동기 호출하고 결과가 왔을 때 this._items에 각 아이템을 this._createTodoBinding(items[i])로 처리하여 추가(push)하는 것을 볼 수 있다.

(XPlat.)Storage 모듈은 services.ts 파일에 정의되어 있는데, 앞선 AngularJS나 BackboneJS 샘플처럼 LocalStorage나 AzureStorage에 대한 구현과 Bing Maps API를 사용하는 부분의 코드가 들어있다.

비동기 호출 이후, 결과 데이터가 왔을 때 처리하는 _createToDoBinding() 코드를 잠깐 살펴보자.

image

WinJS.Binding.as()를 이용해서 바인딩할 수 있는 bindingItem 오브젝트를 만들고, changeText/toggleDone/remove 등의 변수에 람다식 문법(() =>{})을 이용하여 bindingItem 오브젝트과 함께 실행할 메서드들을 묶어서 이벤트 핸들러 함수를 만들고 이를 WinJS.UI.eventHandler()를 통해 html에서 사용할 수 있게 한다.

image

index.html의 템플릿 코드를 보면 위와 같이 onchange: changeText나 onclick: remove, onmousedown: toggleDone 핸들러가 지정되어 있는 것을 볼 수 있다. 각 bindingItem이 이 템플릿의 context가 되기 때문에 changeText는 bindingItem.changeText를 가르킨다.

services.ts

마지막으로 services.ts를 간단히 살펴보면 다음과 같은 클래스 구현을 볼 수 있다.

image 

TypeScript의 interface/implements 키워드를 이용하여 IStorageImplementation 인터페이스와 LocalStorage, WindowsAzureStorage의 클래스 구현을 만들고, storageImplementation 변수에 둘 중에 하나의 참조를 넣은 후, getAllTodoItems() 등의 함수에서 이를 사용하여 데이터에 대한 처리를 구현한다.

여기까지 간단히 WinJS와 TypeScript로 구현된 Codova 샘플을 살펴보았다.

AngularJS, BackboneJS, WinJS 등 3가지 하이브리드 앱 샘플을 살펴보면서 느낀 각각의 장단점을 간단히 정리하자면,

  • AngularJS – 바인딩과 html 확장이 편리하며 코드가 간결하다. 처음에 여러 가지 개념 및 스코프 동작 등의 개념을 이해하기 어렵고 JS 코드 가독성이 다소 떨어진다.
  • BackboneJS – 한 페이지에서 여러 화면을 가지는 애플리케이션 구현이 간단하다. HTML을 확장하지 않지만, 그로 인해서 JS에서 처리해야 하는 코드가 많아지고 MVC의 구분이 명확하지 않아서 코드가 지저분해 질 수 있다.
  • WinJS – 템플릿과 바인딩을 활용하여 코드를 간결하게 작성할 수 있고 앱 구현에 유용한 컨트롤이나 네비게이션 기능 등이 제공된다. 바인딩이나 UI 컨트롤이 동작하는 방식을 이해하기 어렵다.

TypeScript에 대해서는 모듈 기능이 따로 제공되지 않는 WinJS와 함께 사용하면 코드의 가독성을 상당히 높일 수 있어서 유용하고, AngularJS 등과도 함께 쓰면 좋겠지만 이미 모듈 기능을 제공하고 있으므로 함께 사용하는 방법을 좀 더 고민해 볼 필요가 있을 듯 하다.

Advertisements