'Windows 8 App'에 해당되는 글 2건

  1. 2012.10.30 윈도우 8, 반토막짜리 WinRT와 WinRT SDK (1)
  2. 2012.09.11 Windows 8 스타일 앱 개발에 대한 고찰

윈도우 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

    글 잘 보았습니다.

Windows 8 스타일 개발이 한창 유행이다. 물론 모바일 생태계 전반전인 유행은 아니더라도 Microsoft 기술을 하는 사람들에게는 관심 대상이다. Windows 8 운영체제가 탑재되는 테블릿도 출시가 되고, New iPad 보다 하드웨어 스팩이 좋은 테블릿 출시도 준비중인 곳이 많다고 들었다. 새로운 마켓이 열리는 만큼 테블릿 사용자에게는 새로운 재미를 선사해줄 것은 분명한 사실일 것이다.

Windows 8 스타일 ! 개발을 위해 가지 알아야 구조적인 개념이나 유의사항 정도만 언급하기 위해 글을 나간다. C++/CX, C#,VB XAML(eXtensible Application Markup Language) 이용하여 WPF 데스크탑 응용 프로그램처럼 프로그래밍을 있다. 그리고 HTML/JavaScript 조합으로 개발 환경과 유사하게 개발을 있다. 아마 대부분의 Windows 8 스타일 개발자라면 알고 있는 내용일 것이다. 그리나 포스팅에서는 C++/CX C# 개발 언어를 기준으로 아티클 내용을 채울 것이다.

 

Windows 8 스타일 런타임 관점의 구조

[이미지 링크]

   

WinRT(Windows Runtime) 플랫폼의 구조적 아키텍처 이미지이다. 기존 Windows Desktop 응용 프로그램 환경과 다른점은 WinRT APIs 중간에 끼어있다. WinRT Windows 8 스타일 앱의 핵심이며, Windows 시작하는 Namespace 모두 WinRT 이다.

C#,VB 개발 환경은 그나마 편리한 Library Subset 제공한다. .NET Framework 최소화 버전이라고 보면 된다. 이를 .NET for Windows Store apps 이라고 부르며, 위의 이미지에는 내용이 빠져있다.

C++/CX 잘라 .NET for Windows Stores apps 제공되지 않는다. .NET 개발자라면 System(mscorlib.dll) 으로 시작하는 Namespace 얼마만큼 편한지 알텐데, Library Subset 제공되지 않으니 다른 방법을 사용해야 한다. 쉬운 예로 HttpClient 같은 클래스도 C++/CX MsXml COM 컴포넌트를 이용하는 편이 낫다. 그렇다고 모든 C++ 라이브러리를 사용할 있는 것도 아니다. 이 부분에서 특히 라이브러리의 제한이 있으므로 C:\Program Files (x86)\Windows Kits\8.0\Include\shared 폴더에서 사용가능한 Header 파일을 확인해보도록 하자.

만약 Header 파일의 pragma 선언이 Dektop Family 라면 Windows 8 스타일 앱에서는 사용할 없는 라이브러리이며, 상당한 Header들이 Desktop Family 속하여, 당장 .NET for Windows Stores apps 만큼 쓸만한 클래스들이 없다는 것이 조금 슬프다. 다만, 좋은 소식이라면 C++ boost Library 등이 C++/CX 용으로 컨버전을 시도하는 분들이 많으므로, 조금만 기다려보면 쓸만한 라이브러리들이 대거 출연할 것으로 보인다.

   

더불어 C#, C++ 개발자들도 알고 있어야 하는 중에 하나가 WinRT COM 컴포넌트 기반의 라이브러리라는 것쯤은 들어보았을 것이다. 그래서 Windows 8 스타일 개발자들은 COM 대한 개념과 나아가 이를 구현할 있다면 좋다. 특히 C#, VB 에서 WinRT 컴포넌트를 만드는 것은 가지 지켜야할 제약이 있으므로 다음의 링크를 참고하는 것이 좋다.

C# Visual Basic으로 Windows Runtime 구성 요소 만들기 http://msdn.microsoft.com/ko-kr/library/windows/apps/br230301.aspx

   

