Daybreakin Things

Posted
Filed under 컴퓨터

올해 봄학기 마지막으로 조교를 맡았을 때 개강 전날 교수님과 한 학기 커리큘럼을 의논하면서 했던 이야기이기도 하고, 내가 전산학을 공부 + 연구해오면서 느낀 부분들이라 따로 글로 정리해본다.

시스템을 설계하는 건 복잡성을 해결하는 과정이다.

내 학번부터 KAIST 전산과의 졸업필수과목이 된 CS408 전산학 프로젝트(Capstone Project) 과목에서는 학생들이 팀을 이뤄 한 학기 내내 그 동안 배운 모든 지식과 기술을 동원하여 '적절한 수준의 복잡도를 지닌' 시스템을 설계·구현한다. 내가 이 과목을 수강했을 때 가장 불만이었던 부분은 과연 얼마나 복잡해야 하는가에 대한 기준이 매우 주관적이었다는 것과, 실제로 그러한 복잡성을 해결하면서 시스템을 설계하는 방법에 관해서는 거의 강의가 이뤄지지 않았다는 점이다. CS350 소프트웨어 공학개론 과목에서 모듈화의 개념이라든가 decoupling의 중요성 등 기초적인 원리를 일정 부분 가르쳐주기는 하지만, 실제로 프로그램을 작성할 때 이를 어떻게 적용해야 하는가에 대한 실전적인 지식은 거의 알려주지 않는다.

이때 채우지 못한, 시스템 설계를 어떻게 "잘" 해야 하는가에 대한 목마름이 내 대학원 생활에서도 상당히 아쉬움으로 남는 부분이라는 걸, 좀 늦게 깨달았다.

내 연구 주제인 패킷 처리 시스템 정도면 "매우 많이" 복잡한 시스템이라고 할 수 있다. 목표는 고성능 패킷 처리 프레임워크를 Linux 기반 환경에서 GPU와 갈은 보조프로세서를 활용해 구현하고, 여기에 CPU와 GPU로 패킷을 잘 배분해서 어떻게 하면 최적 성능에 다다를 것인가에 대한 문제를 푸는 것이다. 나는 사용자들이 새로운 패킷 처리 모듈들을 손쉽게 구현하고 추가·삭제할 수 있게 해야 한다고 보았기 때문에, 단순히 특정한 종류의 application만 동작하는 prototype 프로그램이 아니라 어느 환경에서나 configuration만으로 프로그램 수정 없이 돌릴 수 있는 framework로 만들려고 했고 이를 위해 복잡도가 매우 올라갔다.

예를 들면 어떤 모듈을 실행할 것인지에 관해서는 Click configuration language를 모방한 별도의 DSL(domain-specific language)로 작성된 설정 파일이 있고 이를 해석하는 parser가 달려있으며, 어떤 하드웨어 리소스를 사용할 것인지에 대해서는 embedded Python interpreter를 이용해 직접 시스템 정보를 전달해주고 사용자가 작성한 Python 스크립트가 자동으로 설정하게 했다. 네트워크 카드로부터 패킷을 입력받아 각 모듈들의 CPU 버전 코드를 실행하고 패킷을 출력하는 worker thread들이 여러 CPU 코어를 사용해 돌아가고 GPU를 사용할 필요가 있다고 판단한 경우 패킷들을 모아서 GPU 전담 thread로 보내고 실제 GPU 관련 코드를 실행해주는 부분도 있다. 이 모든 과정은 polling과 event-driven model을 혼합하여 작성한 것이며 병렬화와 batch 처리의 효율성을 모두 극대화하는 것을 목표로 코드를 작성했다.

가장 아쉬웠던 부분은, 어떻게든 프레임워크를 돌아가는 상태로 만들어서 논문을 써놓고 나니, 추상화와 동작 여부 사이에서 trade-off가 너무 많았고(논문을 쓰려면 당연히 최소한 '돌아는 가야' 하니까) 추상화는 결국 내 스스로도 100% 만족하기 힘든 상태가 되어버렸다는 점이다. 처음에는 논문 내용 자체를 framework의 우수성(?)으로 썼다가 여러 차례 학회에 재도전한 끝에 CPU/GPU load balancing 알고리즘을 중심으로 쓰고 framework는 들러리만 서는 형태로 논문을 제출하고 말았다. 그 이유는 '남들이 다 해놓은 거 짜집기한 것 아니냐'라는 내부 피드백을 넘어설 수가 없었고, 넘어설 수 없었던 이유는 설계 결과만 늘어놓는 것이 아니라 왜 좋은가에 대한 설명을 충분히 잘 드러나게 할 만큼 writing skill이 좋지 못함과 동시에 현실과 타협한 부분들이 너무 많았기 때문이다.

