컴파일러,
컴퓨터가 다양한 언어를 이해하는 유일한 방법


 
  사람이 육체와 정신으로 구성되어 있다면 컴퓨터는 하드웨어와 소프트웨어로 이루어져 있다고 볼 수 있다. 세상의 모든 기계는 눈에 보이는 부품들로 존재하지만, 보이지 않는 곳에 논리적으로 잘 짜인 프로그램이 들어가 있기에 우리가 원하는 기능을 수행할 수 있다. 그래서 소프트웨어 개발자들은 프로그램을 만들 수 있는 컴퓨터 언어를 배우는 것이다.

@nionx / page URL: http://mrg.bz/009uDq Image URL: http://mrg.bz/IWndvs

 
하지만 모든 기계는 그들만이 이해하는 언어(기계어)가 따로 있다. 기계는 결국 전기의 흐름(ON=1)과 흐르지 않음(OFF=0)으로 이해하지만 이러한 기계어를 인간이 배워 프로그래밍하기에는 너무도 어렵고 힘들다. 그래서 이 기계어를 인간이 이해할 수 있는 수준으로 쉽게 바꾼 것이 바로 프로그래밍 언어라는 것이다. 우리들에게는 ‘C, C++, Java’ 등으로 많이 알러져 있다.

@imelenchon / Page URL: http://mrg.bz/xJqkIW Image URL: http://mrg.bz/jV3enF


  프로그래밍 언어컴퓨터와 대화하기 위한 일종의 대화 수단이다. 예를 들어, 한국인과 프랑스인이 의사소통을 하기 위해서는 프랑스인이 한국어를 배우거나 한국인이 프랑스어를 배워야만 대화를 할 수 있다. 즉, 서로 다른 언어체계를 가지고 있는 두 사람이 의사소통을 하기 위해서는 그들 사이의 공통적인 대화수단이 마련되어야 하는 것이다.

  그런데 프랑스인은 한국어를 모르고, 한국인도 프랑스어를 모른다면 어떻게 해야 할까. 두 언어를 다 알고 있는 통역사의 도움을 받으면 가능하다. 하지만 이 통역사는 한국어를 모르고 영어와 프랑스어 밖에 하지 못한다. 이때 한국인이 영어를 할 수 있다면 통역사를 통해 프랑스인과 대화할 수 있다. 여기서 영어가 프로그래밍 언어에 해당한다고 볼 수 있다. 그래도 낯선 프랑스어보다는 학창시절 12년 간 배운 영어가 더 배우기 쉽지 않을까. (경우에 따라서는 아닐 수도 있겠지만;;)

컴파일러의 필요성

  인간이 컴퓨터에게 일을 시키기 위해서는 컴퓨터와 사람이 이해할 수 있는 공통적인 대화수단이 필요하다고 했다. 그러나 불행히도 이런 대화 수단은 존재하지 않는다. 컴퓨터는 사람의 말을 이해하지 못하고, 사람도 컴퓨터가 인식할 수 있는 기계어를 알지 못한다. 그렇다고 사람이 컴퓨터가 이해하는 기계어를 공부하기 위해서는 부담이 너무 크다. 반대로 컴퓨터에게 사람의 언어를 정확히 가르친다는 것도 아직까지는 불가능하다. 그래서 인간이 쉽게 배울 수 있는 수준의 프로그래밍 언어도 이해하고 기계어도 알고 있는 통역사를 두고 있다고 생각하면 쉽다. 우리는 이 통역사를 “컴파일러(Compiler)”라 부른다.

  컴파일러는 참 똑똑하다. 어떤 프로그래밍 언어도 컴퓨터가 이해하는 기계어(1과 0)로 바꿔준다. 영어 통역사, 프랑스어 통역사가 있는 것처럼, C언어 컴파일러, C++언어 컴파일러, Java 컴파일러가 각각 존재한다. 우리는 목적에 따라 효과적인 프로그래밍 언어를 선택해서 배우고 그에 맞는 컴파일러를 이용하면 컴퓨터에게 일을 시킬 수 있다.

