[C#] 컴파일 과정
Table of Contents
C# 컴파일 과정 #
- C# 코드를 빌드하면 CIL 이라는 중간 코드(Intermediate Language; 어셈블리 코드의 일종) 를 만들어 낸다.
- 프로그램 실행시 런타임에 CLR이 이 IL 코드를 읽어서 JIT 컴파일(Just In Time Compile; 적시 컴파일) 방식을 이용해서 Native 코드로 변경한다.
- JIT 컴파일이란, 매번 실행될 때마다 실시간으로 컴파일을 해서 실행한다는 의미이다.
- 장점
- IL 방식의 가장 큰 장점은 실행 머신 환경 (32/64 bit, x86/AMD 등)에 관계없이 .Net Framework가 설치된 어떤 환경에서도 동일 코드를 실행할 수 있다는 것이다.
- 단점
- IL 방식의 단점은 실행시 어쨌든 IL 코드를 컴파일해야 한다는 것인데, 이는 속도를 저하시키는 원인이 된다.
- .NET에서는 이러한 속도 저하를 최대한 줄이기 위해 프로그램 실행시 전체 IL 코드를 컴파일하는 것이 아니라 호출되는 메서드 단위로 컴파일을 진행한다. 즉 실행 중 어떤 메서드가 호출되면 그 메서드만 JIT 컴파일러가 Native로 변경하는 것이다. 따라서 만약 프로그램 실행 전 과정에서 어떤 메서드가 한번도 호출되지 않는다면 그 메서드는 Native 코드로 변경되지 않는다.
- 이 외에도 CLR은…
- 프로그램의 예외가 발생했을 때 이것을 처리하도록 도와준다.
- 언어 간의 상속을 지원한다.
- COM과의 상호 운영성을 지원한다.
- 자동 메모리 관리 기능인 가비지 컬렉션(Garbage Collection)을 제공한다.
.NET Assembly #
- 어셈블리란 버전 관리되고 배포되는 프로그램의 단위이다.
- 실행 파일(.exe) 또는 동적 연결 라이브러리(.dll) 파일의 형태를 가진다.
- 응용 프로그램 하나에서만 사용하는 전용 어셈블리와, 여러 프로그램에서 공유하는 공유 어셈블리가 있다.
- .NET 플랫폼에서는 한 덩어리의 실행 파일을 여러 개의 어셈블리 파일로 나눌 수 있다. 따라서 바이너리 파일이 하나인 어셈블리(단일 파일 어셈블리)가 될 수도 있고, 여러 바이너리 파일이 모여서 다중 파일 어셈블리가 될 수도 있다.
- 다중 파일 어셈블리에서, 컴파일 완료된 바이너리 파일의 각각을 모듈이라고 한다.
- 이때 어셈블리에 관한 정보를 가지고 있는 Manifest를 가진 모듈을 주모듈, 아닌 경우를 부모듈이라고 한다.
구성요소 | 설명 |
---|---|
Manifest | 어셈블리의 버전 요구 사항과 보안 ID를 지정하는 데 필요한 모든 메타데이터와 어셈블리의 범위를 정의한다. 리소스나 다른 모듈에 대한 참조를 확인하는 데 필요한 모든 메타데이터를 포함한다. 즉, 어셈블리 내의 모든 모듈의 참조 정보를 갖는 메타데이터이다. |
Type Metadata | 어셈블리 내에서 사용되는 모든 타입에 대한 구체적인 정보를 가지고 있다. 이것 덕분에 리플렉션(객체의 클래스 타입, 메서드, 프로퍼티 등의 메타 정보를 런타임 중에 알아내는 기능)이 가능하다 |
CIL Code | 공통 언어 기반과 닷넷 프레임워크에서 인간이 이해할 수 있는 가장 낮은 수준의 프로그래밍 언어이다. 객체 지향 어셈블리어이며, 완전한 스택기반이다. CLR이 런타임에 이 코드를 Native 코드로 변경한다. |
References #
- https://docs.microsoft.com/ko-kr/dotnet/standard/assembly/
- https://blog.shovelman.dev/634
- https://rito15.github.io/posts/cs-dotnet-compile/