윈도우 8, 요즘 인기가 많다. 일반 사용자들의 후기도 많이 보이고, 더불어 개발자들에게도 기존의 개발 경험을 살려 그래도 개발이 가능해서 인기가 많다. 더불어 C++/CX와 HTML5로 개발이 가능하다.

   

WinRT와 WinMD

그 중에서 C#/XAML을 이용하여 앱을 개발할 경우 Windows 8 Runtime(WinRT)의 라이브러리를 이용하여 개발하게 되는데, 마이크로소프트에서는 이 WinRT를 관리 언어가(Managed 플랫폼 환경) 아닌 C++로 만들어진 네이티브(Native)로 컴파일 되어 있다. 확장된 COM 기반이기 때문에 C#과 HTML5에서 모두 이 라이브러리 APIs 집합을 사용할 수 있다. 이것은 매우 큰 장점이 분명하다.

그런데 말이다. 이 WinRT 자체가 매우 성급하게 만들어진 라이브러리라는 것이 여럿 보인다. 그 중 네이티브로 컴파일된 환경에서 C#과 유사하게 런타임상의 객체나 타입 정보를 알아내기 위해 RTTI(RunTime Type Identification)을 C++/CX 컴파일 시에 자동으로 구현이 된다. 그리고 RTTI를 위해 사용되는 WinRT의 API 정보의 일부는 .WinMD 파일로 저장이 된다. 이를 윈도우 런타임 라이브러리(Windows Runtime Library)라고 하며, 이 라이브러리는 윈도우 8 앱을 개발하는 환경 모두에서 사용할 수 있다.

   

   

   

   

윈도우8 WinRT, XAML의 미완성을 의미하는 IXamlMetadataProvider와 IXamlType 인터페이스

여기에서 문제가 발생한다. 모든 객체들은 C++/CX과 C#에서 XAML(eXtensible Application Markup Language)에서 다룰 수 있다. 그리고 Windows.UI.Xaml 네임스페이스에 XAML과 관련된 APIs 집합이 있다. 그런데 WinRT는 XAML을 핸들링 할 수 있는 라이브러리를 완벽하게 구현해 놓지 못했다.

그래서 WinRT의 IXamlMetadataProviderIXamlType 인터페이스가 생겼다. 이 인터페이스가 WinRT가 XAML을 (꽁수로) 핸들링하기 위해 만들어진 인터페이스로 보인다.

코드에서 새로운 객체를 생성해서 사용하고 싶으면 var obj = new LoginView(); 와 같이 새로운 객체를 생성하는 new 키워드를 사용하면 된다.

객체지향을 완벽하게 표현하는 XAML에서도 마찬가지다. XAML에서 다음처럼 LoginView 객체를 생성할 수 있다.

   

   

여기에서 IXamlMetadataProvider가 미완성 XAML임을 증명해 준다. 윈도우8 모던 앱(Modern App)에서 XAML에서 객체가 생성되는 경우 컴파일 시에 자동으로 생성되는 XamlMetadataProvider.g.cs 파일에서 객체를 생성해 준다. (g는 Generated를 의미한다). 자동으로 생성되는 이 코드는 다음과 같은 코드가 포함이 되어있다.   

   

XAML에서 LoginView 객체 생성을 요청할 경우 IXamlMetadataProvider를 구현한 코드를 통해 객체를 대신 생성한다. 다시 말해, 하드 코딩이 되어있다.   

이는 매우 유감이다. 이는 즉, 런타임상에 동적으로 생성되는 객체나 앱 컴파일 시에 해당 클래스가 포함이 되어 있지 않다면, XAML은 객체를 생성하지 못하게 된다. 동적인 무언가에 의해 생성되는 객체는 XAML에서 명시적으로 객체를 생성할 수 있는 방법이 없어진 것이다. (단, 명시적인 호출)

   

   

사용자가 구현하는 IXamlMetadataProvider

일단 WinRT가 이렇게 구현되어 있으니, 어쩔 수 없다. 동적으로 생성되는 객체에 대해서 XAML에서 명시적으로 객체를 생성하기 위해서는 Custom IXamlMetadataProvider를 구현해 주어야 한다.   

아래는 필자가 개발 중인 Umc.Core.WinRT.dll 에 포함된 Custom IXamlMetadataProvider이다. 윈도우8 모던 앱을 컴파일할 때 MSBuild는 참조되는 어셈블리의 메타데이터를 검색하여 IXamlMetadataProvider 인터페이스를 구현한 객체를 XamlMetadataProvider.g.cs 코드에 자동으로 추가를 해준다. 그리고 컴파일이 된다.

   

   

   

IXamlMetadataProvider가 필요한 경우의 예시

아마 일반적으로 윈도우8 앱을 개발할 때 이 인터페이스를 구현할 필요는 없다. 하지만, 앱을 캡슐화하려고 하고, IoC(Inversion of Control) Container 등을 활용하고자 하고, 동적인 객체가 필요한 경우라면 이 인터페이스를 구현해야 할 필요가 있을 것이다.   


C#이 지원하는 System.Dynamic.ExpandoObject 객체를 생성한다면 이 객체는 XAML에서 명시적으로 호출을 할 수 없다.   

또, System.Dynamic.DynamicObject 를 구현하는 객체도 마찬가지이다. 아래는 Umc.Core.WinRT에 포함된 코드의 일부이다.

   

