패키징 레이아웃으로 패키지 만들기

자산 패키지가 도입되면서 개발자는 이제 더 많은 패키지 유형 외에도 더 많은 패키지를 빌드할 수 있는 도구를 갖게 되었습니다. 앱이 더 크고 복잡해지면 더 많은 패키지로 구성되는 경우가 많으며, 이러한 패키지를 관리하는 데 어려움이 증가합니다(특히 Visual Studio 외부에서 빌드하고 매핑 파일을 사용하는 경우). 앱의 패키징 구조 관리를 간소화하기 위해 MakeAppx.exe 지원하는 패키징 레이아웃을 사용할 수 있습니다.

패키징 레이아웃은 앱의 패키징 구조를 설명하는 단일 XML 문서입니다. 앱의 번들(기본 및 선택 사항), 번들의 패키지 및 패키지의 파일을 지정합니다. 다른 폴더, 드라이브 및 네트워크 위치에서 파일을 선택할 수 있습니다. 와일드카드를 사용하여 파일을 선택하거나 제외할 수 있습니다.

앱에 대한 패키징 레이아웃이 설정되면 MakeAppx.exe 함께 사용되어 단일 명령줄 호출에서 앱에 대한 모든 패키지를 만듭니다. 패키징 레이아웃을 편집하여 배포 요구 사항에 맞게 패키지 구조를 변경할 수 있습니다.

간단한 패키징 레이아웃 예제

다음은 간단한 패키징 레이아웃의 예입니다.

<PackagingLayout xmlns="http://schemas.microsoft.com/appx/makeappx/2017">
  <PackageFamily ID="MyGame" FlatBundle="true" ManifestPath="C:\mygame\appxmanifest.xml" ResourceManager="false">
    
    <!-- x64 code package-->
    <Package ID="x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="*" SourcePath="C:\mygame\*"/>
        <File ExcludePath="*C:\mygame\*.txt"/>
      </Files>
    </Package>
    
    <!-- Media asset package -->
    <AssetPackage ID="Media" AllowExecution="false">
      <Files>
        <File DestinationPath="Media\**" SourcePath="C:\mygame\media\**"/>
      </Files>
    </AssetPackage>

  </PackageFamily>
</PackagingLayout>

이 예제를 세분화하여 작동 방식을 알아보겠습니다.

PackageFamily

이 패키징 레이아웃은 x64 아키텍처 패키지 및 "미디어" 자산 패키지가 있는 단일 플랫 앱 번들 파일을 만듭니다.

PackageFamily 요소는 앱 번들을 정의하는 데 사용됩니다. ManifestPath 특성을 사용하여 번들에 AppxManifest를 제공해야 합니다. AppxManifest는 번들의 아키텍처 패키지에 대한 AppxManifest에 해당해야 합니다. ID 특성도 제공해야 합니다. 이 파일은 원하는 경우 이 패키지만 만들 수 있도록 패키지를 만드는 동안 MakeAppx.exe 사용되며, 결과 패키지의 파일 이름이 됩니다. FlatBundle 특성은 만들려는 번들 유형, 플랫 번들에 대해 true(여기서 자세히 읽을 수 있음) 및 클래식 번들에 대해 false를 설명하는 데 사용됩니다. ResourceManager 특성은 이 번들 내의 리소스 패키지가 파일에 액세스하기 위해 MRT를 사용할지 여부를 지정하는 데 사용됩니다. 기본적으로 true이지만버전 1803인 Windows 10 아직 준비되지 않았으므로 이 특성을 false로 설정해야 합니다.

Package 및 AssetPackage

PackageFamily내에서 앱 번들이 포함하거나 참조하는 패키지가 정의됩니다. 여기서 아키텍처 패키지(기본 패키지라고도 함)는 Package 요소로 정의되고 자산 패키지는 AssetPackage 요소로 정의됩니다. 아키텍처 패키지는 패키지의 아키텍처를 "x64", "x86", "arm" 또는 "neutral"으로 지정해야 합니다. 또한 필요에 따라 ManifestPath 특성을 다시 사용하여 이 패키지에 맞게 AppxManifest를 직접 제공할 수도 있습니다. AppxManifest를 제공하지 않으면 PackageFamily에 대해 제공된 AppxManifest에서 자동으로 생성됩니다.

기본적으로 및 AppxManifest는 번들 내의 모든 패키지에 대해 생성됩니다. 자산 패키지의 경우 AllowExecution 특성을 설정할 수도 있습니다. 이 설정을 false(기본값)로 설정하면 실행할 필요가 없는 패키지에 바이러스 검사로 인해 게시 프로세스가 차단되지 않기 때문에 앱의 게시 시간을 줄일 수 있습니다(자산 패키지 소개에서자세히 알아볼 수 있음).

파일

