메아리 저널

언어 독립적인 라이브러리 설계​

누누히 말하지만 프로그래밍 언어는 몇 가지 중요한 부분으로 구성되어 있다.

  1. 문법. 이를테면 Date.new(2010,12,22)new Date(2010,12,22)냐의 문제.
  2. 뜻(의미론). 이를테면 함수 인자의 평가를 최대한 늦게 할지 최대한 빨리 할지의 문제.
  3. 라이브러리. 이를테면 DateTime 객체가 서로 나뉘어 있는지 아니면 하나로 합쳐져 있는지(ECMAScript처럼)의 문제.
  4. 사용자 집단. 이를테면 언어가 강제하지는 않지만 자주 쓰이는 표현이라거나, CPAN/gem/PyPI와 같은 중앙 집중된 패키지 시스템의 존재 같은 얘기.

그리고 네 가지 중 하나라도 어중간하면 프로그래밍 언어 전체가 어중간해지는 현상을 심심찮게 볼 수 있다. 따라서 어느 하나 소홀할 수는 없는데, 보통 새로운 프로그래밍 언어를 만들려는 사람들은 처음에는 문법, 그리고 좀 경험이 생기면 뜻에 치중하는 경향을 자주 볼 수 있다. 그러니까 처음에는 세미콜론이 붙는 게 좋냐 나쁘냐 하는 걸로 논쟁하다가, 시간이 지나면 lexical scoping이니 느긋한 계산법(lazy evaluation)이니 하는 것들을 고민하기 시작하는 것이다. 그러나 어느 쪽도 라이브러리나 사용자 집단에 큰 관심을 가지지는 못 하는데, 기실 대부분의 새로운 프로그래밍 언어는 이들을 신경쓰기 전에 망하게(…) 마련이기 때문에 사실 어쩔 수 없는 문제이기도 하다. (혹자는 포트란 이래 매주마다 새로운 언어가 하나씩 만들어지고 있다라고 할 정도니.)

개인적으로 보기에 사용자 집단은 언어 설계자가 가장 건들기 어려운 요소로 보이며, 사실 운(얼마나 괜찮은 사람들이 그 언어에 관심을 가지는가?)에도 상당한 영향을 받는 것 같아서 심지어 성공한 언어 설계자조차도 이 요소에 한해서는 자기가 어떻게 해서 성공했는지 설명도 할 수 없을 것이라 생각한다. 그러나 라이브러리라면 어떤가? 대부분의 프로그래머는 자기가 쓴 라이브러리에 대해서 최소한 좋다 나쁘다 하는 감정은 가지고 있고, 라이브러리를 직접 만들어 본 경험이 있다면 그 감정을 좀 더 자세히 구체적으로 설명할 수도 있을 것이다.

자, 여기서부터 아이디어이다. 대부분의 언어 설계자는 언어의 문법과 뜻을 설계하는 것에 관심이 있지 라이브러리를 설계하는 것에 공을 들이기는 쉽지 않지만, 그럼에도 불구하고 라이브러리는 언어의 사용자 경험에 상당한 공을 차지하고 앞에 말했듯 사용자 집단보다는 훨씬 건들기 좋은 편이다. 그럼 언어와 독립적인 라이브러리 설계를 가져다 쓰는 것은 어떤가? 운영체제 만들 때는 OSKit이 있고(망했지만) 가상 기계를 만들 때는 VMKit이 있듯, 새로운 언어를 위한 기본 라이브러리를 위한 설계 지침이나 프레임워크가 있는 것이 어떨까? 물론 언어의 특성에 따라 다소간의 변경은 필요하겠지만, 설계 자체는 언어의 큰 분류가 바뀌지 않는 한 크게 바뀌지 않을 것 같기 때문에 기본적으로는 비슷하게 하는 게 가능하지 않을까 싶다.

예를 들어 보자. 아까 전에 Date 객체에 대한 얘기를 했는데, 이걸 설계하는 것이 간단해 보이지만 사실 전혀 그렇지 않다. 이를테면 이런 걸 고려해 봐야 한다.

