C# 실행 과정 및 주요 개념 정리

  • 7 minutes to read

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# 프로그램이 실행되는 전체 흐름을 정리하면 다음과 같습니다.

  1. C# 코드 작성 → (CSC 컴파일러) → IL 코드 (.dll 또는 .exe) 생성
  2. 실행 방식에 따라 분기
    • JIT 실행 시: Tier 0 (빠른 실행) → Tier 1 (최적화) → Dynamic PGO (추가 최적화)
    • AOT 실행 시: IL을 미리 네이티브 코드로 변환하여 실행 (JIT 없이 곧바로 네이티브 코드 실행)
  3. 최종적으로 네이티브 코드 실행

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 없이도 미리 네이티브 코드로 변환하여 실행 속도 향상 가능.

참고 동영상

VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com