boxmile 님과 이과장님이 알려주신 유용한 유틸리티, SilverlightDefaultStyleBrowser.
이게 없으면 실버라이트 스타일을 어떻게 했을까 몰라요.^^
무지 유용한 툴이니까 한번쯤 꼭 써보세요.



여튼 한가지 불편한 점은 스타일의 일부만 선택하고 Ctrl+C를 눌렀을 때 테스트 복사가 되지 않는다는 점이었는 데요, Ctrl+C로 클립보드에 복사되도록 코드를 수정해서 올립니다.
보너스로 각 엘리먼트 앞에 있는 접기/열기 표시인 -, +도 제거하도록 했어요.

신고
Posted by gongdo

토요일, 훈스닷넷의 시삽 MT를 다녀오느라 인터넷을 못했는데 갔다오니 엄청난 글들이 쌓여있네요. 먼저 우리의 거쓰리 아저씨가 포스팅한 First Look at Silverlight 2. ※더 이상 실버라이트 '2.0'이라고 하지 않고 실버라이트 '2'라고 부르는 것에 주의!

일전에 포스팅했던 2007/11/30 - [프로그래밍/Silverlight] - 실버라이트 2.0!
소개와 거의 같고 약간 더 구체적으로 표현했을 뿐이죠. 여기에서 가장 중요한 것은 실버라이트가 WPF에 점점 더 가까워져 간다는 사실인 것 같아요. 심지어 실버라이트 2의 큰 특징 중 하나를 WPF UI Framework라고 표현했을 정도니까요.

이것은 무엇을 의미할까요?

기본적으로 실버라이트가 WPF의 강력한 프레임워크를 지향하고 있다는 것을 시사해요. 바로 실버라이트 2뿐만 아니라 이후의 버전이 어느 정도의 능력을 가지게 될 지 예상해 볼 수 있다는 것 말이죠.

다음으로 클라이언트 프로그래밍과 웹 프로그래밍의 갭이 줄어들고 개발자와 디자이너는 좀 더 일관성있는 작업이 가능해질 것이라는 것을 의미해요. WPF는 이미 XBAP이라는 데스크탑과 웹의 차이를 아무것도 아닌 것으로 만든 서브셋을 가지고 있지만 XBAP은 윈도에서만 동작한다는, 웹 환경에서는 용납하기 어려운 결정적 문제점이 있다는 것이죠. 실버라이트는 XBAP과는 달리 크로스 플랫폼, 크로스 브라우저를 지향하고 실제로 그렇게 구현되어 있어서 XBAP이 실현하지 못한 웹 애플리케이션으로서의 폭넓은 유연성을 가지게 되죠.

특히 실버라이트 2에서는 XAML의 중요한 기능중 하나인 Template을 드디어 지원하게 되고 이것은 기존의 커스텀 컨트롤에서 제공하기 힘들었던 코드와 표현presentation의 분리를 플랫폼 레벨에서 강제하고 보장할 수 있게 되죠. 재사용성reusability이라는 현대적 프로그래밍의 기본 사항이 드디어 디자인의 영역에서까지 일관적인 규칙으로 표현될 수 있다는 말이에요. 이 점에 대해서는 다른 글로 포스팅하고 싶네요.

그러나, WPF가 아니라 실버라이트 1.1을 통해 XAML과 닷넷 프레임워크를 접하게 된 개발자들에게는 많은 혼란과 두려움을 줄 수 있을거에요.

실버라이트 1.0과 1.1에서는 XAML의 엄청난 기능중에서 극히 일부의 기능만을 사용했고 그나마도 정말 사용하기에 쉬운 부분만을 다루었기에 누구나 배우기 쉬웠죠. 하지만 XAML은 결코 배우기에 만만한 언어는 아니에요. XAML로 표현되는 마크업과 닷넷 프로그래밍으로 작성되는 코드 비하인드를 적절한 구조로 설계하고 사용하는 것은 많은 프로그래머에게 익숙하지 않은 일이고 상당한 연습을 필요로 하죠.

