C# 실행 과정 및 주요 개념 정리
C# 학습 과정에서 등장하는 실행 관련 용어들을 정리하였습니다. 학습자에게 필수적인 내용은 아니므로 참고용으로 가볍게 읽어보시면 좋겠습니다.
C# 프로그램이 실행되기까지의 과정을 이해하는 것은 .NET 환경에서 최적화 및 성능 향상을 고려할 때 중요합니다. 본 아티클에서는 CSC, IL, JIT, Tiered Compilation, Dynamic PGO, AOT, Native Assembly 등의 개념을 하나의 흐름으로 정리하여 설명합니다.
1. CSC (C# Compiler)
C# 컴파일러(C# Compiler, CSC)는 C# 소스 코드(.cs
)를 Common Intermediate Language (CIL, IL) 코드로 변환하는 역할을 합니다.
- .NET SDK에서 제공하는
csc.exe
또는dotnet build
명령을 통해 실행됩니다. - 결과물은
.dll
또는.exe
파일이며, .NET 런타임에서 실행됩니다.
2. IL (Intermediate Language, 중간 언어)
IL은 C# 소스 코드가 컴파일된 후 생성되는 플랫폼 독립적인 중간 코드입니다.
- .NET 런타임에서 실행되기 전에 JIT 컴파일을 거쳐 네이티브 코드로 변환됩니다.
- 사람이 읽을 수 있는 어셈블리 코드와 유사하며,
ildasm
(IL Disassembler) 같은 도구로 확인할 수 있습니다.
3. JIT (Just-In-Time Compiler, 즉시 컴파일러)
JIT는 실행 시점에 IL을 **기계어(네이티브 코드)**로 변환하는 컴파일러입니다.
- 프로그램이 실행될 때 처음으로 호출되는 IL 코드가 JIT 컴파일을 거쳐 네이티브 코드로 변환됩니다.
- 변환된 코드는 캐시되어 이후에는 컴파일 없이 실행됩니다.
4. Tiered Compilation (계층적 컴파일)
.NET Core 2.1부터 도입된 Tiered Compilation(계층적 컴파일) 방식은 실행 성능을 최적화하기 위해 여러 단계를 거칩니다.
4.1 Tier 0 (기본 JIT 컴파일 단계)
- 프로그램 실행을 최대한 빠르게 하기 위해 최소한의 최적화만 수행합니다.
- 빠르게 실행되도록 IL을 네이티브 코드로 변환하지만, 성능 최적화는 적용되지 않습니다.
4.2 Tier 1 (최적화된 JIT 컴파일 단계)
- 자주 실행되는 메서드를 감지하여 성능을 최적화합니다.
- Tier 0보다 더 적극적인 최적화를 수행하여 실행 속도를 높입니다.
- .NET 런타임이 메서드 호출 패턴을 감지한 후, 최적화된 코드로 다시 JIT 컴파일합니다.
5. Dynamic PGO (Profile-Guided Optimization, 동적 프로파일 기반 최적화)
Dynamic PGO는 실행 도중에 수집된 프로파일 데이터를 활용하여 JIT 최적화 수준을 동적으로 조정하는 기술입니다.
- 실행 중 코드의 사용 패턴을 분석하여 자주 실행되는 코드 경로를 최적화합니다.
- Tier 1 이후에도 성능을 개선할 수 있도록 최적화 단계를 지속적으로 조정합니다.
6. AOT (Ahead-of-Time Compilation, 사전 컴파일)
JIT은 실행 중에 IL을 네이티브 코드로 변환하지만, AOT(Ahead-of-Time Compilation)는 실행 전에 IL을 미리 네이티브 코드로 변환하는 방식입니다.
- JIT을 대체하는 기술로, JIT 오버헤드를 제거하고 앱 시작 속도를 크게 향상시킬 수 있습니다.
- 대표적인 AOT 방식
- ReadyToRun (R2R): .NET에서 IL을 부분적으로 AOT 컴파일하여 배포할 수 있음.
- Native AOT: .NET 7+에서 지원하는 완전한 AOT 방식으로, 네이티브 바이너리를 생성하여 JIT 없이 실행 가능.
7. Native Assembly (네이티브 어셈블리)
JIT 또는 AOT 과정을 거친 후 IL이 변환된 CPU가 직접 실행할 수 있는 기계어 코드를 의미합니다.
- JIT 기반 실행에서는 네이티브 코드가 런타임 중에 생성됩니다.
- AOT를 사용하면 애플리케이션이 배포될 때부터 이미 네이티브 코드가 포함됩니다.
8. 실행 과정 요약
C# 프로그램이 실행되는 전체 흐름을 정리하면 다음과 같습니다.
- C# 코드 작성 → (CSC 컴파일러) → IL 코드 (
.dll
또는.exe
) 생성 - 실행 방식에 따라 분기
- JIT 실행 시: Tier 0 (빠른 실행) → Tier 1 (최적화) → Dynamic PGO (추가 최적화)
- AOT 실행 시: IL을 미리 네이티브 코드로 변환하여 실행 (JIT 없이 곧바로 네이티브 코드 실행)
- 최종적으로 네이티브 코드 실행
9. 정리
개념 | 설명 |
---|---|
CSC | C# 소스 코드를 IL로 변환하는 컴파일러 |
IL | 플랫폼 독립적인 중간 언어 |
JIT | 실행 시 IL을 네이티브 코드로 변환하는 컴파일러 |
Tier 0 | 빠르게 실행하기 위한 최소한의 JIT 단계 |
Tier 1 | 자주 실행되는 메서드를 최적화하여 다시 JIT 컴파일 |
Dynamic PGO | 실행 중 동적으로 최적화 |
AOT | IL을 미리 네이티브 코드로 변환하여 실행 |
Native Assembly | 네이티브 코드로 변환된 실행 가능한 기계어 코드 |
10. 추가 참고
.NET 6+
에서는 Tiered Compilation과 Dynamic PGO가 기본 활성화되어 성능이 향상됨.- AOT 컴파일을 사용하면 JIT 없이도 미리 네이티브 코드로 변환하여 실행 속도 향상 가능.