해당 포스트는
compile
/interpreter
/transpile
에 대해 정리한 포스트입니다.
주관적으로 해석한 내용이 들어가 있어서 잘못된 내용이 포함될 수 있습니다.
❓ 컴파일러 등장 배경
어셈블리어(
Assembly
)란 기계어와 1:1로 대응되는 저급 언어입니다.
기계어는 컴퓨터가 해석할 수 있는 언어입니다.
옛날에는 어셈블리어로 프로그램을 개발했다고 합니다.
그런데 문제는 컴퓨터에 따라 어셈블리어를 읽는 방식이 달라서 새로운 컴퓨터가 개발되면 또 그에 맞춰서 프로그램을 수정해야 했었습니다.
그 문제를 해결하기 위해 고급언어와 그것을 컴파일해주는 컴파일러가 나왔습니다.
컴파일러를 사용해서 고급언어를 컴퓨터에 맞게 어셈블리어로 변환시켜주는 과정을 통해서 해결했다고 합니다.
🛠️ 컴파일러와 인터프리터
그러면 이제 컴파일러는 어렴풋이 알겠는데 인터프리터는 뭐고 그 두 개의 차이는 무엇일까요?
0️⃣ 컴파일러
컴파일러는 실행하기전에 한번에 모든 소스 코드를 읽고 모두 기계어로 변환합니다.
그리고 변환한 기계어를 이용해서 프로그램을 실행하는 방식입니다.
( 컴파일이라는 개념이 고수준의 언어를 바이트 단위의 기계어로 옮기는 것에만 국한된 의미는 아니라고 합니다. 그래서 트랜스파일링도 컴파일에 포함되는 개념입니다. ( 확실하지 않음 ) )
대표적으로 C
, C++
, Java
가 컴파일러 언어입니다.
1️⃣ 인터프리터
인터프리터는 소스 코드를 한 줄 씩 읽으면서 즉시 번역하고 실행합니다.
즉, 실행을 하면 읽고 번역하고 실행하는 과정을 한 줄 씩 처리합니다.
대표적으로 JavaScript
, Python
, Ruby
가 인터프리터 언어입니다.
2️⃣ 컴파일러 vs 인터프리터
컴파일러와 인터프리터의 차이에 대해서 알아보겠습니다.
1. 실행 속도
초기 실행 속도는 인터프리터가 빠르지만, 이후에는 컴파일러가 더 빠릅니다.
초기에 컴파일러는 모든 소스 코드를 번역하기 때문에 비교적 느릴 수 밖에 없습니다.
하지만 모두 번역하고 나면 인터프리터처럼 한 줄 씩 번역하지 않고 바로 실행이 가능하기 때문에 더 빠릅니다.
2. 메모리
인터프리터가 사용하는 메모리가 비교적 더 적습니다.
인터프리터는 한 줄 읽고 번역하고 실행하고 필요 없는 것은 버리면 됩니다.
하지만 컴파일러는 모두 번역해서 가지고 있어야 하기 때문에 메모리를 더 많이 사용하게 됩니다.
3. 오류 찾기
컴파일러는 실행전에 모든 소스 코드를 해석하기 때문에 먼저 오류를 찾을 수 있습니다.
하지만 인터프리터는 실행을 해야 소스 코드를 해석하기 때문에 실행하는 시점에 오류를 찾습니다.
4. 동적/정적
C
/Java
를 써보시면 알겠지만 모든 변수에 타입이 존재합니다.
정해진 타입에 정해진 타입의 값만 들어갈 수 있죠.
왜냐하면 코드를 실행하기전에 모두 해석해서 문제를 파악해야 하는데 타입을 알 수 없으면 문제가 있는지 파악할 수 없기 때문입니다.( 확실하지 않음 )
하지만 JavaScript
/Python
같은 언어는 변수에 타입이 존재하지 않습니다.
왜냐하면 프로그램을 실행하면 코드를 읽고 적용하기 때문에 실행하는 시점에 타입을 정할 수 있기 때문입니다.
상황에 맞게 유연하게 동작하기 때문에 처음 배울 때는 컴파일러 언어보다는 비교적 쉽게 느껴집니다.
하지만 복잡하고 얽혀있는 많은 코드를 작성하다보면 처음에 느꼈던 장점이 단점으로 바뀌게 됩니다.
예를 들면 어떤 변수의 값이 무조건 number
라고 생각하고 코드를 구성했는데 다른 곳에서 string
으로 들어오고 그게 현재 상태에서는 정상적으로 동작하다가 나중에 다른 곳에서 문제를 일으킵니다.
그러면 디버깅하는 시간이 엄청나게 소모될 수 있고, 막상 문제를 찾아도 별거 아닌 부분에서 사소한 문제로 시간만 날리게 되죠.
그래서 TypeScript
가 등장했습니다.( 물론 다른 이유도 많이 있을겁니다. )
이전에 TypeScript
를 사용해봤다면 이제 이상하게 느껴지는 게 있습니다.
“인터프리터 언어인데 어떻게 타입이 존재하고 실행하기도 전에 오류를 체크해줄 수 있지?”라는 생각이 들 수 있습니다.
그것을 가능하게 해주는 것이 트랜스파일이라는 개념이고 babel을 통해서 트랜스파일을 진행하게 됩니다.
📎 트랜스파일
JavaScript
에서는babel
을 통해서 트랜스파일링을 처리합니다.
한 언어로 작성된 소스 코드를 비슷한 수준의 추상화를 가진 다른 언어로 변환하는 것을 의미합니다.
대표적으로 TypeScript
-> JavaScript
, JSX
-> JS
과 같이 변화시키는 것을 트랜스파일링이라고 합니다.
소스 코드를 번역해서 새로운 소스 코드로 만들어내죠.
TypeScript
가 변수의 타입을 체킹할 수 있는 이유가 바로 트랜스파일과정이 있기 때문입니다.
TypeScript
코드를 바로 실행하지 않고 중간에 컴파일러 언어처럼 트랜스파일하는 과정이 있습니다.
그 과정을 통해서 다른 정적 언어처럼 타입 체크도 하고 실행전에 에러가 있는지 확인할 수 있습니다.
그리고 TypeScript
가 아니더라도 유용하게 사용할 수 있습니다.
React
를 사용할 때는 JSX
문법을 사용하는데 그 문법을 변화시켜주는데도 사용하고 옛날 브라우저가 지원해주지 않는 최신 문법을 옛날 문법으로 바꿔주는데도 사용합니다.