어떻게 해야 할까요?

저는 이렇게 제안하고 싶어요. 실버라이트 2 Beta1의 릴리즈를 불과 한 달도 채 남겨놓지 않은 이 시점에서 실버라이트 2를 더욱 잘 사용하고 이해하기 위해서는 WPF에 대해 공부하세요. 분명히 실버라이트 2 Beta1이 릴리즈 되면서 많은 문서들과 글들과 자료가 쏟아지겠지만 대부분의 정보는 -당연히- 영어로 나올거에요. 부담이죠. WPF와 WPF에서 사용되는 XAML에 대해서는 이미 훌륭한 서적들과 더욱 확정적이고 구체적인 MSDN 문서들 그리고 친절하게 한국어로 만들어진 강좌들이 널려있어요. WPF의 구조를 이해하면 실버라이트를 더 잘 이해할 수 있게 되고 나아가 XAML을 더 잘 이해할 수 있게 될 거에요.

만약, 영어로 된 정보에 익숙한 분이라면 굳이 그럴 필요 없이 실버라이트 2를 공부할 수도 있겠죠. 아마도 이 경우는 상당한 경력을 가진 분이라고 예상 할 수 있는데요, 이런 분은 아마도 실버라이트를 통해 WPF로 역주행(?)을 하는 것도 무리는 없을 거에요.

어느 경우든, 실버라이트는 WPF의 서브셋으로서 둘의 차이는 점점 간격을 줄여나갈 것이고 둘 모두 XAML로 표현되는만큼 XAML에 대해 좀 더 깊은 이해가 필요할 거에요.

실버라이트 2와 XAML에 관해서는 하고 싶은 얘기가 정말 많네요. 다음 글에서 뵙죠.

신고
Posted by gongdo
거두절미하고 바로 발표자료부터 :)
20080216_HOONS_UX세미나_7주차.zip

UX 커뮤니티 세미나 7주차 1세션 발표자료



이번 세미나에서는 드디어(!) 죽음의 강행군을 하지 않고 마쳤던 것 같아요. 스스로에게 축하를. :D
그런데 이번에도 역시 서금욱님은 발표직전까지의 죽음의 강행군을 계속 해야만 했었죠. 함께한 장미연님도 수고 많으셨어요.
훌륭한 수준의 UCC 데모를 만들어주신 이도한님과 서미연님의 콤비 플레이도 멋졌고, 오일석님의 플래시 개발자로서 실버라이트를 접하는 관점은 저에게 많은 도움이 되었어요.

이번 세미나에서는 끝나고 질문이 많이 이어져서 좋았던 것 같아요. 항상 세미나를 준비할 때에는 이번에는 더 재밌게 해봐야지 해봐야지 하면서도 잘 안되는데 적어도 이런 Q&A정도라도 제대로 참여할 수 있게 하는게 중요한 것 같아요. 여튼 다음 번에는 더 재밌고 유익한 시간을 만들어봐야죠.

발표자료 외에도 궁금하신 사항은 제 블로그는 물론 훈스닷넷 실버라이트 Q&A 게시판 또는 네이버 실버라이트 카페의 Q&A 게시판에 질문을 올려주세요.

추운 날씨에 와주신 모든 분들께 감사드려요.
신고
Posted by gongdo

XAML이 컴파일 될 때2

지난 포스팅
에서 WPF 애플리케이션이 컴파일될 때 배경에서 일어나는 일들을 알아봤습니다.
가장 중요한 내용은 XAML이 컴파일 될 때 obj/Release (혹은 Debug)폴더에 name.g.cs라는 이름의 컴파일러가 자동으로 생성하는 코드가 작성된다는 것이었죠. 그리고 미처 소개하지 못한 사실이 하나 더 있다고 예고했는데요, 바로 .baml 파일입니다.

마크업의 약점 
대표적인 마크업인 HTML을 생각해보면 마크업이 가질 수밖에 없는 치명적인 약점을 알 수 있는데요, 바로 마크업이 담고 있는 개체들을 렌더링하는 것보다 마크업 자체를 개체화 하기위해 구문을 파싱하는 노력과 시간이 훨씬 더 많이 들어간다는 점이죠.

