Fascination
article thumbnail

Chapter 01. 서론

프로그래밍 언어론 원리와 실제 - 창병모 교수님


1.1 프로그래밍 언어란 무엇인가?

1) 프로그래밍 언어란 무엇인가?

- 프로그래밍 언어: 계산 과정을 기계가 읽을 수 있고 사람이 읽을 수 있도록 기술하기 위한 일종의 표기법. 즉, 기계가 해석할 수 있고 사람이 이해할 수 있어야 함

  • 계산(Computation): 컴퓨터가 할 수 있는 연산들을 나타내며 덧셈, 뺄셈, 비교와 같은 데이터 조작, 문자 입출력과 같은 텍스트 처리, 정보 저장 및 검색 등을 의미
  • 기계 읽기(machine readability): 효율적인 번역 혹은 실행이 가능해야 함을 뜻함
  • 사람 읽기(human readability): 사람이 쉽게 프로그래밍할 수 있도록 편의성을 제공해야 하며 컴퓨터 연산들이 이해하기 쉬운 형태로 추상화 혹은 요약되어야 한다는 점을 의미함

 

2) 프로그래밍 언어의 중요성

- 소프트웨어의 발전은 프로그래밍 언어를 매개로 하여 발전함

- 언어에 따라 사고방식이 달라짐

  • 절차형(명령형) 언어(procedual language) → 계산과정의 절차를 기술하는 것
  • 함수형 언어(functional language)
  • 논리 언어(logic language) → 논리 규칙 형태로 작성
  • 객체-지향 언어(object-oriented language)

 

3) 주요 주제

- 주요 언어 이론

  • 구문론(syntax): 문장을 구성하는 방법
  • 의미론(semantics): 작성된 문장의 의미를 결정
  • 타입 시스템(type system): 타입의올바른 사용법

- 프로그래밍 언어의 설계

  • 동기, 원리
  • 샘플 언어 설계

- 프로그래밍 언어의 구현 기술

  • 주요 구현 기술
  • 샘플 언어의 인터프리터

- 주요 프로그래밍 패러다임

  • 명령형 언어
  • 객체지향 언어
  • 함수형 언어
  • 논리 언어

- 프로그래밍 언어의 역사

  • 기계어나 어셈블이어와 같은 저급 언어의 문제점을 해결하기 위한 고급 프로그래밍 언어의 개발은 1950년대부터 시작되어 지금까지 계속됨
  • 이러한 고급 언어의 발전과 더불어 컴퓨터 및 소프트웨어의 발전이 계속되고 있음

 

 

1.2 프로그래밍 언어의 종류

1) 프로그래밍 패러다임

명령형 프로그래밍
(procedual(절차형)/
imperative programming)
  • 문제를 해결하는 절차(명령)를 기술하는 방식의 프로그래밍
  • 수행할 명령들로 구성됨
  • 명령어들은 주로 프로그램의 상태를 바꾸는 역할을 함
  • C, Pascal, Python
함수형 프로그래밍
(functional programming)
  • 프로그램의 계산 과정을 수학 함수 형태로 프로그래밍
  • 프로그램은 함수 정의들로 구성됨
  • 순수한 함수는 원칙적으로 부수 효과(상태 변경 혹은 데이터 수정)을 허용하지 않지만 함수형 언어는 언어에 따라 부수 효과를 허용함
  • Lisp, Scheme, ML, Haskell
논리 프로그래밍
(logic programming)
  • 정형 논리(formal logic)를 기반으로 한 프로그래밍
  • 프로그램은 문제에 대한 사실/규칙을 표현하는 논리 문장들의 집합으로 구성 → "p→q" 즉, 술어 논리를 기반으로 함
  • declarative programming이라고도 함
  • Prolog
객체지향 프로그래밍
(object-oriented programming)
  • 실세계를 모의 실험하기 위한 언어로 고안되었으며 객체 개념을 기반으로 하는 프로그래밍
  • 객체는 속성과 그 속성에 대한 행동(함수 메소드)들을 포괄하는 개념
  • 프로그램 실행은 객체 사이의 상호작용에 의해 이루어짐
  • C++, Java, C#, Object-C, Swift, Python, Visaul Basic

 

2) 함수형 언어(Functional language)

