시작 및 활성화를 처리하는 방법을 개선하여 최적의 시작 시간을 사용하여 UWP(유니버설 Windows 플랫폼) 앱을 만듭니다.
앱의 시작 성능에 대한 모범 사례
부분적으로 사용자는 앱이 시작하는 데 걸리는 시간을 기준으로 앱이 빠르거나 느린지 여부를 인식합니다. 이 항목의 목적을 위해 앱의 시작 시간은 사용자가 앱을 시작할 때 시작되고 사용자가 의미 있는 방식으로 앱과 상호 작용할 수 있을 때 종료됩니다. 이 섹션에서는 앱이 시작될 때 더 나은 성능을 얻는 방법에 대한 제안을 제공합니다.
앱의 시작 시간 측정
실제로 시작 시간을 측정하기 전에 앱을 몇 번 시작해야 합니다. 이렇게 하면 측정에 대한 기준이 제공되고 가능한 한 짧은 시작 시간을 측정할 수 있습니다.
UWP 앱이 고객의 컴퓨터에 도착할 때까지 앱은 .NET 네이티브 도구 체인으로 컴파일되었습니다. .NET 네이티브는 MSIL을 고유하게 실행 가능한 머신 코드로 변환하는 미리 컴파일 기술입니다. .NET 네이티브 앱은 MSIL 앱보다 더 빠르게 시작하고, 메모리를 적게 사용하고, 배터리를 적게 사용합니다. .NET Native로 빌드된 애플리케이션은 사용자 지정 런타임에 정적으로 링크되며, 모든 디바이스에서 실행할 수 있는 새롭게 통합된 .NET Core를 사용하여 기본 제공 .NET 구현에 의존하지 않습니다. 개발 머신에서 기본적으로 앱은 "릴리스" 모드로 빌드하는 경우 .NET 네이티브를 사용하고, "디버그" 모드에서 빌드하는 경우 CoreCLR을 사용합니다. Visual Studio의 빌드 페이지에서 "속성"(C#) 또는 "내 프로젝트"(VB)의 Compile->Advanced에서 구성할 수 있습니다. ".NET 네이티브 도구 체인으로 컴파일"이라고 되어 있는 확인란을 찾습니다.
물론 최종 사용자가 경험하게 될 내용을 나타내는 측정값을 수행해야 합니다. 따라서 개발 컴퓨터에서 네이티브 코드로 앱을 컴파일하고 있는지 확실하지 않은 경우 시작 시간을 측정하기 전에 네이티브 이미지 생성기(Ngen.exe) 도구를 실행하여 앱을 미리 컴파일할 수 있습니다.
다음 절차에서는 Ngen.exe 실행하여 앱을 미리 컴파일하는 방법을 설명합니다.
실행하려면 Ngen.exe
앱이 Ngen.exe에 의해 감지되는지 확인하려면 최소한 한 번 실행하십시오.
다음 중 하나를 수행하여 작업 스케줄러 엽니다.
- 시작 화면에서 "작업 스케줄러"를 검색합니다.
- "taskschd.msc"를 실행합니다.
작업 스케줄러왼쪽 창에서 작업 스케줄러 라이브러리확장합니다.
Microsoft를 확장합니다.
Windows를 확장합니다.
.NET Framework선택합니다.
작업 목록에서 .NET Framework NGEN 4.x 선택합니다.
64비트 컴퓨터를 사용하는 경우 .NET Framework NGEN v4.x 64도 있습니다. 64비트 앱을 빌드하는 경우,NET Framework NGEN v4.x 64을 선택하세요.
작업 메뉴에서 실행클릭하세요.
Ngen.exe 사용된 컴퓨터의 모든 앱 중 네이티브 이미지가 없는 것을 사전 컴파일합니다. 미리 컴파일해야 하는 앱이 많은 경우 시간이 오래 걸릴 수 있지만 후속 실행은 훨씬 빠릅니다.
앱을 다시 컴파일하면 네이티브 이미지가 더 이상 사용되지 않습니다. 대신 앱이 Just-In-Time 컴파일되므로 앱이 실행될 때 컴파일됩니다. 새 네이티브 이미지를 가져오려면 Ngen.exe 다시 실행해야 합니다.
가능한 한 오래 작업 연기
앱의 시작 시간을 개선하려면 사용자가 앱과 상호 작용을 시작할 수 있도록 반드시 수행해야 하는 작업만 수행합니다. 이는 추가 어셈블리 로드를 지연할 수 있는 경우에 특히 유용합니다. 공용 언어 런타임은 어셈블리를 처음 사용할 때 로드합니다. 로드되는 어셈블리 수를 최소화할 수 있는 경우 앱의 시작 시간과 메모리 사용량을 향상시킬 수 있습니다.
장기 실행 작업을 독립적으로 수행
앱이 완전히 작동하지 않는 부분이 있더라도 앱은 대화형일 수 있습니다. 예를 들어 앱에서 검색하는 데 시간이 걸리는 데이터를 표시하는 경우 데이터를 비동기적으로 검색하여 해당 코드를 앱의 시작 코드와 독립적으로 실행하도록 할 수 있습니다. 데이터를 사용할 수 있는 경우 앱의 사용자 인터페이스를 데이터로 채웁니다.
데이터를 검색하는 대부분의 UWP(유니버설 Windows 플랫폼) API는 비동기이므로 어쨌든 데이터를 비동기적으로 검색할 수 있습니다. 비동기 API에 대한 자세한 내용은 C# 또는 Visual Basic의 비동기 API 호출에 대해 설명하는 또는을 참고하세요. 비동기 API를 사용하지 않는 작업을 수행하는 경우 사용자가 앱과 상호 작용하는 것을 차단하지 않도록 Task 클래스를 사용하여 장기 실행 작업을 수행할 수 있습니다. 이렇게 하면 데이터가 로드되는 동안 앱이 사용자에게 응답하도록 유지됩니다.
앱이 UI의 일부를 로드하는 데 특히 오랜 시간이 걸리는 경우 사용자가 앱이 여전히 처리 중임을 알 수 있도록 "최신 데이터 가져오기"와 같은 문자열을 해당 영역에 추가하는 것이 좋습니다.
시작 시간 최소화
가장 간단한 앱을 제외한 모든 앱은 리소스를 로드하고, XAML을 구문 분석하고, 데이터 구조를 설정하고, 활성화 시 논리를 실행하는 데 상당한 시간이 필요합니다. 여기서는 활성화 프로세스를 세 단계로 나누어 분석합니다. 또한 각 단계에서 소요되는 시간을 줄이기 위한 팁과 앱 시작의 각 단계를 사용자에게 더 맛있게 만들기 위한 기술을 제공합니다.
활성화 기간은 사용자가 앱을 시작하는 순간과 앱이 작동하는 순간 사이의 시간입니다. 이는 앱에 대한 사용자의 첫 인상이기 때문에 중요한 시기입니다. 시스템 및 앱에서 즉각적이고 지속적인 피드백을 기대합니다. 앱이 빠르게 시작되지 않을 때 시스템과 앱이 손상되거나 제대로 설계되지 않은 것으로 인식됩니다. 설상가상으로 앱을 활성화하는 데 시간이 너무 오래 걸리면 PLM(프로세스 수명 관리자)이 앱을 종료하거나 사용자가 제거할 수 있습니다.
시작 단계 소개
시작에는 다양한 이동 조각이 포함되며, 최상의 사용자 환경을 위해 모든 부분을 올바르게 조정해야 합니다. 다음 단계는 앱 타일을 클릭하는 사용자와 표시되는 애플리케이션 콘텐츠 간에 발생합니다.
- Windows 셸이 프로세스를 시작하고 Main이 호출됩니다.
- Application 개체가 만들어집니다.
- (프로젝트 템플릿) 생성자는 InitializeComponent를 호출하여 App.xaml을 구문 분석하고 개체를 만듭니다.
- Application.OnLaunched 이벤트가 발생합니다.
- (ProjectTemplate) 앱 코드는 프레임을 만들고 MainPage로 이동합니다.
- (ProjectTemplate) Mainpage 생성자는 InitializeComponent를 호출하여 MainPage.xaml을 구문 분석하고 개체를 만듭니다.
- ProjectTemplate) Window.Current.Activate()가 호출됩니다.
- XAML 플랫폼은 측정값 및 정렬을 포함한 레이아웃 패스를 실행합니다.
- ApplyTemplate은 각 컨트롤에 대한 컨트롤 템플릿 콘텐츠를 생성하며, 이는 일반적으로 시작 시 레이아웃 시간의 대부분을 차지합니다.
- 랜더가 모든 창 내용의 시각적 효과를 만들기 위해 호출됩니다.
- 프레임은 DWM(데스크톱 Windows 관리자)에 표시됩니다.
시작 경로에서 더 적은 작업을 수행합니다.
필요하지 않은 항목을 첫 번째 프레임에서 시작 코드 경로에 포함하지 않도록 유지하세요.
- 첫 번째 프레임 동안 필요하지 않은 컨트롤을 포함하는 사용자 dll이 있는 경우 로드를 지연하는 것이 좋습니다.
- 클라우드의 데이터에 종속된 UI의 일부가 있는 경우 해당 UI를 분할합니다. 먼저 클라우드 데이터에 종속되지 않은 UI를 가져오고 클라우드 종속 UI를 비동기적으로 표시합니다. 또한 애플리케이션이 오프라인으로 작동하거나 느린 네트워크 연결의 영향을 받지 않도록 데이터를 로컬로 캐싱하는 것도 고려해야 합니다.
- UI가 데이터를 대기 중일 때 진행 상황 UI를 표시합니다.
- 구성 파일의 구문 분석이 많은 앱 디자인 또는 코드에서 동적으로 생성되는 UI를 주의해야 합니다.
요소 수 줄이기
XAML 앱의 시작 성능은 시작 중에 만드는 요소 수와 직접 상관 관계가 있습니다. 만드는 요소가 적을수록 앱을 시작하는 데 걸리는 시간이 줄어듭니다. 대략적인 벤치마크로 각 요소를 만드는 데 1ms가 소요되는 것이 좋습니다.
- 항목 컨트롤에 사용되는 템플릿은 여러 번 반복되므로 가장 큰 영향을 미칠 수 있습니다. ListView 및 GridView UI 최적화참조하세요.
- UserControls 및 컨트롤 템플릿이 확장되므로 이러한 템플릿도 고려해야 합니다.
- 화면에 표시되지 않는 XAML을 만드는 경우 시작 중에 이러한 XAML 조각을 만들어야 하는지 여부를 정당화해야 합니다.
Visual Studio Live Visual Tree 창에는 트리의 각 노드에 대한 자식 요소 수가 표시됩니다.
시각적 라이브 트리
지연사용합니다. 요소를 축소하거나 불투명도를 0으로 설정해도 요소가 만들어지지는 않습니다. x:Load 또는 x:DeferLoadStrategy를 사용하면 UI의 로드를 지연하고 필요할 때 로드할 수 있습니다. 이는 필요한 경우 또는 지연된 논리 집합의 일부로 로드할 수 있도록 시작 화면 중에 표시되지 않는 UI 처리를 지연하는 좋은 방법입니다. 로드를 트리거하려면 요소에 대한 FindName만 호출하면 됩니다. 예제 및 자세한 내용은 x:Load 특성 및 x:DeferLoadStrategy 특성참조하세요.
가상화. UI에 목록 또는 반복기 콘텐츠가 있는 경우 UI 가상화를 사용하는 것이 좋습니다. 목록 UI가 가상화되지 않은 경우 모든 요소를 미리 만드는 데 드는 비용을 지불하므로 시작 속도가 느려질 수 있습니다. ListView 및 GridView UI 최적화참조하세요.
애플리케이션 성능은 원시 성능뿐만 아니라 인식에 관한 것입니다. 시각적 측면이 먼저 발생하도록 작업 순서를 변경하면 일반적으로 사용자가 애플리케이션이 더 빠른 것처럼 느끼게 됩니다. 사용자는 콘텐츠가 화면에 표시될 때 로드된 애플리케이션을 고려합니다. 일반적으로 애플리케이션은 시작의 일부로 여러 작업을 수행해야 하며, UI를 표시하는 데 필수가 아닌 작업들은 UI보다 낮은 우선순위로 설정하거나 지연시켜야 합니다.
이 항목에서는 애니메이션/TV에서 제공되는 "첫 번째 프레임"에 대해 설명하며 최종 사용자가 콘텐츠를 볼 때까지의 기간을 측정합니다.
스타트업 인식 개선
간단한 온라인 게임의 예제를 사용하여 시작의 각 단계와 다양한 기술을 식별하여 프로세스 전체에서 사용자에게 피드백을 제공해 보겠습니다. 이 예제의 경우 활성화의 첫 번째 단계는 사용자가 게임의 타일을 탭하는 시간과 해당 코드를 실행하기 시작하는 게임 사이의 시간입니다. 이 시간 동안 시스템에는 올바른 게임이 시작되었음을 나타내기 위해 사용자에게 표시할 콘텐츠가 없습니다. 그러나 시작 화면을 제공하면 해당 콘텐츠가 시스템에 제공됩니다. 그런 다음 게임은 정적 시작 화면을 코드 실행을 시작할 때 자체 UI로 바꿔서 활성화의 첫 번째 단계가 완료되었음을 사용자에게 알릴 수 있습니다.
활성화의 두 번째 단계는 게임에 중요한 구조를 만들고 초기화하는 것을 포함합니다. 앱이 활성화의 첫 번째 단계 이후 사용할 수 있는 데이터를 사용하여 초기 UI를 빠르게 만들 수 있는 경우 두 번째 단계는 간단하며 UI를 즉시 표시할 수 있습니다. 그렇지 않으면 앱이 초기화되는 동안 로드 페이지를 표시하는 것이 좋습니다.
로드 페이지의 모양은 사용자에게 달려 있으며 진행률 표시줄 또는 진행률 링을 표시하는 것만큼 간단할 수 있습니다. 핵심은 앱이 응답하기 전에 작업을 수행하고 있음을 나타낸다는 것입니다. 게임의 경우 초기 화면을 표시하려고 하지만 UI를 사용하려면 일부 이미지와 소리를 디스크에서 메모리로 로드해야 합니다. 이러한 작업은 몇 초 정도 걸리므로 앱은 시작 화면을 게임 테마와 관련된 간단한 애니메이션을 보여 주는 로드 페이지로 바꿔 사용자에게 알려줍니다.
세 번째 단계는 게임이 로딩 페이지를 대체하는 대화형 UI를 만들기 위한 최소한의 정보 집합이 있는 후에 시작됩니다. 이 시점에서 온라인 게임에 사용할 수 있는 유일한 정보는 앱이 디스크에서 로드한 콘텐츠입니다. 게임은 대화형 UI를 만들기에 충분한 콘텐츠와 함께 제공 될 수 있습니다. 그러나 온라인 게임이기 때문에 인터넷에 연결하고 몇 가지 추가 정보를 다운로드 할 때까지 작동하지 않습니다. 작동해야 하는 모든 정보가 있을 때까지 사용자는 UI와 상호 작용할 수 있지만 웹에서 추가 데이터가 필요한 기능은 콘텐츠가 여전히 로드되고 있다는 피드백을 제공해야 합니다. 앱이 완전히 작동하는 데 시간이 걸릴 수 있으므로 가능한 한 빨리 기능을 사용할 수 있도록 하는 것이 중요합니다.
이제 온라인 게임에서 활성화의 세 단계를 확인했으므로 실제 코드에 연결해 보겠습니다.
1단계
앱을 시작하기 전에 시작 화면으로 표시할 내용을 시스템에 알려야 합니다. 예제와 같이 앱 매니페스트의 SplashScreen 요소에 이미지와 배경색을 제공하여 이 작업을 수행합니다. Windows는 앱이 활성화를 시작한 후 이를 표시합니다.
<Package ...>
...
<Applications>
<Application ...>
<VisualElements ...>
...
<SplashScreen Image="Images\splashscreen.png" BackgroundColor="#000000" />
...
</VisualElements>
</Application>
</Applications>
</Package>
자세한 내용은 스플래시 화면 추가을 참조하세요.
앱의 생성자만 사용하여 앱에 중요한 데이터 구조를 초기화합니다. 생성자는 앱이 처음 실행될 때만 호출되며 앱이 활성화될 때마다 반드시 호출되는 것은 아닙니다. 예를 들어, 생성자는 실행되고 백그라운드로 전환된 후 검색 계약을 통해 활성화된 앱에 대해 호출되지 않습니다.
2단계
앱이 활성화되는 데는 여러 가지 이유가 있으며, 각각 다르게 처리할 수 있습니다. OnActivated,
public partial class App : Application
{
// A handler for regular activation.
async protected override void OnLaunched(LaunchActivatedEventArgs args)
{
base.OnLaunched(args);
// Asynchronously restore state based on generic launch.
// Create the ExtendedSplash screen which serves as a loading page while the
// reader downloads the section information.
ExtendedSplash eSplash = new ExtendedSplash();
// Set the content of the window to the extended splash screen.
Window.Current.Content = eSplash;
// Notify the Window that the process of activation is completed
Window.Current.Activate();
}
// a different handler for activation via the search contract
async protected override void OnSearchActivated(SearchActivatedEventArgs args)
{
base.OnSearchActivated(args);
// Do an asynchronous restore based on Search activation
// the rest of the code is the same as the OnLaunched method
}
}
partial class ExtendedSplash : Page
{
// This is the UIELement that's the game's home page.
private GameHomePage homePage;
public ExtendedSplash()
{
InitializeComponent();
homePage = new GameHomePage();
}
// Shown for demonstration purposes only.
// This is typically autogenerated by Visual Studio.
private void InitializeComponent()
{
}
}
Partial Public Class App
Inherits Application
' A handler for regular activation.
Protected Overrides Async Sub OnLaunched(ByVal args As LaunchActivatedEventArgs)
MyBase.OnLaunched(args)
' Asynchronously restore state based on generic launch.
' Create the ExtendedSplash screen which serves as a loading page while the
' reader downloads the section information.
Dim eSplash As New ExtendedSplash()
' Set the content of the window to the extended splash screen.
Window.Current.Content = eSplash
' Notify the Window that the process of activation is completed
Window.Current.Activate()
End Sub
' a different handler for activation via the search contract
Protected Overrides Async Sub OnSearchActivated(ByVal args As SearchActivatedEventArgs)
MyBase.OnSearchActivated(args)
' Do an asynchronous restore based on Search activation
' the rest of the code is the same as the OnLaunched method
End Sub
End Class
Partial Friend Class ExtendedSplash
Inherits Page
Public Sub New()
InitializeComponent()
' Downloading the data necessary for
' initial UI on a background thread.
Task.Run(Sub() DownloadData())
End Sub
Private Sub DownloadData()
' Download data to populate the initial UI.
' Create the first page.
Dim firstPage As New MainPage()
' Add the data just downloaded to the first page
' Replace the loading page, which is currently
' set as the window's content, with the initial UI for the app
Window.Current.Content = firstPage
End Sub
' Shown for demonstration purposes only.
' This is typically autogenerated by Visual Studio.
Private Sub InitializeComponent()
End Sub
End Class
활성화 처리기에서 로드 페이지를 표시하는 앱은 백그라운드에서 UI를 만들기 위한 작업을 시작합니다. 그 요소가 생성된 후, FrameworkElement.Loaded 이벤트가 발생합니다. 이벤트 처리기에서 현재 로드 화면인 창의 콘텐츠를 새로 만든 홈페이지로 바꿉 있습니다.
초기화 기간이 연장된 앱은 로드 페이지를 표시하는 것이 중요합니다. 정품 인증 프로세스에 대한 사용자 피드백을 제공하는 것 외에도, 활성화 프로세스가 시작된 후 15초 이내에 Window.Activate가 호출되지 않으면, 프로세스가 종료됩니다.
partial class GameHomePage : Page
{
public GameHomePage()
{
InitializeComponent();
// add a handler to be called when the home page has been loaded
this.Loaded += ReaderHomePageLoaded;
// load the minimal amount of image and sound data from disk necessary to create the home page.
}
void ReaderHomePageLoaded(object sender, RoutedEventArgs e)
{
// set the content of the window to the home page now that it's ready to be displayed.
Window.Current.Content = this;
}
// Shown for demonstration purposes only.
// This is typically autogenerated by Visual Studio.
private void InitializeComponent()
{
}
}
Partial Friend Class GameHomePage
Inherits Page
Public Sub New()
InitializeComponent()
' add a handler to be called when the home page has been loaded
AddHandler Me.Loaded, AddressOf ReaderHomePageLoaded
' load the minimal amount of image and sound data from disk necessary to create the home page.
End Sub
Private Sub ReaderHomePageLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
' set the content of the window to the home page now that it's ready to be displayed.
Window.Current.Content = Me
End Sub
' Shown for demonstration purposes only.
' This is typically autogenerated by Visual Studio.
Private Sub InitializeComponent()
End Sub
End Class
확장된 시작 화면을 사용하는 예제는 스플래시 화면 샘플참조하세요.
3단계
앱이 UI를 표시했다고 해서 UI를 완전히 사용할 준비가 되었음을 의미하지는 않습니다. 우리 게임의 경우, 인터넷 데이터가 필요한 기능에 대한 자리 표시자와 함께 UI가 표시됩니다. 이 시점에서 게임은 앱이 완벽하게 작동하도록 하는 데 필요한 추가 데이터를 다운로드하고 데이터를 획득할 때 점진적으로 기능을 사용하도록 설정합니다.
경우에 따라 활성화에 필요한 콘텐츠의 대부분을 앱으로 패키지할 수 있습니다. 이러한 간단한 게임의 경우입니다. 이렇게 하면 활성화 프로세스가 매우 간단합니다. 그러나 많은 프로그램(예: 뉴스 독자 및 사진 시청자)이 작동하려면 웹에서 정보를 가져와야 합니다. 이 데이터는 클 수 있으며 다운로드하는 데 상당한 시간이 걸릴 수 있습니다. 활성화 프로세스 중에 앱이 이 데이터를 가져오는 방법은 앱의 인식된 성능에 큰 영향을 미칠 수 있습니다.
앱이 활성화 단계 1 또는 2에서 필요한 전체 데이터 세트를 다운로드하려고 하면 몇 분 동안 로딩 페이지나, 심지어 시작 화면을 표시할 수도 있습니다. 이렇게 하면 앱이 중단된 것처럼 보이거나 시스템에 의해 종료됩니다. 앱은 최소 양의 데이터를 다운로드하여 2단계에서 자리 표시자 요소가 있는 대화형 UI를 표시한 다음, 3단계에서 자리 표시자 요소를 대체하는 데이터를 점진적으로 로드하는 것이 좋습니다. 데이터 처리에 대한 자세한 내용은 ListView 및 GridView최적화를 참조하세요.
앱이 시작의 각 단계에 정확히 어떻게 반응하는지는 전적으로 사용자에게 달려 있지만 가능한 한 많은 피드백(시작 화면, 로드 화면, 데이터 로드 중 UI)을 제공하면 사용자는 앱과 시스템 전체가 빠른 것처럼 느껴집니다.
시작 경로에서 관리되는 어셈블리 최소화
재사용 가능한 코드는 종종 프로젝트에 포함된 모듈(DLL) 형식으로 제공됩니다. 이러한 모듈을 로드하려면 디스크에 액세스해야 하며, 상상할 수 있듯이 이러한 모듈을 로드하는 데 드는 비용이 더해질 수 있습니다. 이는 콜드 스타트업에 가장 큰 영향을 주지만 따뜻한 시작에도 영향을 미칠 수 있습니다. C# 및 Visual Basic의 경우 CLR은 요청 시 어셈블리를 로드하여 가능한 한 많은 비용을 지연하려고 합니다. 즉, CLR은 실행된 메서드가 모듈을 참조할 때까지 모듈을 로드하지 않습니다. 따라서 CLR이 불필요한 모듈을 로드하지 않도록 시작 코드에서 앱을 시작하는 데 필요한 어셈블리만 참조합니다. 시작 경로에 불필요한 참조가 있는 사용되지 않는 코드 경로가 있는 경우 이러한 코드 경로를 다른 메서드로 이동하여 불필요한 로드를 방지할 수 있습니다.
모듈 로드를 줄이는 또 다른 방법은 앱 모듈을 결합하는 것입니다. 하나의 큰 어셈블리를 로드하는 데는 일반적으로 두 개의 작은 어셈블리를 로드하는 것보다 시간이 적게 걸립니다. 항상 가능한 것은 아니며, 모듈이 개발자 생산성 또는 코드 재사용성에 중대한 차이를 만들지 않는 경우에만 모듈을 결합해야 합니다. PerfView 또는 WPA(Windows Performance Analyzer) 같은 도구를 사용하여 시작할 때 로드되는 모듈을 확인할 수 있습니다.
스마트 웹 요청 만들기
XAML, 이미지 및 앱에 중요한 기타 파일을 포함하여 콘텐츠를 로컬로 패키징하여 앱의 로드 시간을 크게 향상시킬 수 있습니다. 디스크 작업은 네트워크 작업보다 빠릅니다. 초기화 시 앱에 특정 파일이 필요한 경우 원격 서버에서 검색하는 대신 디스크에서 로드하여 전체 시작 시간을 줄일 수 있습니다.
저널 및 캐시 페이지를 효율적으로 관리하기
프레임 컨트롤은 탐색 기능을 제공합니다. 페이지 탐색(Navigate 메서드), 탐색 저널링(BackStack/ForwardStack 속성, GoForward/GoBack 메서드), 페이지 캐싱(Page.NavigationCacheMode) 및 serialization 지원(GetNavigationState 메서드)을 제공합니다.
Frame에서 알아야 할 성능은 주로 저널링 및 페이지 캐싱을 중심으로 합니다.
프레임 저널링. Frame.Navigate()가 있는 페이지로 이동하면 현재 페이지의 PageStackEntry가 Frame.BackStack 컬렉션에 추가됩니다. PageStackEntry는 비교적 작지만 BackStack 컬렉션의 크기에 대한 기본 제공 제한은 없습니다. 잠재적으로 사용자는 루프에서 탐색하고 이 컬렉션을 무기한 확장할 수 있습니다.
PageStackEntry에는 Frame.Navigate() 메서드에 전달된 매개 변수도 포함됩니다. Frame.GetNavigationState() 메서드가 작동할 수 있도록 하려면 매개 변수를 기본 직렬화 가능 형식(예: int 또는 string)으로 사용하는 것이 좋습니다. 그러나 이 매개 변수는 더 많은 양의 작업 집합 또는 기타 리소스를 차지하는 개체를 참조할 수 있으므로 BackStack의 각 항목이 훨씬 더 비쌉니다. 예를 들어 잠재적으로 StorageFile을 매개 변수로 사용할 수 있으며, 따라서 BackStack은 무한 개수의 파일을 열어 둡니다.
따라서 탐색 매개 변수를 작게 유지하고 BackStack의 크기를 제한하는 것이 좋습니다. BackStack은 표준 벡터(C#의 IList, C++/CX의 Platform::Vector)이므로 항목을 제거하여 간단히 트리밍할 수 있습니다.
페이지 캐싱. 기본적으로 Frame.Navigate 메서드를 사용하여 페이지로 이동하면 페이지의 새 인스턴스가 인스턴스화됩니다. 마찬가지로 Frame.GoBack을 사용하여 이전 페이지로 다시 이동하면 이전 페이지의 새 인스턴스가 할당됩니다.
그러나 프레임은 이러한 인스턴스화를 방지할 수 있는 선택적 페이지 캐시를 제공합니다. 페이지를 캐시에 넣려면 Page.NavigationCacheMode 속성을 사용합니다. 모드를 '필수'로 설정하면 페이지가 강제로 캐시되며, '사용'으로 설정하면 캐시할 수 있습니다. 기본적으로 캐시 크기는 10페이지이지만 Frame.CacheSize 속성으로 재정의할 수 있습니다. 모든 필수 페이지가 캐시되고, 캐시 크기의 필수 페이지보다 적은 경우 활성화된 페이지도 캐시할 수 있습니다.
페이지 캐싱은 인스턴스화를 방지하여 성능에 도움이 되므로 탐색 성능이 향상됩니다. 페이지 캐싱은 오버 캐싱으로 인해 성능이 저하되어 작업 집합에 영향을 줄 수 있습니다.
따라서 애플리케이션에 맞게 페이지 캐싱을 사용하는 것이 좋습니다. 예를 들어 프레임에 항목 목록을 표시하는 앱이 있고 항목을 탭하면 해당 항목의 세부 정보 페이지로 프레임을 탐색합니다. 목록 페이지는 캐시로 설정해야 합니다. 모든 항목에 대해 세부 정보 페이지가 동일한 경우 캐시해야 할 수도 있습니다. 그러나 세부 정보 페이지가 이질적인 경우 캐싱을 해제하는 것이 더 좋을 수 있습니다.