C# 코드는 어떻게 실행되는가 - 2편, CIL과 메타데이터 그리고 JIT
컴파일하면 바로 기계어가 될까?
C++의 전통적인 네이티브 빌드 흐름에 익숙하다면, 컴파일 결과는 곧 CPU 명령이라고 생각하기 쉽다. 하지만 일반적인 .NET 빌드에서 C# 컴파일러가 만드는 핵심 결과물은 특정 CPU용 기계어가 아니라 CIL과 메타데이터가 들어 있는 어셈블리다.
아래 코드는 이번 포스팅에서 이해를 위해 지속적으로 사용할 예제 코드이다. 이 메서드가 빌드 파일 안에서 어떤 형태로 저장되고, 실행 순간 어떤 명령으로 바뀌는지를 보면서 .NET 실행 모델 전체를 그려본다.
public class Caculator
{
public int Add(int a, int b)
{
return a + b;
}
}
01. 어셈블리는 스스로를 설명하는 실행 단위다
.NET의 어셈블리는 단순히 기계어를 모은 파일이 아니다. 실행할 CIL과 그 코드를 해석하는 데 필요한 구조 정보가 함께 들어간다. 보통 .dll 또는 .exe 형태이며, CLR이 로드하고 버전·참조·타입을 파악하는 기본 단위가 된다.
01
어셈블리 매니페스트
02
타입 메타데이터
03
CIL 코드
04
리소스
02. CIL은 CPU 대신 평가 스택을 대상으로 한다
CIL은 x64나 ARM 레지스터를 직접 지정하지 않는다. 많은 명령이 값을 평가 스택에 올리고, 꺼내고, 연산하는 방식으로 표현된다. 그래서 같은 CIL을 여러 CPU용 런타임이 각자의 네이티브 명령으로 변환할 수 있다.
public int Add(int a, int b)
{
return a+b;
}
—>
ldarg.1 // a를 스택에 적재
ldarg.2 // b를 스택에 적재
add // 두 값을 더함
ret // 결과를 반환왜 중간 언어를 둘까?
언어 컴파일러는 CLI 규칙에 맞는 CIL과 메타데이터를 만들고, 각 플랫폼의 런타임은 그것을 현재 CPU에 맞게 변환한다. 언어와 하드웨어 사이에 공통 계약을 둔 셈이다.
그렇다고 완전한 플랫폼 독립은 아니다.
플랫폼 전용 네이티브 API나 라이브러리를 호출하면 해당 운영체제에 종속된다. CIL 자체의 이식성과 어플리케이션 전체의 이식성은 구분해야 한다.
03. 메터데이터가 없으면 CIL도 의미를 잃는다
CIL이 ‘무엇을 할 것인가’를 나타낸다면 메타데이터는 ‘그 대상이 무엇인가’를 설명한다. CLR은 이 정보를 이용해 타입을 로드하고 메서드 호출을 연결하며 객체의 구조를 이해한다.
—>
04. 서로 다른 언어가 같은 어셈블리를 공유하는 이유
C#, F#, Visual Basic은 문법이 다르지만 .NET을 대상으로 컴파일되면 CLI가 정의한 타입과 메타데이터 형식을 사용한다. 그래서 한 언어로 만든 클래스를 다른 언어에서 호출하거나 상속할 수 있다.
CTS(Common Type System)
타입이 어떻게 선언되고 사용되며 관리 되는지 정의한다. 여러 언어가 서로 다른 문법을 쓰더라도 공통된 타입 모델로 만날 수 있게 한다.
CLS(Common Language Specification)
언어와 라이브러리가 넓게 상호 운용되기 위해 지켜야하는 공통 규칙의 부분집합이다. 모든 언어 기능이 서로 완전히 동일하다는 뜻은 아니다.
05. CLR은 어셈블리를 읽고, JIT은 필요한 메서드를 번역한다.
파일이 만들어졌다고 실행이 끝난 것은 아니다. CLR은 어셈블리를 로드하고 메타데이터로 타입과 참조를 파악한다. 그리고 호출된 메서드의 CIL을 현재 프로세서가 실행할 수 있는 네이티브 코드로 바꾼다.
마무리
이번 포스팅은 C#과 .NET에 대한 기초적인 지식에 대하여 알아 보았다. 아래는 이번 포스팅에서의 핵심 네 가지 문장이다.
01
C#은 언어이고 .NET은 플랫폼이다.
둘은 강하게 결합되어 있지만 동일한 개념은 아니다.
02
C#은 보통 CIL로 컴파일된다.
CLR이 이를 JIT 또는 AOT 방식으로 네이티브 코드와 연결한다.
03
C#은 Java와 관리형 실행 모델을 공유한다.
C++과는 저수준 제어와 자원 관리 철학에서 큰 차이가 난다.
04
어느 언어가 절대적으로 우월한 것은 아니다.
런타임의 편의, 제어 수준, 생태계, 배포 환경에 따라 선택이 달라진다.
더 읽을 자료