- 기본 모델

  • 수학 함수를 기반으로 하는 언어. 즉, 프로그램의 계산 과정을 수학 함수의 수행으로 간주하는 언어
  • 프로그램: 매개변수로 입력을 받아 처리한 후에 반환 값을 출력하는 함수

- 함수

  • 함수 정의(definition)
  • 함수 호출(function call)
  • 매개변수(parameter)
  • 반환값(return value)

- 특징

  • 변수 및 대입문이 없음 → 함수의 매개변수를 통해서 값을 전달할 수 있음
  • 자기호출(recursion)에 의한 반복
  • 루프 같은 반복문 없음 → 재귀호출(recursive call)을 통해서 할 수 있음
  • 순수한 함수 수행은 부수 효과(상태 변경 혹은 데이터 수정)를 허용하지 않음

함수형 언어

- 예제: 함수형 언어 ML을 이용하여 계승(factorial)을 계산하는 함수

f(0) = 1	// 0! = 1
f(n) = n * f(n-1)	// n! = n * (n-1)!

수학적으로 계승 함수 f는 위와 같이 정의할 수 있음

fun fact(n:int) : int = 
	if n<=1 then 1
    else n * fact(n-1);

함수 f를 ML 언어를 이용하여 위와 같이 작성할 수 있음

이 함수는 int 타입의 값을 매개변수로 받아 int 타입의 값을 반환한다고 선언되어 있음

매개변수 n의 값이 0이면 반환 값이 1이며 그렇지 않은 경우에는 n-1 계승을 계산한 결과인 fact(n-1) 값과 n 값을 곱한 값이 반환됨

- 장점

  • 프로그래밍 모델이 기계 모델과 무관함
  • 수학을 기반으로 하고 있으므로 프로그램의 의미를 명확하게 파악할 수 있음

- 예: Lisp, ML, Scheme, Haskell

 

3) 논리 언어(Logic language)

- p → q 형태의 술어 논리(predicate logic)를 기반으로 함

- 선언적으로 프로그래밍하는 언어

- 프로그램: 문제에 대한 사실 혹은 규칙을 표현하는 논리 문장들의 집합. 즉, 문제를 해결하는 방법보다 문제가 무엇인지 논리 문장들로 표현하는 논리 문장들로 구성

- 예: 계승을 논리 언어인 Prolog를 이용하여 논리 문장들로 작성

fact(0, 1).
fact(N, V) :- N > 0, fact(N-1, V1), V is N * V1.
?- fact(3, X)

첫 번째 규칙: 0의 계승은 1이라는 사실 표현

두 번째 규칙: N이 0보다 클 때 적용될 수 있으며 이때 N의 계승 V는 N-1의 계승이 V1이면 N*V1이라는 것을 표현

증명하는 것을 계산하는 것으로 간주함

* ':-' 기호를 기준으로 오른쪽이 가정이고 왼쪽이 결론

- 특징

  • 루프나 선택문 등의 제어 추상화가 없음
  • 제어는 하부 시스템(해석기)에 의해 제공됨
  • 변수는 메모리 위치가 아니라 부분 결과 값에 대한 이름임

- 장점

  • 기계-독립적이고 정확한 의미구조를 가지고 있음
  • 선언적 프로그래밍이 가능

- Prolog: 대표적인 논리언어로 인공지능, 자연어 처리 등의 분야에서 많이 사용됨

 

4) 객체지향 언어(Object-oriented language)

- 실세계를 모의실험 하기 위한 언어로 고안됨 → 즉, 실제 세계에 있는 사물을 컴퓨터에서 표현하기 위해 고안된 것

- 객체 개념을 기반으로 하는 프로그래밍 스타일

- 객체(Object): 속성과 관련 행동(함수, 메소드)들의 모음으로 표현

- 계산과정(computation): 객체들 사이의 상호작용(메소드 호출)

- 클래스(class)

  • 클래스는 객체에 대한 타입 정의
  • 객체는 클래스의 한 실체(instance)임

 

 

1.3 프로그래밍 언어의 역사

- 프로그램 저장 방식의 범용 컴퓨터의 등장과 함께 프로그래밍은 중요한 문제가 됨

- 초기의 프로그램은 기계어 또는 기계어를 표현하는 기호화 코드를 사용하는 어셈블리어를 사용하여 작성함

- 어셈블리어와 같은 '저급(low-level)' 언어를 사용한 프로그래밍은 너무 어렵고 비생산적인 단점을 가짐

