[Programming] 프로그래밍 언어란 | 소개와 구분

프로그래밍 언어란 프로그램을 만드는 표현 규약입니다. 컴퓨터는 인간 언어로 된 명령을 이해할 수 없기 때문에 기계가 알아들을 수 있는 언어가 필요합니다. 이를 기계어라고 합니다. 기계어는 사람이 해독하기에는 너무 힘듭니다. 그래서 저수준 프로그래밍 언어인 기계어와 인간 언어의 중간에 위치하는 고수준 프로그래밍 언어를 개발했습니다. Go 언어, 파이썬, 자바 등 현대에 개발된 프로그래밍 언어는 모두 고수준 언어입니다.

지금부터 프로그래밍 언어가 무엇인지, 또 어떻게 구분하는지 알아봅시다.

 

[Programming] 프로그래밍 언어의 기본 소개와 구분

오늘날 위키백과에는 700개 언어가 등록되어 있습니다. 무료 온라인 컴퓨터 사전 FOLDOC에는 1,000개 언어가 등록되어 있습니다. 실제 언어 수는 이보다 많으리라고 생각되지만 유의미하게 사용되는 언어는 깃허브에서 사용되는 370개 정도로 볼 수 있습니다.

 

1. 초창기 프로그래밍 언어

컴퓨터가 알 수 있는 건 오직 0과 1밖에 없습니다. 컴퓨터는 인간의 언어를 알아듣지 못하므로 기계어가 필요합니다.

예를 들어 3과 4를 더하라는 의미로 ‘ADD 3 4’ 명령을 내리고 싶다고 가정해보겠습니다. 컴퓨터는 ADD도 모르고 3과 4도 모릅니다. 그래서 컴퓨터가 알 수 있게 0과 1을 사용해서 표현해야 합니다. 가령 ADD를 011로 표현하자는 규칙을 정하는 겁니다. 입력 011이 들어오면 내부 회로에서 가산기로 연결하는 스위치를 켜서 가산기가 수행되도록 만드는 겁니다. 이렇게 수행할 명령어를 나타내는 부호를 오퍼레이션 코드(Operation Code), 줄여서 OP 코드라고 부릅니다. 우리말로 명령 코드라고 합니다.

‘ADD 3 4’를 컴퓨터가 알아들을 수 있게 기계어로 표현해봅시다.

 

 

앞 4개 비트인 0011은 OP 코드로 ADD를 의미합니다. 두 번째 4개 비트 0011은 3의 2진법 표현, 마지막 4개 비트 0100은 4의 2진법 표현입니다. 따라서 0011 0011 0100은 ‘ADD 3 4’1를 의미합니다.

초기 프로그래머들은 천공카드에 구멍을 뚫는 방식으로 기계어를 작성해 컴퓨터에 명령을 내렸습니다. 이 시절에는 작은 프로그램 하나를 만드는 데도 천공카드 수백 장에 구멍을 내야 했습니다. 수백 장의 천공카드에 구멍을 내는 일, 컴퓨터에 한 장씩 입력시키는 일, 잘못 뚫린 구멍을 찾는 일 모두 굉장히 힘든 일이었습니다.

천공카드_위키피디아

 

2. 어셈블리어의 등장

‘ADD 3 4’를 ‘0011 0011 0100’으로 변환시켜주는 프로그램을 만들었습니다. 바로 어셈블리어입니다. 어셈블리어는 기계어와 1:1로 대응되는 언어로 인간이 쉽게 읽고 쓸 수 있는 ADD, SUB 같은 문자로 표현할 수 있었습니다.

 

ADD  3, 4
SUB  5, 3
MOV  CX, 1
MOV  AX, 0

 

앞에 연산자를 쓰고 뒤에 인수를 쓰는 형태입니다. 그러면 어셈블러가 기계어로 변환해줍니다.

어셈블리어는 기계어와 1:1로 매칭되기 때문에 매우 빠르고 기계어보다는 상대적으로 쉬웠지만, 칩셋마다 명령을 새로 익혀야 하는 불편함이 있었습니다. 어셈블리어는 현재까지도 기계 장치에 직접 코딩하는 임베디드 프로그래밍에 많이 사용됩니다.

 