일반적으로 자료 구조중에 텍스트가 처리하는 데 프로세서, 메모리를 가장 많이 잡아먹고 그 중에서도 문자열 파싱이 특히 그렇다고 해요.

그렇다면 XAML은?
XAML은 이런 마크업의 약점을 보완하기 위해 프로젝트 컴파일시 XAML 파일 역시 컴파일하여 바이너리 형태로 변환합니다. MSDN의 http://msdn2.microsoft.com/en-us/library/aa970678.aspx#The_Windows_Presentation_Foundation_Build_Pipeline 을 보면 컴파일된 XAML 파일(compiled XAML file)이란 표현을 사용하는데요, 이것은 정확하게는 name.baml 파일을 의미하며 BAML의 B는 Binary를 말합니다.

MSDN에서 설명하는 BAML은 미리 분석되어(pre-tokenized) 런타임에 XAML파일보다 빨리 로딩될 수 있다고 하네요.

새 윈도 애플리케이션 프로젝트를 시작하고 빌드한 후 obj\Release 폴더를 보세요.
아마 Window1.baml 이란 파일이 있을거에요. 앞서 말한 바와 같이 이 파일은 바이너리니까 열어봐도 별 소용은 없을거에요.

어쨌든 XAML은 마크업이 가지는 로딩시 파싱 속도의 문제를 미리 컴파일하여 바이너리화 된 BAML 파일을 생성함으로써 극복하고 있다는 걸 알 수 있습니다.

겨우 이거?
WPF의 초기엔 BAML에다가 CAML이란것도 있었어요. Compiled XAML이란 건데, 이건 WPF의 개발 과정에서 BAML이 충분히 CAML의 속도를 따라 잡았고 CAML은 지역화가 불가능한 문제가 있는 등 여러가지 사정으로 CAML은 사라지고 BAML만 남았지요.

롱혼 SDK에는 XAML을 BAML로 컴파일하는 Xamlc.exe란 애플리케이션도 있었는데 지금은 MSBuild 엔진에 모두 통합되어 더이상 사용되지 않는다고 하네요.

또 과거 WPF를 위한 .NET API에서 LoadBAML이란 메소드가 존재했었는데 이것도 지금은 사라지고 LoadComponent란 메소드로 대체되었고 이 LoadComponent는 XAML이건 BAML이건 가리지 않고 제대로 로드하게 되어있다고 하네요.

지난 포스팅을 쓸 때만 해도 아직 이 사실들을 제대로 모르고 BAML이란 숨겨진 요소(?)에 꽤 흥분했었거든요. 그래서 뭔가 재밌는 비밀이 있을 걸로 기대했는데, 결과적으로 최근엔 개발자를 불편하게 하는 차이점은 죄다 통합되고 사라지게 되었네요. 썰렁;

신고
Posted by gongdo
오 Main이여 어디있는가?

애플리케이션이 실행 될 때
많은 프레임웍이 그렇듯 WPF도 애플리케이션을 대표하고 애플리케이션 전역에서 공통적으로 필요한 많은 기능들을 제공하는 클래스를 제공합니다. VC프로그래머라면 MFC에서 애플리케이션이 CWinApp를 상속받은 클래스를 theApp라는 전역 개체로 인스턴스화 하여 사용했던 기억이 날 거에요.

WPF는 그러한 애플리케이션의 대표자로써 Application 클래스를 제공합니다. Application 클래스는 .NET Framework 3.0에서 System.Windows 네임스페이스에 정의되어 있고 마크업(XAML)에서는 Application 엘리먼트로 표현되지요.
예를 들어 XAML에서 Window1.xaml을 시작 윈도로 정의하는 애플리케이션을 다음과 같이 정의할 수 있습니다. (XAML에 대한 내용은 이 글의 주제에서 벗어나니 다른 문서를 참고해주세요.) 어떻게 만드냐구요? 간단해요 이 포스팅을 확인하시고 먼저 .NET Framework 3.0 개발환경을 갖추신 후 VS2005에서 새 프로젝트->C#->.NET Framework 3.0->Windows Application(WPF)를 선택하세요.

