Ethan Hur's blog

프로그래밍 언어 에세이

2019-10-29

프로그래밍 언어 시간에 과제로 했던 에세이

느낀 것

프로그래밍 언어의 발전은 프로그래머 생산성과 프로그램 안정성에 대한 발전임을 느꼈다. malloc/free 로 직접 메모리를 관리하던 방식에서 Garbage Collection 을 이용하는 방식으로 발전하면서 프로그래머의 생산성이 증가했고, 타입 시스템이 발전하면서 프로그램의 안정성이 증가했다.

프로그래머의 생산성을 올리기 위해, 프로그래밍 언어는 프로그래머에게 지워진 책임을 점점 줄여주게끔 발전했다. 비교적 오래전에 만들어진 C 언어는 프로그래머에게 많은 책임을 요구하는 언어이다. C 언어 프로그래머는 직접 메모리를 관리함으로 인해 memory leak 이라는, 끊임없이 프로그래머를 괴롭히는 난제를 풀어야 하기도 했고 low-level operation 에 프로그래머의 시간과 자원을 투자해야 했다. 현대의 프로그래밍 언어들은 이러한 문제들을 언어 자체의 기능으로 추가해버리면서, 프로그래머의 생산성에 많은 도움을 줬다. GC 가 생기면서 memory leak 과 싸우는 시간을 절약할 수 있었고, 타입 체크를 통해 실제 런타임에서 발생할 수 있는 버그를 줄일 수 있게 해주었다.

프로그램의 안정성은 학문적 발전의 결과를 적용하면서 증가했다. 앞 문단에서 말한 것과 마찬가지로, 런타임에 발견될만한 버그를 컴파일 타임에 체크하기 위해 정교한 타입 시스템을 적용했고, concurrency 로 인한 버그를 줄이기 위해 side effect 없는 functional programming 이론을 적용했다. 실제로 Javascript 에 Type 시스템을 더하여 15프로의 버그를 미리 발견할 수 있었다는 연구도 있다.

프로그래밍 언어가 계속해서 발전할수록 컴파일러의 역할도 늘어날 것이라고 생각한다. 예전에는 소스 코드를 바이트 코드로 컴파일하고 최적화하는 역할 정도만 하던 컴파일러가, 이제는 타입 추론과 tail recursion 체크, lazy evaluation 등등 점점 더 많은 기능을 수행하는 모습으로 바뀌고 있다. 심지어 Go 언어의 컴파일러는 lint 기능까지 포함되어 있다. 이처럼 프로그래밍 언어가 발전함에 따라 컴파일러의 기능들은 계속해서 추가될 것이며, 이로 인해 컴파일러가 예전보다 더 많은 역할을 수행하게 될 것이다. 언어의 생산성과 안정성에 가장 영향을 많이 끼치는 키 플레이어는 컴파일러가 될 것이다.

프로그래밍 언어의 많은 발전에도 불구하고, 2019년 현재 가장 인기있는 언어들은 여전히 C나 Java와 같은 기계 중심의 언어들이다. 이는 프로그래머의 학습 비용의 문제와, 추상 수준을 낮춰 저수준에서 직접 프로그래밍해야 하는 필요성 때문이라고 생각한다.

새로 만들어진 최신 언어를 사용하는 것은 기업 입장에서 리스크가 큰 일이다. 소프트웨어를 만드는 팀원 구성은 대체 가능해야 하며, 많은 프로그래머들이 소프트웨어를 이해하기 쉬워야 한다. 하지만 Haskell 과 같은 Purely Functional Language 들은 추상화 레벨이 다른 언어들보다 높은 편이라 이해하기가 상대적으로 쉽지 않다. 이러한 특성으로 인해 기업들이 비교적 인력을 구하기 쉬운 기존 패러다임의 언어를 선호한다고 생각한다. Facebook anti-spam 프로그램의 예시는 훌륭한 엔지니어들이 많이 모여있기 때문에 가능했던 일이라고 본다.

또한 기계어에 가깝게 프로그래머가 컨트롤해야 하는 경우도 있다. 중요한 시스템을 프로그래밍하는 경우에는, 소프트웨어 개발자가 저수준의 동작까지 이해해야 한다. 이러한 경우 Purely Functional Language 에서는 지원하지 않는 “위험한” 기능들이 필요하다. 따라서 먼 미래에도 저수준에서 프로그래밍할 수 있는 언어에 대한 수요는 여전히 존재할 것으로 생각된다.

다행스럽게도, 기존 언어들의 최신 스펙에는 함수형 패러다임을 점진적으로 도입하고 있다. C++ 11 버전 이후로는 람다 함수를 지원하고 있고, Java 도 8 버전 이후로는 람다 함수를 지원하고 있다. 이외에도 많은 언어들이 프로그래밍 언어의 발전에 발맞추어 계속 진화중이다.

따라서 미래의 프로그래밍 언어는 기존의 기계 중심 언어의 특성과 값 중심 언어의 특성을 적절히 조합한 하이브리드 언어가 대세가 될 것이라고 생각한다. 대부분의 코드는 고수준의 추상화를 통해 안전하고 생산성 높게 프로그래밍하고, 정말 성능이 중요한 부분은 저수준에서 프로그래밍해서 성능을 올릴 수 있게 작업하는 것이 미래 프로그래밍 언어의 모습이 될 것이라고 믿는다.

질문하고 싶은 것

현대의 프로그래밍 언어들은 보통 Garbage Collection 을 이용해서 메모리 관리를 한다. 초기에는 C언어와 같이 직접 메모리를 관리하는 방식이었고, 그 후 Garbage Collector 가 등장하며 GC가 메모리를 관리해주는 방식으로 진화해왔다.

하지만 Garbage Collection 은 메모리 관리에서의 safety 는 보장해주지만, completeness 를 보장해주지 않는다. 또한 효율성도 좋지 못하다. GC는 앞으로 사용하지 않을 메모리를 “모두” 반환하는 것을 보장하지 않는다. 현대 대부분의 GC 에서 사용되고 있는 포인터 추적 방식은 해제해도 dangling pointer 가 생기지 않는, 다시 말해 “반환해도 안전한” 메모리를 반환할 뿐이다. 또한, 프로그램이 실행될 때 메모리 해제가 언제, 얼마나 일어나는지 예측 불가능하며 이로 인해 프로그램이 순간적으로 정지하는 문제가 생기기도 한다.

따라서 앞으로 만들어질 프로그래밍 언어에서 메모리 관리 기법은 이런 문제를 어떤 방식으로 해결할지 궁금하다. Rust 에서는 이러한 문제를 ownership 이라는 방식을 통해 극복하려고 시도했다. GC 를 사용하는 대신, 메모리의 ownership 을 지정하여 효율적이면서도 safe 한 메모리 관리를 할 수 있게 되었다. Rust 처럼 앞으로 나오는 프로그래밍 언어들에서는 메모리 관리의 측면에서 더 많은 발전이 있을 것이라고 기대하고, 앞으로 얼마나 안전하면서도 효율적인 언어가 등장할 지 지켜보고 싶다.