△ 아래한글 워드프로그램에서는 기본적인 한국어문법이 틀렸을 때 빨간 줄로 표시해 주고 있다. 한국어에서 ‘을/를’이라는 목적격 조사를 구분해 사용하는 기준은 바로 앞 단어에 받침이 있으냐 없느냐다. 아래한글에서는 ‘(‘ (반괄호)로 묶여진 내용은 다음 문장의 조사에 영향이 없도록 정의되어 있음을 알 수 있다. 이와 같은 형식의 규칙들이 컴파일러에는 무수히 정의되어 있다.


  컴파일러는 내부적으로 정해진 문법 규칙이 아니면 오류 메시지를 띄우고 기계어 변환을 중지한다. 예를 들어 “나는 당신을 사랑합니다.”를 영어 문법규칙에 따라 “I love you.”라고 적어야 하는데, 이를 무시하고 “I you love”라고 입력하면 사람은 이해할 수 있겠지만 컴퓨터는 절대 이해하지 못한다. 프로그래밍 언어에 ‘{(여는 괄호)’로 시작된 문장이 있다면 반드시 ‘}(닫는 괄호)’가 있어야 하고, 계속 명령어를 다음 문장으로 구분 짓기 위해서는 ;(세미콜론)을 써야 한다는 등의 규칙이 이에 해당한다. 따라서 다양한 프로그래밍 언어로 만들어진 프로그램 코드는 컴파일러가 정하는 문법규칙 내에서만 구성되어야 하고, 경우에 따라서는 프로그래밍 언어가 먼저 만들어지고 컴파일러가 개발되기도 한다.
 
  컴파일러의 동작은 크게 분해하는 과정과 합성하는 과정으로 나눌 수 있다. 분해과정은 I love you.가 I, love, you라는 각각의 단어로 이루어져 있음을 형태소 단위로 구분해 내어 인식하고, 합성과정에서는 이를 목적코드로 변환하여 실제 실행파일로 생성해 준다. 분해 과정의 각 단어와 연산자는 ‘트리(tree)’라고 하는 계층적 구조로 나타낼 수 있다.

컴파일러가 작동하는 순서



  “rate와 5를 곱해서 init와 더한 값을 result에 넣어라”는 명령어, <result = init + rate*5>가 있다고 하자. 어떻게 문자와 숫자가 연산될 수 있을까 의문을 가질 수 있지만 이 문자에는 숫자, 문자를 담을 수 있도록 사전에 약속되어 있다.

  위 명령어는 컴퓨터가 이해할 수 없는 인간의 공식이다. 그러나 컴파일러를 통하면 컴퓨터가 이해할 수 있게 된다. 컴파일러에는 result, init, rate라는 문자가 어떤 값을 넣을 수 있는 변수라는 것, ‘=’는 오른쪽 값을 왼쪽으로 대입하는 기호라는 것, ‘+’ 는 ‘더하라’는 뜻이고, ‘*’는 ‘곱하라’는 의미라는 것이 모두 정의되어 있기 때문이다. 여기에는 ‘*(곱셈)기호는 +(더하기)기호 보다 우선하고 =(대입)기호는 가장 마지막에 연산한다’는 보이지 않는 우선순위까지 정의되어 있다. 이 정도면 정말 놀랍지 않은가. 
  

@littlegreenfroggy / http://www.flickr.com/photos/littlegreenfroggy/2253341684


  그래서 예전에는 컴파일러를 만드는 것이 정말 어려워서 기계어와 거의 1대1로 대응되는 어려운 어셈블리어라는 프로그래밍 언어를 많이 사용했다. (물론 요즘도 하드웨어를 세밀하게 컨트롤하기 위해 많이 쓰인다.) 그러다 포트란이라는 프로그래밍 언어의 컴파일러가 등장(1957년)하면서 컴파일러 제작에 따른 설계와 방법들이 체계적으로 정리되기 시작했고, 지금은 컴퓨터공학과 학생들도 한 학기의 수업을 통해 구현할 수 있는 단계까지 발전했다. 하지만 여전히 쉽게 만들 수 없는 복잡한 이론과 전문적 능력이 다양한 컴파일러를 만드는데 있어 높은 진입장벽으로 작용하고 있다.

  컴파일러는 컴퓨터에 생명을 불어넣는 통역사 역할을 톡톡히 하고 있다. 컴파일러가 없었다면 우리는 복잡하고 어려운 기계어를 익히며 컴퓨터와 직접 대화해야 할 것이다. 최근에는 자연어를 인식하여 동작하는 소프트웨어의 성능이 높아져 언젠가 프로그래밍 언어가 사라지고 한국어로 컴퓨터와 대화하듯 프로그램을 만들고 코딩하는 시대가 올지도 모르겠다. 그렇게 되면 누구나 쉽게 원하는 프로그램을 만들고 사용할 수 있게 될 것이다. 앞으로 얼마나 뛰어난 능력의 컴파일러가 등장할지 기대되는 이유가 바로 여기에 있다.

[참고]
-C프로그래밍, C++프로그래밍(윤성우 저)
-Compilers(Alfred V.Aho, Ravi Sethi, Jeffrey D. Ullman 저)

블로그 이미지

굿가이(Goodguy)

우리 생활 속 과학이야기