프로그래밍 언어 만드는 과정 - peulogeulaeming eon-eo mandeuneun gwajeong

프로그래밍 언어와 빌드 과정 [Build Process]

  • 2020.11.27 00:43
  • 프로그래밍 기초

안녕하세요.  

제가 이 시리즈를 작성할 때 처음 계획했던 것이 있습니다. 최소한의 프로그래밍언어에 대한 작성 방법은 알고 있다는 전제하에 프로그래밍 전반에 관한 내용을 다뤄본다고 했죠.

어떤 특정 언어에 대해 알아보는 것이 아닌지라 이제 막 프로그래밍을 배우는 분들은 조금은 이해하긴 어려울지라도 최소한 C, C++, Java 중 하나 이상을 알면 이해할 수 있도록 하고 있습니다.

이를 위해 가장 먼저 계획한 것이 여러분이 코드를 실행파일로 만들기 까지의 과정중 기초적 뼈대를 이해하기 위해 크게 3가지로 나눴는데요. 먼저 우리가 작성하는 코드에서의 기본적인 문법의 기본 구조를 알아보았고, 기본 구조를 토대로 전체적인 프로그래밍 작성 구조를 알아보았죠.

즉, 우리가 영어, 중국어, 일본어 등을 배울 때 먼저 단어와 기본 문법을 이해한 뒤, 전체적인 글의 구조를 이해하는 식이죠. 제가 포스팅 한 걸로 대입해보면 단어와 기본 문법은 '프로그래밍 언어의 단어와 문법' 포스팅이고, 글의 구조는 '객체지향과 절차적 프로그래밍' 포스팅이 될 겁니다.

이 번 포스팅에서는 문법과 글의 구조를 알았으니 외국어 책을 우리말로 번역하여 만들어보는 과정을 다뤄보고자 합니다. 프로그래밍에서는 이를 실행 파일을 만드는 과정이라고 하죠. 좀 더 전문적으로 말하자면 '빌드(Build)' 한다고 합니다.

⦁ Build 란?

 

먼저 빌드 과정(Build Process)에 대해 간략하게 알아보고 가도록 합시다. 

Build 라는 단어가 '무언가를 짓다'라는 뜻인 것은 모두가 알 겁니다. 우리가 건물을 짓는다고 할 때, 설계도를 기반으로 기초공사를 하고 철근을 세우고, 벽을 세우고, 도색하고... 이러한 과정을 거쳐 집이 완성되는 과정을 짓는다고 하죠.

또 다른 예시로는 해외판 책을 우리나라 말로 번역하는 과정이라고 생각할 수도 있겠습니다.

프로그래밍에서도 마찬가지입니다. 컴퓨터는 근본적으로는 0과 1밖에 모릅니다. 우리가 작성하는 코드들은 거의 대부분 고급언어를 사용하기 때문에 결국에는 컴퓨터(CPU)가 이해할 수 있도록 번역을 해주어야겠죠. (C, Java, C++ 등 어셈블리를 제외한 대부분 언어가 고급언어입니다.)

컴퓨터가 이해하는 언어를 기계어라고 하는데, 우리가 만든 소스 코드가 컴퓨터 입장에서는 해외판 책이 되는 것이고, 이 책을 기계어(machine code)로 번역하여 컴퓨터에서 이해할 수 있는, 즉 실행 가능한 파일로 만드는 과정을 빌드(Build) 라고 합니다.

조금 더 이해하기 쉽게 그림으로 보자면 이렇습니다.

정리하자면 우리가 만든 소스코드를 '빌드'라는 과정을 통해 실행 파일을 얻게 되는 것이죠. 그 실행파일은 exe, exec 등등 여러 종류가 있습니다. 이러한 실행파일은 기계어(Machine Code) 라고 언어(CPU가 읽을 수 있는 이진코드)로 이루어져 있습니다.

하지만 이 것으로 끝을 내기에는 뭔가 아쉽습니다.

프로그래밍에 대해 배우는데 빌드가 어떻게 되는 것인지 모른다는 것은 번역가가 외국어 책을 어떤 방식으로 우리말로 번역되는지를 모른다는 것과 다름이 없죠.

