WPF를 이야기하면서 XAML을 이야기 하지 않는 것은 안꼬없는 찐빵이요, 오아시스 없는 사막이다.
XAML을 어떻게 읽느냐에 대해서도 참 말들이 많다. XAML을 개발/소개한 자료들은 이것을 zammel 이라고 읽으라라고 명기했음에도 우리말이 아니다 보니 많은 사람들이 이마져도 어떻게 읽을지를 몰라, 발음기호인양 자멜이라고 읽기도 하고, 잼블이라고 읽기도 하고 혹은 그냥 액스.에이.엠.엘이라고 읽는 사람들도 있다. 미국현지에서 들어본 XAML의 정확한 발음은 우리글로 옮길경우 "제므얼" 정도가 가장 가까운 발음인것 같다. 제벌이 아니라 제므얼이다.(약간 빠다가 필요한 발음이다)
사실 개발시에 User Interface와 logic을 분리하는 것은 많은 개발자들에게 이미 익숙한 방식이다.
이미 우리는 Win16을 사용할 때부터, DialogBox나 Menu, Cursor등에 대한 정의를 rc 파일로 작성하여 logic을 담고 있는 C/C++ source와 분리하지 않았던가? 이렇게 분리되어 따로 구성되었던 파일은 각각 binary로 컴파일되고 결국 linking과정에서 실행파일을 구성할 때 다시 결합되는 형태를 띄고 있었다. Visual Basic(.net이 아니라)의 경우에도 frm 파일을 notepad로 열어보면 우리가 마우스로 긁적인 Form은 나름대로의 구조를 가진 frm 파일로 작성되고 있음을 알 수 있다.
그런데, C#와 VB.NET 그리고 .NET Framework으로 무장한 Visual Studio.net 2002이 출시되자, 마치 지금까지 code와 ui definition file(frm 이나 rc 등)을 분리하는 것이 마치 비효율적인 것인양 그 구조가 완전히 변경되어 버렸다.
C#에서 UI를 긁적긁적거리면, 그 결과가 모두 C# 코드로(혹은 자신이 지정한 .NET 기반 언어로) 변경되어 저장된다.(고생은 많이 했다만은) 이렇게 작성된 UI 초기화용(?) 코드들은 눈가리고 아웅하듯이 살짝숨겨져 있으며, "맘대로 변경하지마시오" 라고 comment가 달려있었다. 만약 이곳에 포함되어 있는 코드들을 임의로 변경하기라도 하면, Form Designer로는 다시 불러올 수 없는 끔찍한 상황이 벌어지기도 한다. 내가 만드는 souce code를 내가 마음대로 변경할 수 없다는 것이 적절한 것이라고 생각하는가? 쉽게 form을 구성하는 것만큼이나 효율적으로 form을 구성하는 것이 더 중요하다고 믿는 명신에게는 개발툴의 이러한 단점은 최악의 시나리오로 느껴질 뿐이었다. Visual Studio.net 2003을 거쳐 Visual Studio 2005가 출시되었으나, winform desinger는 여전히 변경된 것이 별로 없다. 유일하게 달라진 점이라면, C#의 partial modifier를 이용하여, UI를 구성하는 코드를 독립된 파일로 분리시키고 있을 뿐이다.(partial keyword는 class 선언시에 쓸 수 있는 modifer로써 다수의 파일에서 하나의 class를 동시에 정의할 수 있도록 한다.)
winform으로 application을 작성해본 사람이라면 알겠지만, 하나의 form에 대략 수십개의 control들을 가져다 놓고, 이전 동작을 취소하기 위해서 ctrl+z를 눌러보면 그 느린 속도에 한숨이 나올 정도다. (내부적인 메커니즘은 정확히 확인할 방법이 없으나 ctrl+z를 누르면 UI 작성하는 코드를 재생성 하는 것으로 보인다.)
이렇듯 한심한 방식은 WPF로의 프로그램 기법에서 고전의 방법으로 회기하고 있다. 단지 UI를 표현하는 file을 XML을 기반으로 하고, 새로운 규격을 정의한 것 정도가 새로울 뿐이다. 구관이 명관임을 지나서야 깨달은 것이리라.
이제 XAML 이란 놈은 조금 자세히 살펴볼 필요가 있다. 일단 확장자는 .xaml 이다. XAML이 처음 정의되었을 때는 eXtensible Avalon Markup Language 이었고 나중에 Avalon이 Application으로 바뀌었다.
이미 작성된 XAML 살짝 들여다 보면 다음과 같은 구조로 되어 있음을 알 수 있다.
<Window x:Class="WPFApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPFApp" Height="300" Width="300">
<Button>Hello, XAML</Button>
</Window>
XML을 이해하고 있는 사람이라면 이 코드를 보았을 때, 대략적인 구조를 파악할 수 있다.(XML을 모른다면 곤란하다. 지금 모르는 것은 문제가 되지 않을 것이지만, 나중에도 모를 계획이라면 다른 직업을 찾아보자.)
2개의 namespace가 사용되고 있다.
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" 과 "http://schemas.microsoft.com/winfx/2006/xaml" 이 그것인데, 그 이름을 유심히 살펴볼 필요가 있다. 하나는 /xaml로 끝나고 하나는 거기에 /presentation이 더 붙어 있다.
잠깐 다른 이야기를 하고 다시 돌아오자. .net 에는 serialization이라는 기능이 있다. 이것은 특정 객체의 상태를 저장하거나 전달할 목적으로 객체의 내용을 선영화하는 기법이다. 선영화된 내용은 파일로 저장될 수도 있고, network을 통해서 다른 machine으로 전달될 수도 있다.(강력하지 않은가?) 객체를 어떻게 선영화 할 것인가에 대해서는 규칙이 있어야 한다. .net 에서는 binary serialization,xml serialization, SOAP serialization등을 제공하는데, xml serializer를 이용하면 객체의 상태를 xml로 변경해 준다.(물론 이렇게 저장된 xml 파일은 다시 deserialization 과정을 거쳐 객체로 부활될 수 있다). 아래에 그 예가 있다.
public class OrderForm
{
public DateTime OrderDate;
}
이렇게 생각 class의 instance를 xml serializer를 이용하여 저장하면, 아래와 같은 파일이 만들어진다.
<OrderForm>
<OrderDate>12/12/01</OrderDate>
</OrderForm>
이제 다시 위의 XAML을 다시 보자. 조금 달라보이는가? 중요부분만 때내어 생각해보면,
<Window Title="WPFApp" Height="300" Width="300">
<Button>Hello, XAML</Button>
</Window>
여기서 구조적인 2가지 특성을 파악할 수 있다. 먼저 Window 객체와 Button이 포함관계에 놓여져 있다는 것이고, 다른 하나는 각 객체의 특성을 저장하기 위해서 attirbute 혹은 value를 사용하고 있다는 것이다. 실제로 Window나 Button과 같은 element는 "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 에 의해서 정의되고 있다.
이러한 관점에서 XAML은 다음과 같은 의미를 가지고 있다고 볼 수 있겠다.
"XAML이란 객체들의 속성과 그 상관관계를 XML 기반의 언어로 표현하는 기법"
그런데, 이게 정말 XAML의 실체일까? 위의 정의는 반쪽짜리 정의다. 아직 알아보지 않은 namespace가 있지 않은가?
"http://schemas.microsoft.com/winfx/2006/xaml" 는 무엇일까? 위의 첫번째 예제를 보면 이 namespace를 사용하는 부분은 x:Class="WPFApp.Window1" 이 유일하다. 이것이 의미하는 것은 무엇일까?
또, 잠깐 다른 이야기를 하고 오자, 현대 언어의 대표적인 특성이라면 ADT(abstract data type)를 선언하고, 선언된 ADT를 생성하여 이용한다. 이는 크게 "선언과생성" 이라는 말로 간단히 표현될 수 있을 것이다. 이는 computing language들이 가지는 매우 중요한 특성중에 하나이다. 선언이란 결국 구조나 규칙을 정의하는 것이며, 생성이란 이렇게 작성된 구조나 규칙에 맞도록 값을 채우는 과정이다. XML을 language라고 부를 수 있는 것은 이것이 선언과 생성의 과정을 포함할 수 있기 때문이기도 하다.(flow가 있느냐 없느냐 하는 것은 필수요소가 아니다.) XML에서 선언은 DTD 혹은 XSD에 의해서 이루어 지며, 그 생성은 XML 파일 내에서 element 혹은 attribute로 작성된다.
다시 XAML로 돌아오자, x:Class의 의미는 무엇일까? 답부터 말하면 WPFApp는 언어의 namespace, Windows1은 class의 이름이다. 이게 갑자기 무슨 뜬금없는 소린가 하는 사람도 있을 것이다. XAML언어는 그 명세상 객체의 구조를 정의할 수 있는 기능도 포함하고 있다. 사실 XAML을 어떤 관점으로 보느냐에 따라 이 부분이 XAML의 실체일 수 있다.
실제로 XAML을 이용하면 class간의 상속관계를 표현할 수도 있으며 member의 공개수준을 정의할 수도 있으며, 배열을 표현할 수도 있다. 마치 우리가 C#으로 class를 선언하는 것 처럼 말이다. 몇가지만 예를 들어보자.
<object x:Class="namespace.classname"...>
...
</object>
<object x:Class="namespace.classname" x:ClassModifier="NonPublic">
...
</object>
<object x:Class="namespace.classname" x:Subclass="subclassnamespace.subclassname">
...
</object>
이러한 명세가 선언되어 있는 namespace가 바로 "http://schemas.microsoft.com/winfx/2006/xaml" 이다.
이러한 관점에서 XAML을 살펴본다면, "Application에서 필요한 객체의 구조를 구성하는 언어"로 표현될 수 있을 것이다. 이러한 XAML의 특성은 사실 WPF 자체와는 아무런 연관성을 가지지 않는다. WPF와 관련성을 가진 부분은 단지, 앞서 알아본 "http://schemas.microsoft.com/winfx/2006/xaml/presentation" namespace에서 정의하고 있는 부분뿐이다. 실제로 .NET Framework을 이루고 있는 또하나의 축인 WF(Windows Workflow Foundation)도 workflow를 표현하기 위해서 XAML을 사용하고 있다. 이 경우 WPF와 관련된 namespace는 필요하지 않다.
앞서 알아본 두가지 정의로 XAML을 다시 한번 확인해보자
1. "XAML이란 객체들의 속성과 그 상관관계를 XML 기반의 언어로 표현하는 기법"
2. "Application에서 필요한 객체의 구조를 구성하는 언어"
XAML을 언어의 관점에서 집중한다면 2번의 특성으로 XAML을 정의하는 것이 적절할 것이나, 실제로 2번의 정의만으로는 아무런 동작도 할 수 없을뿐더러 많은 사람들이 1과2의 특성을 묶어서 XAML이라고 말하고 있기 때문에, 명시적인 전제가 없는 한 이 두가지 모두를 XAML로 보는 것이 타당할 것이다.
앞서 과거 운운하면서 UI를 표현하기 위해서 XAML을 만듯 것인냥 이야기 하였지만(XAML을 처음으로 Designe 할때에는 실제로 UI를 표현하기 위한 언어이었을 것이다. 하지만 지금의 XAML은 의미가 많이 확장되어 있다.), 이것은 XAML의 활용예의 하나일 뿐이라는 것을 명확히 할 필요가 있다.
구체적인 사실에 대한 명확한 정의는 추상화를 거침에 따라 그 의미가 확장된다.