프로그래밍언어 개발 역사 및 평가 기준

k_bell·2024년 9월 4일

프로그래밍언어론

목록 보기
1/8
post-thumbnail

프로그래밍 언어의 개발

  • Scientific Applications
    : Fotran

    포트란은 과학적 계산을 효율적으로 하기 위해 개발된 최초의 고급 프로그래밍 언어이다. 1957년 IBM에서 개발되었으며 최초로 컴파일러를 통해 High level language에서 기계어로의 변환을 구현했다. 특이점으로는 큰 수의 계산을 위해 floating point (부동 소수점)을 사용했다는 것인데, 당시에는 floating point를 통해서 모든 수를 정확히 표현하는 것이 불가능하였기 때문에 비즈니스 분야 등에서는 사용되지 못하였다. (돈이 관련된 분야이기 때문에 정확한 계산이 필요할 수밖에 없다.)

  • Business Applications
    : COBOL

    코볼은 1959년에 비즈니스 데이터 처리에 중점을 두고 개발된 언어이다. 포트란과는 다르게 decimal number를 사용하였으며, 이 덕분에 매우 정확한 수의 표현과 계산이 가능했다.

  • Artifical Intelligence
    : LISP

    LISP (LISt Processing)은 1958년에 AI 연구를 위해 개발된 함수형 프로그래밍 언어이다. LISP는 AI 연구에서 리스트 처리가 중요한 역할을 했기 때문에 개발되었으며, 포트란에 함께 가장 오래된 프로그래밍 언어이자 AI 분야에서 거의 표준적으로 사용되며, 후대 언어에 매우 많은 영향을 미치게 되었다.

  • Systems Programming
    : C

    C 언어는 매우 효율적인 성능을 보여주었고, 운영체제나 임베디드 등을 개발하거나 시스템 프로그래밍에서 널리 사용되었다. 어셈블리어와 거의 비슷한 성능을 보여주며, 이것이 고성능 언어들이 판치는 요즘에도 C를 사용하는 분야가 존재하는 가장 큰 이유이다. C 언어의 정신 첫번째가 바로 "프로그래머를 믿어라"인데, 이것의 오늘날의 다른 언어들과의 가장 큰 차이점이다. 요즘의 고생산성 언어들은 프로그래머를 믿지 못해 퍼포먼스 희생을 감수하고서라도 문제가 생길만한 부분들을 컴파일러 혹은 가상머신에서 처리하도록 한다. 따라서 C 언어는 기본적으로 지원되는 기능과 문법이 매우 적다. 이것이 C를 배우기 어려운 이유이기도 하지만, C의 개발 정신과 C가 널리 사용되는 분야를 본다면 C는 자신의 목적에 맞게 완벽히 개발된 프로그래밍 언어라고 볼 수도 있을 것이다.

Language evaluation criteria

  • Readability
    : 코드를 얼마나 쉽게 읽고 이해할 수 있는지?

  • Writablity
    : 얼마나 작성이 쉬운지?

  • Reliablity
    : 언어를 얼마나 신뢰할 수 있는지?

  • Cost
    : 얼마만큼의 비용이 드는지 (컴파일러 등의 개발 및 배포 비용)

Readability

  • Overall simplicity
    : 언어의 규모가 너무 방대해지면 해당 언어가 제공하는 기능의 일부만을 사용하여 코드를 작성하고 개발할 수 있다. 이렇게 되면 하나의 문제가 발생하게 된다. 예를 들어 A가 B 개발자의 코드를 참조하려고 할 때, A는 B가 작성한 코드의 일부분 밖에 이해하지 못하는 상황이 발생할 수도 있다는 것이다.

또한 operator 의 오버로딩은 최소화하는 것이 좋다. 예를 들어 C 언어에서 *은 곱셈을 의미하는 연산자 이기도 하지만 포인터를 의미하기도 한다. 따라서 컴파일러 입장에서는 *B 가 포인터를 의미하는 것인지, 혹은 개발자가 곱셈 연산인데 실수하여 앞에 인자를 작성하지 않은 것인지 판단하기 어렵다는 것이다.

  • Orthogonality
    : orthogonality는 직교성이라는 의미인데, 프로그래밍 언어에서 직교성이란 특성들이 다른 특성과 관계가 없으며 (독립적), 특성들을 조합하여 새로운 특성을 만들어 낼 수 있음을 의미한다. 즉, 언어의 제어구조와 데이터 구조 생성을 위해 적은 수의 기본 구조 (특성)을 조합할 수 있다. 따라서 일반적인 언어 디자인의 목표는 다른 언어들의 여러 특징을 최대한 orthogonal 하게 만들고자 하는 것이다. 좋은 예시의 언어로는 LISP이 있다.

  • Control statements
    : 예를 들어 while, for, recursion를 모두 사용할 수 없는 언어가 있다고 할 때, 우리는 제어문을 사용하고 싶다면 goto를 사용해야 할 것이다. 알다시피 goto는 그렇게 좋은 문법이 아니다. (goto를 사용하면 코드의 특정 부분으로 건너 뛰거나 되돌아 갈 수 있다.) c에서 여러 개의 for문을 깨고 나오고 싶을 때, goto를 사용하면 효과적이지만 그 외의 경우에서 goto를 계속 사용한다면 내가 작성한 코드를 다음날 이해하지 못하는 상황이 발생할 것이다.

  • Data types and structures
    : C에는 boolean 타입이 없다. 따라서 0은 false, 그 이외의 모든 실수는 true로 간주한다. 따라서 c에서 bool을 사용하고 싶다면 아래와 같이 대충 흉내내는 수밖에 없다.

