다음을 통해 공유


XAML 레이아웃 최적화

중요 API

레이아웃은 UI의 시각적 구조를 정의하는 프로세스입니다. XAML에서 레이아웃을 설명하는 기본 메커니즘은 패널을 통해서입니다. 패널을 통해 UI 요소를 배치하고 정렬할 수 있는 컨테이너 개체입니다. 레이아웃은 CPU 사용량과 메모리 오버헤드 모두에서 WinUI 앱의 비용이 많이 드는 부분이 될 수 있습니다. WinUI 앱의 레이아웃 성능을 개선하기 위해 수행할 수 있는 몇 가지 간단한 단계는 다음과 같습니다.

레이아웃 구조 줄이기

레이아웃 성능의 가장 큰 이득은 UI 요소 트리의 계층 구조를 단순화하는 것입니다. 패널은 시각적 트리에 있지만 단추 또는 사각형과 같은 요소를 생성하는 픽셀이 아닌 구조적 요소입니다. 비픽셀 생성 요소의 수를 줄여 트리를 단순화하면 일반적으로 성능이 크게 향상됩니다.

많은 WinUI UI는 패널과 요소의 깊고 복잡한 트리를 생성하는 중첩 패널에 의해 구현됩니다. 패널을 중첩하는 것이 편리하지만 대부분의 경우 더 복잡한 단일 패널을 사용하여 동일한 UI를 달성할 수 있습니다. 단일 패널을 사용하면 성능이 향상됩니다.

레이아웃 구조를 줄이는 경우

레이아웃 구조를 간단한 방식으로 줄이면(예: 최상위 페이지에서 중첩된 패널 하나를 줄이면) 눈에 띄는 효과가 없습니다.

가장 큰 성능 향상은 ListView 또는 GridView와 같이 UI에서 반복되는 레이아웃 구조를 줄이면 발생합니다. 이러한 ItemsControl 요소는 여러 번 인스턴스화되는 UI 요소의 하위 트리를 정의하는 DataTemplate을 사용합니다. 앱에서 동일한 하위 트리가 여러 번 중복되는 경우 해당 하위 트리의 성능이 향상되면 앱의 전반적인 성능에 곱한 영향을 줍니다.

예제

다음 UI를 고려합니다.

양식 레이아웃 예제

다음 예제에서는 동일한 UI를 구현하는 세 가지 방법을 보여 줍니다. 각 구현 선택은 화면에서 거의 동일한 픽셀을 생성하지만 구현 세부 정보는 크게 다릅니다.

옵션 1: 중첩 StackPanel 요소

이 모델은 가장 간단한 모델이지만 5개의 패널 요소를 사용하므로 상당한 오버헤드가 발생합니다.

  <StackPanel>
  <TextBlock Text="Options:" />
  <StackPanel Orientation="Horizontal">
      <CheckBox Content="Power User" />
      <CheckBox Content="Admin" Margin="20,0,0,0" />
  </StackPanel>
  <TextBlock Text="Basic information:" />
  <StackPanel Orientation="Horizontal">
      <TextBlock Text="Name:" Width="75" />
      <TextBox Width="200" />
  </StackPanel>
  <StackPanel Orientation="Horizontal">
      <TextBlock Text="Email:" Width="75" />
      <TextBox Width="200" />
  </StackPanel>
  <StackPanel Orientation="Horizontal">
      <TextBlock Text="Password:" Width="75" />
      <TextBox Width="200" />
  </StackPanel>
  <Button Content="Save" />
</StackPanel>

옵션 2: 단일 그리드

Grid는 복잡성을 더하지만 단일 패널 요소만 사용합니다.

<Grid>
  <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <TextBlock Text="Options:" Grid.ColumnSpan="2" />
  <CheckBox Content="Power User" Grid.Row="1" Grid.ColumnSpan="2" />
  <CheckBox Content="Admin" Margin="150,0,0,0" Grid.Row="1" Grid.ColumnSpan="2" />
  <TextBlock Text="Basic information:" Grid.Row="2" Grid.ColumnSpan="2" />
  <TextBlock Text="Name:" Width="75" Grid.Row="3" />
  <TextBox Width="200" Grid.Row="3" Grid.Column="1" />
  <TextBlock Text="Email:" Width="75" Grid.Row="4" />
  <TextBox Width="200" Grid.Row="4" Grid.Column="1" />
  <TextBlock Text="Password:" Width="75" Grid.Row="5" />
  <TextBox Width="200" Grid.Row="5" Grid.Column="1" />
  <Button Content="Save" Grid.Row="6" />
</Grid>

옵션 3: 단일 RelativePanel

이 단일 패널은 중첩된 패널을 사용하는 것보다 약간 더 복잡하지만 그리드보다 이해하고 유지 관리하기 쉬울 수 있습니다.