3. 고수준 언어의 등장

기계어에 비하면 어셈블리어는 혁신에 가까웠습니다. 천공카드에 일일이 구멍을 뚫던 프로그래머들이 키보드로 프로그램을 작성할 수 있게 되어 정말 행복했을 겁니다. 하지만 어셈블리어는 기계어 명령으로 작성해야 했기 때문에 단순한 프로그램에도 코딩 양이 많았습니다. 그래서 전체 동작을 이해하기 힘들고 버그 발생 확률도 높았습니다. 또한 다른 아키텍처로 쉽게 이식할 수도 없었습니다.

그래서 더 인간의 언어 표현법에 가까운, 즉 더 프로그래밍하기 편한 고수준 프로그래밍 언어가 등장했습니다. 현재 대부분의 프로그래밍 언어는 고수준 언어입니다. 고수준 언어는 높은 생산성, 높은 가독성, 유연한 이식성을 제공합니다.

  • 생산성 : 다양한 기법을 제공해 프로그램을 작성하는 시간이 기계어에 비해 덜 걸립니다.
  • 가독성 : 기계어에 비해 짧고 읽기 쉬울 뿐만 아니라, 오류 가능성이 낮습니다.
  • 이식성 : 기계어에 비해 이식성이 더 좋습니다.

고수준 언어는 아래와 같이 인간이 사용하는 단어들을 사용해서 명령을 작성할 수 있습니다.

 

func main() {
   fmt.Println("Hello World")
}

 

고수준 언어의 등장으로 인간 친화적으로 코드를 작성할 수 있게 됐고, 다양한 고급 기능을 활용할 수 있었습니다. 어셈블리어에 비해서 전체적인 흐름을 이해하기 쉽고 프로그램을 만들 때 필요한 코드 양이 대폭 줄어들게 됐습니다.

 

3.1 고수준 코드가 실행되기까지

어떤 프로그래밍 언어로 작성하든 컴퓨터가 명령을 실행하려면 결국 기계어로 변환되어야 합니다. 어셈블리어는 코드와 기계어가 1:1로 매칭되기 때문에 변환 과정이 매우 빠르고 쉽습니다. 하지만 고수준 언어는 기계어로 바로 변환될 수 없기 때문에 별도의 프로그램을 사용해야 합니다. 이 변환 과정을 컴파일이라고 하고, 기계어로 변환해주는 프로그램을 컴파일러라고 합니다.

각 고수준 언어들은 자신만의 고유한 컴파일러를 가지고 있습니다. C 언어에는 C 컴파일러가 있고 Go 언어에는 Go 컴파일러가 있습니다.

 

 

4. 프로그래밍 언어의 구분

프로그래밍 언어를 여러 기준으로 나눌 수 있습니다. 기준을 살펴보고 예시로 Go 언어가 어디에 속하는지 알아보겠습니다.

 

4.1 정적 컴파일 언어 vs 동적 컴파일 언어

프로그램이 동작하려면 기계어로 변환되는 컴파일 과정이 필요한데 이 컴파일 과정을 언제 할 것인가를 언어를 나누는 기준으로 삼기도 합니다. 미리 컴파일을 해두면 정적 컴파일 언어, 사용할 때 컴파일하면 동적 컴파일 언어입니다.

 

정적 컴파일 언어

미리 기계어로 변환해두었다가 사용하는 방식의 언어를 정적 컴파일 언어라고 합니다. 기계어로 변환해둔 파일을 실행 파일이라고 합니다. 윈도우에서는 .exe 파일이 미리 기계어로 변환된 실행파일입니다. 그래서 실행 파일이란 곧 기계어 코드라고 볼 수 있습니다.* 실행할 때 변환 과정이 필요 없어서 빠르고, 타입 에러를 컴파일 시점에서 발견할 수 있어 타입 안전성이 뛰어납니다.

 

 

동적 컴파일 언어

