본문 바로가기

[Kotlin&Spring] 5기 내일배움캠프

[Kotlin&Spring] 5기 컴파일 방식들과 자바의 컴파일

컴파일(Compile)이란

고급언어로 작성한 코드를 컴퓨터가 인식할 수 있도록 저급언어로 번역해주는 것을 말한다

 

 

컴파일러(Compiler) 방식은 말 그대로 묶음으로 만드는 것이다

프로그램 전체를 스캔한 후 모두 기계어로 번역한다

 

컴파일러의 장점

1. 초기 스캔 시간이 오래 걸리지만 전체 실행시간 자체는 인터프리터 보다 빠르다

초기 스캔 후 실행파일 만들고, 다음 실행 시 이전 실행파일을 실행한다

2. 전체 파일 검사 후 오류 메시지를 생성한다

컴파일 단계(실행 단계 전)에서 오류를 발견할 수 있다

 

컴파일러의 단점

1. 고급언어를 기계어로 번역하는 과정에서 오브젝트 코드(Object Code)파일 만든다

이때 오브젝트 코드 파일들을 묶어서 하나의 실행 파일로 만드는 링킹(Linking) 작업이 필요하다

링킹 작업에서  인터프리터보다 많은 메모리를 사용한다

2. 코드 수정 시마다 컴파일이 필요하다

수정 사항이 빈번할 경우 문제가 발생한다

3. 특정 시스템에서 만들어진 실행 파일이 다른 시스템에서 실행되지 않는 경우가 많다

 

컴파일러를 사용하는 언어의 대표적인 예로 C, C++ 등이 있다

 

 

인터프리터(Interpreter) 방식은 말 그래도 해석하는 것이다

인터프리터는 프로그램 실행시 한 번에 한 문장씩 기계어로 번역한다

고급 언어를 중간 코드(intermediate code)로 변환허고 각 행마다 다른 프로그램으로 실행한다

 

인터프리터의 장점

1. 오브젝트코드를 만들지 않고 링킹과정도 필요없기 때문에 메모리 효율이 좋다

메모리를 별도로 할당받아 수행하지 않고, 필요할 떄 할당한다

덕파이핑이 가능하지만 반대로 정적 분석을 할 수 없다

*덕타이핑(Duck Typing): 타입을 미리 정하지 않고 실행되었을 때 메소드 확인하며 타입을 정하는 것

*정적 분석(Static Analysis): 소드코드의 실행 없이 프로그램의 문제를 찾는 것

2. 런타임(실행 시간)에 실시간 디버깅(Debugging) 및 수정이 가능하다

3. 전체 코드를 컴파일 하지 않아도 되어 수정에 용이하다

4. 시스템간 이식성이 좋다

 

인터프리터의 단점

1. 컴파일러보다 실행시간이 더 오래걸린다

2. 프로그램을 실행시키고 한 문장씩 번역 후 오류를 만나면 프로그램이 중지된다

프로그램을 실행해야만 오류 발견이 가능하다

3. 중간 코드로 해석되기 때문에 프로그램의 코드가 유출될 수 있다

 

인터프리터를 사용하는 대표적인 언어의 예시로 Python, Ruby, Javascript 등이 있다

 

JIT(Just-In-Time) 컴파일 방식은 동적 번역(dynamic translation)이라고 한다

프로그램 실행 중에 자주 사용되는 코드를 기계어로 컴파일하여 성능을 개선한다

 

JIT의 대표적인 예시는 PythonPyPy, JavascriptV8엔진이 있다

 

 

Java는 컴파일러와 인터프리터를 모두 사용하는 하이브리드 언어이다

Java가 두 컴파일 방식을 모두 채택한 이유는 아래와 같다

1. 컴파일러의 경우는 프로그램이 작성된 기계상에서 실행할 떄 매우 효율적으로 실행된다

그러나 기계 종류나 플랫폼에 종속된다

이식성에 대한 문제를 인터프리팅을 함으로써 해결한다

2. 자바 바이트코드는 컴퓨터와 프로그램 사이에 버퍼역할을 한다

보안적으로 장점이 된다

인터넷이나 기타메체를 다운받아 실행할 경우 보장이 된다

인터프리터를 사용함으로써 바이러스나 악성 프로그램에 대응하는 보안 계층에 의해 보호된다

 

 

JavaJIT(Just-In-Time) 컴파일러는 실행 시점에 바이트코드를 기계어로 변환하여 실행 속도를 향상시킨다

인터프리터 실행 속도가 너무 느릴 떄 부분적으로 이용한다

실행 시점에서 인터프리터와 같이 기계어 코드를 생성하다가 해당 코드가 컴파일 대상이 되면 컴파일하고 해당 코드를 캐싱한다

캐시에 저장되어 재사용 시 컴파일이 필요없게 된다

JIT 컴파일은 코드가 실행되는 과정에 실시간으로 일어나며 필요한 부분만 변환한다

JIT 컴파일이 일어나는 조건은얼마나 자주 코드가 실행되었는가이다

기준(임계치)는 메서드 호출 횟수, 메서드가 루프 돈 횟수 기반으로 한다

스택 상의 교체/ORS(on-stack replacement)는 살행중인 메서드의 코드도 최적화하여 빠르게 실행한다

루프 문의 카운터(돈 횟수)가 임계치를 넘으면 컴파일 대상이 된다

JVM은 루프를 위한 코드의 컴파일이 끝나면 다시 반복될 떄의 코드를 컴파일된 코드로 교체하며, 더 빠르게 실행된다

 

Java의 컴파일러는 .java 파일을 javac(java compiler)가 바이트코드로 쓰여진 .class 파일로 변환한다

컴파일러는 자바 소스코드를 JVM을 위한 기계어(자바 바이트 코드)로 변환한다

 

Java의 인터프리터는 .class(클래스파일) 내의 바이트코드를 특정 환경의 기계에서 실행될수 있도록 변환한다

기계어(이진 코드)로 번역이 여기에서 일어난다

기계어는 JVM을 거쳐서 OS(운영체제)에 도달한다

다양한 환경을 지원하기 때문에 인터프리터는 OS나 플랫폼에 종속되지 않는 프로그램의 구동을 가능하게 한다

이는 자바의 모토인 WORA(Write Once Run Anyone)을 실현한다

 

컴파일러, 인터프리터, JIT 등의 다양한 방법과 자바의 컴파일 방식을 알 수 있었다

컴파일 방식에도 장단점이 모두 존재하기 때문에 다른 언어를 공부하게 된다면 오늘 공부한 내용이 유용한 정보가 될 것이라고 생각한다

오늘보다 더 열심히 하는 내일이 되길 바란다 화이팅 ~ !