사실 이게 바로 내가 대학원에 온 후로 계속 고민하고 힘들어했던 부분이다. 지금 생각해보면, 이를 '새로운' 시스템 설계라고 논문의 형식으로 "잘" 주장하는 방법과 논문으로 썰을 잘 풀 수 있게 처음부터 고민하면서 시스템을 설계하는 방법을 나도 모르고 연구를 도와준 선배도 모르고 교수님도 잘 모르셨던 것 같다. (혹은 선배나 교수님은 경험을 통해 알고 있었더라도 그걸 남도 할 수 있게 전달하는 방법을 몰랐거나.) 실제로 코드를 작성하면서 세밀하게 내린 여러 결정들을 다시 머릿속에서 끄집어내서 왜 그게 좋은지 이유만 잘 붙여도 꽤 그럴싸해보일텐데, 문제는 코드를 '돌아만 가는' 것을 목표로 작성하다보니 이유를 충분할 고민할 시간 없이 작성한 legacy가 너무 커져버렸고, 논문을 실제 쓰는 시점이 되어서야 그런 legacy들에 대한 근거를 찾다보니 시간이 부족하고... 이런 악순환이 반복되며 시간을 너무 끌었다.

교수님과 개강 전날 책상에 네트워크·분산 시스템 분야의 여러 대가들이 써놓은 교과서를 주욱 늘어놓고 목차를 보면서 이번 학기 강의에는 어떤 내용들이 들어가야 할까 고민할 때, 눈에 딱 띄는 책이 있었다. MIT의 Jerome H. Saltzer 교수와 Fraans M. Kashoek 교수가 쓴 Principles of Computer System Design: An Introduction. 책 내용을 자세히 읽어보지는 못했지만 그냥 목차만 봐도, 첫 챕터 첫 문단만 봐도 눈물이 나더라. 왜 이런 걸, 이렇게 체계화해서 알려주는 사람이 없었는가 안타까워서 말이다. 오죽했으면 교수님께도 CS408이 이런 내용을 가르치도록 개편되었으면 좋겠다는 건의사항을 그 자리에서 드렸을 정도다.

나의 안타까움은 여기서 다음 질문들로 바뀐다:

  • 코딩을 잘 한다 또는 못 한다의 기준이 뭘까? 소프트웨어 엔지니어와 소프트웨어 아키텍트의 차이는 뭘까? 내 느낌에는 적어도 우리나라에서는 이에 대해 체계화된, 누구나 똑같이 이해할 수 있는 방식으로 설명해주고 또 시스템 설계자로서의 역량을 키워주는 학부 교과목이 존재하지 않는 것 같다.
  • 전산학과 대학원의 목표가 엔지니어의 양성인가 아키텍트의 양성인가 아니면 논문쓰는 연구자의 양성인가? 물론 학부와 대학원은 근본적으로 차이가 있지만, 전산과 대학원에서도 모두가 교수가 되기를 기대하지는 않는다. 연구주제를 가지고 실제 시스템을 만들어 팔도록 창업을 독려하는 경우도 있으니. 그런데 그런 사람들을 잘 키워내고자 한다면 논문을 잘 쓰는 방법보다는 시스템을 잘 설계하는 방법을 연습시키는 것이 맞지 않을까?
  • 논문은 근본적으로 새롭지만 일반화(혹은 객관화)될 수 있는 결과를 요구한다. 하지만 시스템 설계 아이디어는 몇가지 핵심 원리와 요소에서 벗어나기가 어렵고, 매우 맥락(시스템의 목적, 만드는 사람의 '코딩 능력', 사용자의 경험·배경 수준, 설치·운영 환경 등)에 민감하기 때문에 일반화하기 어렵다. 어지간히 썰 푸는 능력(맥락 자체의 중요성 설명)이 좋지 않으면 시스템 설계만을 가지고 논문을 쓰기는 매우 힘들다. (바로 내가 겪은 문제다) 이 간극을 어떻게 메꿔야 할까?