그러니 조금 더 빌드를 세분화하여 보도록 합시다.

⦁ Build Process

앞서 빌드를 번역하는 과정에 빗대어 표현했습니다. 

외국어로 되어있는 책(소스 코드)을 우리나라 말로 번역(빌드)하여 우리(기계)가 읽을 수 있는 책(실행 파일)으로 만드는 과정은 하나만 있는 것이 아닙니다.

예로들어 전문 번역가를 고용한다던지, 구글 번역을 사용한다던지, 파파고를 사용한다던지.. 여러 방식이 있겠죠. 이렇듯 컴퓨터의 빌드 과정도 모든 언어가 각기 다른 방식을 사용하고 있습니다.

빌드과정은 크게 3가지 방식으로 분류를 할 수 있는데, 일단 이름부터 소개하자면 Compile 방식, Interpreter 방식, Hybrid 방식이 있습니다.

일단 간단하게 표를 보고 하나씩 분해해봅시다.

1. Compile Type

먼저 컴파일 타입입니다. 위 설명에서도 나와있듯 우리가 작성한 소스코드를 한꺼번에 번역해서 실행파일로 만들어 줍니다. 한마디로 통번역이죠.

이렇게 한 번에 번역하는 언어들을 보통 Compile Language 라고 하는데, 대표적으로 C, C++, Go 언어가 있습니다. 이러한 언어들의 빌드 과정은 대개 아래와 같습니다.

위 그림을 보면 빌드 과정에 총 4가지 단계가 있습니다.

대부분 컴파일 언어가 위와 같은 과정을 거칩니다. (물론 언어별로 약간의 과정이 추가 또는 생략될 수 있습니다.) 그리고 화살표를 보면 두 개로 나뉘다가 링크 작업에서 하나로 합쳐지는데, 이 또한 의미가 있습니다.

책을 번역 할 때 만약 시리즈로 되어있는 책을 번역한다면 어떻게 번역할까요? 각 단권별로 번역하겠죠? 그런 다음 하나로 묶어 책으로 발간을 할 겁니다.

이렇듯 각 파일 단위로 번역과정을 거친다음 최종적으로 하나로 묶게 되기 때문에 이해하기 편하게 화살표로 그 과정을 그려놓았습니다.

그럼 하나씩 간략하게 알아보죠.

[preprocessing (전처리)]

전처리(preprocess) 과정입니다. 단어를 보면 pre + process 입니다. 대개 전처리라고 하지만 좀 더 쉽게 와닿게 말하자면 그냥 말 그대로 '사전 처리' 라고 보면 됩니다. 전처리 과정은 전처리기(preprocessor) 에 의해 소스코드에 포함 된 매크로나 지시자 같은 것을 포함시켜주죠. 뭔가 말이 어렵게 느껴진다면 다음과 같이 생각하시면 됩니다.

'소스코드의 중심(main)이 실행되기 전에 사전준비 하는 과정'

앞서 빗대어 표현했던 책 번역과정으로 치자면 저자 이름, 책에서 정의하는 표현, 판권, 인용 등 이미 정해져 있는 것들을 먼저 처리하여 이후에 일일이 다시 찾아 쓸 필요 없이 정리해두는 과정이랑 비슷하죠.

프로그래밍 언어로 보자면 C언어나 C++ 에서 # 으로 시작하는 구문들(#include, #define 등)이 있을 겁니다.

[compilation (컴파일)]

우리가 프로그래밍 언어를 다루면 가장 많이 듣는 단어 중 하나죠. compile 이라는 뜻이 '번역하다'라는 뜻입니다. 흔히 컴파일을 소스코드를 실행파일로 만드는 것으로 생각하는 분들이 있는데, 엄연하게는 다릅니다. 말 그대로 '번역'하는 것일 뿐 번역 된 것만으로는 컴퓨터가 실행 할 수는 없죠. (외국어책을 번역만 해놓고 책으로 묶지 않으면 그 건 책이 아니라 그냥 번역만 한 종이일 뿐이죠.)