실행 시점(Runtime, 런 타임)에 기계어로 변환하는 방식의 언어를 동적 컴파일 언어*라고 합니다. 동적컴파일 언어는 기계어로 미리 변환해두지 않고 실행할 때 변환하기 때문에 프로그램 실행 도중 변환 과정이 필요해서 정적 컴파일 언어보다 더 느리게 동작합니다. 동적 컴파일 언어들은 정적 언어보다 나중에 개발됐습니다. 이미 더 빠른 정적 컴파일 언어 방식이 있는데 왜 더 느린 방식을 만들게 된 걸까요? 바로 정적 컴파일 언어가 가진 단점을 극복하기 위해서입니다. 그럼 정적 컴파일 언어에 어떤 단점이 있었는지 살펴봅시다.

칩셋과 운영체제마다 0과 1로 된 바이너리 코드를 표현하는 형식이 다릅니다. 그래서 기계어로 변환할 때 각 칩셋에 맞게 변환해줘야 합니다(코드는 같지만 변환된 기계어는 칩셋마다 다릅니다).

실행 환경은 크게 CPU 아키텍처와 운영체제에 따라서 달라집니다. 예를 들어 CPU가 64비트인지 32비트인지 ARM 계열인지 인텔 계열인지에 따라 달라집니다. 운영체제에 따라서도 달라집니다. 다양한 실행 환경을 지원하려면 그만큼 많은 빌드 과정을 거쳐야 합니다.

하지만 동적 컴파일 언어는 이런 번거로움 없이 하나의 코드로 모든 플랫폼에서 실행됩니다. 그 이유는 프로그램 실행 시점에 환경에 맞는 기계어로 변환되기 때문입니다. 속도를 희생한 대신 범용성을 얻은 겁니다.

Go 언어는 정적 컴파일 언어이기 때문에 각 플랫폼에 맞는 실행 파일을 따로 만들어주어야 합니다. 하지만 Go 내부 환경 변수만 바꿔서 다양한 플랫폼에 맞도록 실행 파일을 만들 수 있어서 비교적 쉽게 대응할 수 있습니다. 또 정적 컴파일 언어답게 매우 빠른 실행 속도를 자랑합니다.

* 물론 윈도우 실행 파일에는 기계어 코드뿐 아니라 다른 정보도 포함되어 있습니다만 실행 파일을 기계어 코드라고 보아도 무리는 없습니다.

* 정적 타입 언어와 동적 타입 언어로 프로그래밍 언어를 구분할 수도 있습니다. 동적 타입 언어와 동적 컴파일 언어는 서로 다른 기준입니다.

 

4.2 약 타입 언어 vs 강 타입 언어

프로그래밍 언어를 나눌 때 타입 검사를 강하게 하는 언어와 그렇지 않은 언어로 나눌 수도 있습니다. 타입 검사를 강하게 하는 언어를 강 타입 언어 또는 정적 타입 언어라 부르고 타입 검사를 약하게 하는 언어를 약 타입 언어 또는 동적 타입 언어라고 말합니다.

예를 들어 “12”라는 값이 있다고 가정해보겠습니다. “12”와 12는 엄밀히 다른 타입의 값입니다. 따옴표로 묶인 글자는 문자열입니다. 반면 12는 숫자입니다. 만약 “12” + 12를 명령하면 어떻게 될까요?

프로그래밍 언어에 따라 “1212”로 만들거나, 24로 계산하기도 합니다. 때로는 에러를 출력하기도 합니다. 결과는 각 언어가 가진 특징에 따라 달라집니다. 서로 다른 타입 간 연산에 관대한 언어를 약 타입 언어(Weakly Typed)라고 하고, 엄격한 언어를 강 타입 언어(Strongly Typed)라고 합니다.

약 타입 언어는 규칙이 관대해 더 편하게 코딩할 수 있는 장점이 있는 반면 예기치 못한 버그를 발생시킬 수 있습니다. 강 타입 언어는 사용하기 까다롭지만 타입 검사를 언어 자체에서 해주기 때문에 타입으로 생길 수 있는 문제를 미연에 방지할 수 있습니다.

