.NET 빌드와 배포 방식의 재창조 (다시)
(devblogs.microsoft.com)- .NET Unified Build 프로젝트는 기존 분산형 저장소 기반 빌드 구조의 복잡성과 비효율을 줄이기 위해, 제품 전체를 ‘가상 단일 저장소(Virtual Monolithic Repository, VMR)’ 형태로 통합한 새로운 빌드 체계
- 기존의 분산형 제품 구성 방식은 독립성과 유연성은 높지만, 의존성 관리·빌드 일관성·속도 측면에서 큰 부담을 초래
- Unified Build는 Linux 배포판용 Source Build의 원리를 확장해, 단일 소스 레이아웃과 ‘수직 빌드(Vertical Build)’ 구조를 도입하여 빌드 시간을 단축하고 예측 가능성을 확보
- 양방향 코드 흐름(two-way code flow) , 시나리오 테스트, 자동 검증 및 서명 인프라 개선 등을 통해 개발자 효율성과 제품 품질을 동시에 향상
- .NET 10에서 정식 도입된 이 체계는 빌드 시간 단축(24시간→7시간 이하) , 유지보수 비용 절감, 배포 신뢰성 향상 등 실질적 성과를 달성
.NET 빌드 구조의 변화 배경
- .NET은 2015~2016년 오픈소스화 과정에서 CoreCLR, CoreFX, ASP.NET Core, SDK 등 다수의 저장소로 분리되어 개발
- 각 저장소가 독립적으로 빌드·배포되며, 전체 제품은 의존성 그래프를 통해 조합되는 구조
- 이 방식은 OSS 생태계와 유사하지만, 보안 패치나 긴급 수정 시 여러 팀의 동시 조율이 필요해 시간 예측 불가 문제가 발생
- 분산형 개발의 장점(레이어링, 커뮤니티 분화, 비동기 개발 등)에도 불구하고, 제품 일관성(coherency) 확보에는 비효율적
제품 구성 복잡성과 오버헤드
-
복잡성(Complexity) : 변경이 고객에게 전달되기까지 필요한 단계 수로 정의
- 저장소·의존성 노드가 많을수록 일관성 확보에 더 많은 시간과 인적 조율 필요
-
오버헤드(Overhead) : 고객에게 전달 가능한 산출물을 직접 생산하지 않는 시간
- 예: PR 생성·승인 대기, 큐잉, 환경 설정 등
- .NET 8 런타임 빌드 분석 결과, 전체 빌드 시간의 약 38.5%가 오버헤드로 확인
- 복잡성과 오버헤드가 결합되면 빌드 효율이 급격히 저하되고, 전체 릴리스 주기가 길어짐
Source Build와 Unified Build의 기원
-
Source Build는 Linux 배포판이 .NET을 단일 소스에서 오프라인 빌드할 수 있도록 설계된 시스템
- 단일 구현, 단일 플랫폼, 단일 빌드 환경 원칙
- 빌드 오케스트레이터가 각 구성요소의 의존성과 빌드 순서를 관리
- Source Build는 낮은 복잡도·낮은 오버헤드로 50분 내 빌드 가능
- Microsoft 내부 빌드에도 이 개념을 적용하려 했으나, 폐쇄 소스·레거시 의존성·플랫폼 간 조인(join) 등으로 어려움 존재
- 이를 해결하기 위해 참조 전용 패키지(source-build-reference-packages) , 단일 구현 원칙, 조인 제거 등의 접근 도입
Unified Build의 목표와 설계
- 단일 커밋으로 전체 .NET 제품 빌드 가능
- 모든 플랫폼별 배포판을 단일 환경에서 생성
- Microsoft 외부에서도 독립적 빌드·검증 가능
- 양방향 코드 흐름을 통해 VMR과 개별 저장소 간 변경 자동 동기화
- 시나리오 테스트를 통해 전체 제품 수준의 기능 검증 수행
-
수직 빌드(Vertical Build) 구조로 플랫폼별 빌드를 병렬화
- 약 35~40개의 빌드 수직선(short/tall stack)으로 구성
Unified Build 구현 단계
- .NET 7: 개념 설계 및 승인
- .NET 8: Source Build 인프라 개선 및 기반 구축
- .NET 9: 수직 빌드 및 코드 흐름 실험
-
.NET 10: 정식 제품화 및 RTM 반영
- Preview 4에서 새 빌드 프로세스 도입, Preview 5부터 완전 전환
주요 구성 요소
Virtual Monolithic Repository (VMR)
- dotnet/dotnet 저장소가 모든 구성요소의 단일 소스 레이아웃 역할
- 개발자는 개별 저장소 또는 VMR에서 작업 가능, 분산형의 유연성과 단일형의 일관성을 동시에 확보
Vertical Build
- 각 플랫폼·런타임별로 독립 빌드 수행
- 병렬 빌드 후 결과를 통합, 일부 조인(join)은 추가 빌드 패스로 처리
Code Flow
- 양방향 코드 동기화: 구성요소 저장소 → VMR, VMR → 구성요소 저장소
-
eng/Version.Details.xml에 마지막 코드 흐름 상태 기록 - 변경 사항을 패치 파일로 생성해 자동 PR 생성
- 충돌 처리 및 오류 복구 로직 내장
Scenario Test Validation
- 기존 단위 테스트 외에 제품 전체 기능을 검증하는 시나리오 테스트 추가
- 빌드 산출물 기준으로 실행되어, 회귀 방지 및 품질 보증 강화
성과와 효과
- 빌드 시간 단축: 24시간 이상 → 7시간 이하(서명 포함)
- 유연성 향상: 빌드·배포 주기 단축, 긴급 수정 반영 용이
- 예측 가능성 확보: 변경 후 빌드 완료 시점 명확
- 인프라 개선: 서명 도구, 로그, 병렬 빌드, 의존성 흐름 자동화 등
- Linux 배포판용 Source Build도 항상 사전 빌드 클린 상태 유지
향후 방향
- .NET 11에서는 코드 흐름 자동화 및 AI 기반 모니터링 에이전트 도입 예정
- PR→제품 반영 과정의 오류 추적 자동화
- 장기적으로 조인 포인트 제거를 통해 빌드 단순화 및 속도 향상 추진
- 목표: 4시간 이내 완전 빌드
결론
- 분산형 빌드 모델의 한계를 극복한 Unified Build는 .NET의 빌드·배포 효율성을 근본적으로 개선
- 복잡성·오버헤드 감소, 일관성·속도·품질 향상이라는 세 가지 축에서 실질적 진전 달성
- .NET 10 RTM부터 이 체계가 전면 적용되어, 향후 버전에서도 지속적 개선 예정
Hacker News 의견
-
나는 .NET 팀을 정말 존경함
그들은 자주 깊이 있는 기술 글을 내고, 성능 최적화에 대한 집착이 대단함 (예: Kestrel, Entity Framework의 발전)
ASP.NET은 Python 2→3 수준의 큰 변화에도 살아남은 몇 안 되는 대형 프로젝트 중 하나임
예전엔 세션 동기화를 위해 마법 같은 기능에 의존했지만, 이제는 완전히 다른 방식으로 작동함
3조 달러 규모의 기업이 내가 쓰는 스택을 진심으로 개선하려 한다는 게 기분 좋음- 예전에 Entity Framework를 써봤는데 너무 느렸음
그래서 Dapper와 직접 만든 마이그레이션 시스템으로 교체했더니, 시작 시 DB 검증 및 시딩 시간이 10초 → 2초 미만으로 줄었음 (저사양 하드웨어 + SQLite 환경)
Entity가 생성하는 쿼리는 불필요한 다중 join이 많았음
요즘은 단순한 Go 백엔드로 전환 중이며, .NET은 다른 솔루션에만 씀
WPF 같은 프레임워크는 Win32 해킹이 필요할 정도로 문제가 많았음
예를 들어 .NET 9에서야 모든 네트워크 인터페이스를 제대로 반환함. 이전 런타임은 활성 NIC만 노출했음
아직도 Windows 7 지원을 유지해야 하는 프로젝트가 있음 - 많은 프로젝트가 .NET Core로 넘어오지 못하고 남겨졌다고 생각함
새 프로젝트에서도 여전히 .NET 4.8을 써야 하는 경우가 있음. 예를 들어 Excel 수식 빌드 시 async/await deadlock 문제가 발생함
또한 Windows 통합 기능이 깨져서, 같은 네트워크 호출이 4.8에서는 인증되지만 Core에서는 실패함
수많은 라이브러리의 하위 호환성 붕괴로 인해 마이그레이션이 쉽지 않음
성능은 좋아졌지만 기능 면에서는 .NET Framework가 화석화된 느낌임
JSON serializer가 표준 라이브러리에 추가되기까지 15년이 걸렸고, webp나 heic 같은 최신 이미지 포맷 지원도 없음
Visual Studio는 매일같이 크래시 메시지를 띄움
예전엔 열렬한 .NET 팬이었지만, Anders의 리더십이 그리움
- 예전에 Entity Framework를 써봤는데 너무 느렸음
-
최근 사이드 프로젝트에서 macOS의 VSCode로 C# REST API 백엔드를 개발하고, 3년째 Linux에 배포 중임
SQLite, EFCore, Minimal API를 쓰는데, 프론트엔드(NextJS/React/MaterialUI, npm 패키지 50개 이상)보다 훨씬 쾌적함- API가 조금 복잡해지면 FastEndpoints 라이브러리를 추천함
개인적으로 가장 좋아하는 API 프레임워크임
차선책은 TS + Hono + Zod-OpenApi + SwaggerUI 조합인데, 타입 컨텍스트 설정이 좀 번거로움
- API가 조금 복잡해지면 FastEndpoints 라이브러리를 추천함
-
.NET의 오픈소스화와 크로스플랫폼화를 위한 기반이 리눅스 배포판 빌드 시스템이었다는 점이 인상적이었음
- 글 작성자인 내가 직접 설명하자면, 배포판 유지보수자들이 .NET을 네이티브 패키지 피드에 포함할 수 있게 하려면 그들이 직접 빌드해야 함
그래서 그들의 요구사항을 만족하는 빌드 시스템이 필요했고, 결국 리눅스 배포판 모델로 통합하는 게 유일한 방향이었음
이 모델은 단순하지만 성능은 떨어짐. 캐싱이 있는 분산 빌드 시스템이 더 빠르지만, 유지보수자 워크플로와 맞지 않음
단순함을 최적화하는 게 커뮤니티 참여를 유도하는 데 더 낫다고 판단함
BSD, S390x 등 다양한 플랫폼 빌드와 배포를 커뮤니티가 직접 할 수 있게 하는 게 목표임 - .NET은 이제 오픈소스 전환을 후회할 단계는 이미 지났다고 생각함
지난 10년간의 풀 리퀘스트와 긍정적 결과물의 양이 놀라울 정도임
- 글 작성자인 내가 직접 설명하자면, 배포판 유지보수자들이 .NET을 네이티브 패키지 피드에 포함할 수 있게 하려면 그들이 직접 빌드해야 함
-
올해 읽은 글 중 가장 인상 깊은 소프트웨어 엔지니어링 글이 Microsoft에서 나올 줄은 몰랐음
.NET의 최근 버전을 좋아하지만, 그 견고함이 우연의 산물이라 생각했었음
그런데 이번 글은 품질 향상을 위한 체계적 노력을 보여줌 (다이어그램, LLM 활용 사례까지 포함)
향후엔 이런 투자가 줄어든다고 해도, 이건 “어떻게 해야 하는가”를 보여주는 좋은 사례임 -
이 프로젝트에 참여한 사람들은 정말 대단한 경험을 했을 것 같음
-
글은 좋았지만, .NET 팀이 Azure DevOps를 버려야 한다고 생각함
큐 대기 시간이 가장 큰 병목임. 베어메탈 빌드 서버를 돌려야 함- Azure DevOps 자체가 문제는 아님. 베어메탈에서도 동작함
Mac 하드웨어는 빠르게 연결되고 시작함
우리는 각 작업마다 클린 VM을 새로 띄워서 컴플라이언스와 안정성을 확보함
미리 준비된 핫 머신을 유지하면 대기 시간을 없앨 수 있지만, 비용이 너무 큼
다양한 SKU를 항상 대기 상태로 유지하는 건 현실적으로 어렵기에 절충함
- Azure DevOps 자체가 문제는 아님. 베어메탈에서도 동작함
-
왜 Microsoft의 Developer Division은 업계 최고 수준인데, 나머지 부서는 무능과 관료주의의 상징이 되었는지 궁금함
- 정치적 이유와 업계 리더 추종 때문임
Bill이 떠난 이후, 스스로를 돌아보는 문화가 사라졌음
- 정치적 이유와 업계 리더 추종 때문임
-
복잡한 시스템을 단순화하려는 추상화 중심 사고방식이 문제의 근원이라 생각함
상위 레벨에서 모든 걸 해결하려 하기보다, 하위 레벨에서부터 쌓아올리는 접근이 더 많은 문제를 근본적으로 없앨 수 있음 -
“한 달에 3~4개의 주요 버전과 수십 개의 SDK 밴드를 빌드한다”는 문장을 보고 왜 이렇게 변형이 많은지 궁금했음
- 현재 .NET 8(LTS), .NET 9(표준 지원), .NET 10(LTS)이 동시에 유지되고 있음
또한 각 버전마다 SDK/aspnet/runtime이 x64/arm32/arm64, Linux/macOS/Windows 등 다양한 플랫폼으로 빌드됨
- 현재 .NET 8(LTS), .NET 9(표준 지원), .NET 10(LTS)이 동시에 유지되고 있음
-
Node가 유행하기 전, .NET은 백엔드 빌드의 탄탄한 선택지였음 (성능도 Node보다 우수함)
최근 Node 생태계의 공급망 공격 이후, 많은 개발자가 안정적인 플랫폼으로 돌아오길 바람- “churn”이 무슨 의미인지 궁금함. 이 글은 내부 빌드 시스템에 대한 내용인데, 불안정성과 무슨 관련이 있는지 모르겠음
- .NET은 여전히 훌륭하고 매 릴리스마다 더 좋아지고 있음
큰 변화는 .NET Core로의 전환이었지만, 그건 거의 10년 전 일임 - C# + JetBrains Rider 조합은 내 커리어에서 가장 만족스러운 개발 경험이었음
- .NET Core 3 이후로는 큰 호환성 문제를 거의 겪지 않았음
프레임워크와 의존성 업데이트는 약간 번거롭지만, React 프로젝트 업데이트에 비하면 훨씬 수월함
짧은 LTS 주기 덕분에 최신 상태 유지가 어렵지 않음. 빠른 개발 주기에서는 이런 유지보수가 당연한 일임 - 다언어 컨설턴트로서, .NET 관련 RFP가 더 많아지길 바람
현실은 Node.js, Java, 저코드(iPaaS) 위주임
그래도 성능 문제 덕분에 가끔 C++ 애드온을 제안할 기회가 생김