여러분이 대개 쓰는 eclipse, Visual Studio, X Code 같은 통합개발환경(IDE : Integrated Development Environment)들은 대부분 한 번 컴파일(또는 빌드)을 하면 실행파일까지 나와버리기 때문에 오해하는 것이 아닌가 싶습니다.

어떤 언어로 번역하느냐. 컴파일 하는 프로그램을 컴파일러(compiler)라고 합니다. 한마디로 번역가죠. C나 C++를 다뤄보셨다면 gcc, g++, Visual C++ 같은 단어를 들어보거나 보셨을 겁니다. 이런 것들이 바로 컴파일러입니다.

컴파일러가 컴파일 하면 바로 기계어(Machine Code)로 번역 될 것 같지만 아닙니다. 흔히 중간언어 또는 저수준 언어라고 하는 놈으로 번역됩니다. 보통은 어셈블리어(Assembly Language)로 번역됩니다.

음 왜 기계어로 바로 번역하지 않고 저수준 언어(low-level Language)로 번역되는지 이해가 가지 않을 수도 있을 것 같습니다. 이유는 프로그래밍의 역사를 보면 쉽게 알 수 있는데, 과거에는 0과 1로만 작업을 했어야 하다보니 여간 불편하기 짝이 없죠. 예로들어 'A'라는 문자를 표현하려면 1000001 이런식으로 했었어야 하니깐요. 이렇다 보니 이런 것들을 부호화(Symbolic) 한 것이죠. 단순히 부호화만 했기 때문에 기계어(Machine Code)와 1대1 매칭이 됩니다. 그렇다 하더라도 우리가 사용하는 Java, C 같은 고급언어처럼 사람이 읽기 쉬운 언어가 아닌 난해한 언어인지라 저수준 언어(low-level language)에 속하게 되는 겁니다.

저수준 언어답게 장점도 있죠. 바로 내부가 어떻게 작동하는지, 즉 하드웨어를 직접적으로 조작하거나 특수 프로세서 명령어에 접근 등을 확인하거나 작업을 할 수가 있다는 것이죠.

한마디로 인간이 기계어를 이해하기 위해 고급언어와 기계어 사이에 중간단계인 저수준 언어로 번역하는 것이죠. 대표적인 C, C++ 모두 어셈블리어라는 저수준 언어로 번역되니 이 걸로 가정하고 가죠.

[assemble (어셈블)]

앞서 컴파일 단계에서 컴파일러가 고급언어를 저수준 언어로 번역을 해줬습니다. 그러면 이 저수준 언어(어셈블리어)를 최종적으로 기계어로 번역을 해주어야겠죠? 이 어셈블리어를 기계어로 번역해주는 프로그램을 어셈블러(Assembler)라고 합니다.

이렇게 CPU가 이해할 수 있는 언어로 번역된 파일을 보통 Object File 이라고도 하는데, 직역하면 '객체 파일'이라고 하지만, 대부분은 객체라 하지 않고 '목적 파일'이라고 합니다.

저는 목적 파일이 맞는 번역인지는 모르겠습니다만.. 우리가 배웠던 것을 응용하여 설명하자면 우리는 앞서 '객체'라는 것을 배웠습니다. 필자가 '객체'를 다음과 같이 설명했죠. (자세한 이야기는 직전 포스팅인 '객체지향과 절차적 프로그래밍'에서 보실 수 있습니다.)

"동작의 주체가 누군지 분류하여 동일성을 갖는 기능들을 하나의 묶음으로 만들어낸 하나의 실체"

즉, 자판기라는 객체는 음료를 갖고있고, 일정 값어치의 돈을 받으면 그에 대응하는 음료를 반환해주는 하나의 실체이듯, 어셈블리어에서 기계어로 번역된 Object File은 앞서 설명했듯 여러개의 연관된 파일을 빌드하면 '링크' 단계 전까지는 각 파일별로 번역되기 때문에 그 번역된 파일 하나하나가 실행하는 최종 파일의 일부분으로서의 객체가 된다고 보면 됩니다. 그래서 Object 라는 단어가 붙게 되는 겁니다.

그리고 컴파일 과정을 여기까지 포함하기도 합니다. 갑자기 무슨말인가 싶겠지만 Compile이라는 단어 자체가 번역이라는 의미죠? 프로그래밍에서는 크게 두 가지로 해석할 수 있습니다.

