프로그래밍 언어는 많다... 엄청.
프로그래밍 언어는 엄청 많습니다. 개수만 따지면 8,000개가 넘고, 자주 쓰이는 것만 추려도 50개는 됩니다. 저만 해도 회사와 개인적으로 쓰고 있는 프로그래밍 언어를 세 보면...
- Kotlin: 회사에서 주로 쓰는 언어
- Java: 회사의 레거시 프로젝트에서 쓰는 언어
- Python: 일부 회사 프로젝트에서 쓰는 언어
- SQL: DB 관련 작업을 할 때 쓰는 언어
- HTML: 회사나 개인 프로젝트에서 웹사이트, 이메일 등의 UI를 표현할 때 쓰는 언어
- CSS: 회사나 개인 프로젝트에서 웹사이트, 이메일 등의 UI를 꾸밀 때 쓰는 언어
- JS: 회사나 개인 프로젝트에서 웹사이트의 로직을 넣을 때 쓰는 언어
- TS: JS에 Type System을 추가한 언어
- Swift: iOS 개발을 할 때 쓰는 언어
이렇게 해서 9개입니다. 이건 사실 정말 자주 쓰는 언어만 센 거지 간단하게 읽을 수 있고 간단한 작업도 할 수 있는 언어를 합치면 20개는 넘을 듯합니다. 왜 이렇게 프로그래밍 언어는 많아야만 할까요? 프로그래머들은 생선성을 그렇게 좋아하는데 왜 모든 걸 할 수 있는 1개의 언어를 만들지 않은 걸까요? 🤔
사실 튜링 완전하기만 하면 모든 언어는 똑같다
프로그래밍 언어는 알고리즘을 묘사하고 풀기 위해 존재합니다. 이런 간단한 알고리즘 부터 복잡한 알고리즘이 모여서 우리가 쓰는 컴퓨터를 이룹니다. 예를 들면...
- 짝수를 찾는 알고리즘
- 두 점 사이의 최단 경로를 찾는 알고리즘
- 인터넷에서 Routing을 하는 알고리즘
- OS에서 어떤 Process를 먼저 실행할지 정하는 알고리즘
이런 알고리즘을 묘사할 수 있는 프로그래밍 언어를 튜링 완전한 언어라고 합니다.
튜링 완전 - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. 튜링 완전(turing completeness)이란 어떤 프로그래밍 언어나 추상 기계가 튜링 기계와 동일한 계산 능력을 가진다는 의미이다. 이것은 튜링 기계로 풀 수 있는 문제,
ko.wikipedia.org
튜링 완전하면 모든 알고리즘을 묘사할 수 있습니다. 그 말은 모든 튜링 완전한 프로그래밍 언어는 다른 튜링 완전한 프로그래밍 언어로 바꿔 쓸 수 있습니다. 그 말은 놀랍게도... 사실 프로그래밍 언어 1개로 모든 걸 할 수 있다는 말입니다. 이론적으로는요...! 그렇다면 왜 그렇게 하지 않고 이렇게 많은 프로그래밍 언어가 난립하고 있을까요?
정답: 프로그래밍 언어는 사람을 위한 거지 컴퓨터를 위한 게 아니다
모든 프로그래밍 언어가 컴퓨터에게 똑같은 건 맞습니다. 하지만 기억해야 할 것은 프로그래밍 언어는 애초에 사람인 프로그래머가 더 편하게 프로그램을 만들기 위해 (알고리즘을 작성하기 위해) 생긴 거라는 겁니다. 그래서 2가지 현상이 생겼는데요.
- 취향이 생긴다
- 타협점이 생긴다
🐜 1 - 취향이 생긴다
취향이 생긴다는 게 프로그래밍 언어 대상이라 이해가 가지 않을 수 있지만 예를 들어 아래의 Kotlin 코드와 Java 코드를 비교해 보겠습니다. Kotlin은 최근에 나온 언어라 기본으로 제공되는 내장 함수가 굉장히 풍부한 편입니다. 그래서 똑같은 문제를 풀더라도 Kotlin은 언어 내부의 Kotlin 특유의 내장 함수들을 많이 활용하고 Java는 모든 프로그래밍 언어에 보편적으로 있는 for 루프 등을 더 활용하게 됩니다.
만약 n부터 m까지 사이의 수가 특정 값을 넘으면 true, 아니면 false를 반환하는 함수
fun isBiggerThanAllTheIntegersBetween(
from: Int,
to: Int,
criteria: Int,
): Boolean {
val size = to - from + 1
List(size) { from + it }
.sumOf { it }
.takeIf { it > criteria }
?: return false
return true
}
누군가는 이 코드가 마음에 들 수도 있습니다. "보기에 깔끔하네! 내장 함수도 어려운 것도 아니고 직관적이니깐 쓰면 어때?"라고 생각할 수도 있습니다. 하지만 누군가는 이 코드가 마음에 들지 않을 수도 있습니다. "굳이 저렇게 써야 해? 저런 함수 말로 다들 아는 더 간단한 문법으로 할 수도 있는데?"라고 할 수도 있습니다. 이 주장도 일리는 있습니다.
public boolean isBiggerThanAllTheIntegersBetween(int from, int to, int criteria) {
int sum = 0;
for (int i = from; i <= to; i++) {
sum += i;
}
return sum > criteria;
}
같은 코드를 Java로 쓰면 이렇게 됩니다. 우선 훨씬 명시적입니다. 함수가 다른 곳에서 접근 가능하다고 public으로 알려 주고 있고, 모든 변수는 반드시 타입을 명시해 줘야 합니다. 위의 코틀린 코드는 선언적으로 이 리스트의 합을 구하고! 이 값이 이 값보다 크면 가져오고! 이런 식으로 돼 있었는데 Java 코드는 그보다는 더 하나하나 어떻게 해야 하는지 알려주는 느낌이 강합니다.
🐜 2 - 타협점이 생긴다
프로그래밍 언어는 각자 다른 규칙이 있습니다. 이 규칙을 너무 엄격하게 적용하면 사용하기 힘들고, 너무 느슨하게 적용하면 속도가 느리고 오류가 많이 납니다. (정확히는 오류를 미리 잡을 수 없고 프로그램 실행 중에 알게 되는 런타임 오류가 많이 발생합니다.)
대표적으로 타입(Type System)이 있습니다. 타입 시스템을 엄격하게 적용한 언어는 명시적으로 타입을 바꾸지 않는 이상 변수와 함수의 타입은 계속 같은 타입으로 유지됩니다.
Java, C, Kotlin 등의 언어는 이런 엄격한 타입을 사용합니다. 이렇게 하면 단점이 타입이 복잡해지면 이 타입을 명시하는데 상당히 많은 시간을 써야 한다는 겁니다. 그리고 프로그램을 빠르게 만들고 싶은데 다른 타입끼리의 변환을 계속 신경 써야 해서 생산성이 떨어질 수 있습니다. (그래서 최근 언어들은 엄격한 타입이더라도 타입 추론을 지원해서 타입을 항상 명시할 필요는 없게 하기도 합니다.)
반대로 Python, Javascript 등의 언어는 느슨한 타입을 사용합니다. 이렇게 하면 타입을 신경 쓰지 않고 빠르게 코딩을 할 수 있어 생산성이 높습니다. 근데 어떤 2가지 변수를 숫자인 줄 알고 더하려 했는데 문자였다면? 아니면 boolean이었다면? 변수의 타입이 엄격하게 강제되지 않기 때문에 프로그램 실행 도중에 의도치 않은 동작이 실행됩니다.
최근에는 엄격한 타입이 더 좋다는 일종의 경험에서 나온 프로그래머 커뮤니티의 의견이 있습니다. 하지만 Javascript나 Python이 얼마나 인기가 높은지 생각해 보면 정답은 없다고 할 수 있는 문제입니다.
이렇게 어떤 선택을 했냐에 따라 어떤 목적에 맞는지가 달라집니다. 타입 시스템의 경우 1~2번 쓸 프로그램이라면 타입이 엄격하지 않은 프로그래밍 언어로 빠르게 끝내는 게 올바른 선택일 수 있습니다. 하지만 몇 십 년 갈 프로그램이라면 타입이 엄격한 언어를 쓰는 게 올바른 선택에 가까울 수 있습니다.
자주 있는 프로그래밍 언어의 타협점들
🐜 타입 시스템
위에서 설명했듯이...
- 타입을 얼마나 강하게 할 것인지
- Compile Time에 확인할 것인지 Runtime에 확인할 것인지
- 명시적으로 타입을 보여줄 것을 강제할 것인지, 추론을 도입해서 생략 가능하게 할 것인지
🐜 메모리 직접 접근
- 포인터를 직접 접근할 수 있게 할 것인지
- 추상화된 무언가를 제공해서 메모리 관리를 직접 하진 않지만 내부적으로는 비슷한 효과를 낼 것인지
- 메모리 관리를 아예 제한하고 프로그래밍 언어가 알아서 하게 할 것인지
🐜 동시성을 어떻게 다룰지
- Thread, Lock
- Async, Await
- Actor
🐜 에러를 어떤 식으로 다룰지
- try, catch, exception
- 함수 리턴 타입에 에러를 리턴하게
- Result 타입
결론
- 튜링 완전하기만 하면 모든 프로그래밍 언어는 똑같기 때문에 사실 1개의 언어로 다 할 수 있다.
- 하지만 프로그래밍 언어는 컴퓨터가 아니라 사람을 위해 있는 거라 취향이나 타협점이 생긴다.
- 그래서 각 목적에 맞는 타협점을 선택한 언어나, 내 취향에 맞는 언어를 선택하다 보니 프로그래밍 언어가 많아졌다.
'CS 이론 > 🖌️ 프로그래밍 언어론' 카테고리의 다른 글
Compiler의 구조 알아보기 (Front-end) (0) | 2025.04.13 |
---|---|
컴파일러가 기본적으로 하는 최적화를 알아보자 (0) | 2025.01.28 |
오토마타 (Automata), 그게 대체 뭔데? (0) | 2023.12.26 |
형식 언어 (Formal Language) (0) | 2023.12.17 |