단일 파일 배포
모든 애플리케이션 종속 파일을 하나의 이진 파일로 묶으면 애플리케이션 개발자가 애플리케이션을 단일 파일로 배포할 수 있습니다. 단일 파일 배포는 프레임워크 종속 배포 모델과 자체 포함 애플리케이션에 모두 사용할 수 있습니다.
자체 포함 애플리케이션의 단일 파일 크기는 런타임 및 프레임워크 라이브러리를 포함하기 때문에 큽니다. .NET 6에서는 자르기 호환 애플리케이션의 전체 크기를 줄이기 위해 잘린 상태로 게시할 수 있습니다. 단일 파일 배포 옵션을 ReadyToRun 및 Trim 게시 옵션과 함께 사용할 수 있습니다.
Important
Windows 7에서 단일 파일 앱을 실행하려면 .NET 런타임 6.0.3 이상을 사용해야 합니다.
샘플 프로젝트 파일
다음은 단일 파일 게시를 지정하는 샘플 프로젝트 파일입니다.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
</Project>
위 속성에는 다음과 같은 함수가 있습니다.
PublishSingleFile
. 단일 파일 게시를 사용하도록 설정합니다.dotnet build
중에 단일 파일 경고도 사용하도록 설정합니다.SelfContained
. 앱이 독립형인지, 프레임워크 종속형인지 결정합니다.RuntimeIdentifier
. 대상 지정하는 OS 및 CPU 형식을 지정합니다. 기본적으로<SelfContained>true</SelfContained>
도 설정합니다.
단일 파일 앱은 항상 OS 및 아키텍처에 따라 다릅니다. Linux x64, Linux Arm64, Windows x64 등과 같은 각 구성에 대해 게시해야 합니다.
*.runtimeconfig.json 및 *.deps.json과 같은 런타임 구성 파일은 단일 파일에 포함됩니다.
단일 파일 앱 게시
dotnet publish 명령을 사용하여 단일 파일 애플리케이션을 게시합니다.
<PublishSingleFile>true</PublishSingleFile>
를 프로젝트 파일에 추가합니다.이 변경으로 인해 자체 포함 게시 시 단일 파일 앱이 생성됩니다. 빌드 중에 단일 파일 호환성 경고도 표시됩니다.
<PropertyGroup> <PublishSingleFile>true</PublishSingleFile> </PropertyGroup>
dotnet publish -r <RID>
를 사용하여 특정 런타임 식별자에 대한 앱을 게시합니다.다음 예제에서는 Windows용 앱을 자체 포함 단일 파일 애플리케이션으로 게시합니다.
dotnet publish -r win-x64
다음 예제에서는 Linux용 앱을 프레임워크 종속 단일 파일 애플리케이션으로 게시합니다.
dotnet publish -r linux-x64 --self-contained false
빌드 중에 파일 분석을 사용하도록 설정하려면 프로젝트 파일에 <PublishSingleFile>
을 설정해야 하지만 다음 옵션을 dotnet publish
인수로 전달할 수도 있습니다.
dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained false
자세한 내용은 .NET CLI를 사용하여 .NET Core 앱 게시를 참조하세요.
파일이 포함되지 않도록 제외
다음 메타데이터를 설정하면 특정 파일이 단일 파일에 포함되지 않도록 명시적으로 제외할 수 있습니다.
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
예를 들어, 일부 파일을 게시 디렉터리에 저장하지만 파일에 묶이지 않도록 하려면 다음을 수행합니다.
<ItemGroup>
<Content Update="Plugin.dll">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</Content>
</ItemGroup>
번들 내에 PDB 파일 포함
어셈블리의 PDB 파일은 아래 설정을 사용하여 어셈블리 자체(.dll
)에 포함할 수 있습니다. 기호는 어셈블리의 일부이므로 애플리케이션의 일부이기도 합니다.
<DebugType>embedded</DebugType>
예를 들어 어셈블리의 프로젝트 파일에 다음 속성을 추가하여 해당 어셈블리에 PDB 파일을 포함합니다.
<PropertyGroup>
<DebugType>embedded</DebugType>
</PropertyGroup>
기타 고려 사항
단일 파일 애플리케이션에는 기본적으로 번들로 제공되지 않고 애플리케이션과 함께 관련된 모든 PDB 파일이 있습니다. 빌드하는 프로젝트의 어셈블리 내부에 PDB를 포함하려면 DebugType
을 embedded
로 설정합니다. 번들 내에 PDB 파일 포함을 참조하세요.
관리되는 C++ 구성 요소는 단일 파일 배포에 적합하지 않습니다. 단일 파일과 호환되도록 C# 또는 관리되지 않는 다른 C++ 언어로 애플리케이션을 작성하는 것이 좋습니다.
네이티브 라이브러리
관리되는 DLL만 앱과 함께 단일 실행 파일로 번들됩니다. 앱이 시작되면 관리형 DLL이 추출되어 메모리에 로드되며 폴더로 추출되지 않습니다. 이 방식을 사용하면 관리되는 이진 파일이 단일 파일 번들에 포함되지만 코어 런타임 자체의 네이티브 이진 파일은 별도의 파일입니다.
추출을 위해 해당 파일을 포함하고 하나의 출력 파일을 가져오려면 IncludeNativeLibrariesForSelfExtract
속성을 true
로 설정합니다.
IncludeAllContentForSelfExtract
를 지정하면 실행 파일을 실행하기 전에 관리되는 어셈블리를 포함한 모든 파일이 추출됩니다. 이는 드물게 발생하는 애플리케이션 호환성 문제에 도움이 될 수 있습니다.
Important
추출을 사용하는 경우 앱이 시작되기 전에 파일이 디스크에 추출됩니다.
DOTNET_BUNDLE_EXTRACT_BASE_DIR
환경 변수가 경로로 설정된 경우 파일은 해당 경로 아래의 디렉터리에 추출됩니다.- 그렇지 않고 Linux 또는 macOS에서 실행 중인 경우 파일은
$HOME/.net
아래의 디렉터리에 추출됩니다. - Windows에서 실행하는 경우 파일은
%TEMP%/.net
아래의 디렉터리에 추출됩니다.
변조를 방지하려면 다른 권한을 가진 사용자나 서비스가 이러한 디렉터리에 쓸 수 없어야 합니다. 대부분의 Linux 및 macOS 시스템에서는 /tmp 또는 /var/tmp를 사용하지 마세요.
참고 항목
systemd
와 같은 일부 Linux 환경에서는 $HOME
이 정의되지 않았기 때문에 기본 추출이 작동하지 않습니다. 이러한 경우에는 $DOTNET_BUNDLE_EXTRACT_BASE_DIR
을 명시적으로 설정하는 것이 좋습니다.
systemd
의 경우 좋은 대안은 서비스 단위 파일에서 DOTNET_BUNDLE_EXTRACT_BASE_DIR
을 %h/.net
으로 정의하는 것입니다. 그러면 서비스를 실행하는 계정에 대해 systemd
가 $HOME/.net
으로 올바르게 확장됩니다.
[Service]
Environment="DOTNET_BUNDLE_EXTRACT_BASE_DIR=%h/.net"
API 비호환성
일부 API는 단일 파일 배포와 호환되지 않습니다. 애플리케이션이 이러한 API를 사용하는 경우 수정이 필요할 수 있습니다. 사용 중인 타사 프레임워크나 패키지에도 이러한 API 중 하나가 사용될 수 있으며, 이 경우 수정이 필요할 수 있습니다. 문제의 가장 일반적인 원인은 애플리케이션과 함께 제공되는 파일 또는 DLL의 파일 경로에 대한 종속성입니다.
아래 표에는 단일 파일 사용을 위한 관련 런타임 라이브러리 API 세부 정보가 나와 있습니다.
API | 참고 항목 |
---|---|
Assembly.CodeBase |
PlatformNotSupportedException을 버립니다. |
Assembly.EscapedCodeBase |
PlatformNotSupportedException을 버립니다. |
Assembly.GetFile |
IOException을 버립니다. |
Assembly.GetFiles |
IOException을 버립니다. |
Assembly.Location |
빈 문자열을 반환합니다. |
AssemblyName.CodeBase |
null 을(를) 반환합니다. |
AssemblyName.EscapedCodeBase |
null 을(를) 반환합니다. |
Module.FullyQualifiedName |
<Unknown> 값이 포함된 문자열을 반환하거나 예외를 throw합니다. |
Marshal.GetHINSTANCE |
-1이 반환됩니다. |
Module.Name |
<Unknown> 값이 포함된 문자열을 반환합니다. |
일반적인 시나리오를 해결하기 위한 몇 가지 권장 사항이 있습니다.
실행 파일 옆의 파일에 액세스하려면 AppContext.BaseDirectory을 사용합니다.
실행 파일의 파일 이름을 찾으려면 Environment.GetCommandLineArgs()의 첫 번째 요소를 사용하거나 .NET 6부터는 ProcessPath의 파일 이름을 사용합니다.
느슨한 파일이 제공되는 것을 완전히 방지하려면 포함 리소스를 사용하는 것이 좋습니다.
묶음 전 사후 처리 이진 파일
일부 워크플로에서는 묶음 전에 이진 파일 사후 처리가 필요합니다. 일반적인 예는 서명입니다. dotnet SDK는 단일 파일 묶음 직전에 이진 파일을 처리할 수 있도록 MSBuild 확장 지점을 제공합니다. 사용 가능한 API는 다음과 같습니다.
GenerateSingleFileBundle
이전에 호출될 대상PrepareForBundle
- 번들로 묶을 모든 파일을 포함하는
<ItemGroup><FilesToBundle /></ItemGroup>
- apphost 템플릿을 지정하는 속성
AppHostFile
. 사후 처리에서는 앱 호스트를 처리에서 제외할 수 있습니다.
여기에 연결하려면 PrepareForBundle
과 GenerateSingleFileBundle
사이에서 실행될 대상을 만들어야 합니다.
다음 .NET 프로젝트 Target
노드 예를 고려합니다.
<Target Name="MySignedBundledFile" BeforeTargets="GenerateSingleFileBundle" DependsOnTargets="PrepareForBundle">
도구가 서명 과정에서 파일을 복사해야 할 수도 있습니다. 원본 파일이 빌드가 소유하지 않은 공유 항목인 경우(예: 파일이 NuGet 캐시에서 가져온 경우) 이런 일이 발생할 수 있습니다. 이러한 경우 도구는 수정된 복사본을 가리키도록 해당 FilesToBundle
항목의 경로를 수정합니다.
단일 파일 앱에서 어셈블리 압축
포함된 어셈블리에서 압축을 사용하도록 설정하여 단일 파일 앱을 만들 수 있습니다. EnableCompressionInSingleFile
속성을 true
로 설정합니다. 생성된 단일 파일에는 모든 포함된 어셈블리가 압축되어 실행 파일의 크기를 크게 줄일 수 있습니다.
압축에는 성능 비용이 필요합니다. 애플리케이션을 시작할 때 어셈블리를 메모리에 압축 해제해야 하며 이 작업은 시간이 걸립니다. 압축을 사용하기 전에 압축 사용하도록 설정에 따른 크기 변경과 시작 비용을 모두 측정하는 것이 좋습니다. 그 영향은 애플리케이션마다 크게 다를 수 있습니다.
단일 파일 앱 검사
단일 파일 앱은 ILSpy 도구를 사용하여 검사할 수 있습니다. 이 도구는 애플리케이션에 번들로 포함된 모든 파일을 표시하고 관리되는 어셈블리의 콘텐츠를 검사할 수 있습니다.
참고 항목
.NET