각 패키지 정의 내에서 File 요소를 사용하여 이 패키지에 포함할 파일을 선택할 수 있습니다. SourcePath 특성은 파일이 로컬에 있는 위치입니다. 다른 폴더(상대 경로 제공), 다른 드라이브(절대 경로 제공) 또는 네트워크 공유(예: 제공)에서 파일을 선택할 수 \\myshare\myapp\* 있습니다. DestinationPath는 패키지 루트를 기준으로 파일이 패키지 내에서 종료되는 위치입니다. 다른 두 특성 대신 ExcludePath를 사용하여 동일한 패키지 내에서 다른 File 요소의 SourcePath 특성에서 선택한 파일에서 제외할 파일을 선택할 수 있습니다.

File 요소는 와일드카드를 사용하여 여러 파일을 선택하는 데 사용할 수 있습니다. 일반적으로 단일 * 와일드카드()는 경로 내의 어느 곳에서든 횟수에 따라 사용할 수 있습니다. 그러나 단일 와일드카드는 폴더 내의 파일만 일치하고 하위 폴더는 일치하지 않습니다. 예를 들어 C:\MyGame\*\*C:\MyGame\*\* 을 사용하여 및 파일을 선택할 C:\MyGame\Audios\UI.mp3 수 있지만 C:\MyGame\Videos\intro.mp4 을 선택할 수는 C:\MyGame\Audios\Level1\warp.mp3 없습니다. 폴더 또는 파일 이름 대신 이중 ** 와일드카드()를 사용하여 재귀적으로 일치시킬 수도 있지만 부분 이름 옆에는 있을 수 없습니다. 예를 들어 는 C:\MyGame\**\Level1\** 및 를 선택할 수 C:\MyGame\Audios\Level1\warp.mp3C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4 있습니다. 와일드카드를 사용하여 원본과 대상 간의 다른 위치에 와일드카드를 사용하는 경우 패키징 프로세스의 일부로 파일 이름을 직접 변경할 수도 있습니다. 예를 들어 C:\MyGame\Audios\* SourcePath 및 C:\MyGame\Audios\* 대해 를 사용하면 Sound\copy_* 를 선택하고 Sound\copy_*C:\MyGame\Audios\UI.mp3 패키지에 로 표시할 수 Sound\copy_UI.mp3 있습니다. 일반적으로 단일 와일드카드와 이중 와일드카드의 수는 단일 File 요소의 SourcePath 및 DestinationPath에 대해 동일해야 합니다.

고급 패키징 레이아웃 예제

다음은 더 복잡한 패키징 레이아웃의 예입니다.

<PackagingLayout xmlns="http://schemas.microsoft.com/appx/makeappx/2017">
  <!-- Main game -->
  <PackageFamily ID="MyGame" FlatBundle="true" ManifestPath="C:\mygame\appxmanifest.xml" ResourceManager="false">
    
    <!-- x64 code package-->
    <Package ID="x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="*" SourcePath="C:\mygame\*"/>
        <File ExcludePath="*C:\mygame\*.txt"/>
      </Files>
    </Package>

    <!-- Media asset package -->
    <AssetPackage ID="Media" AllowExecution="false">
      <Files>
        <File DestinationPath="Media\**" SourcePath="C:\mygame\media\**"/>
      </Files>
    </AssetPackage>
    
    <!-- English resource package -->
    <ResourcePackage ID="en">
      <Files>
        <File DestinationPath="english\**" SourcePath="C:\mygame\english\**"/>
      </Files>
      <Resources Default="true">
        <Resource Language="en"/>
      </Resources>
    </ResourcePackage>

    <!-- French resource package -->
    <ResourcePackage ID="fr">
      <Files>
        <File DestinationPath="french\**" SourcePath="C:\mygame\french\**"/>
      </Files>
      <Resources>
        <Resource Language="fr"/>
      </Resources>
    </ResourcePackage>
  </PackageFamily>

  <!-- DLC in the related set -->
  <PackageFamily ID="DLC" Optional="true" ManifestPath="C:\DLC\appxmanifest.xml">
    <Package ID="DLC.x86" Architecture="x86">
      <Files>
        <File DestinationPath="**" SourcePath="C:\DLC\**"/>
      </Files>
    </Package>
  </PackageFamily>

  <!-- DLC not part of the related set -->
  <PackageFamily ID="Themes" Optional="true" RelatedSet="false" ManifestPath="C:\themes\appxmanifest.xml">
    <Package ID="Themes.main" Architecture="neutral">
      <Files>
        <File DestinationPath="**" SourcePath="C:\themes\**"/>
      </Files>
    </Package>
  </PackageFamily>

  <!-- Existing packages that need to be included/referenced in the bundle -->
  <PrebuiltPackage Path="C:\prebuilt\DLC2.appxbundle" />