- 저급 언어의 단점을 보완하기 위해 고급 언어의 개발이 1950년부터 시작됨

주요 프로그래밍 언어의 발전 과정

 

1) 1950년대: 고급 프로그래밍 언어의 시작

FORTRAN
(FORmula TRANslation)
  • 과학응용 분야를 위한 효율성을 강조한 최초의 고급 언어
  • 설계 목표: 매우 빠르게 실행되는 코드를 생성함
  • 주요 기능: 배열(array), FOR 반복문, 분기 IF-문 등
COBOL
(COmmon Business-Oriented Language)
  • 사무용으로 설계된, 영어와 비슷한 구문을 갖는 명령형 언어
  • 주요 기능: 레코드 구조, 프로그램의 실행부와 분리된 자료구조
  • 다양한 출력 기능 등
LISP
(List Processor)
  • 리스트 자료구조와 함수 적용을 기반으로 함
  • 재귀호출(recursive call)이 매우 일반적임
  • LISP와 후속언어 Scheme은 인공지능 분야에서 많이 사용됨

 

2) 1960년대: 프로그래밍 언어의 다양성

Algol60
  • 알고리즘을 기술하기 위한 강력한 범용 언어
  • 블록-구조 언어로 스택-기반 실행 환경을 도입
  • 구문을 정의하는 방법으로 Backus-Naur 형식(BNF)을 최초로 사용
  • Pascal, C, Modula-2, Ada 같은 현대의 명령형 언어에 영향을 줌
  • 주요 특징: 구조적 문장, begin-end 블록, 자유 양식(free format), 변수 타입의 선언, 재귀 호출, 값 전달 매개변수
Algol68
  • Algol60을 향상하여 더 표현력 있고 이론적으로 완전히 일관성 있는 구조를 생성하려고 함
  • 언어를 정확히 기술하기 위해 엄격한 정의를 가진 새로운 표기법을 개발했으나 표기법이 난해하고 실용적으로 보급되지 못했음
  • 또한 언어가 복잡하고 방대한 사양을 요구하면서 컴파일러 구현이 어려웠고 결과적으로 널리 사용되지 못함
PL/I
  • 일반적이고 보편적인 언어, 즉 모든 언어를 통합하는 언어: FORTRAN, COBOL, Algol60의 좋은 특징을 모두 결합하고 또한 병행성과 예외처리 기능 등을 추가
  • 너무 복잡해서 컴파일러를 작성하기 어려웠고, 컴파일러는 느리고, 너무 크고, 신뢰할 수 없었음
  • 언어 기능들 사이에 예측할 수 없는 상호작용이 많았기 때문에 배우기에 어려웠고 오류가 발생하기 쉬웠음
  • PL/I의 실패는 좋은 기능을 모두 포함하는 포괄적인 언어가 꼭 좋은 것은 아니라는 것을 보여줌
Simula-67
  • 최초의 객체지향 언어로 모의실험(simulation)을 위해 설계됨
  • 객체와 클래스 개념을 소개함으로써 객체지향 언어의 원조가 됨
BASIC
  • 초기 의도는 단순한 언어였지만 PC로 이전되어 학교, 기업, 가정에서 널리 이용됨
  • 현대적 언어 구조의 결여에도 불구하고, 단순성 때문에 교육용 언어 그리고 개인용 컴퓨터 응용을 위한 언어로 사용됨
  • 이후 마이크로소프트사에 의해 Visual Basic 형태로 발전
  • 시각적인 개발 환경과 더불어 BASIC 언어의 연장선상에 있어 초보자가 접근하기 쉬운 장점들을 가짐

 

3) 1970년대: 단순성 및 새로운 언어의 추구

PASCAL
  • 교육용 언어로 Algol의 아이디어를 작고, 단순하고, 효율적이고, 구조화된 언어로 세련되게 만듦
  • 분리 컴파일, 적절한 문자스트링 처리, 확장가능한 입출력 능력 같은 기능의 결여에도 불구하고 실제적으로 응용에서 호응을 얻음
  • 대표적인 블록 구조 언어
