WPF프로젝트를 지난 5년간 진행하면서 덩치가 너무 커진 탓인지
속도가 너무 늦다는 지적을 현장에서 받아오면서, 이 문제를 어떻게 처리할까... 한참을 고민하던 끝에 다음 달 릴리즈를 앞둔 마당에 이 글을 적어봅니다.

초기 표시 (렌더링) 속도 개선방법
여기에서는 초기 표시, 즉 화면을 인스턴스 화해서 그려질 때까지의 시간을 단축하기 위한 개선책과
화면을 다시 그릴 때의 처리시간 단축 방법을 이야기하고자 합니다.

 

렌더링, WPF레이아웃이 무엇이냐?? 아래의 마이크로소프트 링크를 참고하세요.

 

완화: WPF 창 렌더링

Windows 8 이상에서 실행되는 .NET Framework 4.6에서 WPF 창 렌더링의 영향 및 완화에 대해 알아봅니다.

docs.microsoft.com

 

 

완화: WPF 레이아웃

한 픽셀씩 이동하는 개체의 배치와 같이 WPF 컨트롤 레이아웃을 변경하여 발생하는 문제를 완화하는 방법에 대해 알아봅니다.

docs.microsoft.com

 

 

1. 컨트롤의 재배치 처리 횟수를 줄이자
  WPF는 기본적으로 화면의 각 요소는 상대적 좌표 크기를 결정합니다.
  컨트롤의 "HorizontalAlignment"또는 "Width"에 "Auto"를 설정할 수 있는 것이 그 증거입니다.
  이렇게 함으로써 사용자가 화면 크기를 변경하거나 해상도가 다른 디스플레이에서도
  화면의 표시내용을 담아내는 것을 제작하는 것이 가능하게 되어 있습니다.

  그러나 이때의 배치 구조는 Xaml 부모 요소에서 자식 요소에 여러 번 왕래하고 크기를 조정하고
  최종 렌더링 된다는 것입니다.
  이 재배치 처리에 시간이 걸리면 당연히 표시할 때까지의 시간도 늦어집니다.

  이 문제를 해결하려면 다음 방법을 검토하십시오.

크기를 고정한다.
  ⇒Width / Height는 고정값으로 합니다.
부모 패널을 Canvas 한다.
  ⇒ 절대 좌표로 지정하여 그리기 좌표를 재계산하지 않아도 됩니다.
문자 혹은 도형을 코드로 렌더링 한다.
  ⇒ Xaml 대신 코드 측에서 직접 그리는 방법입니다.
   자세한 내용은 코드로 문자 나 도형을 그리기를 참조하십시오.

2. 자신 컨트롤을 UserControl에서 사용자 지정 컨트롤로 변경한다.
  WPF에서 컨트롤을 만드는 방법은 주로 다음 두 가지입니다.
  (1) UserControl에서 컨트롤을 복합적으로 사용한다.
  (2) 사용자 지정 컨트롤 모양과 구조를 직접 구현한다.
    (또는 기존의 컨트롤을 상속 기능을 추가한다.)

  기본적인 것이지만, 컨트롤 클래스는 파생할 정도로 기능이 증가 · 복잡화하고
  재배치 처리에 시간이 걸릴 수 있습니다.
  UserControl은 Window와 마찬가지로 View를 가지고 있기 때문에 재배치 처리에 시간이 걸립니다. 
  UserControl의 수가 증가할수록 내부의 요소가 복잡할수록 그것은 눈에 띄게 됩니다.

  이를 방지하려면 사용자 정의 컨트롤을 구현하십시오.
  사용자 정의 컨트롤을 구현하는 프로젝트는 Visual Studio에 포함되어 있습니다.
  (프로젝트의 추가 메뉴에서 " WPF 사용자 정의 컨트롤 라이브러리"라는 항목이 있습니다.)
  일반 프로젝트에 사용자 지정 컨트롤을 추가하지 않도록 주의합시다.

3. 의존관계 속성을 정확히 사용한다.
  의존관계 속성은 데이터 바인딩을 사용하는 구조에서
  사용자 컨트롤의 속성은 기본적으로 이를 구현합니다.
  일반적 속성도 처음에만 데이터 바인딩은 작동하지만,
  이후의 속성 값의 변화에 대응할 수 없습니다.
  또한 일반적인 속성은 런타임에 데이터 바인딩을 사용할 때,
  리플렉션을 이용하고 있기 때문에 의존관계 속성보다 속도가 느립니다.

4. 렌더링 속도를 향상할 수 있는 속성
  사용자 컨트롤의 기본 클래스 "Control"또는 "FrameworkElement"에는
  값을 설정하여 렌더링 속도를 향상시킬 수있는 몇 가지 속성이 존재합니다.
  Xaml의 상대적인 레이아웃 설정의 장점을 없애는 것도 있지만,
  다음의 속성을 설정하는 것을 고려하십시오.

· IsHitTestVisible (기본값 : false)
   true로 설정하면 컨트롤을 수행할 수 없습니다.
   마우스 오버와 클릭 등의 작업을 일체 행하지 않습니다.
   조작이 불필요한 컨트롤에 이것을 설정하여 불필요한 이벤트가 발생하지 않고,
   속도의 향상을 기대할 수 있습니다.

· ClipToBounds (기본값 : false)
   true로 설정하면 컨트롤의 자식 요소가 자신의 그리기 범위를 벗어난 영역에 그려지지 않습니다.
   그리기 영역이 한정되기 때문에, 동작 속도의 향상을 기대할 수 있습니다.
   그러나 재배치 작업이 발생하는 점에 주의하십시오.

· Width / Height (기본값 : Auto)
   고정 값으로 설정하면 재배치 처리 횟수를 줄일 수 있습니다.
   마찬가지로 "MaxWidth", "MinWidth", "MaxHeight", "MinHeight"도 고정 값으로 설정하는 것을 권장합니다.

UserControl 전반적으로 위의 문제를 다시 한번 생각하고 재배치하여, 
기존 3초 정도의 렌더링 완료가 되었던 화면이 1초 만에 완료되도록 개선되었기에 
정보를 정리해두도록 합니다.

+ Recent posts