APP.XAML

<Application

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    x:Class="App" StartupUri="Window1.xaml" />

WINDOW1.XAML

<Window

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    x:Class="Window1" Width="300" Height="300" />


컴파일하고 빌드해보면 오 놀라워라 애플리케이션이 실행되네요!

윈도우즈 개발자라면 여기서 놀라야 해요. 왜냐? 무슨 언어를 사용하든 윈도우즈 환경에서 윈도우즈 애플리케이션(여기에서는 exe형태로 실행가능한 독립 실행형 애플리케이션)은 Entry point라고 불리는 메인 프로시저(WinMain)를 OS가 호출함으로써 시작되기 때문이죠. C, C++은 말할것도 없고 C#, 심지어 그 오래된 VB조차도 엔트리 포인트를 제공하는데, XAML은 생긴건 HTML이랑 별 차이도 없어보이는게 브라우저 상에서 표시되는 것도 아니고 곧바로 윈도를 띄울 수 있는 exe파일을 만들었잖아요?

놀란 가슴을 진정시키고 생각해보죠. WPF가 제 아무리 편리하고 화려한 기술로 무장하고 있어봤자 윈도우즈 애플리케이션입니다. 지가 무슨 재주로 엔트리 포인트도 없이 애플리케이션으로 실행될 수 있겠어요?
분명 자기가 여러분보다 스마트한줄 알고 있는 VS2005(혹은 Orcas)가 컴파일 과정에서 코드를 자동으로 생성 했음을 짐작할 수 있을거에요. 그런데 사실 VS2005가 저보다는 훨씬 스마트한 것 같아요. VS가 발전하다보면 제가 필요 없어질 날이 올지도 몰라요ㅠ.ㅜ

애플리케이션의 Main 찾기
그러면, 자동으로 생성된 파일은 어딨을까요?
여기에서 이 포스팅의 주제가 나옵니다. 오 Main이여 어디있는가?

아주 조금 눈치 빠른 개발자라면 회심의 미소를 지으며, 어쩌면 머리를 쓸어 넘기며 이렇게 얘기할 것입니다.
"훗, 범인은 솔루션 익스플로러 안에 있어. 범인은 app.xaml 바로 아래에 들어가 있는 app.xaml.cs 너다! 게다가 app.xaml.cs를 보면 Application을 상속하는 App 클래스가 정의되어 있어. 움직일 수 없는 증거지. 음하하핫!"

안됐지만 땡입니다.
app.xaml.cs도 물론 새 WPF 프로젝트를 만들때 위저드가 자동으로 만들어준 파일이긴 한데, app.xaml.cs를 삭제해도 아무런 이상 없이 잘 돌아갑니다. 정말이에요. 한번 새 WPF Windows 애플리케이션을 하나 만들고 app.xaml.cs 파일을 지워보세요. Window1.xaml.cs도 마찬가지구요.

그렇다면 진짜 범인은,
범인은.
범인은!
범인은?

해당 프로젝트 폴더아래의 obj\Debug (또는 Release)안에 App.g.cs안에 있어요. 끝.

썰렁.
옙. 썰렁하지만 그냥 이게 다에요.
...라고 하면 돌이 날라올지도 모르니 좀 더 자세히 얘기해볼께요.

XAML이 컴파일 될 때
서두에 WPF 애플리케이션은 Application 클래스로 대표되고 Application은 XAML에서 Application 엘리먼트로 표현된다고 했습니다. 이 말은 반대로 생각하면 XAML에서 Application 엘리먼트는 내부적으로 Application 클래스를 생성한다고도 할 수 있어요. 따라서 XAML에서 사용된 Application 엘리먼트는 우리의 스마트한 VS2005의 컴파일러가 내부적으로 Application 클래스를 정의하는 C#(또는 VB.NET) 코드를 생성할 거에요.