좁은 의미로는 '소스코드를 저수준 언어로 변환해주는 과정'을 의미하죠. 근데 좀만 생각해보면 어셈블도 번역하는 단계죠. 즉, 컴파일이라고 볼 수도 있습니다. 그래서 좀 더 넓은 의미로는 전처리 과정부터 어셈블 과정까지를 컴파일 단계라고 부르기도 합니다. (또한 컴파일 언어의 빌드 과정에 어셈블이 없다면, 즉, 어셈블리어 같은 저수준 언어가 아닌 바로 기계어로 번역되는 경우는 어셈블 과정이 생략되고 컴파일 단계만 있겠죠.)

[linkig (링크/링킹)]

컴파일(어셈블 포함) 과정을 통해 각 파일들이 기계어로 번역되었다면 이제 하나로 연결해주어야 합니다. 책을 번역할 때도 각 낱장별로 번역된 종이들을 하나로 모아 묶어야 책이듯, 각각의 Object File 은 기계가 이해할 수 있는 번역본일 뿐 실행을 할 수 있는 파일이 아니죠.

즉, Object File 들과 필요한 라이브러리들을 연결 시켜주고 최종적으로 하나의 'executable file (실행가능한 파일)'로 만들어줍니다. 우리가 흔히 어떤 프로그램을 사용할 때 .exe 라는 확장자를 갖는 파일을 실행시킵니다. 이 exe가 바로 executablue 의 줄임말입니다.

전처리-컴파일-어셈블-링크 4단계를 살펴보았습니다.

좀 더 포괄적으로 보면 '전처리-컴파일-어셈블' 단계를 하나의 컴파일 단계라고 본다고도 했죠. 즉, 빌드와 컴파일의 차이점이 여기서 나온는 겁니다. 컴파일은 번역하는 단계로 소스코드를 목적 파일(Object File)로 만들어주는 과정일 뿐 그 결과물이 실행파일인 것은 아닙니다. 이 컴파일 단계에 링크 과정이 포함 되어야 즉, 빌드가 비로소 실행가능한 파일이 나오는 전체 과정을 의미하는 것이죠.

아주아주 쉽게 말하면 '컴파일 + 링크 = 빌드' 라고 이해하시면 됩니다.

컴파일 언어의 장점

  1. 빌드가 완료된 실행가능한 파일은 실행 속도가 빠릅니다.

  2. 매번 번역할 필요 없이 실행 파일만 실행하면 되기 때문에 전체적인 시간면에서 효율적입니다.

컴파일 언어의 단점

  1. 프로그램을 수정해야 할 경우 처음부터 빌드과정을 다시 거쳐야하기 때문에 특히나 대규모 프로그램에서는 생산성이 떨어집니다.

  2. 플랫폼에 매우 의존적입니다.

잠깐 단점 2번에 대해 설명하자면, 플랫폼에 의존적이라는 말은 가장 쉽게 이해하자면 윈도우 실행파일을 맥OS 에서 실행하지 못하는 상황을 생각하면 됩니다.

크게 두 가지 원인이 있는데, 먼저 어셈블리어의 경우 CPU 명령어 세트에 1대1로 매칭된다고 했죠. 즉, CPU에 의존적이라는 것인데 CPU 명령 체계가 거의 비슷하긴 하나 완전히 같지는 않습니다. 그리고 다음으로는 CPU가 이해할 수 있게 번역하여 최종 실행파일로 만들기 위해 우리는 링크라는 작업을 해주었죠? 이 과정에서 OS 마다 서로 다른 라이브러리가 있어 링커는 해당 OS에서 요구하는 라이브러리를 연결하게 됩니다.

이러한 이유 때문에 우리가 프로그램을 내려받을 때 윈도우용, 맥용, 64비트, 32비트 등 이렇게 각 버전에 맞는 프로그램을 까는 이유가 이러한 것 때문이라고 보시면 됩니다. (또한 운영체제별로 지원하는 것도 조금씩 다릅니다.)

한 예로 C언어의 경우 자료형 타입이 각 운영체제마다 크기가 다르죠.

