본문 바로가기
프로그래밍/C#

Incremental Source Generator

by 뽀도 2024. 8. 7.

🖥️ 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()를 탐색해 보면 아래 처럼 뜸 ↓

 

Generators를 통해 자동 생성된 확장 메서드!

 

 

 

※ 모든 .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

댓글