XAML Resources

김정환(John.Kim)
OldbeeDev
Published in
6 min readSep 25, 2017
©manfredsteger (pixabay)

XAML Resource는 Brush, Style, Font, Image 등의 XAML object를 말한다. 한번 정의된 Resource는 XAML 코드에서 재사용할 수 있다.
(참고로 프로젝트에 별도로 추가되는 이미지 파일같은 app resources와는 다른 것이다.)

Without Resources

배경색, 글자색, Margin이 동일한 3개의 버튼을 생성하는 XAML 이다.

<StackPanel>
<Button Margin="5"
Background="Gold" Foreground="White">
버튼1
</Button>
<Button Margin="5"
Background="Gold" Foreground="White">
버튼2
</Button>
<Button Margin="5"
Background="Gold" Foreground="White">
버튼3
</Button>
</StackPanel>

반복, 반복, 반복, 뭔가 Smell이 풍긴다.

Window Resources (Local Resources)

반복되는 배경색, 글자색, Margin을 아래와 같이 Window.Resource 영역에 정의한다. Resource를 정의할 때는 x:Key 속성에 고유한 이름을 입력하고, 버튼에 Resouce를 적용할 때는 StaticResource 구문을 사용한다.

<Window ...>
<Window.Resources>
<Thickness x:Key="ButtonMargin">5,5,5,5</Thickness>
<SolidColorBrush x:Key="ButtonBackgroundBrush" Color="Gold" />
<SolidColorBrush x:Key="ButtonTextBrush" Color="White" />
</Window.Resources>
<StackPanel>
<Button Margin="{StaticResource ButtonMargin}"
Background="{StaticResource ButtonBackgroundBrush}"
Foreground="{StaticResource ButtonTextBrush}"
Content="버튼1" />
...
</StackPanel>
</Window>

Application Resources (Global Resources)

위에서 정의한 ButtonTextBrush은 Window 영역에서만 유효하기 때문에 다른 Window의 버튼에 사용할 수 없다. ButtonTextBrush를 어플리케이션의 모든 버튼에 사용하려면 아래와 같이 App.xaml에 Resource를 정의해야 한다.

<Application ...>
<Application.Resources>
<SolidColorBrush x:Key="ButtonTextBrush" Color="White" />
</Application.Resources>
</Application>

Window.Resources에 정의했던 ButtonTextBrush는 삭제한다. 각 버튼에 적용하는 코드에는 변함이 없다.

Resource Dictionary

Application Resource가 많아지면 이들을 별도의 파일로 관리하는 것이 좀더 효과적일 수 있다. 이렇게 Resource만 모아놓은 xaml 파일을 Resource Dictionary라고 부르며 아래와 같은 순서로 만든다.

  1. 메뉴를 통해 Resource Dictionary를 생성한다.

2. 파일명을 TextResources.xaml로 정하고 ButtonTextBrush Resource를 정의한다.

<ResourceDictionary ... >
<SolidColorBrush x:Key="ButtonTextBrush" Color="White" />
</ResourceDictionary>

3. TextResources.xaml을 App.xaml의 ResourceDictionary.MergedDictionaries 내부에 포함시킨다.

<Application ...>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="TextResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

Resource 오타

Resource 이름에 오타가 있는 경우 컴파일할 때 문제가 걸러지지 않는다. 디버깅 모드일 때는 exception을 띄워주지만 릴리즈 모드일 때는 그냥 조용히 죽는다. 또한 Window1에 정의된 Resource를 Window2에서 사용할 수 없다고 했는데도 불구하고, 만약 그렇게 코딩을 해놓으면 실행 중인 어플리케이션 입장에서는 오타와 다를 바가 없다.

배포 이후에 이런 문제점이 나타나면 원인을 찾기가 매우 어렵다. XAML Desinger에서 undefined resource에 대해 밑줄을 뿌려주기는 하지만 사용해보면 약간 부족하다.

Resource Copy & Paste

어플리케이션의 모든 Resource를 한 곳에 보관하면 편하고 좋을 것 같은데, 실상은 조금 불편한 부분도 존재한다. 예를 들어 A 프로젝트에서 만든 AwesomePopup을 B 프로젝트에서 사용하려고 할 때 모든 Resource가 ResourceDictionary.xaml에 따로 보관되어 있었다면, AwesomePopup에서 실제 사용하는 Resource를 일일이 확인해서 B 프로젝트에 옮겨와야 하는 수고로움이 발생한다. 그러다가 Resource 이름이 충돌나기라도 하면 더 귀찮은 상황이 된다. 만약 AwesomePopup이 Window resources 영역에서만 정의되었다면 그냥 AwesomePopup.xaml 한 파일만 복사하면 간단히 끝났을 것이다.

Wrapup :

XAML의 왠만한 속성 값은 Resource로 정의해서 쓰는 것이 가독성이나 나중 수정을 위해서도 유리하다. = 2017년 생각.
한 XAML 파일 안에서 중복되는 것들은 여전히 Resource로 정의하는 것이 좋지만, Global Resource에 대해서는 좀 더 신중함이 필요하다. Global은 진짜 필요하다고 판단될 때, 그리고 팀원간에 의견을 공유한 후에 적용하는 것이 바람직하다. = 2019년 생각.

--

--