프로그래밍 언어란

주력 언어가 무엇이냐에 대한 질문을 많이 받았다. 사실 이 질문에 대해서 자신이 없었다. 무엇을 만들 때에는 파이썬이 좋았는데 나는 파이썬이 내부적으로 어떻게 돌아가는지, 어떤 특징을 가지고 있는지, 다른 언어와 어떤 점이 다른지 등에 대해서 깊게 알지 못했다. 어떻게 보면 프로그래밍 언어에 대한 이해가 부족한 것 같았다. 그래서 오늘은 프로그래밍 언어란 무엇이며, 어떻게 돌아가는지, 어떤 것들이 있는지 등등에 대해서 간단하게 정리할 것이며, 다음 글에서는 주력언어를 python이라고 하려면 어느 정도는 알고있어야 할까에 대해 정리할 예정이다. 이번 글의 내용은 나무위키 - 프로그래밍언어를 많이 참조하였다.

프로그래밍 언어

컴퓨터는 전자 기계장치이다. 전기신호로 모든 것을 표현한다. 전기신호를 동작시키기 위해서는 제어신호를 작성해야 한다. 초기에는 사람이 제어신호를 직접 작성한 기계어가 사용되었다. 그러나 사람이 알아보기 어려워 기계어와와 특정 기호를 매핑한 어셈블리어가 탄생했다. 시간이 흘러 컴퓨터가 보편화되면서 더욱 생산성이 향상된 C, Java 등의 프로그래밍 언어들이 생겨났다.
프로그래밍 언어는 해석방식, 메모리 관리 방식, 정적/동적 타입, 패러타임에 의해 분류할 수 있다.

해석 방식에 따른 분류

해석 방식에 따른 분류는 언어의 분류라기 보다는 언어 Implementation(구현체)의 분류이다. 구현 방식에 따른 분류라는 말도 맞을 것 같다. 그런데, 꽤나 추상적인 개념인 ‘구현체’라는 것은 무엇일까?

Implementation, 구현체

스택오버플로우에 나와 같은 질문이 있는데 확인해볼만하다. 정리하면, 특정 프로그래밍 언어로 작성한 파일은 컴퓨터에게는 그냥 텍스트다. 이것이 프로그램이 되려면, 특정 프로그래밍 언어 규약에 맞추어 작성된 파일을 컴퓨터가 이해할 언어(=기계어)로 바꿀 무언가가 필요하다. 이 과정(특정 프로그래밍 언어 -> 기계어)을 interpret 또는 compile이라 한다. implementation은 interpret하거나 compile하는 두 과정을 의미하는 것이다. 구현체에 대한 이해를 바탕으로 프로그래밍언어를 구현 방식에 따라 분류하면 다음과 같다.

Compile vs Interpret Compile은 전체 소스코드를 컴퓨터가 바로 실행 가능한 기계어로 번역하는 것이다.
Interpret은 소스코드를 한 줄 한 줄 읽어 Intermediate code로 번역한 후 이 중간 코드를 다시 어떤 프로그램에 의해 실행하여 기계가 읽을 수 있는 기계어로 번역한다.

1. AOT(Ahead-Of-Time) 컴파일 언어

C, Pascal, Haskell 등. 소스코드를 미리 기계어로 번역해서 실행한다.

2. JIT(Just-In-Time) 컴파일 언어

대부분의 고급 언어들이 속한다. Java 및 JVM 언어, Javascript 및 WebAssembly, C# 및 CLR언어, Python, Ruby, PHP 등의 언어들은 모두 기본 구현체가 JIT 컴파일러이다. 대부분 바이트코드를 생성하는 1차 컴파일러, 1차컴파일러가 생성한 바이트코드를 실행하는 VM으로 이루어져 있다. VM 내에는 바이트코드에 대한 인터프리터, 바이트코드를 기계어로 컴파일하는 JIT 컴파일러와 GC를 비롯한 런타임이 포함된다.

3. 인터프리터 언어

소스코드를 한 줄 한 줄 읽어 번역해서 수행한다. bash, BASIC과 같은 언어.

메모리 관리 방식에 따른 분류

1. 관리언어(Managed Language)

동적 할당된 메모리의 라이프사이클이 GC(Garbage Collector)에 의해 자동으로 이루어진다. 개발자가 객체를 소멸시키는 것이 아니라, GC가 객체를 소멸시킨다. Java, C#, Python, Go 등이 속한다. 메모리 관리를 언어 차원에서 책임져 주기 때문에 생산성은 높으나, 성능 면에서 직접적인 제어가 불가능하다.

2. 비관리언어(Unmanaged Language)