대신 C++/CX WinRT 컴포넌트를 만드는 것이 오히려 간단하다. 앞서 말했다시피 WinRT COM 컴포넌트 기반이지만, 기존 C++ 에서 COM 컴포넌트를 만드는 만큼 어렵지가 않다. C++ COM 구현의 첫번째는 IUnknown 인터페이스를 구현하는 것이지만, WinRT 에서는 Iunknown을 상속하는 IInspectable 인터페이스가 더 중요하다. IInspectable 인터페이스는 C++/CX 개발된 응용 프로그램이 런타임 해당 클래스의 정보를 제공하기 위한 인터페이스이다. 물론 기존 C++ 에서도 런타임상 클래스 정보가 필요하여 이를 직접 구현하는 방법도 있다. 하지만 C++/CX IInspectable 인터페이스는 C++/CX 컴파일 과정에서 자동으로 구현을 해준다. 이는 IUnknown 인터페이스까지 자동으로 구현해준다고 보면 된다. 그렇기 때문에 Iunknown 인터페이스의 AddRef, Release 메서드에 대한 객체 수명주기를 WeakReference 클래스를 통해 위임할 있다. WeakReference 통해 금방 해제될 있는 컴포넌트를 가비지 컬렉터 대상이 되도록 지정한다. 그러므로 사용 빈도가 매우 많고, 매번 자원 해제에 대한 비용이 반복되는 것은 WeakReference 효과적으로 객체 수명 주기를 다룰 있게 한다. 이러한 C++/CX 특별히 제공되는 라이브러리는 Microsoft.WRL Namespace 포함되어 있다.

아직 이러한 개념적인 부분이 어렵게 느껴진다면 월간 마이크로소프트 5월호 특집 기사로 기고한 필자의 다음의 글부터 참고 바란다.

[월간 마이크로소프트 5월호 특집기사] C++ 매트로 개발을 위한 C++/CX 언어 http://blog.powerumc.kr/378

   

   

Windows 8 스타일 응용 프로그램 관점

짧게 말해 Windows 8 스타일 개발은 쉽다. Visual Studio 2012에서 훌륭하게 대부분이 구현된 템플릿을 제공하기 때문에, 메서드 중간 중간 원하는 기능을 추가하고, 클래스나 XAML 만들면 된다. 다만, 이는 만든다는 것이 쉽다는 것이지 응용 프로그램 구조적인 측면에서는 전혀 쉽지 않다.

먼저 알아야 것이, Windows 8 스타일 페이지를 상태 관리 것인지, 것인지부터 결정해야 한다. 상태 관리를 유지할 필요가 없다는 것은 개발(ASP.NET/ASP/PHP/JSP) 같은 서버 사이드 개발 환경과 유사하다. 특히 IIS에서부터 ASP.NET까지 연결되는 Application Pipeline 매번의 Request마다 Pooling Thread 활성화되어 서버 랜더링을 통해 사용자에게 HTML Response 전달이 된다.

   

1. 상태 관리를 개별적으로 유지하고 싶다면

다음의 가지 메서드를 재정의하면 된다. ASP.NET Custom Control 구현해 보았다면 VIEWSTATE 상태 유지를 위해 이런 유사한 코드를 구현해야 하는 것을 것이다.

   

Frame.Navigate 메서드는 Page Type 인자로 받고, 매번 새로운 인스턴스를 생성한다. (구현을 다르게 한다면 인스턴스를 이용하도록 수도 있다.) 페이지의 상태 유지야 위의 메서드를 재정의하는 정도로 끝낼 있지만, 페이지에 포함된 UserControl 있다면 상황은 달라진다. 독자마다 구현하는 방법은 다르겠지만, 효과적으로 상태를 관리하기 위해 UserControl 조금 귀찮아지는 존재이다. 인스턴스의 재사용을 위해 자주 사용하는 UserControl 대한 상태 관리를 고민해야 하다니… (현재 아티클은 내용이 대해 오픈 소스 제공으로 효과적인 방법을 제안하도록 필자는 약속 하겠다.)

   

2. 상태 관리를 자동으로 캐싱하고 싶다면

상태 관리를 자동으로 캐싱하는 방법도 매우 쉽다. Page.NavigationCacheMode 프로퍼티를 Enabled 해주면 된다. 물론 XAML 코드에 속성을 추가해도 된다. 하지만 아쉽게도 Frame.Navigate 메서드를 통해 자동으로 상태 관리를 하도록 Page 새로운 인스턴스가 생성이 된다. 상태 관리 캐싱에 대한 조건은 GoBack(), GoFoward() 같은 Frame 이동에 대해서만 유효하다. 조금 이해할 없는 부분은 Page 포함된 UserControl 상태 관리 캐싱 대상에서 제외된다. (물론, 가능하도록 있지만 개념적으로 깊게 이해하고 구현해야 한다.)

   