// 방법 1
typedef enum { false, true } bool;

// 방법 2
typedef char bool;
#define FALSE (0)
#define TRUE (1)

또한 c의 경우에는 새로운 데이터 타입을 만들 수 없다. 위에서 계속 c의 단점들을 언급하고 있는데, c는 정말 최소한의 기능으로 좋은 성능을 보여주는 언어이기 때문에 readability 면에서는 안 좋은 언어가 맞다.

  • Syntax considerations
    : 언어는 좋은 가독성을 위해 문법적으로 일관성을 유지해야 한다. 예를 들어 fortran은 데이터 타입을 변수명으로 지정할 수 있는데, 이런 것은 당연히 실제 코드 작성 시에는 지양해야 하는 부분이다. 또한 c에서는 static이 두 가지 의미를 가지고 있는데, 지역 변수 앞에 static이 붙으면 해당 변수는 원래 값을 끝까지 보존한다는 의미이다. 하지만 함수 앞에 static이 붙는다면 해당 함수는 해당 파일에서만 유의미하다는 것이다. 이처럼 문법적으로 일관적이거나 적합하지 못한 부분이 많을 수록 개발자가 코드를 이해하는데 어려움이 많을 것이다.

    c는 여러 개의 소스코드 파일을 가질 수 있는데, 이때 여러 개발자가 함께 개발하는 경우 동일한 이름의 함수가 서로 다른 소스코드 파일에 존재할 수 있기 때문이다.

Writeability

  • Simplicity and Orthogonality
    : readability에 영향을 미치는 요소들은 모두 마찬가지로 writeability에도 영향을 미친다. 따라서 언어의 문법이 간결하면서도 직교성을 가져야 프로그래머가 더 쉽게 코드를 작성할 수 있다. 하지만 직교성이 너무 과할 경우에는 오히려 writeability가 떨어질 수 있다. 각각의 특성들이 작은 단위로 너무 나뉘어져 있다면, 더욱 복잡할 수 있기 때문이다.

  • Support for Abstraction
    : 추상화는 당연하게도 writeability에 영향을 미친다. 최근의 언어들은 process와 data 모두 abstraction이 가능한데, 코드의 중복과 재사용을 방지함으로써 코드의 간결성을 높이고 구조를 효과적으로 할 수 있다.

  • Expressivity
    : 간단하게 설명하자면 표현할 수 있는 다양한 구문들이 존재하면 더욱 좋다는 것이다. 예를 들어, for 문은 while 문으로 대체할 수 있고, swith 문은 if - else 문으로 대체할 수 있다. 하지만 for 문은 for 문만의 장점이 있고, swith는 switch만의 장점이 있다. 따라서 이처럼 다양한 표현 구문들이 있는 것은 매우 중요하다.

Reliability

  • Type Checking
    : 데이터 타입을 체킹하는 것은 신뢰성에 매우 많은 영향을 미친다. 데이터 타입이 맞지 않는 경우 프로그램이 정상적으로 실행되지 않을 수 있기 때문이다. 따라서 타입 체킹은 가능한 컴파일 시간에 이루어지는 것이 좋다. 런타임 때 타입 체크가 된다면 예외가 발생할 수도 있기 때문이다. 물론 파이썬과 같이 동적으로 타입이 할당되는 경우에는 컴파일러가 타입을 체크할 수 없지만, 이런 예외를 제외한다면 컴파일러가 자동으로 타입을 체크해 줄 수 있어야 한다.

  • Exception Handling
    : 예외 처리 또한 굉장히 중요한 부분이다. 프로그램이 예외가 발생했을 때 이를 처리하지 못하고 강제로 종료된다는 것은 매우 치명적이기 때문이다.

  • Aliasing
    : aliasing은 별칭이라는 의미인데 c 에서 pass of reference를 생각하면 이해하기 쉬울 것이다. 아래 코드와 같이 &b를 생성하고 b를 a의 alias로 할당한다면 이후 a의 값의 관리가 어려워질 것이다. 물론 pass by refernce 자체가 나쁜 것은 아니지만 aliasing이 과도하게 사용된다면 코드의 가독성 뿐만 아니라 결과에 대한 신뢰성도 떨어질 것이다.

int a, &b;
a = 2;
b = a;
b++;
// a = ?

Cost

cost에서는 크게 어렵거나 중요한 부분이 없어서 간단하게 한 문장으로 설명하겠다.

  • Training programmers to use language

  • Compiling programs (Hifh cost of runnung the Ada compiler in 80s)

  • Executing programs (optimization)
    : cpu의 성능이 빨라도 결국에 메모리에 접근하는 시간은 느릴 수 밖에 없기 때문에 병목 현상이 일어난다. 따라서 메모리 접근을 최소화 하는 것이 필요하다.

  • Reliability (poor reliability leads to high costs)

  • Maintaning programs (poor readabilty increase cost to maintenance)

Others

  • Portability
    : 여러 운영체제에서 돌아갈 수 있는가? (자바와 파이썬이 좋은 예시)

  • Generality
    : 여러 분야에서 사용될 수 있는 언어인가?

0개의 댓글