2. Interpreted Type

인터프리트 타입입니다. 소스코드를 통번역 하는 것이 아닌 한 명령 단위로 해석하면서 즉시실행하는 방법입니다. 좀 더 쉽게 생각하면 통역사를 생각하면 됩니다.

위 그림에서 컴파일 언어와 인터프리트 언어의 가장 큰 차이점은 무엇일까요? 바로 목적파일(Object File)을 생성하지 않고 바로(direct) 실행된다는 것이 가장 큽니다.

보통 이러한 인터프리터 언어에 가장 대표적인 언어는 자바스크립트(JavaScript), 파이썬(Python)과 루비(Ruby)로 알려져 있죠.

(이는 정확히 말하자면 절반은 맞고 절반은 틀립니다. 이유는 바로 다음인 하이브리드 언어에서 설명하겠습니다.)

쉽게 말하면 소스코드의 한 명령 세트마다 기계어(Machine Code)로 번역하면서 바로바로 실행해주는 방식을 인터프리트라고 합니다. 그리고 이렇게 번역해주는 프로그램(또는 환경)을 Interpreter(인터프리터)라고 하죠. 즉, 각 운영체제에 맞는 해당 언어의 인터프리터만 설치한다면 어느 운영체제에서든 해당 언어를 사용하더라도 동일한 결과를 얻을 수 있다는 것입니다. 한마디로 플랫폼에 독립적이라는 것이죠. 또한 이렇게 컴파일 과정 없이 인터프리터를 통해 바로 결과를 볼 수 있기 때문에 프로그램 수정에 매우 유리하다는 장점이 있습니다.

음? 그럼 실행가능한 파일은 없는 것인가요? 라고 생각할 수도 있겠습니다만, 소스코드 그 자체가 실행가능한 파일이 되는 거라고 이해하시면 됩니다. 다만, 소스코드를 번역해줄 수 있는 인터프리터를 설치해야겠지요.

인터프리트 언어의 장점

  1. 컴파일과정 없이 바로 실행하기 때문에 수정, 디버깅에 유리합니다. 즉 개발속도에 유리합니다.

  2. 각 플랫폼에 지원하는 인터프리터만 있다면 실행 가능하기 때문에 플랫폼에 독립적입니다.

인터프리트 언어의 단점

  1. 빌드 되어있는 컴파일 언어 프로그램보다 실행시간이 느립니다.

  2. 코드를 열면 다 보이기 때문에 보안에 좋지는 않다.

반대로 컴파일 언어에 비해 매 번 부분씩 번역해야하기 때문에 실행 속도는 느리다는 단점이 있습니다. 하지만 이마저도 요즘 하드웨어의 스펙이 워낙 높아져 일반 사람들에게는 컴파일 언어와 인터프리터 언어의 실행 차이를 체감하기 힘들정도라 오히려 개발 속도가 빠른 인터프리트 방식을 혼합하여 적용을 하려는 경향이 근래 많아졌죠.

3. Hybrid Type

하이브리드 타입입니다. 컴파일 방식과 인터프리트 방식을 혼합한 방법입니다. 그럼 왜 혼합을 했을까요? 컴파일언어의 단점은 실행 가능한 파일이 플랫폼에 의존적이라는 것이지만 실행 속도가 빠르다고 했었죠. 반대로 인터프리터 언어의 단점은 실행속도는 느리지만, 플랫폼에 독립적이라 어느 플랫폼이든 번역기(인터프리터)만 있으면 실행 가능했죠.

이 둘의 단점을 상호 보완하여 만들어 진 것이 바로 하이브리드 방식입니다.

흔히 '바이트 코드 언어(Byte Code Language)' 라고 하죠. 가장 대표적인 언어로는 Java(자바)가 있습니다.

책을 번역하는 과정에 비유해서 들어보자면 이렇습니다. 세계적으로 가장 많이 쓰이는 언어는 영어죠? 영어가 모국어가 아닌 국가라 하더라도 영어를 할 줄 아는 사람들이 많을 것입니다. 그래서 프랑스어, 힌두어 등등 다른 국가의 언어로 번역된 것을 1차적으로 영어로 번역을 해둡니다. 그런 다음 영어로 번역된 것을 한국어로 번역하면 번역 가능한 사람이 많은 만큼 쉽고 빠르게 번역할 수 있을 겁니다.