Go 언어는 다른 강 타입 언어에서 지원하는 자동 타입 변환까지도 지원하지 않는 최강 타입 언어입니다. 그래서 사용하기 좀 까다롭지만 타입이 달라서 발생할 수 있는 문제점이 전혀 발생하지 않습니다. 이에 대해서는 4장 ‘변수’에서 자세히 다룹니다.

 

4.3 가비지 컬렉터 유무

가비지 컬렉터(Garbage Collector) 유무로 프로그래밍 언어를 구분할 수 있습니다. 가비지 컬렉터란, 쓰레기 청소부란 뜻으로 메모리에서 불필요한 영역을 치워줍니다. 가비지 컬렉터가 없는 언어는 프로그래머가 메모리 할당과 해제를 책임져야 합니다. 할당한 메모리를 해제하지 않아 메모리 누수현상이 발생하거나, 이미 해제된 영역을 다시 해제해 버그가 발생하는 문제가 있습니다.

가비지 컬렉터가 있으면 메모리 해제를 자동으로 해주기 때문에 메모리 관련 문제가 줄어든다는 장점이 있지만, 메모리 청소에 CPU 성능을 사용한다는 문제가 있습니다. 그래서 가비지 컬렉터가 없는 프로그래밍 언어가 대체로 더 빠른 성능을 자랑합니다.

Go 언어는 가비지 컬렉터를 제공하기 때문에 사용자가 메모리를 일일이 지우지 않아도 됩니다. 또 Go 언어는 매우 발전된 형태의 가비지 컬렉터를 제공해 성능 손실이 크지 않습니다. 물론 가비지 컬렉터가 없는 언어보다는 느리지만 가비지 컬렉터가 있는 언어 중에서는 상위 성능을 자랑합니다.

지금까지 내용을 정리하여 각 기준에 따른 Go 언어의 특징을 살펴보면 다음과 같습니다.

  • Go는 정적 컴파일 언어입니다. 컴파일 과정을 거쳐 실행 파일을 미리 만들어야 하지만 실행 속도가 빠릅니다.
  • Go는 강 타입 언어입니다. 조금 번거롭지만 타입에 따른 문제점이 없습니다.
  • Go 언어는 가비지 컬렉터를 제공합니다. 그래서 자동으로 불필요한 메모리를 해제해줍니다.

 

마무리

  1. 컴퓨터가 알아들을 수 있는 언어는 기계어뿐입니다.
  2. 초기 프로그래머들은 천공카드에 구멍을 뚫어서 코딩했습니다.
  3. 저수준 언어인 어셈블리어는 기계어와 1:1로 대응됩니다.
  4. 고수준 언어는 코드 이식성이 높고 더 편리하게 프로그래밍할 수 있어 버그 발생율이 낮습니다.
  5. (기계어가 아닌) 코드는 기계어로 변환되어야 실행됩니다. 이 과정을 통칭해 컴파일이라고 합니다.
  6. 기계어로 변환되는 시점에 따라서 정적 컴파일 언어와 동적 컴파일 언어로 나뉩니다.
  7. Go 언어는 고수준, 정적 컴파일, 강 타입 언어이고 가비지 컬렉터를 가지고 있습니다.

 

WRITER

공봉식

13년 차 게임 서버 프로그래머로 다양한 장르의 온라인 게임을 개발했습니다. 넥슨과 네오위즈를 거쳐서 현재는 EA 캐나다에서 근무 중입니다. 「Tucker Programming」 유튜브 채널을 운영합니다.

Leave a Reply

©2020 GoldenRabbit. All rights reserved.
상호명 : 골든래빗 주식회사
(04051) 서울특별시 마포구 양화로 186, 5층 512호, 514호 (동교동, LC타워)
TEL : 0505-398-0505 / FAX : 0505-537-0505
대표이사 : 최현우
사업자등록번호 : 475-87-01581
통신판매업신고 : 2023-서울마포-2391호
master@goldenrabbit.co.kr
개인정보처리방침
배송/반품/환불/교환 안내