컴파일러와 인터프리터

유수민·2024년 10월 9일
0

지식창고

목록 보기
62/64

오늘의 글은 '자바의 신'이라는 책에서 던져준 질문이다. 역시 책은 시간 지나서 다시 읽으면 또 다른 새로운 시각을 준다.

💡 '컴파일이 뭔지 설명할 수 있어?'

오늘은 여러가지 내용 중에 컴파일에 관련된 것에 한번 알아보려고 한다.

컴파일은 뭐야?

우선 책의 내용을 정리하자면, compile이라는 단어는 "엮다"라는 말이다. 즉, 내가 만든 프로그램 코드를 컴퓨터가 이해할 수 있도록 엮어주는 작업이 컴파일이라고 한다. 그래서 컴파일러는 번역기라고 생각하면 된다. 우리랑 컴퓨터랑 언어가 다르니까~


책에서는 딱 이렇게 만 보여줬다 간단하게..ㅎ 궁금하면 나보고 더 파보라는 이야기인가? 이 그림에는 정말 많은 것이 생략되어 있다. 양파같은 녀석..ㅋㅋ

하이브리드 언어

첫번째로 까볼 양파는..🧅 사진에서도 그렇고 책에서도 그렇고 컴파일러만 등장하지만 사실 '인터프리터'도 존재한다. 자바는 대표적인 하이브리드 언어이다.
컴파일러와 인터프리터에 대해 간단히 정리하자면,

컴파일러

  • 전체 파일을 통으로 번역한다. ( 전체적으로 한번만 디코딩해서 실행한다)
  • 한꺼번에 번역하고 저장해야하니 저장공간(메모리)가 많이 필요로 한다.
  • 실행시간 측면에서 인터프리터보다 실행속도가 엄청 빠르다.(초기 스캔 시간은 오래 걸린다.)
  • 스캔하는 과정에서 모든 오류를 한꺼번에 출력해서 실행 전에 오류를 알 수 있다.

인터프리터

  • 한 줄 단위로 번역하기 때문에 실행속도가 드리다.한 줄마다 디코딩해야한다.
  • 한 줄씩만 번역하고 저장하니 메모리를 덜 소비한다.
  • 한 줄씩 실행하기 때문에 오류를 만나면 그제서야 프로그램 중지한다. 프로그램을 실행해봐야지만 오류 발견한다.

그대는 실행속도를 선택할 것인가.. 메모리를 선택할 것인가..

자바는 왜 하이브리드 방식을 선택하였는가?

진행 과정

책의 사진을 내 나름대로 다시 꾸며서 진행과정을 그려보자면 아래 그림으로 된다.

보다시피 바이트 코드 전까지는 컴파일방식이고 그 뒤에는 JIT 컴파일러와 인터프리터가 공존하는 하이브리드 방식이다.

우선적으로 왜 앞부분은 컴파일 방식일까?

Write Once, Run Anywhere

자바의 철학을 엿볼 수 있는 구절이다. "한번 작성하면 어디서든 실행 가능하다" 이를 실현하기 위해 바이트 코드가 필요하고 바이트 코드는 주로 컴파일러가 필요하다.

  • 바이트 코드 : 플랫폼에 독립적인 중간코드로 JVM에서 실행될 수 있도록 변환된 형태이다. 어느 운영체제에서나 실행가능하다.

그럼 컴파일 방식을 쭉 쓰지.. 왜 인터프리터를 왜 써?

다른 언어는 바로 실행하는 것에 비해, 앞에서 설명한 것과 같이 자바는 JVM이 알아들을 수 있는 언어로 바꾸는 작업이 추가로 필요하기 때문에 다른 언어에 비해 출발선이 다르다.
자바 실행했는데 한참 지나도 세월아 하면서 서버가 안뜨면 누가 자바를 쓰겠나?..ㅎㅎ 이때 필요한것은 속도!
컴파일러는 전체를 다 읽어야 하기 때문에 초기 시작 시간이 느린데 인터프리터는 한 줄씩 읽고 즉시 실행하기에 프로그램을 빨리 시작할 수 있다.

이때 우리가 겪을 수 있는 것은 성능문제가 발생한다.
JVM이 바이트 코드를 한 줄씩 해석하여 그때그때 실행하게 되는데, 매번 바이트코드를 읽고 해석하는 과정이 반복되니 자주 실행되는 코드일 수록 오버헤드가 커지게 되는 것이다.
빨리 시작하면 뭐해 점점 느려져.. 이런 소리를 들을 것인가?

JIT 컴파일러 등장!

Wikipedia - Just-in-time compilation
In computing, just-in-time (JIT) compilation (also dynamic translation or run-time compilations) is a way of executing computer code that involves compilation during execution of a program (at run time) rather than before execution.

그래서 등장한것이 JIT 컴파일러이다. 자주 사용되는 코드(핫스팟)을 감지해서 네이티브 코드로 컴파일 한다.

  • 네이티브 코드 : 기계어로 CPU가 바로 실행할 수 있기 때문에 바로 실행된다. 바이트 코드처럼 추가적인 해석 과정이 필요없다.

자주 실행되는 코드, 반복되는 코드, 자주 호출되즌 함수를 네이티브 코드로 변환함으로써 더이상 해석없이 빠르게 실행 할 수 있어 추가적으로 속도와 성능이 향상되는 것이다.

정리하자면

  • JVM에서 초기 실행은 주로 인터프리터 방식을 사용하여 실행 시작을 빠르게 하고,
  • 프로그램이 진행됨에 따라 자주 실행되는 코드에 대해 필요한 부분만 JIT 컴파일러가 개입하여 실행 중에 발생하는 성능 병목을 해결하고 빠른 응답성을 유지하는 것이다.
  • 또한, 자주 사용되지 않는 코드는 굳이 네이티브 코드로 변환하지 않기 때문에 메모리와 CPU 자원을 더 효율적으로 사용할 수 있는 것이다

회고

처음에는 컴파일에 대해서만 쓸려고 했는데 타고타고 가다보니 결론적으로 Execution engine의 일부를 설명하는 글이 되어 버렸다 ㅎㅎ 시간 순삭이다. 재밋긴 했다. 맨날 컴파일 컴파일 해도 그냥 넘겼는데 드디어 양심상 컴파일이라는 단어 앞에 안 작아져도 될 것 같다.


이 글을 쓰면서 벌써 다음 글감이 나왔다. 클래스 로더 ㅋㅋㅋㅋ 야호~

참고

profile
배우는 것이 즐겁다!

0개의 댓글