포스트

[CS] 컴파일러, 인터프리터, 가상머신

[CS] 컴파일러, 인터프리터, 가상머신

컴파일러와 프로그램 생성 과정

컴파일러는 고급 프로그래밍 언어로 작성된 소스 코드를 기계어 또는 중간 코드로 변환하는 소프트웨어입니다.
컴파일러의 주된 역할은 코드 변환, 최적화, 오류 검출 등을 통해 컴퓨터가 실행할 수 있는 프로그램을 생성하는 것입니다.


컴파일러란?

컴파일러(Compiler) 는 소스 코드를 기계어로 변환하여 실행 파일을 생성하는 프로그램입니다.

  • 사람 친화적인 고급 언어를 컴퓨터 친화적인 저급 언어로 변환합니다.
  • 주로 C, C++, Rust, Fortran 같은 언어에서 사용됩니다.

컴파일러의 역할

  1. 코드 변환: 고급 언어를 저급 언어(기계어, 어셈블리어 등)로 변환합니다.
  2. 코드 최적화: 코드 실행 속도와 메모리 사용 효율을 개선합니다.
  3. 오류 검출: 구문 오류나 타입 오류를 컴파일 시점에 감지합니다.
  4. 이식성 확보: 소스 코드를 다양한 플랫폼에서 사용할 수 있도록 변환합니다.

인터프리터란?

인터프리터(Interpreter) 는 소스 코드를 한 줄씩 읽어서 바로 실행하는 소프트웨어입니다.

  • 컴파일러와 달리 기계어로 변환하지 않고 직접 실행합니다.
  • 주로 Python, Ruby, JavaScript 같은 스크립트 언어에서 사용됩니다.

인터프리터의 역할

  1. 실행 시간 해석: 소스 코드를 한 줄씩 해석하여 즉시 실행합니다.
  2. 즉시 피드백: 코드 변경 후 바로 실행 결과를 확인할 수 있습니다.
  3. 동적 특성 반영: 런타임에 변수 타입이 결정되므로 유연성이 높습니다.

인터프리터의 특징

  • 장점: 코드 수정 후 바로 실행 가능, 디버깅이 용이
  • 단점: 실행 속도가 느림, 코드 전체를 미리 분석하지 않음

가상 머신 기반 언어 (C# 등)

C#과 같은 언어는 가상 머신(Virtual Machine) 을 통해 실행됩니다.
가상 머신은 중간 코드(바이트코드) 를 해석하거나 JIT(Just-In-Time) 컴파일로 기계어로 변환하여 실행합니다.

C# 컴파일 과정

  1. 컴파일: C# 코드를 IL 코드(Intermediate Language) 로 변환
    1
    
    csc Program.cs -o Program.exe
    
  2. JIT 컴파일: 실행 시점에 IL 코드를 기계어로 변환하여 실행
  3. 런타임 관리: .NET 런타임(CLR)이 메모리 관리, 가비지 컬렉션 등을 처리

가상 머신 기반의 장점

  • 플랫폼 독립성: 동일한 바이트코드가 다양한 플랫폼에서 실행 가능
  • 런타임 최적화: 실행 중에도 코드 최적화 가능
  • 메모리 관리: 가비지 컬렉션을 통해 메모리 누수 방지

단점

  • 성능 저하: JIT 컴파일로 인한 초기 지연
  • 런타임 의존성: 가상 머신이 설치되어 있어야 실행 가능

컴파일러 vs 인터프리터 vs 가상 머신

특성컴파일러인터프리터가상 머신 (JIT)
실행 속도빠름 (기계어로 변환되어 실행)느림 (코드를 한 줄씩 해석하며 실행)느림 (JIT 컴파일로 인한 초기 지연)
컴파일 시점빌드 시점에 변환실행 중에 한 줄씩 변환실행 시점에 변환
플랫폼 독립성플랫폼마다 별도 컴파일 필요플랫폼 독립적 (해석기 필요)플랫폼 독립적 (바이트코드 실행)
오류 검출컴파일 시점에 대부분 오류 발견실행 중에 오류 발견실행 중에 오류 발생 가능
코드 최적화정적 최적화거의 없음동적 최적화 (실행 중에 최적화 가능)
예시 언어C, C++, RustPython, JavaScript, RubyC#, Java

프로그램 생성 과정 (C/C++ 기준)

  1. 소스 코드 작성: 코드 작성 (예: main.cpp)
  2. 전처리: 매크로와 헤더 파일 처리 (파일 확장자: .i)
    1
    
    g++ -E main.cpp -o main.i
    
  3. 컴파일: 어셈블리 코드로 변환 (파일 확장자: .s)
    1
    
    g++ -S main.i -o main.s
    
  4. 어셈블: 기계어 코드로 변환 (파일 확장자: .o)
    1
    
    g++ -c main.s -o main.o
    
  5. 링킹: 라이브러리 결합 후 실행 파일 생성
    1
    
    g++ main.o -o main
    

결론

컴파일러와 인터프리터는 소스 코드를 실행 가능하게 만드는 방식이 다릅니다.

  • 컴파일러는 실행 전에 기계어로 변환하여 빠르게 실행되지만, 컴파일 시간이 필요합니다.
  • 인터프리터는 한 줄씩 해석하여 즉시 실행할 수 있지만, 속도가 느리고 오류 검출이 늦습니다.
  • 가상 머신 기반 언어(C#, Java)중간 코드(바이트코드) 를 생성하고, 실행 시점에 JIT 컴파일하여 실행하므로 동적 최적화가 가능합니다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.