🖥️ Incremental Source Generator 란?
- .NET 5 이후의 기능으로, 컴파일 타임에 코드 생성을 최적화 하고 성능을 향상시키기 위해 도입된 기술
- 기존의 소스 생성기보다 더 효율적이고 부분적으로 코드 생성을 수행할 수 있는 기능 제공
주요 개념
1. Incremental Source Generation
- 코드 생성을 부분적으로 수행하여, 변경된 부분만 다시 생성
- 전체 코드 베이스를 다시 분석하지 않고 변경된 입력에 대해서만 반응, 더 효율적인 코드 생성 가능
2. Performance
- 대규모 코드베이스에서 소스 생성기의 성능을 크게 향상 시킴
- 반복적인 빌드 및 변경 작업에서 유용
3. Diagnostics
- Incremental Source Generator는 진단 정보를 보다 쉽게 관리하고, 오류 메시지와 경고를 더 명확하게 제공
이라던데.. 예제 코드 만들다보니까 이걸 왜쓰나? 싶다.
윀 😬
😀 일단 폴더 구조를 보자
HelloWorldGeneratedSolution
│
├── HelloWorldGenerated
│ ├── Program.cs
│ ├── HelloWorldGenerated.csproj
│
├── Generators
│ ├── HelloWorldGenerator.cs
│ ├── Generators.csproj
│
└── HelloWorldGeneratedSolution.sln
자 이제 코드를 살펴보자 !
✏️ Generator
1. Generator "클래스 라이브러리"로 프로젝트를 생성한다.
2. Nuget을 설치 : Microsoft.CodeAnalysis.CSharp.Workspaces
3. HelloWorldGenerator.cs 파일 생성 하고 아래의 코드를 작성한다.
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace HelloWorldGenerated
{
[Generator]
public class HelloWorldGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
// 초기화 단계에서는 필요 없는 경우 비워둘 수 있어
}
public void Execute(GeneratorExecutionContext context)
{
// 소스 코드를 생성하는 핵심 로직
string source = @"
using System;
namespace HelloWorldGenerated
{
public static class HelloWorld
{
public static void SayHello() => Console.WriteLine(""Hello, World!"");
}
}";
context.AddSource("HelloWorldGenerated", SourceText.From(source, Encoding.UTF8));
}
}
}
4. Generators.csproj 파일 편집
- Generators 프로젝트 오른쪽 버튼 누르면 "프로젝트 파일 편집" 이 있다, 이걸 누르면 쉽게 편집창으로 이동 가능!
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>preview</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.10.0" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\Generated\Sources</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
이 프로젝트는 analyzer 프로젝트기 때문에 아래의 속성을 true 해줘야 워닝이 뜨지 않는다!
✏️ HelloWorldGenerated
1. HelloWorldGenerated는 "콘솔 애플리케이션"으로 프로젝트를 생성한다.
2. MyClass.cs 추가
namespace HelloWorldGenerated
{
public class MyClass
{
}
}
3. Program.cs 수정
// See https://aka.ms/new-console-template for more information
using HelloWorldGenerated;
Console.WriteLine("Hello, World!");
var instance = new MyClass();
instance.SayHello(); // 생성된 확장 메서드 사용
var msg = Console.ReadLine();
4. Generators 프로젝트를 HelloWorldGenerated 프로젝트에 참조 추가
4-1. HelloWorldGenerated.csproj 파일 수정
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<!--※ ReferenceOutputAssembly="false" OutputItemType="Analyzer" 를 반드시 추가 해야함-->
<ItemGroup>
<ProjectReference Include="..\Generators\Generators.csproj" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
</ItemGroup>
</Project>
5. instance.SayHello()를 탐색해 보면 아래 처럼 뜸 ↓
※ 모든 .cs 파일의 네임스페이스를 HelloWorldGenerated 맞춰줘야 정상적으로 사용 가능하다.
심지어 Generators안에 HelloWorldGenerators.cs 도 네임스페이스를 맞춰줘야 한다.
HelloWorldGenerated에서 Generators를 참조할때 꼭 ReferenceOutputAssembly="false" OutputItemType="Analyzer" 를 추가 해야한다.
💡 자 이걸 왜 따로 공부했냐??
MemoryPack 공부하다 보니까,
Incremental Source Generator
MemoryPack fully adopts the Incremental Source Generator enhanced in .NET 6. In terms of usage, it is not so different from MessagePack for C#, except for changing the target type to partial.
>> MemoryPack은 Incremental source Generator를 전면 채택하고있음!!!
이라고 써있길래 그게 뭔데 하고 찾아보다가 공부하게 되었다.
아직은 내가 직접 만들기는 싫지만, 구현되어있는걸 쓰는건 괜찮은것 같다.
'프로그래밍 > C#' 카테고리의 다른 글
가중치에 따른 랜덤 값 뽑기 (2) | 2024.11.15 |
---|---|
MemoryPack 라이브러리 (0) | 2024.08.07 |
[C#] Global Using (0) | 2024.08.05 |
오버헤드 (0) | 2024.07.31 |
비동기에서[async/await] lock 사용하기 (0) | 2024.07.11 |
댓글