닷넷 프레임워크(.NET Framework)는 2002년에 마이크로소프트에서 발표한 어플리케이션 개발 환경이다. 닷넷 프레임워크는 가상 머신이기 때문에, 닷넷 프레임워크를 기반으로 만들어진 어플리케이션은 반드시 닷넷 프레임워크가 설치된 환경에서만 실행된다. 달리 말하면, 닷넷 프레임워크가 설치되어 있다면 운영체제에 종속되지 않고 실행된다는 이야기이다.
윈도우 운영체제를 기준으로 닷넷 프레임워크를 설치하면 가상 머신 역할을 하는 CLR(Common Language Runtime) 구성요소가 실행될 수 있는 환경이 윈도우 운영체제에 마련된다. CLR은 프로세스가 실행되면 메모리에 함께 로드되어 실행된다. 닷넷 프레임워크를 기반으로 만들어진 프로그램은 겉으로 보았을 때에는 EXE/DLL로 기존 프로그램과 동일한 구조를 가지고 있지만, 내부적으로는 CLR 구성요소가 먼저 로드된 다음, CLR이 EXE/DLL에 함께 저장되어 있는 닷넷 코드를 실행하는 것이다.
EXE는 윈도우 운영체제의 네이티브 실행 파일을 의미하는 확장자이며, DLL은 윈도우 운영체제에서 구현된 동적 라이브러리로, 내부에 다른 프로그램이 호출해서 사용할 수 있는 다양한 함수를 가지고 있다.
닷넷 프레임워크에서 사용되는 대표적인 언어인 C#은 C# 컴파일러가 .cs 소스코드를 CPU가 바로 실행할 수 있는 기계어가 아닌 IL(Intermediate Language)
이라 불리는 중간 언어로 만들고, 이를 EXE/DLL 파일 내부에 위치시킨다. 이 중간 언어는 닷넷 프레임워크를 기반으로 만들어진 어플리케이션이 처음 실행되면 CLR을 가장 먼저 로드하는 코드를 자동으로 EXE/DLL 파일 내부에 생성시킨다. 이것을 통해 사용자가 어플리케이션을 실행하면 내부적으로 가장 먼저 CLR이 로드되고, CLR은 중간 언어 코드를 로드하여 본격적인 어플리케이션 실행 단계에 들어가게 된다.
JVM(Java Vitual Machine)에서는 중간 언어를 바이트코드(Bytecode)라고 부른다. 마찬가지로 가상 머신인 닷넷 프레임워크의 CLR에서는 이것을 CIL(공통 중간 언어)라고 부르며, 보통 줄여서 IL 코드 또는 MSIL 코드라고 한다.
CPU는 IL 코드를 직접 읽어 실행할 수 없으며, IL 코드는 CPU에 독립적이기 때문에 모든 닷넷 호환 언어(C#, VB, F#, C++/CLI 등)는 소스코드를 컴파일 하면 IL 코드로 결과물이 나오게 된다. IL 코드는 그 자체로 프로그래밍 언어의 문법을 가지고 있으며, ilasm.exe라는 컴파일러를 가지고 있다. 이렇게 만들어진 IL 코드는 프로그램이 실행되고, CLR이 실행되는 순간에 CPU가 읽을 수 있는 기계어로 최종 변환된다. 따라서 C#으로 만들어진 소스코드가 CPU가 읽을 수 있는 기계어로 변환되는 과정을 다음과 같이 나타낼 수 있다.
여기서 IL 코드는 가상 머신 내부에서 기계어로 대응되기 때문에, 기계어와 유사하다고 볼 수 있다. IL 코드가 기계어라면 기계어로 가기 전 단계인 어셈블리어도 닷넷 프레임워크 가상 머신 상에 존재할 수 있다고 생각해볼 수 있다. 실제로 IL 코드도 가상 머신 내부에서 일대일 대응되는 IL 언어라고 하는 가상 머신의 어셈블리어를 가지고 있다. IL 언어를 ilasm.exe 컴파일러로 컴파일 하게 되면 IL 코드가 실행되는 것과 동일한 결과물이 생성된다.
따라서 닷넷 프레임워크의 호환 언어는 공통 중간 언어의 이러한 특징 덕분에 두 가지 방식으로 구현된다.
첫 번째는 프로그래밍 언어 소스코드에서 곧바로 중간 언어를 생성하여 사용하는 방식이다. 위의 C# 소스코드가 변환되는 과정의 예시처럼 .cs 파일을 컴파일하여 곧바로 가상 머신에서 실행될 수 있는 중간 언어인 IL 코드로 변환하여 실행하는 것이다.
두 번째는 프로그래밍 언어 소스코드를 IL 언어로 변환하고, 이것을 ilasm.exe로 컴파일하여 실행 파일을 만드는 방식이다.