이렇게 컴파일러에 의해 자동으로 생성된 코드가 바로 "파일명.g.cs"(VB일 경우 .vb)인데요 추가 확장자 .g는 바로 자동으로 생성되었다는 Generated를 의미합니다.

기술적으로 좀더 정확하게 표현하자면 Application 엘리먼트는 반드시 x:Class 어트리뷰트를 통해 생성할 클래스의 이름을 정의해야하고 이렇게 정의된 클래스가 Application 클래스를 상속하여 코드로 구현되는거지요. 위의 예제에서라면 x:Class="App"라고 선언했으니 내부적으로 Class App : Application (VB.NET이라면 Class App Inherits Application)이란 코드를 생성해야겠죠. 이런 특성은 디자인타임에 프로젝트에 포함되어 컴파일되는 모든 XAML에 동일하게 적용되구요, 예를 들어 Window1.xaml이 어떤 클래스 정의을 가지고 있다면 Window1.g.cs란 파일이 생성되겠지요.

친절한 컴파일러씨
정말로 컴파일러가 필요한 클래스들을 정의했는지 app.g.cs를 열어볼까요? 눈치채셨겠지만 이미 다 확인하고 얘기하는거에요. 믿으세요. :-)

app.g.cs

//------------------------------------------------------------------------------

// <auto-generated>

//    This code was generated by a tool.

//    Runtime Version:2.0.50727.1302

//

//    Changes to this file may cause incorrect behavior and will be lost if

//    the code is regenerated.

// </auto-generated>

//------------------------------------------------------------------------------


using System;

// 나머지 using 선언은 생략...


namespace WindowsApplication2 {



    /// <summary>

    /// App

    /// </summary>

    public partial class App : System.Windows.Application {


        /// <summary>

        /// InitializeComponent

        /// </summary>

        [System.Diagnostics.DebuggerNonUserCodeAttribute()]

        public void InitializeComponent() {


            #line 4 "..\..\App.xaml"

            this.StartupUri = new System.Uri("Window1.xaml", System.UriKind.Relative);


            #line default

            #line hidden

        }


        /// <summary>

        /// Application Entry Point.

        /// </summary>

        [System.STAThreadAttribute()]

        [System.Diagnostics.DebuggerNonUserCodeAttribute()]