3. 남발되는 async/await 의한 동기화 문제

Windows 8 스타일 앱을 사용하다가 자주 멈짓 멈짓 한다면 분명 사용자는 짜증날 것이다. 때문에 async / await 키워드를 더욱 자주 사용하는 편이다. 그렇기 때문에 UI 상태에 대한 비동기와 컴포넌트나 인스턴스 메서드 호출에 대한 비동기, 모두 정확하게 Threading 대한 지식이 필요하고, 자유 자재로 Threading 다룰 있다면 더욱 좋다. Windows 8 스타일 앱에서 가장 많이 발생하는 Threading 문제는 Thread 실행 인스턴스 해제에 대한 동기화와 Thread Cancel 대한 동기화다.

문제를 피하기 위해서는 클래스나 라이브러리를 만들때 부터 async / await 대한 고려가 필요하다. 쉽게 이야기하자면 자주 쓰지 않는 편이 좋고, 써야 곳에 써야 한다.

   

이를 판단하려면 Thread 동기화에 대해 적어도 가지는 반드시 익히는 것이 좋다. MSDN 아래의 글들을 번정도 필독하기 바란다.

관리되는 스레딩 기본 사항 http://msdn.microsoft.com/ko-kr/library/hyz69czz
스레딩(C# Visual Basic) http://msdn.microsoft.com/ko-kr/library/ms173178(v=vs.110)

   

      

Windows 8 스타일 배포와 라이브러리 배포 문제

부분은 매우 민감한 부분이고 조심스럽다. 실제 Windows App Store에서 테스트할 없을 뿐더러 개발 환경에서 발생하는 문제이므로, 실제 Windows App Store 통해 발생할 수도 있을 가능성이 있을 같다. COM 기반 라이브러리나 DLL 구성 요소 등은 공유 메모리에 로드가 된다는 것을 것이다. 특히 부분은 COM 컴포넌트에서 민감하게 다루는 IUnknown 인터페이스의 의미와 일맥 상통한다. , COM 객체의 참조 카운트(Reference Cout) 0 되지 않으면, 자원은 해제되지 않는다. 여기에서 COM 가장 고질적인 문제가 발생한다. 바로 DLL 지옥이다. Windows 8 스타일 앱의 메모리 위치는 메모리 영역이 아닌 공유되는 메모리 영역에 위치하고 있고, DLL Verserning 자유롭지 못하다. .NET 처럼 GAC(Global Assembly Cache)에서 DLL 버전별로 관리되지 않는다.

따라서, WinRT 런타임 라이브러리를 개발하여 배포된 Windows 8 앱이 활성화 상태일 새로운 앱에서 버전업 WinRT 런타임 라이브러리 배포시에 다른 프로세스가 점유하고 있다는 오류가 발생한다. 이는 앱이 초절전 유휴 상태에 진입되어도 마찬가지이다.

이찌되었든 개발 환경에서는 충분히 발생된 문제이니, 차후 Windows App Store에서도 발생할지는 지켜보아야 것이다.

   

Windows 8 Windows Runtime 재배포 정책 업데이트

런타임 라이브러리인 만큼 라이브러리 코드가 완벽하지는 않을 것이다. .NET Framework 1.0부터 4.5까지 버전업이 되어왔는데 과연 Windows 8 Windows Runtime 어떻게 버전업이 될까? 사용자의 동의 없이 업데이트나 패치는 불가능하다.

   

Windows 8 Features Pack 1,2,3… 시리즈로 업데이트가 될까?
Windows 8 Service Pack 1,2,3… 시리즈로 업데이트가 될까?

   

만약 이렇게 되면, Windows 8 스타일 간에 호환성 문제가 발생할 것이 분명하다. Apple iPhone 모바일 폰의 운영체제 업데이트가 실시간으로, 온라인으로 이루어진다. Windows 8 iPhone 업데이트와 차원이 달라진다. WinRT 지원하는 ARM 버전과 기존의 Windows 8 Desktop 지원하는 x86 버전 가지의 에디션이 있다.

혹시 부분에 대해서 알고 있는 정보가 있으면 공유 부탁 드립니다.

Posted by 땡초 POWERUMC

댓글을 달아 주세요