* 프로그램 언어의 발전
1. 컴퓨터 시스템의 발전
- 아이디어 : 튜링기계 : 계산 자동화를 위한 상상 속의 기계 설계
- 전자식 컴퓨터 : 에니악, 콜로서스 : 전자 신호를 통한 계산기계
- 프로그램 저장 방식 컴퓨터 : 에드박 : 프로그램과 처리기를 분리
2. 운영체제의 발전
1) 일괄처리 운영체제 : 관리자(operator)를 대신할 프로그램 등장
2) 시분할 운영체제 : 한 컴퓨터를 여러 사람이 사용
ㄴ 마치 컴퓨터에서 여러 프로그램이 동시에 진행되는 것 처럼 보이게 한 것
ex) 1초 동안은 A라는 프로그램, 그 다음 1초는 B프로그램, 그 다음 1초는 C 프로그램을 동작, 그 다음 1초는 A프로그램...
이런식으로 나눠서 처리.
3) DOS : IBM 컴퓨터, Apple 등 개인용 컴퓨터(PC)의 등장
ㄴ 이전까지는 서버 컴퓨터가 있어서 커다란 서버에 여러 사용자들이 붙어서 조금씩 컴퓨터를 나눠서 사용하는 형태였음
ㄴ 이제는 개인용 컴퓨터가 등장함.
ㄴ 즉, 사용자가 오롯이 혼자서 컴퓨터를 다 사용할 수 있게됨.
4) PC 환경 운영체제 발전 : GUI 운영체제와 Linux의 발전
3. 프로그래밍 언어의 발전
1) 1950년대 : 초기 프로그래밍 언어
(1) Fortran : 수식과 문장, 제어문의 등장.
- IBM의 존 배커스에 의해 개발됨
- 과학계산용 언어
(2) Algol : 구조화 프로그래밍의 발전
- 본래 이름 : IAL (International Algebraic Language)
- 국제 위원회 ACM-GAMM을 통해 설계된 언어
- 알고리즘 기술 언어
(3) LISP : 초기 함수형 언어
- MIT의 존 매카시가 설계함
- 최초의 함수형 언어
2) 1960년대 : 프로그래밍 언어의 발전
(1) Cobol : 레코드 타입의 소개
- 미 해군에서 그레이스 호퍼가 이끄는 팀에 의해 개발됨
- 사무용 언어
(2) PL/I : 너무 복잡.
- 모든 언어를 합쳐 보았으나 결과적으로 너무 복잡해짐.
(3) BASIC : 교육용 언어.
- Beginner's All-purpose Symbolic Instruction Code
(4) Simula : 객체지향의 등장
- 시뮬레이션 언어.
3) 1970년대 : 프로그래밍 언어의 단순화.
(1) Pascal : 차세대 교육용 언어.
- 구조화 프로그래밍 지원.
(2) C : 진정한 시스템 프로그래밍 언어.
- Unix 개발용 시스템 프로그래밍 언어.
- Objective-C, C++, Java, C# 등 다양한 언어에 지대한 영향을 끼침.
(3) Prolog : 선언적 논리 언어.
- 최초의 논리 언어
(4) Smalltalk : 객체지향 언어의 발전
- 최초의 GUI, 마우스 등을 도입
(5) Ada : 안전성을 위한 대장정
- 미 국방성(DoD) 공모
- 매우 복잡한 언어로 1983년에 첫 컴파일러 등장
(6) ML : 타입 시스템을 갖춘 현대 프로그래밍 언어
- 강력한 정적 타입 검사, 타입 추론, 패턴 검사, 예외처리 등
(7) Scheme : 간결한 LISP
- MIT 학생들의 기초 프로그래밍 언어
4) 1980년대 : 현대 프로그래밍 언어 등장
(1) Common Lisp : 방대한 LISP의 통합
- 함수형 언어 패러다임과 객체지향 패러다임을 동시에 지원
(2) Objective-C : C의 탈을 쓴 Smalltalk
- C를 기초로 한 객체지향 언어의 신호탄
- Apple의 애플리케이션 작성 언어로 발전
(3) C++ : 객체지향으로 변신한 C
- 클래스 개념을 C에 도입
(4) Perl : 문자열 처리를 위한 언어
- 정규식을 바탕으로 한 강력한 패턴 매칭 기능 포함
5) 1990년대 이후 : 프로그래밍 언어의 대중화
(1) Java : 단순한 객체지향 언어
- 원래 목적은 임베디드 컴퓨팅 분야였으나 웹 브라우저에 탑재되면서 인기
- JVM (Java Virtual Machine)
ㄴ 웹 브라우저 안에서 JVM이라고 하는 것을 지원하게 되면, 이걸 통해서 웹 브라우저상에서 Java로 짠 프로그램이 동작하게됨.
ㄴ 자바 애플릿(자바로 짠 프로그램을 컴파일 시키면 중간 코드 형태로등장하게 됨).
이 자바 애플릿을 웹브라우저에 넣어주면 사용자 쪽에 넘어가서 동작함.
(2) JavaScript : 웹 프로그래밍 언어
- Netscape
- Elm, TypeScript 등 다양한 변종 언어로 발전
- 스크립트 언어 --> 자바보다 좀 더 가볍게, 쉽게 웹상에서 동작 가능.
(3) Python : 빠른 프로토타이핑 언어
- 스크립트 언어
- 동적 언어를 추구
- 다중 패러다임 언어
(4) Haskell : 순수 함수형 언어
- 모나드(monad)가 탑재되면서 점차 인기
- Scala에 영향을 줌
* 프로그램 동작 원리
1. 컴퓨터 구조
- CPU와 메모리, 저장장치 등이 BUS로 연결.
- 다양한 입출력 장치도 BUS에 연결될 수 있음.
2. 컴퓨터 동작 원리
- 전원 : 운영체제 적재(저장장치 --> 메모리) --> 수행
- CPU는 인출-해석-실행 주기를 반복하여 메모리의 명령어를 실행.
- 상세설명)
ㄴ 전원을 넣으면, 저장장치에 미리 저장되어 있던 운영체제(OS)가, BUS를 통해서 메모리에 적재가 됨.
전원을 넣으면, 저장장치에 있던 운영체제가 메모리로 적재됨.
적재가 되면, 전원이 켜진 컴퓨터는, 메모리에 적재된 운영체제(OS)가 알아서 그 컴퓨터를 관장하게 됨.
ㄴ 그렇다면 운영체제는 어떻게 동작하는가?
운영체제가 메모리에만 가만히 있으면, 아무 일도 하지 않음
운영체제가 일을 하기 위해서는 CPU가 작업을 해야함.
ㄴ CPU가 하는 일은 인출,해석,실행이라고 하는 기본 단위를 가지고 명령어를 처리함.
1) 인출 : 메모리에 들어있던 운영체제의 특정 명령어 하나를 뽑아서 CPU로 가지고 오는 것.
2) 해석 : CPU로 가져온 명령어를, CPU가 보고서 '아! 뭐를 하라는 명령이구나! 내가 3번 명령을 해야하는구나!'
이런 식으로 해석하게됨.
3) 실행
ㄴ ex) move라는 명령어가 들어왔다 (인출)
--> CPU는 그 move 명령어에 맞춰서 '몇 번지에 있는 값을 다른 레지스터로 값을 옮기면 되는구나.'하고 해석함 (해석)
--> CPU가 이것을 처리하게됨. (실행)
3. 프로그램 동작 원리
- CPU는 인출-해석-실행 주기를 반복하여 메모리에 적재된 프로그램의 명령어를 실행.
4. 프로그래밍 언어 구현이 필요한 이유
1) 기계어
- 기계, 즉 CPU가 이해하고 수행할 수 있는 명령어.
ㄴ 컴퓨터는, 최종적으로는, 기계어로 된 프로그램만 수행할 수 있음.
- 이진수 형태의 명령어를 사람이 이해하는 것은 매우 난해함.
2) 어셈블리어
- 기계어에 거의 1:1 대응하는 형태의 기호 언어
ㄴ 사람이 직접 기계어로 코딩하는 것이 힘들므로, 2진수 명령어들 중에서 명령어 몇 개를 사람이 보기 좋게 기호로 변환한 것.
ex) 기계어로 10001000이라고 하면 사람이 보기 좋게 MOV라는 명령어로 표현해보자.
- CPU에 종속적 --> 이식성이 거의 0
ㄴ 기계어보다는 사람이 이해하기 좋기는 하지만, 여전히 이 명령어 자체는 CPU가 바로 이해할 수 있는 수준의 언어이기 때문에 이 어셈블리어도 역시 CPU에 종속적임.
ㄴ CPU에 종속적이라는 말은, 특별한 A라고 하는 CPU에서만 동작하는 프로그램이라는 말.
즉, 이 어셈블리어는 C라고 하는 다른 회사에서 만들어낸 CPU에서는 동작하지 못함.
회사가 다르고 CPU 종류가 달라지면 그 CPU들이 처리할 수 있는 명령어들이 달라지기 때문에,
A회사의 CPU에 맞춰진 프로그램은 C회사에서 만든 CPU에서는 동작하지 못함.
3) 고급 프로그래밍 언어
- 사람에 가까운 표현으로 프로그램을 나타냄
- 특정 기계에 종속적이지 않음
- 고급 프로그래밍 언어로 작성한 것은, 최종적으로는 CPU(기계)가 알아듣는 기계어로 표현을 바꿔줘야함
ㄴ 소스 프로그램 : 프로그래머가 작성한 프로그램. 보통 고급 언어.
CPU는 소스 프로그램을 바로 실행시킬 수는 없다.
ㄴ 목적 프로그램 : 프로그래머가 작성한 것을 컴파일러가 변환해서, 기계어, 즉 CPU가 알아들을 수 있는 형태로,
즉 컴퓨터 하드웨어가 수행할 수 있는 형태로 바뀐 프로그램.
ㄴ 소스 프로그램 --- 컴파일러 ----> 목적 프로그램
아래의 이미지 참고! :)
ㄴ 인터프리터 : 소스 프로그램을, 명령어 하나하나 직접 그때그때마다 해석하고 실행하고 하게 해주는 것.
5. 프로그래밍 언어의 구현 방법
1) 인터프리터
- 프로그래밍 언어로 작성된 고수준의 명령을 해석하여 수행하는 프로그램
- 인터프리터는 CPU의 인출-해석-실행 주기를 흉내냄.
ㄴ CPU가 기계어 프로그램을 보고 명령어 하나를 가지고 인출,해석,실행하는 것처럼 인터프리터가 활동함.
ㄴ 즉, 인터프리터가 고수준의 소스 프로그램 명령어 하나를 가지고 와서, 그것을 해석해서, 거기서 나오는 실행에 필요한 여러가지 기계어들을 하드웨어에게 던져줌. 그러면 그 순간에 CPU가 그 명령어 몇개를 처리함.
이게 끝나고 나면, 인터프리터가 이제 고수준 언어의 두번째 명령어를 가지고 옴. 이걸 또 인터프리터가 두번째 명령어를 해석해서 기계어 명령어로 변환되고 하드웨어가 처리하는....
ㄴ 매번 고급 언어의 명령어 하나를 가지고 와서 해석하고 실행함.
ㄴ 소스 프로그램을, 명령어 하나하나 직접 그때그때마다 해석하고 실행하고 하게 해주는 것.
2) 컴파일러
- 프로그램을 CPU가 수행할 수 있는 형태로 바꾸어서 CPU가 실행
- 소스 프로그램을 목적 프로그램으로 바꿔줌.
- 인터프리터가 하는 해석 과정을 미리 모두 수행 (효율적)
ㄴ 소스 프로그램을 컴파일러가 최초 한 번에 전체 통 번역을 해서 목적 프로그램(기계어)로 바꿔서 효율적, 빠르게 동작 가능.
ㄴ 즉, 인터프리터는 해석 과정이 실행 시간에 계속 이루어지지만, 컴파일러 방식은 해석까지 미리 다 끝내버렸기 때문에 실제 동작하는 실행 시간에는 실행하는 역할만 해주면 됨. 복잡한 고급 언어를 번역할 필요 X. 따라서 효율적.
- 상용 프로그램은 컴파일 방식으로 번역된 후 판매
ㄴ 일반적으로 우리가 쓰는 프로그램들은 다 컴파일러 방식을 사용함! :)
3) 하이브리드 구현
- 인터프리터 방식과 컴파일러 방식을 조합한 방식.
- 중간코드까지 컴파일한 후 인터프리터를 통해 해석
ㄴ 소스 프로그램을, 최종 목적지인 기계어까지 해석하는게 아니라, 중간 코드까지 컴파일한 후 인터프리터를 통해서 해석함.
ㄴ 컴파일러 방식으로 일단 기본적으로 많은 해석을 해두긴함. 일단은 기본적으로 변환을 하기 때문에, 고급 언어를 직접 인터프리터로 돌리는 것보다 효율적이긴함. 근데 왜 이렇게 했느냐? 이 중간 코드라고 하는 것은 하드웨어와 무관하게 만들어낼 수 있다. 그래서 인터프리터에 적합한 코드 형태로 바꾸기 때문에, 특정 A회사의 CPU, B회사의 CPU가 아닌, 이 인터프리터가 해석할 수 있는 그 특별한 중간코드로 만들어졌기 때문에, A라는 CPU에 가서도 이 인터프리터만 있으면 바로 이 프로그램 중간 코드를 실행할 수 있고, C라는 CPU를 쓰더라도 역시 이 동일한 인터프리터만 있으면 이 중간코드를 가지고 역시 C라는 CPU에서도 동작시킬 수 있다.
- 이 인터프리터를 가상기계(VM)라고 부름.
ex) Java : 하이브리드 방식으로 구현된 언어.
ㄴ 최초에 컴파일을 하고 나면 중간 코드, '바이트 코드'라고 부르는 프로그램이 됨.
그러면 어디든지간에 JVM만 있으면, 한 번 컴팡링르 시켰던 그 자바 프로그램(바이트 코드)를 던져만 주면 어느곳에서든 다 실행이 되더라.
- 유연성을 늘리면서도 (초반에 한 번 번역을 했기 때문에) 실행 효율성을 높인 것.
6. 프로그래밍 언어의 요구사항
1) 표현 풍부성(expressiveness) : 프로그래머의 아이디어를 표현할 수 있어야 함
2) 유지 보수성(maintainability): 변화에 쉽게 대처할 수 있어야함
3) 실행 가능성(executability) : 컴퓨터에서 실행할 수 있어야 함
7. 프로그래밍 언어의 설계 원칙
1) 규칙성(regularity) : 언어의 기능이 잘 조합될 수 있어야함
ㄴ 일반성, 직교성, 일관성
2) 추상화 지원(support of abstraction)
: 실세계의 대상을 추상화하여 나타낼 수 있고, 이를 대상으로 어떤 연산을 수행할 수 있어야함
ㄴ 데이터 추상화, 제어 추상화, 추상 데이터 타입 정의
3) 복잡도 제어(complexity control) : 복잡한 대상 및 처리 방법을 제어할 수 있어야함
ㄴ 캡슐화, 모듈화
8. 프로그래밍 언어의 평가 기준
1) 작성력 : 프로그램 수식이나 문장, 기능을 쉽게 표현할 수 있는가
2) 가독성 : 작성된 프로그램을 보고 쉽게 이해할 수 있도록 하는가
3) 신뢰성 : 작성된 프로그램이 오류에 빠지는 가능성을 줄이는가
4) 직교성 : 언어 기능이 서로 간섭하지 않고 자유롭게 조합될 수 있는가
5) 일관성 : 유사한 기능을 같은 형태로 나타낼 수 있는가
6) 확장성 : 사용자가 원하는 새로운 기능을 추가할 수 있는가
7) 효율성 : 작성도니 프로그램이 효율적으로 수행될 수 있도록 하는가
8) 유연성 : 프로그래머가 표현하고 싶은 내용을 유연하게 수용하는가
9) 이식성 : 프로그램을 다른 실행 환경으로 이전할 수 있는가
'Programming > Computer Science Fundamentals' 카테고리의 다른 글
[빅데이터의 이해] 3. 빅데이터의 활용1 (0) | 2021.09.09 |
---|---|
[빅데이터의 이해] 2. 빅데이터의 정의2 (0) | 2021.09.09 |
[빅데이터의 이해] 1. 빅데이터의 정의 1 (0) | 2021.09.09 |
[프로그래밍 언어론] 4. 구문론과 의미론 (0) | 2021.09.09 |
[프로그래밍 언어론] 3. 프로그래밍 언어 패러다임 (0) | 2021.09.09 |
[프로그래밍 언어론] 1. 프로그래밍 언어 소개 (0) | 2021.09.07 |
[운영체제] 운영체제의 구성, 프로세스, 쓰레드 (0) | 2021.04.08 |
[데이터베이스시스템] ER모델 (2장. 데이터베이스 모델링) (2) | 2021.04.01 |