        public static void Main() {

            WindowsApplication2.App app = new WindowsApplication2.App();

            app.InitializeComponent();

            app.Run();

        }

    }


첫머리에 <auto-generated>라고 박혀있고 고쳐봤자 헛수고이니 삽질하지 말라고 친절하게 경고충고해주고 있네요.

다음으로 애플리케이션에서 사용하게될 어셈블리들을 using 문으로 선언해줬구요.
그 아래에 드디어 얘기 드린 Application을 상속하는 App 클래스의 정의가 나옵니다.
멤버 메소드로 InitializeComponent가 만들어져 있는데 자세한건 좀 이따가 보고 그 아래에 더 중요한 Main() 프로시저를 먼저 살펴볼께요.

네, 이 포스팅의 주제인 Main의 행방을 드디어 찾았네요. 이 시점에 바로 무릎을 치거나 이마를 치거나 손가락으로 딱 소리를 내면서 '그럼 그렇지 Main이 어디 가겠어!'라고 해야 합니다. 전 그랬어요. ㄱ-

Main의 코드 구성에 대해 설명드리는건 아마도 C#(또는 VB)를 해보신 분께는 무의미하겠구요, 그렇지 않은 분께는 죄송하게도 저 역시 .NET 언어를 제대로 공부하지 않은 상태라서 무리일 것 같습니다. 단순히 통빱으로 얘기드릴테니 헛소리한다 싶으면 가차없이 지적해주세요.

다시 반복하자면 Main() 프로시저는 곧 이 애플리케이션을 실행할 때 OS에 의해 호출되는 첫번째 프로시저이자 애플리케이션의 시작 지점이 됩니다. 흔히 엔트리 포인트라고 부르지요.
당연히 이 Main() 프로시저는 애플리케이션 전역에서 유일해야 하므로 Static 으로 선언되었죠.

바로 이 유일한 Main() 프로시저 내에서 우리가 작성할 애플리케이션의 새 인스턴스를 생성하고 뭐하는 놈인지 InitializeComponent 메소드를 호출한 후 너무나도 명백하게 애플리케이션을 시작하라는 Run 메소드를 호출하는게 전부입니다.

여기서 통밥이 있는 개발자라면 '아 Run은 애플리케이션이 어떻게든 종료되기 전까지는 반환되지 않겠군'이라고 감이 오실겁니다. 이에 대한 자세한 내용은 다음 기회로 미루고요. 먼저 밀려있는 InitializeComponent를 살펴보죠.

뭐 의미상으로는 명백합니다. 바로 해당 XAML에서 사용될 컴포넌트, 즉 마크업에서 정의된 엘리먼트나 엘리먼트의 어트리뷰트를 코드-비하인드의 클래스 및 속성으로 치환해주는 역할이죠.

곧바로 보기도 애매한 #line 지시자가 나오는데요, 보면 #line 4, #line default, #line hidden이 있네요. #line 4는 해당 라인의 해당 파일에 있는 코드라는 것을 의미하고, #line default/hidden은 디버깅시 브레이크 포인트를 보일지 숨길지 여부인데 어차피 이 코드들은 컴파일러가 자동으로 작성하니까 크게 중요하진 않아요.

중요한건, 아래의 코드죠.
this.StartupUri = new System.Uri("Window1.xaml", System.UriKind.Relative);
이건 좀 의미심장하죠? 바로 위의 #line 지시자가 가리키는 App.xaml의 4번째 라인을 볼까요?
StartupUri="Window1.xaml"
네, 바로 XAML에서 정의한 StartupUri가 어떻게 코드로 변환되었는지를 보여줍니다. XAML이 얼마나 직관적으로 프로그래밍을 할 수 있는지를 잘 보여줍니다.

나는 내 코드를 통제하고 싶다.
오 과연 친절한데다가 똑똑하기까지한 VS. 그간의 골치아픈 코드와의 전쟁은 가고 바야흐로 인간 중심적인 프로그래밍의 신천지가 열리는 것인가!

다시 한번 안됐지만 그럴리가 있겠습니까. 공짜 점심도 한두번이죠.
위의 예제야 단순한 코드라서 XAML의 장점이 눈에 띄지만 XAML이 만능은 아니에요.
분명히 XAML은 어떤 개체를 선언하고 속성을 설정하는데에는 C#, VB코드에 비해 보다 직관적이고 간단하지만 어떤 고도의 연산 작업이나 논리적인 상태를 관리하는데에는 절대적으로 코드가 우수합니다.

필연적으로 XAML의 선언만으로 코드를 자동 생성해서 쓰는게 아니라 내가 직접 작성한 코드를 끼워넣고 나아가 코드를 통해 XAML로 선언한 개체들을 제어할 필요가 있을 거에요. 개발자라면 내가 작성하는 애플리케이션의 코드는 내가 원하는대로 통제하고 싶어하는 게 당연하잖아요?

그런데 예제의 경우만 봐도 XAML에서 정의한 App 클래스가 멋대로 자동 생성 코드에서 정의 되어버렸죠. 그럼 자동으로 생성된 App 클래스를 수정해봤자 다시 컴파일하면 도루묵이 된단 얘기잖아요?!

상황이 역전되었지만 그럴리가 있겠습니까.
XAML에서 생성한 클래스는 얼마든지 개발자가 직접 작성한 코드에서 다시 정의할 수 있습니다. 바로 partial 키워드 덕분이죠.

쪼개고 쪼개고 또 쪼개고
객체지향의 개념이 등장한 이래로 코드 블럭은 점점 더 작아지고 갈라지고 전문화 되는게 일반적인 스타일이 되었죠. partial 키워드는 여기에 한술 더 떠서 동일한 클래스, 상속받거나 포함하는게 아닌 정확히 같은 클래스에 대한 정의를 코드의 다른 장소에서 할 수 있게 해줍니다.

※ 전통적인 C/C++에서 어떤 클래스를 컴파일러에게 알려주는 것을 선언(declaration)이라고 하고 선언된 클래스의 코드를 작성하여 구현한 것을 정의(definition)이라고 명백하게 구분하고 있지만 C#이나 VB처럼 선언과 동시에 정의하는 언어에서는 이 둘의 구분은 별 의미가 없을 것 같습니다. 본문에서 선언과 정의를 혼용하는 경우가 있으니 널리 양해 바랍니다.
다시 한번 졸린 눈을 비비고 App 클래스의 정의를 살펴볼까요?
public partial class App : System.Windows.Application
이 코드를 보고 아무 느낌이 없으셨다면 이미 이 글을 보실 필요가 없는 레벨의 분이거나 진지하게 자아비판을 좀 하셔야 할 분이겠습니다. 이 코드를 보고 뭔가 이상한 냄새를 맡았거나 partial이 뭐야? 하신 분은 축하합니다. 안드로메다 깐따삐야 별의 이름을 걸고 단언컨대 개발자로 대성하실거에요!

앞서 말한 것처럼 partial 키워드는 클래스의 정의를 다른 곳에서도 할 수 있게 하므로 App 클래스는 우리가 원하는 위치에 제어하고 싶은 코드를 자유롭게 배치할 수 있다는 거죠.

시작하면서 지워버렸던 App.xaml.cs 기억나시나요? 바로 여기에 위의 코드와 마찬가지로 Application을 상속하는 App 클래스가 정의되어 있었죠. 벌써 지워버린걸 어떻게 확인하겠습니까. 귀찮더라도 프로젝트를 하나 더 만들어서 확인해보죠.

App.xaml.cs

using System;

// 나머지 using 선언은 또 생략...

namespace WindowsApplication2

{

