Daybreakin Things
요즘 연구실에서 워크샵 논문을 하나 준비하고 있다. 얼핏 보면 그리 어렵지 않은 듯하면서도, 막상 실제로 구현하려면 꽤 생각해야 할 것이 있어서 생각보다 어려움을 겪고 있다. 이미 있는 코드 분량이 꽤 되고 리눅스 커널 드라이버도 함께 맞물려 돌아가는 프로그램인데다 성능도 민감하기 때문에 생각보다 고려해야 할 것이 많은 것이다.
문제는 추상화다. 나도 '추상화의 덫'에 걸리지 않도록 조심해야 한다는 사실 정도는 알고 있지만, '나중에 유지보수할 일'을 생각해서 코드를 짤 때 되도록이면 기본적인 추상화는 하려고 하는 편이다. 하지만 프로그래밍에 데드라인이 생기면서부터는 이것이 만만치 않은 일이 된다. 추상화는 잘 할수록 나중에 좋지만, 데드라인이 있는 일에서는 결국 어느 정도 수준까지만 하고 포기해야 하는데, 가끔 이럴 때 장인정신(...)이 발휘되면 곤란한 상황에 처한다.
이쪽 시스템 분야로 내공을 쌓으신 연구실 선배와 이야기하다보면 많이 느끼는 차이점이 있다. 프로그램의 어떤 부분에서 임의의 16-bit integer key로 table lookup을 해야 하는데 나는 이것을 hash table로 짜야 되나, 그럼 이걸 어떻게 간단하게(적은 노력으로) 짤 수 있을까, 라이브러리를 쓴다면 뭘 쓰는 게 좋을까, C++ 인터페이스를 쓰는 게 좋을까 그냥 C로 하는 게 좋을까, random dereference를 하면 그 자체가 lookup 오버헤드가 되지는 않을까 등등등을 꼬리에 꼬리를 물고 고민하는데, 선배들과 이야기해보니 간단하게 그 table에 들어가는 item 개수가 많아야 수백개 정도일 것이므로 그냥 array에 때려박고 index로 접근하게 한 다음 table 변경될 때도 일부만 잘 고치려 할 필요 없이 전체 다 재생성하도록 해보고 나중에 성능 보고 더 나은 방법을 쓸지 말지 결정하자는 결론이 나왔다.
그러니까 요는 처음부터 너무 미래의 걱정을 하지 말라는 이야기다. 일단 지금 필요한 수준에 맞게만 구현하고 문제가 있으면 그때 가서 고치자는 것. 이 이야기를 건축에 비교해볼 수 있다. 물리학이나 공학이 지금처럼 발전하기 전에는 (상징성이나 예술성이 목적인 경우를 제외하면) 같은 기능적 목표를 충족시키기 위해 지금보다 훨씬 많은 재료가 들어갔으나 기술이 발전할수록 점점 그것이 최소한 필요한 만큼만 쓰게 되는데---사실 건축뿐만 아니라 많은 분야가 그렇다---처음부터 프로그램을 모든 경우를 대비해서 비대하게 짤 필요 없이 필요한 만큼씩만 덧붙여나가는 것이 이와 비슷하다.
그나마 '얼핏 보기에 간단한' 정도의 일도 이런 고민을 하게 만드는데, '얼핏 보기에도 어려운' 정도의 일을 하려면 아직도 내공을 더 많이 쌓아야 할 것 같다. 프로그래밍이라는 게 항상 끊임없는 의사결정의 과정인지라 개발자 자신이 처한 사회적 맥락, 프로그램 코드가 속해있는 기술적 맥락 모두를 잘 꿰뚫어보지 않으면 여러 의미로 좋은 코드가 나오기가 정말 어렵다.
(살짝 덧붙이자면, 그래도 ipv4와 ipv6를 하나의 인터페이스로 통합하려고 했던 시도는 그나마 빨리 접어서(...) 다행이다. -0-)