1. 컴파일이란 무엇인가?
저희는 컴파일러가 무엇인지에 대해 알아보기에 앞서, 어셈블리어에 대해 먼저 알아보아야 합니다.
- 어셈블리어
어셈블리어(assembly language) 또는 어셈블리 언어는 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어입니다. 컴퓨터 구조에 따라 사용하는 기계어가 달라지며, 따라서 기계어에 대응되어 만들어지는 어셈블리어도 각각 다르게 됩니다.
- 왜 다른지?에 대해 간단하게만 알아두면, 컴퓨터 CPU마다 지원하는 오퍼레이션 타입과 개수는 제각각이며, 레지스터의 크기와 개수, 저장된 데이터 형의 표현도 각기 다르기 때문이다 정도로 알아두시면 좋을 것 같습니다.
본론으로 돌아와서, 지금 컴파일에 대해 알아보려고 했던 것인데 왜 어셈블리어에 대한 설명을 하는지에 대해 궁금하실겁니다. 그 핵심 이유는 위에 언급한 한 문장에 있습니다.
- 컴퓨터 구조에 따라 사용하는 기계어가 달라지며, 따라서 기계어에 대응되어 만들어지는 어셈블리어도 각각 다르다
초기 컴퓨터 프로그램은 어셈블리어로 작성되었습니다. 그렇기에 서로 다른 CPU 아키텍처가 등장할 때 마다 매번 똑같은 프로그램을 새로운 아키텍처에 맞는 다른 어셈블리어로 작성해야 하기에 비용과 시간 측면에서 큰 불효율성이 생겼고, 고급 프로그래밍 언어의 필요성이 대두되었습니다.
그래서 고급 프로그래밍 언어가 탄생하게 되었습니다. 하지만 컴퓨터는 우리가 고급 언어로 작성한 코드를 바로 알아들을 수 없었기에 이를 컴퓨터 언어에 맞게 번역해줄 과정의 필요성 또한 대두되었고, 이것이 저희가 아는 컴파일입니다.
2. 컴파일러(Compiler) vs 인터프리터(Interpreter)
위 내용처럼, 우리는 고급 프로그래밍을 사용하게 되었고 이를 어셈블리어로 번역해주는 작업의 역사가 시작되었습니다. 이 번역 방식에는 2가지가 있는데, 하나는 컴파일러 방식이고 하나는 인터프리터 방식입니다.
2-1. 컴파일러(Compiler)
컴파일러는 특정 프로그래밍 언어로 쓰여 있는 문서를 다른 프로그래밍 언어로 옮기는 언어 번역 프로그램을 말합니다. 즉, 컴파일러는 사람이 이해할 수 있는 고급 프로그래밍 언어를 실행 프로그램으로 만들기 위해 컴퓨터 프로세서가 이해할 수 있는 저급 프로그래밍 언어(ex. 어셈블리 언어, machine code 등) 또는 이진 숫자로 바꾸는데 사용됩니다.
컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역합니다. 전체를 스캔하여 번역을 하기에 대체로 컴파일러는 초기 스캔 시간이 오래 걸립니다. 하지만 실행에 있어서는 인터프리터에 비해 빠릅니다.
쉽게 생각하면, 영어 원서에 적힌 내용을 발표 할때 발표에 앞서 미리 전부 번역해두는 것이랑 같습니다. 처음 준비는 오래걸릴 지언정, 발표 때는 막힘없이 빠르게 읽어나갈 수 있는 장점이 있습니다.
또한 컴파일러는 먼저 모든 코드를 스캔 하는 과정을 거치기에 컴파일 후 모든 오류를 표시합니다. 그래서 실행 전에 오류를 발견할 수 있는 장점이 있습니다.
하지만 단점도 존재합니다. 위 그림에서도 볼 수 있듯이 컴파일러는 고급언어로 작성된 소스를 기계어로 번역하고 이 과정에서 오브젝트 파일을 생성하는데, 이 오브젝트 코드를 묶어서 하나의 실행 파일로 만드는 링킹(linking) 이라는 작업도 수행해야 합니다. 이런 여러 복잡한 과정을 거치기 때문에 컴파일러는 일반적으로 인터프리터에 비해 많은 메모리를 사용해야 하는 단점이 있습니다.
대표적인 언어로는 C, C++, JAVA 등이 있습니다.
2-2. 인터프리터(Interpreter)
인터프리터는 고급 프로그래밍 언어를 프로그램 실행 시 한 번에 한 문장씩 기계어로 번역하는 프로그램입니다. 인터프리터는 소스 코드를 직접 실행하거나, 효율적인 다른 중간 코드로 변환하고 변환한 것을 바로 실행하거나, 인터프리터 시스템의 일부인 컴파일러가 만든, 미리 컴파일된 저장 코드의 실행을 호출하는 과정 중 하나를 거칩니다.
컴파일러와 대비되는 성격을 지니고 있습니다. 앞선 든 예시로 다시 살펴보면, 원서 발표시에 미리 번역을 해두지 않고 그 자리에서 한 문장씩 해석하며 발표하는 상황과 같습니다. 때문에 초기 시간은 빠를 지언정 실행 시간 면에서는 불리할 수 밖에 없습니다. 한 문장씩 읽고 번역하는 과정을 반복하는 것은 한번 만들어 둔 프로그램을 실행하는 것에 비해 힘들기 때문입니다.
하지만 인터프리터는 컴파일러에 비해 메모리 효율은 좋습니다. 컴파일러 처럼 목적코드도 만들지 않으며, 링킹 과정도 거치지 않기 때문입니다. 따라서 메모리 사용에는 효율적인 모습을 보일 수 있습니다.
또한 인터프리터는 오류 메시지 생성과정이 컴파일러와 다릅니다. 인터프리터는 한번에 한 문장만 번역하기 때문에 프로그램을 실행시키고 한 문장씩 번역될 때 마다 오류를 만나게 되면 바로 프로그램을 중지하게 됩니다. 그래서 프로그램을 실행해야지 오류를 발견할 수 있다는 특징이 있습니다.
대표적인 언어로는 Python, Ruby, JavaScript 등이 있습니다.
3. 차이점 정리
Complier | Interpreter | |
번역 단위 | 전체를 한번에 번역 | 한번에 한 문장씩 번역 |
프로그램 실행 속도 | 빠름 | 느림 |
실행파일 생성 | 생성 | 미생성 |
오류 발생 시점 | 컴파일 시점 | 실행 시 |
- 사진 출처 및 참고 문헌