Windows Runtime 8.x 프로젝트를 UWP 프로젝트로 포팅하기
포팅 프로세스를 시작하는 경우 두 가지 옵션이 있습니다. 하나는 앱 패키지 매니페스트를 포함하여 기존 프로젝트 파일의 복사본을 편집하는 것입니다(해당 옵션의 경우, 프로젝트 파일을 앱 마이그레이션에서 Universal Windows Platform(UWP)으로 업데이트하는 방법에 대한 정보 참조). 다른 하나의 옵션은 Visual Studio에서 새로운 Windows 10 프로젝트를 만들고 파일을 복사하는 것입니다. 이 항목의 첫 번째 토픽은 두 번째 옵션을 설명하지만, 두 옵션에 적용할 수 있는 추가 정보는 나머지 항목에 있습니다. 새로운 Windows 10 프로젝트를 기존 프로젝트와 동일한 솔루션에 유지하고 공유 프로젝트를 사용하여 소스 코드 파일을 공유하도록 선택할 수도 있습니다. 또는 Visual Studio에서 연결된 파일 기능을 사용하여 새로운 프로젝트를 자체 솔루션에 유지하고 소스 코드 파일을 공유할 수 있습니다.
프로젝트를 만들고 해당 프로젝트에 파일을 복사합니다
이러한 단계는 Visual Studio에서 새로운 Windows 10 프로젝트를 만들고 파일을 복사하는 옵션에 중점을 줍니다. 만드는 프로젝트 수와 복사하는 파일에 대한 몇 가지 세부 사항은 Universal 8.1 앱이 있는 경우 설명된 요소 및 결정 사항과 그 뒤에 오는 섹션에 따라 달라집니다. 이러한 단계에서는 가장 간단한 사례를 가정합니다.
- Microsoft Visual Studio 2015를 시작하고 새로운 비어 있는 애플리케이션(Windows Universal) 프로젝트를 만듭니다. 자세한 정보는 템플릿(C#, C++, Visual Basic)을 사용하여 Windows Runtime 8.x 앱 시작하기를 참조하세요. 새로운 프로젝트는 모든 장치 패밀리에서 실행되는 앱 패키지(appx 파일)를 빌드합니다.
- Universal 8.1 앱 프로젝트에서 재사용하려는 모든 소스 코드 파일 및 시각적 개체 자산 파일을 식별합니다. 파일 탐색기를 사용하여 데이터 모델을 복사하고, 보기 모델, 시각적 개체 자산, 리소스 사전, 폴더 구조 및 다시 사용하려는 기타 모든 항목을 새 프로젝트에 복사합니다. 필요에 따라 하위 폴더를 디스크에 복사하거나 만듭니다.
- 보기(예시: MainPage.xaml 및 MainPage.xaml.cs)도 새로운 프로젝트에 복사합니다. 필요에 따라 새로운 하위 폴더를 만들고 프로젝트에서 기존 보기를 제거합니다. 그러나 나중에 참조하기 유용할 수 있으므로 Visual Studio에서 생성한 보기를 과도하게 쓰거나 제거하기 전에 복사본을 유지합니다. Universal 8.1 앱을 포팅하는 첫 번째 단계에서는 하나의 장치 패밀리에서 제대로 보이고 제대로 작동하도록 하는 데 중점을 둡니다. 나중에 보기가 모든 폼 팩터에 잘 맞게 조정되도록 하고, 필요에 따라 특정 장치 패밀리에서 최대한 활용하기 위해 적응 코드를 추가하는 데 주의를 기울입니다.
- 솔루션 탐색기에서 모든 파일 표시로 전환되어 있는지 확인합니다. 복사한 파일을 선택하고 마우스 우클릭한 다음, 프로젝트에 포함을 클릭합니다. 여기에는 포함된 폴더가 자동으로 포함됩니다. 그런 다음 원하는 경우 모든 파일 표시를 해제할 수 있습니다. 원하는 경우 Visual Studio 솔루션 탐색기에서 필요한 하위 폴더를 만든 기존 항목 추가 명령을 사용하는 것이 좋습니다. 시각적 개체 자산에 빌드 작업이 콘텐츠로 설정되고 출력 디렉터리로 복사가 복사되지 않음으로 설정된 것을 다시 확인합니다.
- 몇 가지 빌드 오류가 이 단계에서 표시될 수 있습니다. 그러나 변경해야 하는 사항을 알고 있는 경우 Visual Studio의 찾기 및 바꾸기 명령을 사용하여 소스 코드를 대량으로 변경할 수 있습니다. 또한 Visual Studio의 명령적 코드 편집기에서 상황에 맞는 메뉴의 해결 및 사용 구성하기 명령을 사용하여 더 많은 대상을 변경할 수 있습니다.
태그 및 코드 재사용 최대화하기
모든 장치 패밀리에서 작동하는 태그 및 코드를 최대화하려면 약간의 리팩터링 및/또는 적응 코드(아래에 설명됨)를 추가할 수 있습니다. 세부 사항은 다음과 같습니다.
- 모든 장치 패밀리에 공통적인 파일은 특별히 고려할 필요가 없습니다. 앱이 실행하는 모든 장치 패밀리에서 이러한 파일이 사용됩니다. 이는 XAML 태그 파일, 명령적 소스 코드 파일 및 자산 파일을 포함합니다.
- 앱이 실행 중인 장치 패밀리를 감지하고 해당 장치 패밀리를 위해 특별히 설계된 보기로 이동할 수 있습니다. 자세한 정보는 앱이 실행 중인 플랫폼 감지하기를 참조하세요.
- 대안이 없는 경우 유용할 수 있는 유사한 기술은 태그 파일 또는 ResourceDictionary 파일(또는 파일이 포함된 폴더)에 특수 이름을 지정하여 앱이 특정 장치 패밀리에서 실행되는 경우에만 런타임에 자동으로 로드되도록 하는 것입니다. Bookstore1 사례 연구에서 이 기술을 설명합니다.
- Windows 10만 지원해야 하는 경우 Universa 8.1 앱의 소스 코드에서 조건부 컴파일 지시문을 많이 제거할 수 있어야 합니다. 이 토픽의 조건부 컴파일 및 적응 코드를 참조하세요.
- 일부 장치 패밀리(예를 들어 프린터, 스캐너 또는 카메라 버튼)에서 사용할 수 없는 기능을 사용하려면 적응 코드를 작성할 수 있습니다. 이 토픽의 조건부 컴파일 및 적응 코드에서 세 번째 예제를 참조하세요.
- Windows 8.1, Windows Phone 8.1 및 Windows 10을 지원하려는 경우, 세 개의 프로젝트를 동일한 솔루션에 유지하고 공유 프로젝트와 코드를 공유할 수 있습니다. 또는 소스 코드 파일을 프로젝트 간에 공유할 수 있습니다. 방법은 다음과 같습니다. Visual Studio의 솔루션 탐색기에서 프로젝트를 마우스 우클릭한 뒤, 기존 항목 추가를 선택하고, 공유할 파일을 선택한 다음, 링크로 추가를 클릭합니다. 연결한 프로젝트에서 볼 수 있는 파일 시스템의 공통 폴더에 소스 코드 파일을 저장합니다. 소스 제어에 추가하는 것을 잊지 마세요.
- 소스 코드 수준이 아닌 이진 수준에서 재사용하려면 C# 및 Visual Basic에서 Windows Runtime 구성 요소 만들기를 참조하세요. Windows 8.1용 .NET Framework, Windows Phone 8.1 및 Windows 10 앱(.NET Core) 및 전체 .NET Framework에서 사용할 수 있는 .NET API의 하위 집합을 지원하는 포팅 가능한 클래스 라이브러리도 있습니다. 포팅 가능한 클래스 라이브러리 어셈블리는 이러한 모든 플랫폼과 이진 호환됩니다. Visual Studio를 활용하여 포팅 가능한 클래스 라이브러리를 대상으로 하는 프로젝트를 만듭니다. 포팅 가능한 클래스 라이브러리로 플랫폼 간 개발을 참조하세요.
확장 SDK
유니버설 장치 패밀리라고 하는 API 집합에서 Universal 8.1 앱이 이미 호출하는 대부분의 Windows Runtime API가 구현됩니다. 그러나 일부는 확장 SDK에서 구현되며 Visual Studio는 앱의 대상 장치 패밀리 또는 참조한 모든 확장 SDK에서 구현되는 API만 인식합니다.
찾을 수 없는 네임스페이스 또는 형식 또는 멤버에 대한 컴파일 오류가 발생하는 경우, 이것이 원인일 수 있습니다. API 참조 설명서에서 API의 토픽을 열고 요구 사항 섹션으로 이동합니다. 그러면 구현 장치 패밀리가 무엇인지 알 수 있습니다. 대상 장치 패밀리가 아닌 경우, 프로젝트에서 API를 사용할 수 있도록 하려면 해당 장치 패밀리에 대한 확장 SDK에 대한 참조가 필요합니다.
프로젝트>참조 추가>Windows Universal>확장을 클릭하고 적절한 확장 SDK를 선택합니다. 예를 들어 모바일 장치 패밀리에서만 호출하려는 API를 사용할 수 있고 버전 10.0.x.y에서 도입된 경우 UWP용 Windows 모바일 확장을 선택합니다.
이렇게 하면 프로젝트 파일에 다음의 참조가 추가됩니다.
<ItemGroup>
<SDKReference Include="WindowsMobile, Version=10.0.x.y">
<Name>Windows Mobile Extensions for the UWP</Name>
</SDKReference>
</ItemGroup>
이름 및 버전 번호는 SDK의 설치된 위치에 있는 폴더와 일치합니다. 예를 들어, 위의 정보는 이 폴더 이름과 일치합니다.
\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsMobile\10.0.x.y
앱이 API를 구현하는 장치 패밀리를 대상으로 하지 않는 한, ApiInformation 클래스를 사용하여 API를 호출하기 전에 API의 존재를 테스트해야 합니다(적응 코드라고 함). 이 조건은 앱이 실행되는 모든 위치에서 평가되지만, API가 있어 호출할 수 있는 장치에서만 true로 평가됩니다. 유니버설 API가 존재하는지 여부를 먼저 검사한 뒤, 확장 SDK 및 적응 코드만 사용합니다. 아래의 섹션에는 몇 가지 예가 나와 있습니다.
또한 앱 패키지 매니페스트를 참조하세요.
조건부 컴파일 및 적응 코드
코드 파일이 Windows 8.1 및 Windows Phone 8.1 모두에서 작동할 수 있도록 조건부 컴파일(C# 전처리기 지시문 포함)을 사용하는 경우, 이제 Windows 10에서 수행된 수렴 작업을 고려하여 조건부 컴파일을 검토할 수 있습니다. 수렴은 Windows 10 앱에서 일부 조건을 완전히 제거할 수 있음을 의미합니다. 다른 사항들은 아래 예시와 같이 런타임 검사로 변경됩니다.
참고 단일 코드 파일에서 Windows 8.1, Windows Phone 8.1 및 Windows 10을 지원하려는 경우에도 이 작업을 수행할 수 있습니다. 프로젝트 속성 페이지에서 Windows 10 프로젝트를 살펴보는 경우, 프로젝트가 WINDOWS\_UAP를 조건부 컴파일 기호로 정의한 것을 알 수 있습니다. 따라서 WINDOWS_APP 및 WINDOWS_PHONE_APP와 결합하여 사용할 수 있습니다. 다음의 예시는 Universal 8.1 앱에서 조건부 컴파일을 제거하고 Windows 10 앱에 해당하는 코드를 대체하는 간단한 사례를 보여 줍니다.
이 첫 번째 예시는 PickSingleFileAsync API(Windows 8.1에만 적용됨) 및 PickSingleFileAndContinue API(Windows Phone 8.1에만 적용됨)의 사용 패턴을 보여 줍니다.
#if WINDOWS_APP
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAsync
#else
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAndContinue
#endif // WINDOWS_APP
Windows 10은 PickSingleFileAsync API에 수렴되므로, 다음과 같이 코드가 간소화됩니다.
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAsync
이 예시는 하드웨어 백 버튼을 처리합니다(Windows Phone에서만).
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed += this.HardwareButtons_BackPressed;
#endif // WINDOWS_PHONE_APP
...
#if WINDOWS_PHONE_APP
void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
// Handle the event.
}
#endif // WINDOWS_PHONE_APP
Windows 10에서 백 버튼 이벤트는 범용 개념입니다. 하드웨어 또는 소프트웨어에서 구현된 백 버튼은 모두 BackRequested 이벤트를 발생시키므로 이를 처리해야 합니다.
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested +=
this.ViewModelLocator_BackRequested;
...
private void ViewModelLocator_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
// Handle the event.
}
이 마지막 예시는 앞의 예시와 유사합니다. 여기서는 하드웨어 카메라 버튼을 처리하지만 Windows Phone 앱 패키지로 컴파일된 코드에서만 처리합니다.
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.CameraPressed += this.HardwareButtons_CameraPressed;
#endif // WINDOWS_PHONE_APP
...
#if WINDOWS_PHONE_APP
void HardwareButtons_CameraPressed(object sender, Windows.Phone.UI.Input.CameraEventArgs e)
{
// Handle the event.
}
#endif // WINDOWS_PHONE_APP
Windows 10에서 하드웨어 카메라 버튼은 모바일 장치 패밀리에 있어서 특정한 개념입니다. 모든 장치에서 하나의 앱 패키지가 실행되므로 적응 코드라고 하는 것을 사용하여 컴파일 시간 조건을 런타임 조건으로 변경합니다. 이를 위해 ApiInformation 클래스를 사용하여 런타임에 HardwareButtons 클래스가 있는지 쿼리합니다. HardwareButtons는 모바일 확장 SDK에 정의되어 있으므로 이 코드를 컴파일하려면 프로젝트에 해당 SDK에 대한 참조를 추가해야 합니다. 그러나 처리기는 모바일 확장 SDK에 정의된 형식을 구현하는 장치에서만 실행되며 모바일 장치 패밀리입니다. 따라서 이 코드는 Universal 8.1 코드와 도덕적으로 동일하며, 다른 방식으로 이를 달성하지만 존재하는 기능만 사용하는 것이 조심스럽다는 것입니다.
// Note: Cache the value instead of querying it more than once.
bool isHardwareButtonsAPIPresent = Windows.Foundation.Metadata.ApiInformation.IsTypePresent
("Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
Windows.Phone.UI.Input.HardwareButtons.CameraPressed +=
this.HardwareButtons_CameraPressed;
}
...
private void HardwareButtons_CameraPressed(object sender, Windows.Phone.UI.Input.CameraEventArgs e)
{
// Handle the event.
}
또한 앱이 실행되고 있는 플랫폼 검색하기를 참조합니다.
앱 패키지 매니페스트
Windows 10의 변경 내용 토픽에는 추가, 제거 및 변경된 요소를 포함하여 Windows 10에 대한 패키지 매니페스트 스키마 참조의 변경 내용이 나열됩니다. 스키마의 모든 요소, 특성 및 유형에 대해 알아보려면 요소 계층 구조를 참조하세요. Windows Phone Store 앱을 포팅하거나 앱이 Windows Phone Store의 앱에 대한 업데이트인 경우 mp:PhoneIdentity 요소가 이전 앱의 앱 매니페스트에 있는 것과 일치하는지 확인합니다(Store에서 앱에 할당한 것과 동일한 GUID 사용). 이렇게 하면 Windows 10 또는 Windows 11로 업그레이드하는 앱 사용자가 새로운 앱을 중복이 아닌 업데이트로 받게 됩니다. 자세한 정보는 mp:PhoneIdentity 참조 토픽을 참조하세요.
프로젝트의 설정(확장 SDK 참조 포함)이 앱이 호출할 수 있는 API 노출 영역을 결정합니다. 그러나 앱 패키지 매니페스트는 고객이 Store에서 앱을 설치할 수 있는 실제 장치 집합을 결정합니다. 자세한 정보는 TargetDeviceFamily의 예시를 참조하세요.
일부 기능에 필요한 다양한 선언, 기능 및 기타 설정을 설정하기 위해 앱 패키지 매니페스트를 편집할 수 있습니다. Visual Studio 앱 패키지 매니페스트 편집기를 사용하여 편집할 수 있습니다. 솔루션 탐색기가 표시되지 않으면 보기 메뉴에서 선택합니다. Package.appxmanifest를 더블 클릭합니다. 그러면 매니페스트 편집기 창이 열립니다. 적절한 탭을 선택하여 변경한 뒤 저장합니다.
다음 토픽은 문제 해결하기입니다.