    /// <summary>

    /// Interaction logic for App.xaml

    /// </summary>


    public partial class App : System.Windows.Application

    {


    }

}


비록 내부에 아무런 코드도 없지만 컴파일러가 자동으로 생성한 App 클래스의 정의와 정확히 일치하는걸 확인할 수 있네요. partial 키워드가 서로 다른 위치에서 클래스의 정의를 할 수 있다고 해도 당연히 같은 클래스는 같은 형(type)을 가져야 합니다.

제가 얘기한게 참말인지 거짓말인지 확인하려면 간단히 partial 키워드를 지워보거나 public을 private으로 바꿔보시면 빌드에 실패하는 것을 확인할 수 있을거에요.

물론 C#이나 VB.NET을 제대로 공부하셨다면 partial 쯤이야 대수롭지 않게 여기시겠지만 저처럼 곁눈질로 공부하신 분이라면 MSDN을 참고하세요. 다행히 한글로도 있네요. :)


WPF는 화장빨?
WPF라고 해도 Foundation, 기초화장에 지나지 않아요. 화장이란건 때론 변장에 가까울 정도로 진할때도 있잖아요? WPF는 특히나 더 예쁘고 진한 화장을 위한 기초라고 생각해요. 그 뒤에는 아직 WIN32 API가 자리잡고 있죠. 뭔가 속은 듯한 기분도 들고 그렇죠?

하지만 Foundation이 '기초'화장이란것에 주목하세요. 분명 그 위에 개발자와 디자이너가 꿈꾸는 화려하고 멋진 인터페이스를 올려나갈 수 있다는게 더 중요하죠.

어쩌면 WPF가 화장빨인지 모르겠지만, 사실 사용자들에겐 밤새워 최적화한 눈물어린 코드 보다는 적당히 화사한 화장빨이 훨씬 더 잘 먹히잖아요? 늘 하는 얘기지만 좋은게 좋은거죠. :)


다음회 예고!
아직 XAML이 컴파일될 때 일어나는 비밀스런 일 중에 아직 소개하지 못한 것이 있었으니... 기대하시라 개봉박두?
신고
Posted by gongdo


티스토리 툴바