C언어
  • 유닉스 운영체제 개발을 위해 개발된 시스템 프로그래밍 언어
  • 언어를 정확히 기술하기 위해 엄격한 정의를 가진 새로운 표기법을 개발했으나 표기법이 난해하고 실용적으로 보급되지 못했음
  • 또한 언어가 복잡하고 방대한 사양을 요구하면서 컴파일러 구현이 어려웠고 결과적으로 널리 사용되지 못함
Prolog
  • 논리식을 토대로 하여 개체 간의 관계에 관한 문제를 해결하기 위해 주로 사용
  • p→q 형태의 술어 논리를 사용하는 대표적인 논리 프로그래밍 언어
  • 증명하는 것을 계산하는 것으로 간주
  • 프로그램 자체는 사실(fact)과 논리 규칙(logical rule) 형태로 만들고, 그 프로그램을 실행하는 처리기가 증명기가 됨
  • 인공지능, 자연어 처리 등의 분야에서 많이 사용
Scheme
  • 다른 버전보다 더 형식적이고 람다 계산에 더 가깝게 설계된 향상된 LISP 버전
ML
  • Pascal과 가까운 구문, 유사한 타입 검사 메커니즘. 즉, 다형 타입 검사 메커니즘을 제공하는 함수형 언어
  • 유연하다는 점에서 이전의 함수형 언어와 다른 특징을 가짐

 

4) 1980년대: 추상 자료형과 객체 지향

Ada
  • 미 국방성(DoD)의 후원으로 개발된 영향력 있고 포괄적인 언어
  • 주요 기능: 패키지(추상 자료형), 태스크(병행 프로그래밍 기능), 예외 처리 등과 같은 새로운 기능을 포함
Modula
  • 범용 절차형 언어이면서 시스템 프로그래밍 언어로 개발
  • Pascal처럼 가능한 자고 단순한 언어로 개발
  • 주요 기능: 모듈(추상 자료형), 코루틴(부분적인 병행성)
Smalltalk
  • 일괄적인 방법으로 객체지향 접근 방법을 적용하기 위해 설계됨
  • 순수한 객체지향 언어
  • Ruby, Objective-C, Java, Python, Scala 등의 언어에 많은 영향을 줌
  • 최초로 GUI를 제공하는 언어였으며, 매킨토시의 그래픽 사용자 인터페이스에도 영향을 줌
C++
  • C언어를 확장함 특히 C언어의 구조체를 클래스 형태로 확장
  • C언어의 효율성을 유지하면서도 객체지향 프로그래밍 가능
  • 포인터와 같은 C 언어의 중요한 특징을 그대로 포함하고 있음

 

5) 1990년대: 인터넷 언어와 새로운 시도

Python
  • 대화형 인터프리터 방식의 프로그래밍 언어
  • 플랫폼 독립성, 객체 지향, 동적 타입(dynamic type)
  • 실사용률과 생산성도 높은 강력한 언어로 접근성과 응용력이 좋음
  • 교육용 및 빅데이터를 비롯한 다양한 분야에서 응용되고 있음
Java
  • 인터넷 환경을 위한 객체지향 언어
  • 웹 애플리켕션, 모바일 앱 개발 등에 가장 많이 사용하는 언어
  • 플랫폼 독립성: 컴파일 된 바이트 코드가 JVM이 설치된 어느 플랫폼에서도 실행 가능
JavaScript
  • 객체 기반의 스크립트 프로그래밍 언어로 개발
  • 웹 브라우저 내에서 실행되는 클라이언트 프로그램에 주로 사용
  • Node.js와 같은 런타임 환경과 같이 서버 프로그래밍에도 사용

 

6) 2000년대: 새로운 미래를 향하여 

C#
  • Java를 모방한 마이크로소프트 버전
  • 닷넷 프레임워크를 기반으로 함
  • 가상머신 사용으로 C/C++보다 느림
Scala
  • 객체지향(ex.자바)과 함수형 언어의 요소가 결합된 다중패러다임 언어
  • 자바 바이트코드를 사용하기 때문에 JVM에서 실행 가능
  • Java 언어와 호환: 대부분의 자바 API를 그대로 사용 가능
Objective-C와
Swift
  • Swift는 기존의 Mac용 언어인 Objective-C와 함께 공존
  • Objective-C처럼 LLVM으로 빌드되고 같은 런타임 시스템을 공유
  • 특징: 클로저, 다중 리턴 타입, 네임스페이스, 제네릭, 타입 유추
  • 코드 내부에서 C나 Objective-C 코드를 섞어서 프로그래밍하거나 스크립트 언어처럼 실시간으로 상호작용하며 프로그래밍 할 수 있음

 

 