위와 같은 코드를 이용하여 동적인 객체를 생성하였다면, 명시적으로 구현한 클래스가 없으므로 당연히 XAML에서도 이 객체를 생성할 수 없다.   

이와 같은 경우에 IXamlMetadataProvider를 구현하면 된다.

   


그 밖에 필요한 것들

아마 WinRT는 윈도우폰7 의 API 보다 더 작다. 작은 만큼 없는 것이 많고, 포기해야 하는 것이 많다. 아래에 나열되는 구현체는 http://umcore.codeplex.com 의 필자가 만든 코드를 WinRT용으로 마이그레이션한 것들이다. 조만간 Umc.Core.WinRT도 공개할 것을 약속한다.   

1. WinRT 설계 자체가 IoC Container를 활용하기 매우 너그럽지 못한 구조이다. 그래서 기본적인 WinRT 구조를 많이 벗어난 구조를 직접 구현해야 했다.      


2. MarkupExtension등을 지원하지 않아 Markup 확장이 불가능하여 다른 형태의 XAML답지 못한 요소나 속성들을 따로 만들어야 한다. MarkupExtension등으로 IoC Container 등과 통합을 쉽게 할 수 있으나, 어쩔 수 없이 필자는 Attached Property로 아래와 같이 구현해야 했다.

또는 아래와 같이 LambdaExpression을 이용하여 동적 Compile() 하여 사용하는 형태로 다음과 같이 사용이 가능토록 할 것이다. 이 경우, 위의 방법보다 더 나은 성능을 보여줄 것이다.

 

3. Frame.Navigation은 객체의 Type으로 뷰를 이동한다. 하지만, 하나의 타입에 두 개의 뷰를 만들 수 있는 APIs 를 제공해 주지 않는다 따라서 INavigationService와 NavigationServiceFrame을 직접 구현하여 다음과 같이 하나의 Type 으로 생성되는 뷰는 여러 개의 뷰 객체를 생성할 수 있도록 했다.

다음과 같이 인터페이스를 정의하였고, 기존의 Windows.UI.Xaml.Controls.Frame은 Umc.Core.ModernApp.NavigationServiceFrame으로 대체하도록 하였고, UniquqKey로 구분하여 하나의 Type에 여러 뷰를 생성하여 네비게이션 할 수 있도록 했다.

   

4. IoC Container와 통합된 EventAggregator

뷰에 이벤트를 전달하거나 전역 이벤트를 전달하기 위해서 좀 쉬운 구조로 가기 위해 IoC Container에 EventAggregator를 함께 넣어보았다. Message 방식을 통해 뷰의 이벤트나 전역 이벤트를 구독할 수 있다.

   

그리고 구독을 뷰에서 제어할 수 있도록 하였다.

   

5. IoC Container와 통합된 인젝션. 객체의 인젝션(Injection-주입)은 다음과 같이 이루어진다.

   

6. IoC Container의 Configuration File 구성

이건 이전에 http://umccore.codeplex.com 에 구현해 놓은 것을 WinRT 용으로 마이그레이션 하였다. patterns & practices - Unity의 경우 Configuration을 지원하지 않지만, UmC Core의 IoC는 이를 한번 더 Wrapping 하였기 때문에 구성 파일로 만드는 것이 가능하다.

   

7. IoC Container에서 지원하는 AOP

이는 WinRT 구조상 이를 구현하기가 그리 쉽지는 않다. WinRT에서는 직접 MSIL(MS Intermediate Language)을 이용하여 런타임에 Instructions을 생성할 수 없다. 다만, APIs 가 모자란 만큼 모자란 대로 구현을 할 수 밖에 없다.

예를 들면, C#의 dynamic 을 이용하여 다음과 같이 구현 가능하겠다.

   

   

다음 버전의 윈도우8 앱 SDK 구조는 또 얼마나 바뀔까 걱정!

실버라이트의 일부와 윈도우 폰7에서도 그러하듯 이번 WinRT도 초기 버전이라는 생각이 든다. 생각해보라. 실버라이트 1,2까지 얼마나 개발자의 Needs를 만족해주지 못하였는지. 앞으로 등장할 윈도우 폰8 개발 SDK도 하위 호환성을 일부 포기한다고 알고 있다.   

현재까지 윈도우8 앱 개발 SDK 환경을 본다면, 기존에 가능하던 것들이 WinRT 환경에서 매우 많은 제약이 따른다는 것이 불편하다. 현재 WinRT와 윈도우8 앱 개발 플랫폼의 구조를 본다면, 차기 개발 SDK에서는 WinRT를 얼마나 개선할 수 있을지 알 수는 없다. 아마 WinRT/SDK를 만드신 분들도 참 많이 고민을 했을 것이다.   

다만 WinRT/SDK를 사용하는 개발자에게 그 동안 밟아왔던 원망스러웠던 수순을 밟지 않기를 바랄 뿐이다. 

어쨌든, 윈도우8 WinRT/SDK의 불합리하거나 불편했던 부분을 필자가 구현한 이전에 공개했던 http://umccore.codeplex.com 에 추가로 공개할 예정이다.

신고

'O/S > Windows 8' 카테고리의 다른 글

윈도우 8, 무서운 드라이버와 궁합  (0) 2013.06.05
윈도우 8, 반토막짜리 WinRT와 WinRT SDK  (1) 2012.10.30
Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 김종남 2016.05.15 21:03 신고 Address Modify/Delete Reply

    글 잘 보았습니다.