<RelativePanel>
  <TextBlock Text="Options:" x:Name="Options" />
  <CheckBox Content="Power User" x:Name="PowerUser" RelativePanel.Below="Options" />
  <CheckBox Content="Admin" Margin="20,0,0,0" 
            RelativePanel.RightOf="PowerUser" RelativePanel.Below="Options" />
  <TextBlock Text="Basic information:" x:Name="BasicInformation"
           RelativePanel.Below="PowerUser" />
  <TextBlock Text="Name:" RelativePanel.AlignVerticalCenterWith="NameBox" />
  <TextBox Width="200" Margin="75,0,0,0" x:Name="NameBox"               
           RelativePanel.Below="BasicInformation" />
  <TextBlock Text="Email:"  RelativePanel.AlignVerticalCenterWith="EmailBox" />
  <TextBox Width="200" Margin="75,0,0,0" x:Name="EmailBox"
           RelativePanel.Below="NameBox" />
  <TextBlock Text="Password:" RelativePanel.AlignVerticalCenterWith="PasswordBox" />
  <TextBox Width="200" Margin="75,0,0,0" x:Name="PasswordBox"
           RelativePanel.Below="EmailBox" />
  <Button Content="Save" RelativePanel.Below="PasswordBox" />
</RelativePanel>

이러한 예제에서와 같이 동일한 UI를 달성하는 방법에는 여러 가지가 있습니다. 성능, 가독성 및 유지 관리를 비롯한 모든 장단 사항을 신중하게 고려하여 선택해야 합니다.

겹치는 UI에 단일 셀 표 사용

일반적인 UI 요구 사항은 요소가 서로 겹치는 레이아웃을 갖는 것입니다. 일반적으로 내부 여백, 외부 여백, 정렬 및 변형은 요소를 이러한 방식으로 배치하는 데 사용됩니다. XAML Grid 컨트롤은 겹치는 요소의 레이아웃 성능을 향상시키기 위해 최적화되어 있습니다.

중요 향상된 내용을 보려면 단일 셀 그리드를 사용합니다. RowDefinitions 또는 ColumnDefinitions를 정의하지 마세요.

예제

<Grid>
    <Ellipse Fill="Red" Width="200" Height="200" />
    <TextBlock Text="Test" 
               HorizontalAlignment="Center" 
               VerticalAlignment="Center" />
</Grid>

원 위에 겹쳐진 텍스트

<Grid Width="200" BorderBrush="Black" BorderThickness="1">
    <TextBlock Text="Test1" HorizontalAlignment="Left" />
    <TextBlock Text="Test2" HorizontalAlignment="Right" />
</Grid>

표에 있는 두 개의 텍스트 블록

패널의 기본 제공 테두리 속성 사용

Grid, StackPanel, RelativePanelContentPresenter 컨트롤에는 XAML에 테두리 요소를 추가하지 않고 테두리를 그릴 수 있는 기본 제공 테두리 속성이 있습니다. 기본 제공 테두리를 지원하는 새로운 속성은 BorderBrush, BorderThickness, CornerRadiusPadding입니다. 이러한 각 항목은 DependencyProperty이므로 바인딩 및 애니메이션과 함께 사용할 수 있습니다. 별도의 Border 요소를 완전히 대체하도록 설계되었습니다.

UI에 이러한 패널 주위에 테두리 요소가 있는 경우 기본 제공 테두리를 대신 사용하여 앱의 레이아웃 구조에 추가 요소를 저장합니다. 앞에서 설명한 것처럼 이는 특히 반복되는 UI의 경우 상당한 절감이 될 수 있습니다.

예제

<RelativePanel BorderBrush="Red" BorderThickness="2" CornerRadius="10" Padding="12">
    <TextBox x:Name="textBox1" RelativePanel.AlignLeftWithPanel="True"/>
    <Button Content="Submit" RelativePanel.Below="textBox1"/>
</RelativePanel>

SizeChanged 이벤트를 사용하여 레이아웃 변경에 응답

FrameworkElement 클래스는 레이아웃 변경에 응답하기 위한 두 가지 유사한 이벤트인 LayoutUpdatedSizeChanged를 노출합니다. 레이아웃 중에 요소의 크기가 조정될 때 이러한 이벤트 중 하나를 사용하여 알림을 받을 수 있습니다. 두 이벤트의 의미 체계는 다르며 둘 중에서 선택할 때 중요한 성능 고려 사항이 있습니다.

좋은 성능을 위해 SizeChanged 는 거의 항상 올바른 선택입니다. SizeChanged 에는 직관적인 의미 체계가 있습니다. FrameworkElement의 크기가 업데이트된 경우 레이아웃 중에 발생합니다.

LayoutUpdated 는 레이아웃 중에도 발생하지만 전역 의미 체계가 있으며 요소가 업데이트될 때마다 모든 요소에서 발생합니다. 이벤트 처리기에서만 로컬 처리를 수행하는 것이 일반적이며, 이 경우 코드가 필요 이상으로 자주 실행됩니다. 크기를 변경하지 않고 요소의 위치를 변경해야 하는 경우에만 LayoutUpdated 를 사용합니다(일반적이지는 않습니다).

패널 중 선택하기

일반적으로 성능은 개별 패널 중에서 선택할 때 고려 사항이 아닙니다. 이러한 선택은 일반적으로 구현하는 UI에 가장 가까운 레이아웃 동작을 제공하는 패널을 고려하여 결정됩니다. 예를 들어 Grid, StackPanelRelativePanel 중에서 선택하는 경우 구현의 정신 모델에 가장 가까운 매핑을 제공하는 패널을 선택해야 합니다.

모든 XAML 패널은 우수한 성능을 위해 최적화되며, 모든 패널은 유사한 UI에 유사한 성능을 제공합니다.