1.4 추상화와 명령형 언어의 발전

1) 프로그래밍 언어 발전 과정

- 최초의 프로그램 저장 방식의 컴퓨터 ENIAC가 만들어지면서 프로그래밍 언어가 개발되기 시작함

- 이때 만들어진 컴퓨터는 폰 노이만(Von Neuman) 모델 컴퓨터이며 초창기 프로그램은 컴퓨터에 명령하는 기계어 명령어들의 집합이었음

- 프로그램 저장 방식의 범용 컴퓨터의 등장으로 프로그래밍은 중요한 문제가 됨

  • 초기의 프로그램은 기계어로 작성하였는데 이후 이것은 기계어를 표현하는 기호화 코드를 사용하는 어셈블리어로 발전
  • 하지만 어셈블리어 역시 기계에 매우 의존적이었으며, 구문 역시 자연어와 동떨어져 있었음 → 저급(low-level) 언어

 

2) 폰 노이만 모델 컴퓨터

- 프로그램 내장 방식 컴퓨터: stored-program computer

- 프로그램은 명령어와 데이터로 구성되며 작성된 프로그램은 실행을 위해 먼저 주 메모리에 적재되어야 함

- 메모리에 저장된 명령어 순차 실행

  • CPU는 순차적으로 메모리에 저장된 명령어를 실행함
  • PC: 다음 실행할 명령어를 가리키는 레지스터

- 명령어: 메모리에 저장된 값을 조작 혹은 연산

폰 노이만 모델 컴퓨터 구조

- 인출-해석-실행(fetch-decode-execute) wnrl

  • CPU는 주 메모리 내에 저장되어 있는 프로그램의 명령어를 한 번에 하나씩 읽어 들여 해석하고 실행함

인출-해석-실행 주기

 

3) 명령형 언어(Imperative language)

- 명령형 프로그래밍 언어는 폰 노이만 모델 컴퓨터의 연산을 흉내 내거나 추상화하는 것으로부터 시작되었음

- 예: Fortran, C, Basic

- 폰 노이만 모델 컴퓨터의 특징을 많이 가지고 있음

  • 순차적 명령어 실행
  • 메모리 위치를 나타내는 변수 사용
  • 대입문을 사용한 변수 값 변경
  • 사람의 필요보다는 컴퓨터 모델을 기반으로 한 언어

4) 추상화(Abstraction)

- 추상화는 실제적이고 구체적인 개념들을 요약하여 보다 높은 수준의 개념을 유도하는 과정

- 명령형 언어는 컴퓨터의 데이터, 연산, 명령어 등을 추상화

- 무엇을 요약하여 추상화하느냐에 따라 데이터 추상화와 명령어 추상화가 있음

- 데이터 추상화(Data Abstraction)

  • 데이터 추상화는 저수준의 데이터나 자료형들을 요약하고 추상화하여 보다 고차원의 새로운 자료형 또는 자료구조를 만드는 과정을 의미
  • 기본 추상화: 기본적인 데이터와 관련된 간단한 추상화 ex) 변수, 자료형
  • 변수: 데이터 값을 저장하는 메모리 위치 ex) 메모리 120 번지를 추상화하여 변수 x라고 할 수 있음
  • 자료형: 값들의 종류에 대한 이름 ex) int, float, double
  • 복잡하고 구조적: 관련된 여러 값이나 변수들의 모음을 요약하여 추상화 ex) 배열, 레코드
  • 프로그래밍 언어는 이러한 추상화된 개념을 제공하고 프로그래머는 이러한 개념을 기반으로 프로그래밍함

- 제어 추상화(Control abstraction)

  • 제어: 프로그램 내의 명령어의 실행 순서를 의미함. 따라서 제어는 명령어 실행 순서를 제어한다는 것을 의미
  • 제어 추상화는 실행 흐름을 나타내는 저수준 명령어들을 요약하고 추상화하여 보다 높은 수준의 제어구조를 만드는 과정
  • 기본 추상화: 몇 개의 기계어 명령어들을 하나의 문장으로 요약 ex) 대입문, goto문(jump 명령어의 요약)