(주로 포인터를 이용하여) 메모리에 직접 접근이 가능하다. 동적할당된 메모리의 해제를 수동으로 해야한다. C, C++ 등이 속한다.

정적 타입, 동적 타입에 따른 분류

1. 정적 타입 언어

자료형(Type)이 고정되어 있는 언어이다. 자료형을 바꾸기 위해서는 명시적인 형 변환(Type casting)을 해야 한다. C, C++, Java, C# 등이 속한다. 강하고 안정적이기에 일상적 프로그래밍 오류를 미연에 방지한다.

2. 동적 타입 언어

자료형이 상황에 따라 바뀐다. 함수에 선언된 파라미터 등에 맞게 자료형이 바뀐다. Python, Javascript, Ruby 등이 속한다. (파이썬의 동적타입에 대해서는 Python internals: Arbitrary-precision integer implementation, Why Python is Slow: Looking Under the Hood 두 글을 통해 조금 더 알아볼 수 있다.)

패러다임에 따른 분류

A paradigm is ‘a set of assumptions, concepts, values, and practices that constitutes a way of viewing reality for the community that shares them, especially in an intellectual discipline’.(hackr.io)

프로그래밍 패러다임(programming paradigm)은 쉽게 생각하면 ‘어떻게 프로그래밍할 것인가’에 대한 스타일, 틀이라고 생각한다. 프로그래밍은 현실 세계를 반영하여 프로그램을 만드는 것인데, 어떻게/어떤 관점/어떤 틀을 기준으로 구현할 것인지에 대한 스타일을 프로그래밍 패러다임이라고 한다. 하나의 프로그래밍 언어는 복수 개의 패러다임을 지원하기도 한다. 프로그래밍 언어는 대표적으로 4개의 패러다임으로 갈린다.

1. 절차적 언어(Procedural Programming Language)

순서에 따라 단계적으로 실행되는 프로그래밍 언어이다. 프로그램을 작성할 때 컴퓨터에게 단계적으로 실행할 명령들을 나열한다. C, Pascal등이 속한다.

2. 객체 지향 언어(Object Oriented Language)

‘객체’라는 작은 단위들을 조합하여 프로그램을 만든다. ‘객체’란 하나의 역할/특성을 가지는 메소드와 변수의 조합으로 만든다. ‘캡슐화, 상속화, 추상화, 다형성’이라는 특징을 가진다. Java, Python, C++등이 속한다.

3. 선언형 언어(Declarative Language)

함수형 언어

수학에서의 함수처럼 실행되도록 작성한 언어이다. 수학에서의 함수란 input을 입력했을 때에 output이 나오는 것이다. 예를들어, 수학에서 f(x)=x+1이라는 함수를 생각해보자. x값을 입력받아 x+1를 리턴할 뿐 그 외에 어떤 변수를 수정하거나 변경하는 등의 작업은 하지 않는다. 반대로, 파이썬에서 A = [2, 4, 1, 3]이란 리스트가 있다고 해보자. A.sort()라는 함수를 사용하면 A의값은 [1, 2, 3, 4]로 바뀐다. 전자와 후자는 분명 느낌이 다르다. 프로그래밍을 처음 배웠을 때에, 수학의 함수와 코딩할 때의 함수는 조금 다르다고 생각했었다. 이처럼 함수형 언어는 수학의 함수처럼 input을 통해 output을 리턴할 뿐 프로그램의 상태값을 변경하는 등 외부에 영향을 끼치는 작업은 허용되지 않는다. Haskell, Scala, Erlang

논리형 언어

논리형 프로그래밍 언어는 패러다임을 전혀 이해하지 못해 위키피디아로 대체하겠다.

특수 목적 언어

이 외에 SQL, MATLAB, PHP 등이 있다. 특수 목적 언어는 해당 분야를 벗어나면 사용하기 어렵다는 단점이 있다. 그래서 일반적으로는 메인으로 C, Java, Python등의 일언어들 중 하나를, 그리고 여러 특수 목적 언어들을 동시에 사용하여 프로그램을 만들게 된다.



이번 글을 요약하면, 프로그래밍 언어는 그 자체로는 그냥 언어일 뿐이다. 정말 그냥 언어 규약일 뿐이다. 가만히 두면 그냥 텍스트다. 특정 프로그래밍 언어의 규약에 맞추어 작성된 이 텍스트 파일은 컴퓨터가 알아들을 수 있는 기계어로 변형되어야 하는데, 그 일을 각 언어에 따라 compiler 또는 interpreter가 해주는 것이다. 언어간의 차이를 이해하고 언어의 특성을 이해하여 좋은 프로그램을 만들도록 하자.