개요
C# Source Generator는 컴파일 시점에 사용자 코드를 검사(Inspect)하고, 그 결과로 새로운 C# 소스 코드를 생성해 같은 컴파일 단위에 넣을 수 있게 해 주는 Roslyn 기반 기능이다. 런타임 리플렉션 없이 타입·구조를 분석하고, 생성된 코드는 기존 코드와 함께 한 번에 컴파일된다.
Source Generator가 제공하는 두 가지 핵심 기능은 다음과 같다.
- 컴파일 객체 접근: 현재 컴파일 중인 코드의 Compilation 객체를 얻을 수 있다. Syntax Tree·Semantic Model과 연동해 분석 로직을 작성할 수 있다.
- 소스 추가: 컴파일 과정 중에 새 C# 소스 파일을 컴파일에 추가할 수 있다. 즉, 분석 결과를 C# 코드로 만들어 기존 프로젝트에 끼워 넣는 방식이다.
이를 통해 런타임 리플렉션 부담을 줄이고, AOT(Ahead-of-Time) 컴파일·트리밍 친화적인 코드 생성이 가능해진다.
동작 흐름
Source Generator는 컴파일 파이프라인 안에서 한 단계로 동작한다. 사용자 소스 → Compilation 구성 → Generator 실행 → 생성 소스 추가 → 최종 컴파일 순서로 이어진다.
flowchart LR UserCode["사용자 C# 소스"] Compilation["Compilation구성"] SourceGen["Source Generator실행"] GeneratedSource["생성된 소스추가"] FinalComp["최종 컴파일"] UserCode --> Compilation Compilation --> SourceGen SourceGen -->|"AddSource()"| GeneratedSource GeneratedSource --> FinalComp Compilation -.->|"구성 참조"| SourceGen
기존 코드 생성·분석 방식과의 비교
Source Generator를 쓰기 전에 흔히 쓰이던 방식은 다음과 같다.
| 방식 | 설명 | 한계 |
|---|---|---|
| 런타임 리플렉션 | 앱 실행 시 타입·멤버를 조회해 동작 결정 | 시작 시 비용, AOT/트리밍에 불리 |
| MSBuild 작업 연동 | CSC를 여러 번 호출해 중간 결과를 활용 | 빌드 시간 증가, 복잡도 상승 |
| IL Weaving | 빌드 후 IL을 수정 | 도구 의존성, 디버깅·호환 이슈 |
Source Generator는 컴파일 단계에서만 동작하며, 사용자 소스를 수정하지 않고 추가만 할 수 있다. 그래서 기존 코드 동작이 바뀌지 않으며, 런타임 비용을 줄이면서도 강한 타입 정보를 활용할 수 있다.
프로젝트 구성
생성기 프로젝트(.NET Standard 2.0)
Source Generator는 .NET Standard 2.0 라이브러리로 작성한다. Roslyn 패키지를 참조하고, [Generator]와 ISourceGenerator를 사용한다.
프로젝트 파일 예시
| |
- TFM:
netstandard2.0을 사용한다. - 패키지:
Microsoft.CodeAnalysis.CSharp,Microsoft.CodeAnalysis.Analyzers를 PackageReference로 추가하고, 생성기는 실행 시점에 노출되지 않도록PrivateAssets="all"등을 설정한다.
Generator 클래스 골격
Generator는 ISourceGenerator를 구현하고 [Generator] 특성을 붙인다.
| |
Execute: 컴파일 시 호출되며,context.Compilation으로 사용자 코드를 분석하고context.AddSource()로 생성 소스를 넣는다.Initialize:Execute가 여러 번 호출될 수 있으므로, 여기서 공통 초기화·캐싱을 할 수 있다.
Hello World 예제
1. HelloWorldGenerator 구현
생성기 프로젝트에 다음 클래스를 추가한다. 컴파일에 포함된 Syntax Tree 목록을 출력하는 HelloWorldGenerated.HelloWorld.SayHello() 메서드를 생성한다.
| |
context.Compilation.SyntaxTrees: 현재 컴파일에 포함된 모든 Syntax Tree를 열거한다.context.AddSource(파일명, SourceText): 생성된 문자열을 가상의 C# 파일로 컴파일에 추가한다. 파일명은 고유해야 하며, 일반적으로.cs는 붙이지 않아도 된다.
2. 생성 코드를 사용하는 콘솔 프로젝트
콘솔 앱 프로젝트에서 위 생성기 프로젝트를 Analyzer로 참조한다.
| |
빌드 시 Generator가 HelloWorldGenerated.HelloWorld를 생성하므로, 위처럼 정적으로 호출할 수 있다.
콘솔 프로젝트에서 생성기 참조 예시
- 프로젝트 참조에
OutputItemType="Analyzer",ReferenceOutputAssembly="false"를 주면, 생성기 DLL은 실행 파일에 포함되지 않고 Analyzer로만 사용된다. - 최신 SDK에서는 ProjectReference만 추가해도 Source Generator로 인식되는 경우가 많다. 문제가 있으면 공식 문서의 참조 방식을 따른다.
활용 팁
- 즉시 반영: 생성된 코드는 다음 컴파일부터 사용 가능하다. IDE에서 생성 타입이 안 보이면 한 번 빌드하거나 솔루션을 다시 로드해 보자.
- 재빌드: Generator 구현을 수정한 뒤에는 전체 재빌드(Clean + Build)를 하는 것이 안전하다.
- 디버깅: Visual Studio 16.10 이후에는 “Roslyn Component” 디버그 런치로 Generator에 브레이크포인트를 걸 수 있다. 솔루션 탐색기에서 Analyzers 하위에 “Source Generators"로 생성된 파일 목록을 볼 수 있다.
참고 문헌
- Introducing C# Source Generators — .NET Blog 공식 소개
- Source Generators (Microsoft Learn) — Roslyn SDK 문서
- Source Generators Cookbook — 권장 패턴·예제
- Source Generators 샘플 — dotnet/roslyn-sdk 저장소
- C# - Source Generator 소개 (정성태) — 한글 실습 가이드
- New C# Source Generator Samples — CSV·Mustache 등 예제
- Solving the source generator ‘marker attribute’ problem (Andrew Lock) — 마커 특성 배포 전략
![Featured image of post [C#] Source Generator 개요와 Hello World 예제](/post/2022-04-05-source-gernerator/wordcloud_hu_86e363a135dc9a6d.webp)
![[Rust] Comprehensive Rust 무료 강의 정리 및 코스 구조](/post/2022-12-30-comprehensive-rust/wordcloud_hu_d1420ff38434cdb6.webp)
![[Hardware] LattePanda Alpha에 Ubuntu 16.04 LTS 설치 가이드](/post/2018-12-06-install-ubuntu-16.04-on-lattepanda/wordcloud_hu_fc536f8de2cbd4bf.webp)
![[.NET] 런타임별 Finalizer 호출 차이와 IDisposable 권장](/post/2021-04-27-distructor-called-by-runtime/wordcloud_hu_7b7dd809a5d4bdc3.webp)
![[Tutorial] Learn Prompting - 프롬프트 엔지니어링 무료 가이드 정리](/post/2022-12-30-learn-prompting/wordcloud_hu_6a9d105de4834753.webp)
![[RPM] Spec 파일에서 주석과 매크로 동시 사용 시 주의사항](/post/2021-11-24-rpm-spec-comments/wordcloud_hu_6d09ac09623081c7.webp)