</PackagingLayout>

이 예제는 ResourcePackage선택적 요소를 추가하는 간단한 예제와 다릅니다.

리소스 패키지는 ResourcePackage 요소로 지정할 수 있습니다. ResourcePackage내에서 Resources 요소를 사용하여 리소스 팩의 리소스 한정자를 지정해야 합니다. 리소스 한정자는 리소스 팩에서 지원하는 리소스입니다. 여기서는 두 개의 리소스 팩이 정의되어 있으며 각각 영어 및 프랑스어 관련 파일을 포함하고 있음을 알 수 있습니다. 리소스 팩에는 두 개 이상의 한정자를 사용할 수 있습니다. 이 작업은 Resources 내에 다른 Resource 요소를 추가하여 수행할 수 있습니다. 차원이 있는 경우 리소스 차원에 대한 기본 리소스도 지정해야 합니다(언어, 배율, dxfl인 차원). 여기서 영어가 기본 언어임을 알 수 있습니다. 즉, 프랑스어 집합의 시스템 언어가 없는 사용자의 경우 영어 리소스 팩 다운로드로 대체되고 영어로 표시됩니다.

선택적 패키지는 각각 고유한 패키지 패밀리 이름을 가지며 PackageFamily 요소로 정의되어야 하며 Optional 특성을 true로 지정해야 합니다. RelatedSet 특성은 선택적 패키지가 관련 집합 내에 있는지(기본적으로 true) - 선택적 패키지를 기본 패키지로 업데이트해야 하는지 여부를 지정하는 데 사용됩니다.

PrebuiltPackage 요소는 빌드할 앱 번들 파일에 포함되거나 참조될 패키징 레이아웃에 정의되지 않은 패키지를 추가하는 데 사용됩니다. 이 경우 기본 앱 번들 파일이 이를 참조하고 관련 집합의 일부가 될 수 있도록 다른 DLC 선택적 패키지가 여기에 포함됩니다.

패키징 레이아웃을 통해 앱 패키지 빌드 및 MakeAppx.exe

앱에 대한 패키징 레이아웃이 있으면 MakeAppx.exe 사용하여 앱 패키지를 빌드할 수 있습니다. 패키징 레이아웃에 정의된 모든 패키지를 빌드하려면 명령을 사용합니다.

MakeAppx.exe build /f PackagingLayout.xml /op OutputPackages\

그러나 앱을 업데이트하고 일부 패키지에 변경된 파일이 없는 경우 변경된 패키지만 빌드할 수 있습니다. 이 페이지의 간단한 패키징 레이아웃 예제를 사용하고 x64 아키텍처 패키지를 빌드하면 명령이 다음과 같이 표시됩니다.

MakeAppx.exe build /f PackagingLayout.xml /id "x64" /ip PreviousVersion\ /op OutputPackages\ /iv

/id플래그는 레이아웃의 /id 특성에 해당하는 패키징 레이아웃에서 빌드할 패키지를 선택하는 데 사용할 수 있습니다. /ip은 이 경우 이전 버전의 패키지가 있는 위치를 나타내는 데 사용됩니다. 앱 번들 파일은 여전히 이전 버전의 Media 패키지를 참조해야 하므로 이전 버전을 제공해야 합니다. /iv플래그는 /iv버전을 변경하는 대신 빌드 중인 패키지의 버전을 자동으로 증가시키기 위해 사용됩니다. 또는 스위치 및 를 /pv/bv 사용하여 패키지 버전(만들 모든 패키지의 경우) 및 번들 버전(만들 모든 번들에 대해)을 직접 제공할 수 있습니다. 이 페이지의 고급 패키징 레이아웃 예제를 사용하여 테마 선택적 번들 및 참조하는 Themes.main 앱 패키지만 빌드하려면 다음 명령을 사용합니다.

MakeAppx.exe build /f PackagingLayout.xml /id "Themes" /op OutputPackages\ /bc /nbp

/bc플래그는 /bc 번들의 자식도 빌드해야 임을 나타내는 데 사용됩니다(이 경우 Themes.main이 빌드됩니다). /nbp플래그는 /nbp 번들의 부모가 빌드되지 않아야 임을 나타내는 데 사용됩니다. 선택적 앱 번들인 테마의부모는 기본 앱 번들인 MyGame입니다. 일반적으로 관련 집합의 선택적 패키지의 경우 선택적 패키지가 관련 집합에 있을 때(기본 패키지와 선택적 패키지 간의 버전 지정을 보장하기 위해) 기본 앱 번들에서도 참조되므로 선택적 패키지를 설치할 수 있도록 기본 앱 번들을 빌드해야 합니다. 패키지 간의 부모 자식 관계는 다음 다이어그램에 설명되어 있습니다.

레이아웃 다이어그램 패키징