영어는 어디서든 대부분 쓰기 때문에 조금은 번거롭더라도 중간 번역과정을 한 번 거쳐두면 그 다음부터는 재사용을 하기도 쉽고 다른 언어로 번역하기도 쉽다는 장점을 살린 것처럼 프로그래밍에서도 이를 적용한 방식이 바로 하이브리드 방식입니다.

어디서든 대부분 쓰일 수 있다는 것을 해석하자면 플랫폼에 대해 독립적이라는 말이겠죠?

그림을 보기 전에 잠깐 설명하자면 고급 언어로 작성된 소스코드를 바이트 코드(bytecode)로 변환합니다. 바이트 코드란 일종의 중간 언어라고 생각하면 됩니다. 그리고 VM(Virtual Machine : 가상머신) 이라는 프로그램에 의해 바이트코드를 기계어로 바꿔줍니다.

이 때 중요한 것은 바로 VM인데요. VM은 하나의 프로그램이라고 생각하시면 됩니다.

아주아주 쉽게 생각하면 프로그램을 VM 이라는 가상머신에서 실행한다고 보시면 됩니다. 즉, 각 플랫폼에 맞는 VM들이 만들어져 있다면 우리는 같은 소스코드를 어느 플랫폼에서든지 동일한 결과를 얻어낼 수 있다는 것이죠.

요즘은 어떨지 모르겠습니다만, 예전에 마인크래프트가 한참 유행일 때 마인크래프트를 실행하기 위해서는 Java 를 설치해야 했었죠? 그 설치한 Java 프로그램에 바로 가상머신이 포함되어 있기 때문에 java로 코딩된 소스코드를 실행하기 위해 Java를 설치하라고 했던 것이죠. (정확히는 JRE(Java Runtime Enviroment)를 설치했었을 겁니다.)

일단 그림으로 한 번 보죠. 

여기서는 그럼 실행가능한 파일이 무엇일까요? 바로 바이트 코드가 됩니다. 

컴파일과 인터프리트 과정은 이미 설명했으니 우리가 보지 못했던 새로운 것 몇 개만 설명해보도록 하겠습니다.

먼저 바이트코드(Byte Code)는 가상머신(Virtual Machine)이 이해할 수 있는 중간언어(intermediate language)라고 보시면 됩니다. 앞선 비유에서 '영어'라고 보시면 되겠습니다. 예로들어 Java를 컴파일하면 .class 파일이 생성될 겁니다. 또는 C#을 배워본 사람은 CIL(common intermediate language)라는 말을 들어보셨을 겁니다. 바이트코드는 기계어는 아니지만 어셈블리어처럼 '기계에 조금 더 가까운 언어'로 되어있죠.

다만 컴파일언어의 목적파일과 차이가 있다면 컴파일 언어에서는 하드웨어에 의해 처리되는 기계어로 되어있었다면, 바이트 코드 파일의 경우 하드웨어가 직접 처리하는 것이 아닌 소프트웨어(가상 머신)에 의해 처리된다는 것입니다.

역으로 생각하자면 바이트코드는 해당 가상머신 전용 기계어라고 보면 됩니다.

그러면 마지막으로 VM입니다. VM 은 가상머신(Virtual Machine)의 줄임말인데, 감이 잘 안오실 수 있습니다만 쉽게 생각해서 가상 컴퓨터라고 보시면 됩니다. 하나의 컴퓨터 환경을 구현했다고 생각하면 이해가 좀 더 편할 수도 있겠네요.

바이트 코드는 이 가상머신이 이해할 수 있는 코드로 되어있다고 보면 됩니다. 그리고 그 가상머신 안에는 인터프리터 같은 해석기가 있어 이들이 바이트코드를 해석하여 각 OS에 맞게 명령어를 해석하고 작동하는 하나의 프로그램이라고 보면 되죠.

