본문 바로가기
Language

[Programming Language] 1. 서론

by 삼준 2023. 7. 7.
반응형

● 들어가기 전 블로거 한마디

<프로그래밍 언어> 과목은 프로그래밍 언어 설계 및 구현시 고려되어야 하는 사항과 그에 따른 언어별 특징 등을 배우는 과목입니다.

각종 언어들에 대한 예제 코드가 나오지만, 그에 대한 문법적인 설명은 따로 제공하지 않으므로, 기본적인 문법, 특히 C, Python, Java 세 언어의 기본문법은 알고 보시는게 좋습니다.

 

● 컴퓨터 구조가 언어 설계에 미친 영향

현대의 컴퓨터 구조는 모두 폰 노이만 구조에 기반함.

- 폰 노이만 구조

  • 데이터와 프로그램이 모두 동일한 기억 장소에 저장됨
  • 명령어를 실행하는 CPU는 기억 장소로부터 떨어져 있음.
  • 명령어와 데이터는 CPU에 전달되어야 하고, 연산 결과는 다시 기억 장소로 전달되어야 함. (인출-실행 사이클, 해당 과정에서 Program Counter, PC가 쓰임.)

해당 구조는 언어 설계에 큰 영향을 미쳤고, 폰 노이만 구조에 기반한 언어를 명령형 언어라고 함.

- 명령형 언어의 특징

  • 변수: 기억장소 셀 모델링
  • 배정문: 데이터 이동 연산 담당
  • 반복문: 반복 연산 구현

- 함수형 언어

명령형 언어의 대체제로 떠오르고 있는 언어. 비-폰노이만 구조가 설계된다면 명령형 언어에 비해 더 효율적으로 실행이 가능할 것으로 보이지만, 두 종류의 언어에 대한 전망은 사람마다 다르게 예측함.

 

● 프로그래밍 언어 구현 방법

1. 컴파일러 구현

프로그램을 기계어로 번역하는 구현.

번역 과정이 완료되면 매우 빠른 실행을 할 수 있다는 장점을 가짐.

대표적인 언어로 C가 있음.

 

- 컴파일 과정 & 구성 요소

원시 언어로 이루어진 프로그램은 전처리기 -> 컴파일러 -> 어셈블러 -> 링커를 순서대로 거쳐서 컴파일됨. 컴파일러를 거친 프로그램은 어셈블리 언어로 구성되고, 어셈블러를 거친 프로그램은 기계어로 구성됨. 

C언어 프로그램을 예로 들면, 확장자가 .c 였던 파일은 전처리기를 거쳐서 .i 파일이되고, 컴파일러를 거치면 .s 파일이되며, 어셈블러를 거치면 .o 파일이 되고, 마지막 링커를 거치면 실행 파일(.exe)이 됨.

  • 원시 언어 (Source Language): 컴파일러가 번역하는 언어
  • 어휘 분석기 (Lexical Analyzer): 프로그램을 어휘 단위로 구분
  • 구문 분석기 (Syntax analyzer): 어휘 단위들을 가져와 파스 트리(Parse Tree)라고 불리는 계층적 구조 생성
  • 중간 코드 생성기 (Intermediate Code Generator): 중간 수준 언어 프로그램 생성(ex. 어셈블리어)
  • 코드 생성기 (Code Generator): 기계어 프로그램으로 변환
  • 심볼 테이블 (Symbol Table): 컴파일 과정에서 데이터베이스로 사용됨

※참고※ '컴파일러'라는 단어는 (1)컴파일 전체과정을 돕는 프로그램, (2)원시 언어를 어셈블리언어로 바꾸는 프로그램  두 가지 의미로 사용이 되기 때문에, 문맥에 따라 구분할 줄 알아야 함.

 

- 링킹(Linking)

사용자가 만든 프로그램은 거의 항상 다른 코드(라이브러리, 다른 개발자의 코드 등)를 필요로 하며, 그러한 코드들이 요구될 때 컴파일러는 해당 코드에 대한 호출을 생성해 줌. 링킹 연산은 요구된 코드들의 시작 주소를 사용자 프로그램 상의 요구된 코드 호출 위치에 저장하는 것을 의미하며, 이 과정에서 스택(Stack)이 사용됨. 해당 연산이 완료된 프로그램을 적재 모듈(Load Module) 또는 실행 가능 이미지(Executable Image)라고 함.

 

2. 순수 인터프리터 구현

컴파일러 구현과 정반대에 위치하는 구현 방법.

번역 과정이 없이, 인터프리터라 불리는 프로그램에 의해 해석됨.

JavaScript, PHP, WebScript, 초기 Python 등이 해당됨.

 

- 장점

  • 많은 소스레벨 디버깅 연산을 쉽게 구현할 수 있음.

- 단점

  • 실행 시간이 컴파일된 시스템보다 심각히 느림. (실행할 때마다 해석해야 하고, 고급 언어 해석은 기계어 해석에 비해 월등히 복잡하기 때문)
  • 더 많은 기억 공간을 요구함. (심볼 테이블이 해석 과정에 존재해야 하기 때문)

- Python

현재의 파이썬은 소스 코드를 컴파일하여 바이트 코드로 만들어둠으로써 다음 수행시 빠른 속도를 보여줌.

 

3. 혼합형 구현

앞의 두 구현 간의 절충된 구현

고급 언어 프로그램을 중간 언어로 번역함.

순수 인터프리터 구현보다 빠름.

초기 Java 등이 해당됨.

 

- Java

초창기는 혼합형 구현이었으나, 현재에는 자바 바이트 코드를 기계 코드로 번역하는 시스템이 존재함.

 

- JIT(Just In Time) 구현 시스템

프로그램을 중간 언어로 번역함.

실행 중에 중간 언어 메소드가 호출될 때, 그 메소드를 기계 코드로 번역하고, 다음 번 호출에 대비해 보관됨.

Java에서 널리 쓰이고 있으며, .NET 언어는 모두 JIT 시스템으로 구현됨.

반응형

댓글