ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 프로그래밍 언어, 컴파일러, 인터프리터
    소프트웨어 엔지니어링 2019. 2. 27. 17:50

    소프트웨어 엔지니어링의 세계로 처음 들어오는 사람들이 가장 배우는 것 중 하나가 바로 프로그래밍 언어이다. 인간인 우리가 프로그래밍 언어로 프로그램을 작성하면 컴퓨터가 이를 실행하기 때문이다. 프로그래밍 언어를 배우지 않으면 어떤 컴퓨터 전문가라도 어느 순간 벽에 부딪히고 만다. 또 프로그래밍 언어를 통해 컴퓨터의 동작 방식이나 한계점을 유추 해 볼 수도 있다. 그래서 많은 사람들이 원하는 프로그래밍 언어를 습득하면서 소프트웨어 엔지니어링을 처음 시작한다. 하지만 이렇게 진입로가 되는 프로그래밍 언어, 우리는 제대로 이해하고 있을까? 프로그래밍 언어란 대체 무엇인가? 컴퓨터가 이해하는 언어라는 것은 알고 있다. 그렇다면 컴퓨터가 이해한다는 것은 무슨 의미인가?

    목차

    • 프로그래밍 언어란?
    • 컴파일러(Compiler)
    • 인터프리터(Interpreter)
    • 하이브리드(Compiler-Interpreter-Compiler)

    프로그래밍 언어란?

    컴퓨터는 이진수만 이해한다는 사실은 많이 알려져 있을 것이다. 즉 컴퓨터는 우리가 사용하는 언어가 아닌 10101010만을 이해한다는 뜻이다. 10101101010만을 이해한다는게 도대체 무슨 소리일까?


    <MIPS Instruction Set의 일부>

    컴퓨터가 이진수를 이해한다는 뜻은 CPU가 실행 할 수 있는 명령어가 1과 0으로 되어있다는 뜻이다. 하나의 CPU가 이해 할 수 있는 모든 명령어를 모아 놓은 것을 기계어 명령어 셋(instruction set)이라고 부른다. 예를들어서 위의 add같은 경우 dest = src1 + src2를 실행한다. src1, src2, dest도 모두 이진수이다. 다 보지 말고 function만 보자. add와 sub의 이진 명령어가 다른 것을 확인 할 수 있다.


    참고! 컴퓨터가 이진수를 이해한다는 뜻은 정확히 말하면 전기가 CPU에 들어 올 때 전압의  강도(전압의 크기가 크면 1, 작으면 0)인 1과 0의 조합에 따라서 다른 명령을 실행한다는 뜻이다. 예를들어 add의 맨 처음 1은 ALU(Arithmatic Logic Unit)으로 들어가 src1, src2 값을 add해 dest에 저장한다. sub도 마찬가지로 ALU로 들어간다 하지만 뒤에서 두번째 값이 1이면 src2을 음수로 바꾼다. 이후 덧셈은 동일하게 진행된다. <- 이런 식이다.


    기계어 명령어 셋은 그럼 누가 만들까? 기계어 명령어 셋은 바로 인텔, AMD와 같은 CPU칩 회사들이 만드는 것이다. x86, x64, IA-32아키텍쳐와 같은 말을 들어본적이 있는가? 칩의 회사나 버전에 따라 이런 명령어셋이 다를 수 있다.

    근데 이게 프로그래밍 언어랑 무슨 상관인가? 상관이 아주 많다. 프로그래밍 언어로 프로그램을 만들고 실행 할 때 한번이라도 이런 10001과 같은 명령어를 사용해야 한 적이 있는가? 없다. 근데 위의 내용에 따르면 컴퓨터는 바이너리만 이해한다. 그렇다면 도대체 우리가 작성한 영문으로 된 프로그램을 어떻게 컴퓨터가 실행하는 것일까? 모든 프로그래밍언어는 그 프로그래밍 언어를 기계어 명령어로 번역 해 줄 번역기가 존재한다. 그리고 그 번역기가 영문으로 된 프로그래밍 언어(이런 사람이 이해하기 쉬운 언어를 고급언어라고 부른다)를 기계어 명령어로 번역해준다.

    여러분은 처음 프로그래밍 언어를 배울 때 환경 설정을 한다. 예를들어 자바라면 JDK를 설치하고, 파이썬이라면 파이썬을 설치하고, C라면 gcc와 같은 프로그램을 설치한다. 여러분이 프로그래밍 언어를 배우기 위해 환경 설정 할 때 설치했던 바로 그 개발환경설정 툴 중에 이 번역기가 반드시 포함되어 있다. 번역기는 번역 시기에 따라 크게 컴파일러와 인터프리터로 구분된다.

    컴파일러(Compiler)

    한 언어에서 다른 언어로 번역하는 프로그램을 컴파일러라고 부른다. 컴파일러는 무조건 기계어로 번역 할 필요는 없다. 예를들어 자바 -> C언어로 번역하는 번역기도 컴파일러이다. 여기서은 고급언어에서 기계어로 번역하는 컴파일러에 대해 이야기 하겠다. 컴파일러는 우리가 작성한 프로그램을 한꺼번에 기계어로 번역한다. 컴파일러를 실행시키면 보통 번역해야 할 언어의 파일들과 번역 결과를 저장 할 파일의 이름을 받는다. 그리고 그 파일들을 모두 번역해서 하나의 바이너리(또는 어셈블리)파일로 저장한다. 그러면 이후에 사용자가 이 바이너리 파일을 실행시키면 프로그램이 실행되는 것이다. 즉, 컴파일러가 필요한 프로그래밍 언어는 1. 프로그램을 작성한다 2. 컴파일을 한다. 3. 실행을 한다. 이렇게 세가지 과정을 거쳐 실행된다.

    장점은 무엇일까? 바이너리를 실행시키는 것이기 때문에 실행속도가 인터프리터에 비해 빠르다.

    단점은 무엇일까? 앞서 말했듯이 컴퓨터의 칩마다 명령어 셋이 다를 수 있다. 따라서 한 컴퓨터에서 컴파일 해서 실행한 프로그램은 명령어 셋이 다른 컴퓨터에서 동작하지 않을 수 있다. 따라서 명령어 셋이 다른 컴퓨터 마다 컴파일을 해 줘야 한다. (e.g, 윈도우즈에서 x86과 x64를 구분해서 다운받는 이유이다.) 이런 언어들을 보통 프로그래밍 언어라고 부른다. C가 대표적인 예이다.

    인터프리터(Interpreter)


    인터프리터는 번역해야 할 파일을 받아 한 줄씩 실행시킨다. 예를들어 배시 인터프리터를 실행시키면 배시 인터프리터가 해당 파일의 첫번째 줄을 읽어 기계어 명령어로 번역 한 후 CPU에 바로 돌린다. 즉 인터프리터가 필요한 명령어는 1. 프로그램을 작성한다. 2. 인터프리터에 실행시킨다. 이렇게 작성된다. 

    장점은 무엇일까? 인터프리터만 설치되어 있으면 같은 프로그램(스크립트)을 다른 컴퓨터에서도 실행 시킬 수 있다. (인터프리터가 컴퓨터마다 다르게 컴파일 되어야겠지만 그건 인터프리터를 만드는 애들이 할 일이다..)

    단점은 무엇일까? 인터프리터가 실행할 때마다 1. 번역한다, 2. 실행한다를 거쳐야 한다. 이렇게 두 가지 일을 해야 하니 그냥 바이너리 파일을 냅다 실행시키기만 하는 컴파일된 프로그램에 비해 속도가 느릴 수 밖에 없다.

    이렇게 인터프리터가 번역해야하는 프로그래밍 언어를 '스크립팅' 언어라고 부른다. Javascript, Python(바이트코드 인터프리터), PHP(바이트코드 인터프리터)등이 이에 해당된다. 어떤 언어들은 바로 기계어로 번역되고, 어떤 언어들은 바이트코드로 한번 컴파일 된 후 해석(interpret)된다.

    하이브리드(Compiler-Interpreter-Compiler)

    컴파일러와 인터프리터를 혼합 해 놓은 하이브리드 형식의 번역기가 존재한다. 앞서 말했듯 컴파일러는 한 언어에서 다른 언어로 번역해주는 프로그램을 컴파일러라고 부른다. 하이브리드 언어는 보통 고급언어를 약간 기계어에 가까운 언어로 번역 한 후 실행시 그 '약간 기계어에 가까운 언어'를 인터프리터를 이용해 한 줄씩 완전한 기계어로 번역한다. 대표적인 하이브리드 형태로 작동하는 언어로는 자바가 있다.

    예를들어 temp.java는 컴파일시 temp.class라는 파일로 컴파일된다. 자바 컴파일러는 java를 16진수로 된 바이트코드(bytecode)라는 class파일로 컴파일한다. 그리고 자바 인터프리터가 자바를 실행 시 이 바이트코드를 한 줄씩 번역해 CPU에 실행시킨다. 이 인터프리터는 JVM의 일부로 동작한다. 또 자바는 인터프리터의 단적을 극복하기 위해 JIT(Just-in-Time)컴파일러라는 것을 사용해 자주 사용되는 바이트코드를  기계어로 컴파일 해 사용한다. 이 점이 바로 자바를 하이브리드로 만든다. 파이썬 또한 JIT 컴파일러를 지원하는 버전이 있다고 한다.

    이번 포스트를 통해 프로그래밍 언어랑 무엇이며 프로그래밍 언어를 기계어로 번역하는 번역기들(컴파일러, 인터프리터, 하이브리드 등)의 종류과 장단점에 대해 이야기 해 보았다. 

    어떤 프로그래밍 언어가 프로그래밍 언어인지 스크립팅 언어인지는 그 언어의 컴파일러가 존재하는지 인터프리터가 존재하는지에 따라 결정된다. 컴파일러와 인터프리터가 모두 존재하는 경우도 있다. 예를들어 파이썬은 대표적인 스크립팅언어로 알려져 있지만 구현에 따라 중간언어 또는 아얘 기계어로 컴파일 되는 경우도 있다. 현대의 언어는 대부분 일정부분 컴파일, 일정부분을 인터프리트된다고 봐도 과언이 아닐 것 같다.




    댓글

f.software engineer @ All Right Reserved