이게 없으면 실버라이트 스타일을 어떻게 했을까 몰라요.^^
무지 유용한 툴이니까 한번쯤 꼭 써보세요.
여튼 한가지 불편한 점은 스타일의 일부만 선택하고 Ctrl+C를 눌렀을 때 테스트 복사가 되지 않는다는 점이었는 데요, Ctrl+C로 클립보드에 복사되도록 코드를 수정해서 올립니다.
보너스로 각 엘리먼트 앞에 있는 접기/열기 표시인 -, +도 제거하도록 했어요.
토요일, 훈스닷넷의 시삽 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에 관해서는 하고 싶은 얘기가 정말 많네요. 다음 글에서 뵙죠.
20080216_HOONS_UX세미나_7주차.zipUX 커뮤니티 세미나 7주차 1세션 발표자료
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이란 숨겨진 요소(?)에 꽤 흥분했었거든요. 그래서 뭔가 재밌는 비밀이 있을 걸로 기대했는데, 결과적으로 최근엔 개발자를 불편하게 하는 차이점은 죄다 통합되고 사라지게 되었네요. 썰렁;
<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" />
<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" />
"훗, 범인은 솔루션 익스플로러 안에 있어. 범인은 app.xaml 바로 아래에 들어가 있는 app.xaml.cs 너다! 게다가 app.xaml.cs를 보면 Application을 상속하는 App 클래스가 정의되어 있어. 움직일 수 없는 증거지. 음하하핫!"
//------------------------------------------------------------------------------
// <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();
}
}
this.StartupUri = new System.Uri("Window1.xaml", System.UriKind.Relative);이건 좀 의미심장하죠? 바로 위의 #line 지시자가 가리키는 App.xaml의 4번째 라인을 볼까요?
StartupUri="Window1.xaml"네, 바로 XAML에서 정의한 StartupUri가 어떻게 코드로 변환되었는지를 보여줍니다. XAML이 얼마나 직관적으로 프로그래밍을 할 수 있는지를 잘 보여줍니다.
※ 전통적인 C/C++에서 어떤 클래스를 컴파일러에게 알려주는 것을 선언(declaration)이라고 하고 선언된 클래스의 코드를 작성하여 구현한 것을 정의(definition)이라고 명백하게 구분하고 있지만 C#이나 VB처럼 선언과 동시에 정의하는 언어에서는 이 둘의 구분은 별 의미가 없을 것 같습니다. 본문에서 선언과 정의를 혼용하는 경우가 있으니 널리 양해 바랍니다.다시 한번 졸린 눈을 비비고 App 클래스의 정의를 살펴볼까요?
public partial class App : System.Windows.Application이 코드를 보고 아무 느낌이 없으셨다면 이미 이 글을 보실 필요가 없는 레벨의 분이거나 진지하게 자아비판을 좀 하셔야 할 분이겠습니다. 이 코드를 보고 뭔가 이상한 냄새를 맡았거나 partial이 뭐야? 하신 분은 축하합니다. 안드로메다 깐따삐야 별의 이름을 걸고 단언컨대 개발자로 대성하실거에요!
using System;
// 나머지 using 선언은 또 생략...
namespace WindowsApplication2
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : System.Windows.Application
{
}
}