'이것이 C#이다 개정판'의 chapter 1, 2를 정리한 글입니다.
컴파일러와 인터프리터
[컴파일러]
- 컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역합니다.
- 컴파일러는 소스 코드를 컴파일하여 실행 파일로 만듭니다.
- 프로그램을 실행하기 위해서는 '실행 파일'만 있으면 됩니다.
- 오류가 발견되었을 때, 이를 수정하고 확인하려면 무조건 컴파일 과정을 거쳐야 합니다.
[인터프리터]
- 인터프리터는 프로그램 실행 시 한 번에 한 문장씩 번역합니다.
- 소스 코드를 미리 실행 파일로 만드는 작업이 필요하지 않습니다.
- 소스 코드를 실시간으로 기계어로 해석해서 실행해줍니다.
- 오류를 발견했을 때 코드를 수정하면 바로 실행이 가능하므로 컴파일 방식에 비해 개발 속도가 빠른 편입니다.
- 인터프리터 방식의 프로그래밍 언어로는 PHP, Pyhon, Ruby, Javascript 등이 있습니다.
[차이점]
- 실행 시간의 측면
- 컴파일러는 초기 스캔을 마친 후 실행 파일을 만들어놓기에, 인터프리터보다 실행 시간이 더 빠릅니다.
- 메모리 효율의 측면
- 컴파일러는 컴파일 과정에서 오브젝트 코드(Object Code) 파일을 생성하고, 생성된 오브젝트 코드 파일들을 하나의 실행 파일로 만드는 링킹(Linking)이라는 작업을 진행합니다.
- 인터프리터는 목적 코드(오브젝트 코드)를 만들지도 않고, 링킹 과정도 거치지 않습니다.
- 메모리 사용에 있어서는 컴파일러보다 인터프리터가 더 효율적입니다.
using static
특정 데이터 형식의 정적 멤버를 데이터 형식의 이름을 명시하지 않고 참조하겠다고 선언하는 기능을 합니다.
using static System.Console;
static void Main(string[] args) { }
해당 메소드는 프로그램의 진입점으로서 프로그램을 시작하면 실행되고, 이 메소드가 종료되면 프로그램도 역시 종료됩니다.
모든 프로그램은 반드시 Main이라는 이름을 가진 메소드를 하나 가지고 있어야 합니다.
※ static 키워드
- 한정자
- 한정자는 접근 제어와 관련이 있는 키워드이며, 멤버가 어떤 범위에서 접근 가능한지를 정의합니다.
- static은 접근성을 제어하는 것은 아니지만, 멤버의 성격을 정의하는 키워드입니다.
- static이 한정자로 언급되는 것은 그 멤버의 성격을 정의하는 측면에서 이해할 수 있습니다.
- 한정자에 대해 쉽게 생각하자면, 문장의 다른 요소를 꾸며주는 역할을 하는 성분이라고 이해하면 됩니다.
- static 한정자를 사용하면, 특정 개체가 아니라 형식 자체에 속하는 정적 멤버를 선언할 수 있습니다.
- static 키워드로 수식되는 코드는 프로그램이 처음 구동될 때부터 진작에 메모리에 할당된다는 특징을 가집니다.
- 프로그램이 구동될 때부터 메모리에 할당되므로, 클래스의 인스턴스 없이도 메서드를 호출할 수 있습니다.
※ CLR (Common Language Runtime)
- C#으로 만든 프로그램이 실행되는 환경
- 이름이 Common Language Runtime인 이유는 C# 뿐 아니라 CLS(Common Language Specification) 규격을 따르는 모든 언어로 작성된 프로그램을 지원하기 때문입니다.
- Main () 메소드가 static 키워드로 수식되어 있지 않다면, CLR은 진입점을 찾지 못했을 것입니다.
※ CLR이 static 키워드로 수식되어 있지 않은 Main() 메소드를 실행하려면..
이론적으로는 가능할 수도 있지만, 실제로는 불가능합니다.
이론적으로 Main 메서드를 static이 아닌 인스턴스 메서드로 정의한다면, 프로그램이 시작될 때 먼저 해당 클래스의 인스턴스를 생성해야합니다.
public class MainApp
{
public void main(string[] args) // 기존 Main 메소드
{
// 코드
}
}
class Program
{
static void Main(string[] args)
{
MainApp app = new MainApp(); // 인스턴스 생성
app.Main(args); // 인스턴스 메서드 호출
}
}
그러나 C#에서는 Main 메서드를 static으로 선언하는 것이 필수적이기에, 실제로는 static 없이 Main 메서드를 진입점으로 사용할 수 없습니다.
위의 코드와 같이 결국은 static으로 Main 메서드를 선언해야하기 때문에, 실용적이지도 않고 필요하지도 않은 과정이라고 생각하면 됩니다.
C#의 컴파일
C#으로 만든 프로그램은 CLR 위에서 실행되고, JIT 컴파일을 동반합니다.
[JIT 컴파일]
C# 컴파일러는 C# 소스 코드를 컴파일해서 IL(Intermediate Language)이라는 중간 언어로 작성된 실행 파일을 만들어냅니다. 그 후, 사용자가 이 파일을 실행시키면 CLR이 중간 코드를 읽어 들여 다시 하드웨어가 이해할 수 있는 네이티브 코드로 컴파일한 후 실행시킵니다.
위와 같은 과정을 JIT 컴파일(적시 컴파일)이라고 합니다.
요약하면, 실행에 필요한 코드를 실행할 때마다 실시간으로 컴파일해서 실행한다는 뜻입니다.
두 번씩이나 컴파일하는 복잡한 과정을 거치는 이유는 Common Language라는 이름을 보면 알다시피, 최적화를 위함입니다.
CLR이 다른 언어도 지원하도록 설계되어 있고, 서로 다른 언어들이 만나기 위한 지점이 바로 IL이라는 중간언어입니다.
이 언어로 쓰인 코드를 CLR이 다시 자신이 설치된 플랫폼에 최적화시켜 컴파일 한 후 실행하는 것입니다.
컴파일 비용이 조금 부담스럽긴 해도 최적화를 통하여 최고의 성능을 낸다고 생각하면 됩니다.
'C#' 카테고리의 다른 글
| [C#] 메소드 (0) | 2025.04.11 |
|---|---|
| [C#] Switch, 반복문, 점프문 (0) | 2025.04.10 |
| [C#] 연산자 (2) | 2025.04.07 |
| [C# 기본 정리 3] 형 변환, Nullable, var, 전역변수, 문자열 (0) | 2025.04.04 |
| [C# 기본 정리 2] 변수, 힙, 데이터 형식, 오버플로우와 언더플로 (0) | 2025.04.03 |