기본 추상화

  • 구조적 제어 추상화: 테스트 내의 중첩된 기계어 명령어들을 하나의 문장으로 요약 ex) if, switch, for, while 문

구조적 제어 추상화

- 프로시저(함수, 메소드) 추상화

  • 선언: 일련의 계산 과정을 하나의 이름으로 요약해서 정의
  • 호출: 이름과 실 매개변수를 이용하여 호출

프로시저 추상화

A부터 실행을 시작하여 GOTO B를 만나면 B이하 부분을 실행하고 다시 되돌아옴

레이블 B 이하의 일련의 계산 과정을 하나의 이름으로 요약해서 정의하는 것이 함수 혹은 프로시저 정의라고 함

GOTO B: 함수 호출

GOTO C: 함수로부터의 리턴

- 제어 추상화의 장점

  • 기계에 대한 추상화된 관점 혹은 개념을 제공하므로 이러한 개념을 이용하면 보다 쉽게 프로그래밍할 수 있음
  • 다른 제어 관련 문장들과 쉽게 중첩되어 사용될 수 있게 해 주므로 이러한 추상화된 개념을 이용하면 보다 복잡한 프로그램을 쉽게 작성할 수 있음
  • 특히 프로시저 추상화는 크고 복잡한 프로그램을 쉽게 작성할 수 있는 여러 개의 프로시저로 구분하여 작성하게 함으로써 프로그래밍의 복잡도를 줄일 수 있음

 

5) 추상 자료형(Abstract Data Type)

- 데이터 추상화와 제어 추상화를 통합해 만든 자료형

- 데이터와 관련된 연산들을 캡슐화하여 정의한 자료형 ex) 스택 자료형(스택을 표현하기 위한 자료구조와 push, pop 등과 같은 연산들을 한데 묶어 추상 자료형으로 정의)

- Modual-2의 모듈, Ada의 패키지, C++, Java 등이 클래스에서 사용

추상 자료형

 

 

1.5 프로그래밍 언어의 정의 및 구현

1) 프로그래밍 언어의 정의 방법

- 어휘 구조(lexial structure)

  • 언어에서 사용하는 단어의 구조, 철자법 등을 의미

- 구문법(syntax)

  • 구성요소를 이용하여 문장/프로그램을 구성하는 방법
  • 문법을 이용하여 기술할 수 있음
  • Context-free grammar in BNF(Backus-Naur Form)

- 의미론(semantics)

  • 문장/프로그램의 의미를 정하는 것
  • 자연어 혹은 수학적으로 기술

 

2) 프로그래밍 언어 구현

- 인터프리터

  • 소스 프로그램을 입력받아 구문법에 맞게 작성되었는지 검사하고 그 의미를 파악하여 의미에 맞게 동작하도록 해석함
  • 프로그램 내의 문장을 해석할 때 입력 혹은 출력 문을 만나면 사용자로부터 입력을 받거나 사용자에게 출력함

인터프리터

- 컴파일러

  • 소스 프로그램을 입력받아 구문법에 맞게 작성되었는지 검사하고 그 의미를 파악하여 의미에 맞게 동작하도록 기계어 명령어들로 번역
  • 기계어 프로그램을 목적 프로그램(target program)이라고 하며 이 프로그램이 실행됨
  • 프로그램 실행 중에 입력 혹은 출력 문을 만나면 사용자로부터 입력을 받거나 사용자에게 출력함

컴파일러

 

- 구문 분석(syntax analyzer or parser): 컴파일러나 인터프리터가 소스 프로그램을 입력받아 그 프로그램이 구문법에 맞게 작성되어 있는지 검사하는 것

- 어휘 분석(lexical analyzer or scanner): 구문 분석에 앞서 소스 프로그램을 토큰이라는 의미 있는 어휘 단위로 분리하는 것

- 의미 분석(semantic analyzer): 구문 분석 이후 변수 중복 선언 검사, 타입 검사 등을 통해 의미에 맞게 사용되고 있는지 검사

- 의미에 따라 컴파일러는 코드를 생성하고 인터프리터는 해석하여 실행함

컴파일러와 인터프리터의 내부 구조

소스 프로그램을 입력으로 받아 어휘 분석, 구문 분석, 그리고 의미 분석을 수행하고

컴파일러는 목적 코드를 생성하고 인터프리터는 해석하여 실행함

profile

Fascination

@euna-319

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!