빌드의 진화사
새로운 방식이 등장할때는 기존의 방식에 어떤 문제점이 있고, 그 문제점을 해결하기 위해 등장합니다. 이 발전 순서를 따라가면 이해가 쉬워지는 것 같습니다.
AOT 컴파일러
C, C++
동작 방식
C언어 코드를 컴파일러가 실행파일로 번역합니다. 이 과정을 '컴파일' 이라고 하고, 이 실행파일을 실행시키면 런타임으로 들어가게 됩니다.
컴파일 타임 : C언어 코드 -> 기계어 (실행파일)
런타임 : 기계어 -> CPU 로드
이 과정이 완전히 분리되어있습니다.
이 방식의 장점과 단점은 어떻게 될까요?
장점
1. 런타임이 빠릅니다. 기계어가 이미 만들어져 있기 때문에 다른 처리 없이 머신에 올려주기만 하면 됩니다.
2. 코드 자체도 빠릅니다. 머신에 가장 가까운 언어로 미리 통번역을 하기 때문에 기계어 최적화가 가능합니다.
단점
1. 컴파일 과정이 번거롭습니다.
코드 일부만 수정해서 그 파트만 잘 실행되는지 확인하고 싶으면 전체 덩어리를 다 새로 컴파일해줘야합니다. 코드 규모가 크면 컴파일하는 시간도 부담입니다.
2. 머신에 따라서 실행파일을 따로 만들어줘야합니다.
기계어라는게 윈도우, 리눅스, 32bit, 64bit 등 하드웨어와 운영체제에 종속적이기 때문에 이런 하드웨어 상황들을 고려해서 실행파일을 만들어줘야합니다. 이때 __int16, __int32, __int64 같은 자료형 등등 C언어 코드 자체를 수정해야할 수도 있습니다.
3. 런타임 오류가 발생한 위치가 C언어 상에서 어딘지 알기가 힘들기 때문에 런타임 오류 디버깅이 어렵습니다.
이런 단점들을 커버할 수 있는, 더욱 코더 친화적인 방식이 개발됩니다.
인터프리터
동작 방식
컴파일 과정을 완전히 생략한 방식입니다. '인터프리터' 가 기존의 컴파일러의 역할을 실시간으로 수행합니다. 실행시킬때마다 코드를 한줄 읽고 번역해서 머신에 올립니다.
장점
컴파일 방식의 단점을 모두 커버합니다.
1. 필요한 파트만 돌려보는게 가능합니다.
2. (머신에 따라서 다른 인터프리터가 필요하겠지만,) 머신과 관계 없이 똑같은 파일을 옮겨서도 바로바로 돌려볼 수 있습니다.
3. 런타임 오류가 발생한 위치가 코드상 어디인지 알 수 있기 때문에 디버깅이 매우 쉬워집니다.
단점
1. 매번 번역해야하므로 컴파일 언어에 비해서 매우 느립니다.
2. 기계어 최적화도 불가능합니다.
컴파일 언어의 장단점을 정확하게 반대로 수행하는 방식인것같습니다. 인터프리터 언어의 코더 친화적인 작동 방식은 개발 효율을 매우 높여주기 때문에 포기하기 어렵습니다.
인터프리터의 코더 친화적 성격을 유지하면서 속도면을 개선시키기 위한 방식이 등장합니다.
바이트코드 인터프리터
CPython
동작 방식
최대한 저수준의 언어로 번역해놓자는 방식입니다. 이 방식은 컴파일 단계가 존재하고, '바이트코드' 라는 단계까지만 컴파일합니다. 기계어보다는 고수준의 언어입니다. 실행 단계에서는 이 바이트코드를 cpu에 올리기 위해 가상머신을 사용합니다. 자바에서는 JVM, 파이썬에서는 PVM 이라는 런타임 엔진을 사용합니다.
어느정도 최적화가 가능해졌고, 컴퓨터별 호환성도 유지할 수 있습니다.
캐싱으로 속도를 더 개선시킨 방식이 등장합니다.
JIT 컴파일러
pypy, JAVA
동작 방식
많이 실행되는 파트를 핫스팟으로 지정하고 핫스팟은 바이트코드를 기계어 수준까지 컴파일해서 따로 저장합니다. 코드 실행중에 컴파일이 진행되어서 JIT (Just In Time) 컴파일 이라고 합니다.
인터프리터의 성향을 유지하되 자주 호출되는 일부분만 기계어로 번역하는, AOT와 인터프리터의 장점을 최대한 살리기 위해서 줄타기한 방식인 것 같습니다.
'CS' 카테고리의 다른 글
동시 처리 (Concurrent) vs 병렬 처리 (Parallel) (0) | 2024.01.04 |
---|