ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 인터프리터와 컴파일러
    공부 2016. 7. 6. 15:06

    인터프리터란?

    컴파일러와는 다른 방식으로 코드를 기계어로 번역해 주는 프로그램. 스크립트 언어의 사실상 전부가 인터프리터 방식이고 각종 DSL(도메인 특화 언어)의 해석 엔진도 인터프리터로 구현된다. 코드를 한 줄씩 번역하는 방식으로 기계어 번역을 진행하기 때문에 실행 속도는 컴파일 언어보다는 느리다. 그러나 요즘의 인터프리터는 번역 결과를 캐싱하거나 JIT를 사용하는 등의 방법으로 실행 속도를 컴파일 언어에 상당히 근접한 수준으로 따라잡긴 했다. (그래도 컴파일 언어보단 느림)

    여기까지 읽었다면 그 느린 것을 왜 쓰느냐는 의문에 도달하겠지만, 인터프리터 언어는 프로그램 수정이 간단하다는 장점이 있다. 컴파일러는 소스 코드를 번역해서 실행 파일을 만들기 때문에 프로그램에 수정 사항이 발생하면 소스코드를 수정해서 다시 컴파일을 해야 한다. 프로그램이 작고 간단하면 문제가 없지만 프로그램 덩치가 커지면 컴파일이 시간 단위가 되는 일이 많아진다. 하지만 인터프리터는 소스코드를 수정해서 실행시키면 끝. 이 장점 때문에 인터프리터 언어는 수정이 빈번히 발생하는 용도의 프로그래밍에서 많이 사용된다. 이 장점을 최대한 살려서 인터프리터를 적극적으로 채용한 것이 스크립트 언어다.

    코드 상에 문법 오류가 있으면 컴파일을 거부하는 컴파일 언어와 달리, 구문 오류가 있는 곳까지는 일단 진행하고 보기 때문에 디버그에 유리하다는 장점이 있다. 물론 문법 오류가 잘 실행되지 않는 부분에 있으면 오류가 잘 잡히지 않아서 버그 있는 채로 출시할 수 있는 가능성이 컴파일 언어보다 다소 높은 편이다. 컴파일 언어는 문법 오류가 컴파일 단계에서 모두 잡히기 때문이다. 그러나 인터프리터 언어는 오류를 즉석에서 수정한 뒤 바로 실행하는 것이 가능하다는 크나큰 장점이 있기 때문에 그다지 큰 단점은 되지 못한다. 그리고 어차피 크리티컬한 오류는 문법 오류가 아닌 프로그램 자체의 버그로 발생하므로 문법 오류로 두 방식의 우열을 가리는 건 거의 무의미하다.

    기계어로 된 목적 프로그램을 따로 생성해야 하는 컴파일러와는 달리, 소스 코드 그 자체로 실행하는 방식이다. 따라서 이론적으로는 소스 코드를 자기 자신이 수정하면서 실행하는 것도 가능하다.  컴파일 과정이 없기 때문에 수정이 간단하고 빠르다는 장점도 있다. 그러나 단점은, 소스 코드 공개를 막을 방법이 없다는 것. 때문에 몇몇 프로그래밍 언어에서는 인터프리터와 컴파일러를 둘 다 제공하기도 한다.


    즉, 프로그래밍 언어의 소스 코드를 바로 실행하는 컴퓨터 프로그램 또는 환경을 말한다

    컴파일러란?

    어떤 프로그래밍 언어로 쓰여진 소스 파일을 다른 언어로 바꾸어주는 번역 프로그램. 대부분 고수준 언어를 기계어로 번역하는 프로그램을 일컫지만 엄밀히는 어떤 언어 A를 B로 바꾸면 그게 컴파일러다. Scheme을 C언어로 번역한다든지, 심지어 기계어를 C언어로 번역하더라도 컴파일러라고 칭할 수 있다. 

    초기엔 어떤 프로그램을 작성하기 위해서는 컴퓨터 위에서 바로 돌아가는 기계어를 통하여 프로그래밍을 했다. 그러나 이런 과정은 생산성, 기기 간 호환성, 디버깅 등 모든 면에서 효율적이지 않기 때문에 컴퓨터 공학의 발전과 더불어 많은 부분이 추상화된 고수준 언어를 작성하고 이를 번역기를 통해 기계어로 번역하기 시작했는데, 이 번역기가 바로 컴파일러이다. 현재 많은 프로그램은 컴파일러를 통하여 전체를 기계어로 번역하여 실행하므로 프로그램 개발에 필수적인 툴 중에 하나다. 


    반면에 소스를 한꺼번에 번역하지 않고 명령 하나하나를 실행할 때마다 해석하여 계산하는 방법도 있는데 이 해석기를 인터프리터라 해서 따로 분류한다.( 컴파일러가 번역기라면 인터프리터는 통역기인셈)

    재밌는 것은 컴파일러도 결국 하나의 언어로 짜여진 프로그램이라는 점. 따라서 원리상 C언어 프로그램이 C언어를 번역하는 일이 가능하다. 이 경우, C 컴파일러를 사용하기 위하여 이 컴파일러를 컴파일하는데 C 컴파일러가 필요하다(..) 심지어 최근 버전의 gcc 컴파일러의 경우 C++을 사용하기 때문에 C 컴파일러를 컴파일하는데 C++ 컴파일러가 필요하다. 이런 현상을 부트스트래핑(bootstrapping)이라고 한다. 언어를 최초 설계할 때만 사용 가능한 다른 언어로 짜여진 컴파일러의 도움을 받은 이후로는 언어를 번역하는 컴파일러가 자기 자신의 언어로 짜여질 수 있다. 얼핏보면 모순적이지만 맨 처음에만 다른 언어의 도움을 받는다면 충분히 가능하다. 일반적으로 고수준 언어로 갈수록 생산성이 높아지므로 이런 접근은 컴파일러를 작성하는데 들이는 비용을 효과적으로 줄일 수 있다. 일례로, GHC라는 Haskell 컴파일러는 최초에 Lazy ML이라는 다른 언어로 작성되었다가, 자기 자신의 언어인 Haskell로 재작성 되었다.


    원칙적으로 컴파일러는 프로그램을 기계어로 바꾸기만 할 뿐 이를 바로 실행이 가능하게 하지는 않는다. 여러 소스 파일에서 나온 결과물을 합치고 라이브러리도 포함시키는 등 별도의 작업을 거쳐야 실행이 가능해지는데 이를 수행하는 프로그램이 링커이다. 하지만 보통은 그냥 뭉뚱그려 컴파일러라 부르는 경우가 많다. 또한 요즘은 그냥 프로그램 하나만 돌리면 컴파일과 링킹을 한 번에 끝낼 수 있게 되어 있다. 물론 내부적으로는 컴파일러와 링커가 따로 있어서 이를 이용하는 경우가 많지만.

    단점은 수정이 용이하지 않다는 점이다. 수정 사항이 발생하면 다시 컴파일을 해야 되는데, 작은 프로그램일 경우에는 문제가 되지 않지만 컴파일이 몇 시간씩 걸리는 덩치 큰 프로그램에서는 문제가 된다. 특히 수정 사항이 빈번하게 발생할 경우에는 큰 문제가 된다. 이 때문에 수정 사항이 빈번하게 발생할 것 같은 부분은 인터프리터를 쓰는스크립트 언어로 따로 빼 두는 기법을 많이 사용한다. (인터프리터는 속도는 느리지만 수정이 간단하다는 장점이 있다.)

    어셈블리어를 번역하는 프로그램은 컴파일러라 하지 않고 따로 어셈블러라 한다.

    요즘 컴파일러들은 기계가 프로그램을 빠르게 돌릴 수 있도록 적절한 최적화 작업을 하고 프로그래머가 실수할만한 부분을 경고하는 등 갈수록 똑똑해지는 추세이다.

    OS와 함께 프로그래머의 스킬트리에서 최상위에 군림하는 스킬. 운영체제와 컴파일러를 스스로 만들 수준이 되면 일단 프로그래머 스킬트리는 전부 다 최소 한 개씩은 찍은 것이다. 거기서 더 나가면 최적화 가 있는데 이건 컴파일러의 보조 스킬. 대학교 컴퓨터공학 커리큘럼의 가장 마지막(4학년)에 있는 과목이기도 하다. 이걸 제작하려면 하드웨어와 소프트웨어 전부를 이해하고 있어야 하고 자료구조와 알고리즘에 대한 심도 깊은 이해와 함께 전산수학에도 능해야 한다. 그래서 컴파일러 1렙을 찍으면 취직 퀘스트는 통과를 못 하는 게 이상할 정도가 된다.

    C 등의 고급 언어에서 CPU의 인스트럭션 하나로 해결할 수 있는 복잡한 기능(?)을 사용할 경우 특정 함수를 호출하면 컴파일러가 함수를 호출하는 명령을 넣어 주는 것이 아니라 그냥 그 자리에 어셈블리를 사용한 것과 동일하게 기계어 코드를 때려박는 경우가 있는데 이것을 intrinsic, 혹은 built-in function이라고 한다(인라인 함수와는 다르다). Compare-And-Exchange의 예를 들어(현대적인 CPU는 대부분 지원한다) a값이 m인 경우 n으로 바꾸는 코드의 경우 x86 CPU는 cmpxchg 인스트럭션 하나로 해결이 가능하다. 이러한 경우 컴파일러가 지원하는 인트린식을 사용하면 된다.


    즉 컴파일러는 특정 프로그래밍 언어로 쓰여진 문서를 다른 프로그래밍 언어로 옮기는 프로그램을 말한다. 기존의 문서를 소스 코드 또는 원시 코드라 부르고, 출력되는 문서를 목적 코드라고 부른다. 목적 코드는 주로 다른 프로그램이나 하드웨어가 처리하기 용이한 형태로 출력되지만! 그 외에도 사람이 읽을 수 있는 문서 파일이나 그림 파일 등으로 옮기는 경우도 있다. 

    고수준 언어 → 저수준 언어(어셈블리어, 기계어)

    인터프리터와 컴파일러 차이


    컴파일러인터프리터
    번역단위전체한 줄씩
    실행속도빠름느림
    목적프로그램(소스코드 외 타 프로그램)생성생성 X
    메모리할당목적 프로그램생성시 사용할당 X


    댓글