WPF에서 정적 리소스와 동적 리소스의 차이 및 실질적인 동작 방식

WPF에서는 리소스를 StaticResourceDynamicResource 두 가지 방식으로 참조할 수 있습니다. 이 둘은 문법상으로는 비슷해 보이지만, 작동 시점과 갱신 방식에 중요한 차이가 있습니다. 아래 예제를 통해 그 동작을 자세히 살펴보겠습니다.

기본 예제: 두 버튼이 같은 브러시 리소스 참조

다음 XAML 코드는 하나의 SolidColorBrush 리소스를 정의하고, 이를 두 개의 버튼이 각각 다른 방식으로 참조하는 상황을 보여줍니다.

XAML 코드 보기
<Window x:Class="WpfAppDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Resource Test" Height="300" Width="500">
    
    <Window.Resources>
        <SolidColorBrush x:Key="SharedBrush" Color="Blue"/>
    </Window.Resources>

    <StackPanel Margin="20">
        <Button Content="Apply Change" Width="150" Height="40" 
                Click="ChangeBrushColor_Click" Margin="0,0,0,20"/>

        <!-- DynamicResource로 참조 -->
        <Button Content="Dynamic Button" Background="{DynamicResource SharedBrush}" 
                Width="200" Height="50" Margin="0,0,0,10"/>

        <!-- StaticResource로 참조 -->
        <Button Content="Static Button" Background="{StaticResource SharedBrush}" 
                Width="200" Height="50"/>
    </StackPanel>
</Window>

코드비하인드: 리소스 속성 변경

버튼 클릭 시 리소스의 Color 프로퍼티를 수정하는 이벤트 핸들러입니다.

C# 코드 보기
private void ChangeBrushColor_Click(object sender, RoutedEventArgs e)
{
    if (Resources.Contains("SharedBrush"))
    {
        var brush = (SolidColorBrush)Resources["SharedBrush"];
        brush.Color = Colors.Purple; // 색상 변경
    }
}

실행 결과 및 분석

위 코드를 실행하고 "Apply Change" 버튼을 클릭하면, 두 버튼 모두 색상이 변합니다. 이는 다소 직관적이지 않을 수 있지만, 그 이유는 다음과 같습니다:

  • 리소스 공유 메커니즘: WPF에서 리소스 딕셔너리에 등록된 객체는 기본적으로 참조로 공유됩니다. 즉, {StaticResource SharedBrush}{DynamicResource SharedBrush} 모두 동일한 SolidColorBrush 인스턴스를 가리킵니다.
  • 프로퍼티 변경 vs 리소스 교체: 여기서는 리소스 자체를 제거하거나 새로 추가하지 않고, 기존 객체의 Color 프로퍼티만 수정했습니다. 따라서 이 객체를 참조하는 모든 UI 요소는 변경된 값을 반영하게 됩니다.

정적 리소스도 왜 업데이트되는가?

일반적인 오해는 StaticResource가 초기 로드 시 한 번만 해석되고 이후에는 갱신되지 않는다는 점입니다. 맞는 말이긴 하지만, 객체 상태의 변경까지 무시하는 것은 아닙니다. 정적 리소스는 참조 시점에 객체를 가져오지만, 그 객체가 후에 변경되면 UI에서도 변화가 나타날 수 있습니다 — 특히 해당 객체가 Freezable 계열이고 프로퍼티 변경 알림을 지원할 경우 그렇습니다.

실시간 반응 없애는 방법

만약 정적 리소스를 사용하는 컨트롤이 리소스 변경에 반응하지 않기를 원한다면, 다음 중 하나의 전략을 사용해야 합니다.

방법 1: 리소스 전체를 재등록

기존 리소스를 제거하고 새로운 인스턴스를 삽입하면, 정적 리소스로 참조된 객체는 여전히 이전 인스턴스를 유지하지만, 동적 리소스는 새 인스턴스를 바인딩하게 됩니다.

private void ChangeBrushColor_Click(object sender, RoutedEventArgs e)
{
    Resources.Remove("SharedBrush");
    Resources.Add("SharedBrush", new SolidColorBrush(Colors.Orange));
}

방법 2: 정적 값으로 직접 지정

리소스 참조 대신 배경색을 직접 지정하면, 리소스 변경과 완전히 독립됩니다.

<Button Content="Static Button" Background="Blue" Width="200" Height="50"/>

방법 3: 복사본 생성 후 할당

리소스로부터 복사본을 만들어 정적 컨텍스트에 사용하면, 공유 참조를 피할 수 있습니다.

var originalBrush = (SolidColorBrush)Resources["SharedBrush"];
var copiedBrush = originalBrush.Clone();
btnStatic.Background = copiedBrush;

이처럼, StaticResourceDynamicResource의 차이는 단순히 "갱신 여부"보다 더 깊은 객체 생명주기와 공유 모델에 달려 있음을 이해하는 것이 중요합니다.

태그: WPF StaticResource DynamicResource 리소스 관리 XAML

7월 18일 18:36에 게시됨