쉽게 자바로 예로 들자면, 자바 소스코드를 컴파일 하면 .class 파일이 나올겁니다. 이 파일만 있으면 JVM이 설치된 어느 컴퓨터에서든 실행 할 수 있을 뿐만 아니라 거의 동일한 결과를 내보일 수 있죠. 

가장 대표적인 VM은 Java Virtual Machine 인 JVM 이 있습니다. 또한 C#의 경우는 .NET의 CLR 이 있죠. 이들의 장점은 VM(가상머신)이 해당 운영체제에 맞게 지원만 해준다면 플랫폼에 독립적으로 실행할 수 있다는 장점이 있습니다. 인터프리터랑 같은 원리인 것이죠. (물론 VM이 인터프리트만 하는 것이 아니라 최근에는 컴파일 방식과 혼용하여 구현되어 있습니다. 대표적으로 JIT(Just-in-Time) 이 있습니다.)

즉, VM을 통해 '플랫폼에 독립적'인 장점을 갖고왔고, 초기 컴파일 단계를 통해 바이트코드로 기계어에 더 가까운 언어로 번역을 한 번 해놓았기 때문에 속도도 기존 인터프리터 언어에 비해 더 빠르다는 장점 또한 갖고오게 되었죠.

하이브리드 언어의 장점

  1. 각 플랫폼에 지원하는 가상머신 있다면 실행 가능하기 때문에 플랫폼에 독립적입니다. 

하이브리드 언어의 단점

  1. 컴파일 언어처럼 하드웨어를 직접 제어하는 작업은 불가능하다.

더보기

(이 부분은 조금 어려울 수 있어 참고로만 알아두면 되겠습니다.)

앞서 인터프리터 언어를 설명할 때 루비, 파이썬은 인터프리트 언어라 하는 것이 절반만 맞다고 했습니다. (좀 더 친숙한 파이썬을 중심으로 설명하겠습니다.)

그 이유가 일반적으로 Python은 C로 구현되어 있습니다. 이 구현체를 CPython이라고 하는데, 가끔 여러분이 파이썬을 실행하면 .pcy 라는 확장자를 갖는 파일이 나오는 경우가 있을겁니다.

이 파일이 바로 파이썬을 바이트 코드로 컴파일한 파일입니다. 즉, py 확장자를 갖는(우리가 일반적으로 작성하는 소스코드) 파일을 바이트코드(.pcy)로 컴파일하여 가상머신(인터프리터)가 해석하는 방식입니다.

그래서 절반은 맞고 절반은 틀렸다는 것이 바로 이러한 부분 때문입니다. (루비 또한 여러 구현들이 있어 루비 = 인터프리트 언어 라고 1대 1 매칭을 할 수는 없습니다.) 

⦁ 정리하기

이렇게 3가지 방식의 빌드 과정을 알아보았습니다. 다만, 여러분이 명심해야 할 것이 C언어 = 컴파일언어, Python = 인터프리트언어 이런식으로 생각하면 '절대' 안됩니다.

어디까지나 '대표적인' 언어일 뿐이지 1대 1로 매칭되는 개념이 아니라 빌드 과정의 구현의 차이일 뿐입니다.

언어는 어디까지나 언어고 이를 기계어로 바꾸는 수단은 매우매우 많습니다. 예로들어 C나 C++ 전용 interpreter(인터프리터)를 사용하여 인터프리트처럼 사용할 수 있고, python 코드를 JVM 에서 실행할 수 있도록 할 수도 있죠.

우리가 책을 번역하는 것에 비유하면서 작성을 했는데, 책을 번역하는 방식이 꼭 한 가지만 있는 것이 아닌 것처럼 각 프로그래밍 언어들도 한 가지 방식으로만 빌드할 수 있는 것도 아니라는 것을 알아주셨으면 합니다.

다만, 위 3개의 빌드 과정을 이해하면 이후에 다른 언어를 접하거나, 다른 환경의 IDE를 사용하는 경우 어떤 과정을 거쳐 실행하는지를 좀 더 쉽게 이해 할 수 있을 겁니다.

혹시 어려운 부분이 있다면 댓글을 남겨주시면 감사하겠습니다 :)

Toplist

최신 우편물

태그