날짜와 시각을 별도의 자료형으로 취급해야 하는가? 그리고 시각과 시간을 구분해야 하는가?
이 쪽은 딱히 맞는 답은 없어 보이는데, ISO 8601과의 호환을 위해서라면 모두 분리하는 게 좋긴 하지만 자칫하면 사람들을 헷갈리게 할 수도 있다.
날짜 관련 객체들이 변경 가능해야 하는가?
변경 가능한 값들에 일정 제약이 있는 언어들의 경우 이 구분이 중요할 수도 있다. 개인적으로는 날짜를 제자리에서 바꿔야 할 일이 그렇게 많은 것 같진 않다. 이 질문에 대해서 가장 최악의 언어는 ECMAScript인데, 자바에서 모조리 복사해 버렸기 때문에 실제로는 사용하지 않음에도 불구하고 set* 메소드가 존재한다;
시각을 얼마나 자세히 표현할 수 있게 할 것인가?
이를테면 ISO C의 날짜 관련 함수들은 초 단위까지만 지원하지만, 현재는 초 단위는 커녕 마이크로초 단위도 모자란 게 아닌가 싶다.
날짜 범위를 언제부터 언제까지로 할 것인가? 그리고 그 범위를 벗어난 결과가 나왔을 때 사용자에게 어떻게 알려 줄 것인가?
ECMAScript의 Date는 모든 날짜 값을 하나의 숫자로 매핑시키는 정책을 쓰고, 덕택에 (날짜 범위를 벗어날 때 반환되는) NaN도 올바른 날짜 값으로 인식되어 이 질문에 대해서는 비교적 잘 구현된 편인데, 문제는 이러면 다음 질문에 답하기 어려워진다는 것일 터.
윤초를 지원할 것인가?
한 언어 안에서도 이 질문에 대한 답이 오락가락하는 경우를 종종 볼 수 있다(대표적으로 파이썬의 datetime과 time 모듈). 계산 과정에서 윤초가 들어 가기 시작하면 좀 더 복잡해진다.
그레고리력이 만들어지기 이전의 날짜를 어떻게 처리할 것인가?
루비의 Date 클래스가 이 질문에 대해서 매우 독보적인(!) 접근을 취하고 있는데, 그레고리력 이전의 날짜를 율리우스력으로 처리할 뿐만이 아니라 그레고리력 전환 날짜를 사용자가 지정할 수 있게 한다. 그러나 개인적으로는 복잡도 면에서나 실용성 면에서나 이 접근은 틀렸다고 본다. (역법 변환을 위한 별도의 라이브러리가 있는 게 맞다.)
시간대 정보를 어떻게 구현할 것인가?
잘못 구현하면 파이썬과 같은 꼴이 나게 십상이다. 일광절약시간까지 고려하기 시작하면 아마 골이 터질 것이다. 시간대가 있는 날짜와 없는 날짜를 다른 자료형으로 구현할지 같은 걸로 구현할 지도 좀 생각해 봐야 할 것이고.
기본으로 어떤 시간대를 제공할 것인가?
물론 tzdata 데이터베이스를 모조리 저장하면 모든 일이 해결될 수도 있으나 구현체 입장에서 전혀 달갑지 않은 선택일 것이고, 사용자 정의 시간대 인터페이스를 잘 만들어서 pytz처럼 별개의 구현이 그 일을 떠맡게 만들 수도 있다. (물론 파이썬은 여기에 너무 기댄 나머지 UTC조차 기본으로 지원하지 않는 삽질을 해 버렸지만…)

이런 것들을 모두 파악하려면 상당한 고민이 필요하다.1 실제로 내가 delight를 만들 적에 구현한 delight.time.datetime 모듈을 보면 내가 이 질문들에 대해 어떻게 답하려고 했는지에 대해서 대강 감을 잡을 수 있다. 그러나 나라면 몰라도, 모든 언어 설계자가 이런 고민을 하는 데 시간을 낭비(!)하는 것은 전혀 생산적인 일이 아니라고 본다. 내 아이디어는, 언어 설계자는 가장 재밌어 보이는(?) 언어의 문법 및 의미론에 집중하고 기본 라이브러리는 미리 만들어진 잘 된 설계 중 하나를 가져다 쓸 수 있도록 지원하자는 것이다.

물론 이런 걸 실제로 만들려면 넘어야 할 산은 많다. 여러 가지 가능성을 생각해 볼 수 있으나 간단한 예를 들면, 이미지 처리 라이브러리를 이런 식으로 지원한다고 치자. 근데 어떤 사람이 기본 라이브러리에서 제공하지 않는 이미지 포맷을 직접 구현해서 기본 라이브러리에서 이 포맷을 사용할 수 있게 하고 싶다 하자. 언어의 설계에 따라서 이런 류의 확장을 지원하는 방법이 여럿이 될 수 있는데, 이를테면 단순히 registerExtension 함수 따위를 지원한다거나, 동적인 모듈 시스템이 있다면 그걸 쓰도록 하거나, 멀티메소드를 지원한다면 그걸 쓰거나, 스칼라처럼 implicit한 인자를 쓰도록 한다거나, 아니면 처음부터 이미지를 불러 오는 인터페이스와 이미지를 조작하는 인터페이스를 나눈다거나(근데 이러면 개인적으로는 귀찮을 것 같다만). 그러나 이런 것들이 설계 자체에 큰 영향을 주는 것은 아니기 때문에, 이런 것들을 하나로 잘 통합하는 모종의 메타데이터가 필요할 것이다.

…아무래도 이것도 아이디어만 제시하고 구현은 안 하는 대표적인 사례가 될 것 같다.


  1. 그나마 이 쪽은 사정이 나은 편이다. 문자열은 어떤가? 이 쪽은 좀 더 심각하다


노트들

  1. arachneng posted this
텀블러를 씁니다.