NuGet을 게시하기 위해 알아야 할 모든 것
Source: Dev.to
이전 기사에서는 소비자 입장에서 의존성 지옥을 어떻게 살아남을지 분석했습니다. 하지만 기술 경력에서 진정한 도약은 패키지를 다운로드하는 사람에서 패키지를 설계하는 사람으로 변할 때 일어납니다.
NuGet이 해결하는 근본적인 문제는 단순히 *“DLL을 내려받는 것”*이 아니라 아키텍처 수준에서 DRY(Do not Repeat Yourself) 원칙을 위반하는 것입니다.
예를 들어 AuditLog.cs 혹은 StringUtils.cs 클래스를 가지고 있다고 가정해 보세요. 새로운 마이크로서비스를 시작할 때 가장 “빠른” 방법은 파일을 복사‑붙여넣기 하는 것입니다. 몇 달 후 해당 클래스에 치명적인 보안 버그가 발견되면 10개의 서로 다른 레포지토리를 일일이 수동으로 패치해야 합니다.
전문적인 해결책은 이를 패키징하는 것이며, NuGet으로 어떻게 하는지 알아보겠습니다.
NuGet Library
라이브러리를 만드는 데 마법은 필요 없고 메타데이터가 필요합니다. .csproj 파일은 단순 설정 파일에서 제품 매니페스트로 변합니다. .dll이 제품이라면, .csproj는 배송 라벨과 같은 역할을 합니다; 이 라벨이 없으면 누구도 그것이 무엇인지, 어떻게 쓰이는지, 안전한지 알 수 없습니다.
기본 설정
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<PackageId>MyCompany.Common</PackageId>
<Version>1.0.0</Version>
<Authors>Equipo de Arquitectura</Authors>
<Company>Mi Empresa S.A.</Company>
<Description>Librería base para validaciones y logs estandarizados.</Description>
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Deterministic>true</Deterministic>
<PackageTags>logs;validation;common;architecture</PackageTags>
<PackageOutputPath>./nupkg</PackageOutputPath>
<RepositoryUrl>https://github.com/mi-empresa/my-common-lib</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSource>true</IncludeSource>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
</Project>
왜 각 라인이 중요한가?
🎯 Target(멀티‑타깃) 딜레마
netstandard2.0: 거의 모든 환경(.NET Framework 4.6.1 이상 포함)에서 동작합니다.net8.0: 최신 성능 최적화를 활용합니다.
NuGet은 소비자 프로젝트에 맞춰 자동으로 올바른 DLL을 제공하게 됩니다.
📁 Assets(아이콘 & Readme)
PackageIcon: 로고(PNG 128×128)를 포함합니다.PackageReadmeFile:README.md가 Visual Studio의 NuGet 탭에 표시돼 즉시 문서를 확인할 수 있습니다.
🔒 결정적 빌드
Deterministic=true는 코드가 변하지 않는 한 바이너리가 비트 단위까지 동일하게 생성됨을 보장합니다. 이는 보안 검증 및 기업 캐시 전략에 필수적입니다.
📦 전이적 의존성
Serilog를 PackageReference로 선언하면 패키지를 사용하는 모든 프로젝트가 자동으로 해당 의존성을 받게 되어 수동 설치를 피할 수 있습니다.
🏷️ 레포지토리 태그
RepositoryUrl과 RepositoryType은 패키지를 소스 코드와 연결해 신뢰성을 높이고 감사(audit)를 용이하게 합니다.
🗂️ 버전 관리 전략
여기서는 정적 버전(1.0.0)을 사용했지만, 실제 현업에서는 MinVer와 같은 도구를 이용해 Git Tag 기반의 의미 체계 버전을 자동으로 생성하는 것이 권장됩니다.
⚖️ 법적 라이선스
- 오픈소스: 표준 식별자(MIT, Apache‑2.0 등)를 사용합니다.
- 프로프라이어터리/기업: 패키지 내부
LICENSE.txt파일을 가리키는 식으로 지정합니다.

NuGet Tools
라이브러리가 애플리케이션에 통합되는 반면, NuGet Tools는 애플리케이션과 함께 실행되는 도구(dotnet‑ef 등)입니다. 콘솔 애플리케이션을 패키징해 자체 기업 도구를 만들 수 있습니다.
PackAsTool
핵심 차이는 PackAsTool 속성에 있습니다. 이 속성은 NuGet에게 패키지에 실행 파일이 포함돼 있음을 알려줍니다(라이브러리가 아님).
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<PackAsTool>true</PackAsTool>
<ToolCommandName>my-scaffolder</ToolCommandName>
<PackageId>MyCompany.Scaffolder</PackageId>
<Version>1.0.0</Version>
<PackageOutputPath>./nupkg</PackageOutputPath>
</PropertyGroup>
</Project>
도구 사용법
# 전역 설치
dotnet tool install -g MyCompany.Scaffolder
# 실행
my-scaffolder "NuevoServicio"
💡 전역 설치를 피하고 싶다면 Local Tools(dotnet new tool-manifest)를 사용하고 dotnet tool restore로 버전을 공유할 수 있습니다.
배포 전략
.nupkg 아티팩트를 만든 것이 첫 단계일 뿐입니다. 중요한 결정은 어디에 호스팅하느냐입니다. 배포하려면 NuGet.config에 대상 피드를 등록해야 합니다. 이 파일은 양방향 “주소록” 역할을 하며, 외부 피드에서 패키지를 소비하고 우리 패키지를 다른 팀이나 커뮤니티에 공개하는 두 가지 용도로 사용됩니다.
(NuGet.config 설정, nuget.org, Azure Artifacts, GitHub Packages 등에 게시하는 내용은 계속됩니다.)