[번역] 프로그래머를 위한 카테고리 이론 - 0. 서문
    프로그래밍

    [번역] 프로그래머를 위한 카테고리 이론 - 0. 서문


    얼마 전부터 나는 프로그래머를 대상으로 하는 카테고리 이론에 대한 책을 작성하려는 아이디어를 떠올렸다. 즉 이 책은 컴퓨터 과학자가 아닌 프로그래머, 그리고 과학자보다는 엔지니어들을 대상으로 하는 책이다.

    분명 과학과 엔지니어링 사이에는 큰 간극이 존재한다. 게다가 나는 그 간극의 양쪽 끝에서 일해보기도 했기 때문에 다른 사람들에게는 이런 아이디어가 미친 생각처럼 보일 수도 있을 것이다. 하지만 나는 항상 이 이론을 제대로 설명하고 싶다는 강한 의지를 가지고 있었다.

    나는 단순한 설명의 달인인 물리학자 리처드 파인만을 굉장히 존경해왔다. 물론 내가 파인만처럼 잘 설명할 수는 없겠지만 그래도 한번 최선을 다 해볼 것이다.

    우선 카테고리 이론을 학습하려는 독자들에게 동기를 부여하기 위해 이 서문을 작성함으로써, 이 서문이 앞으로 활발한 토론과 피드백을 구할 수 있는 초석이 되기를 바란다.

    우선 다음 몇 문단을 통해 이 책이 여러분을 위해 작성된 것이며 당신이 “남는 시간”을 투자하는 것만으로도 가장 추상적인 수학 분야 중 하나를 배우는 것에 대해 전혀 거부감을 가질 필요가 없다는 것을 보여주려고 한다. 나의 이러한 낙관론은 관찰 끝에 나온 몇 가지 사실들에 기반을 두고 있다.

    첫째, 카테고리 이론은 매우 유용한 프로그래밍 아이디어들의 보물 창고이다. 이미 오래전부터 Haskell 프로그래머들은 이 아이디어들을 사용해왔고, 이제는 슬슬 이 아이디어들이 다른 언어로도 퍼지고 있기는 하지만, 이 과정은 느려도 너무 느리다. 우리는 이 전파 속도를 가속시켜야 한다.

    둘째, 수학에는 많은 분야가 있으며, 이 분야들은 모두 각기 다른 대상에 대한 연구를 하고 있다. 물론 여러분이 미적분학이나 대수학 같은 것들에 대한 알레르기가 있을 수는 있겠지만, 그렇다고 해서 카테고리 이론을 즐길 수 없는 것은 아니다.

    사실 카테고리 이론은 어떤 구체적인 계산과 같은 내용이 아닌 추상적인 구조에 대한 이야기를 하고 있기 때문에 특히 프로그래머의 사고방식과 잘 맞는 수학 분야이다. 카테고리 이론은 프로그램을 합성 가능하도록(composable) 만들 수 있는 구조에 대해서 다룬다.

    합성이라는 것은 카테고리 이론을 이루는 가장 근본적인 개념이며, 프로그래밍의 본질이기도 하다. 옛날옛적 몇몇 위대한 엔지니어가 서브루틴이라는 개념을 도입하기 이전부터 우리는 이미 합성이라는 행위를 하고 있었다.

    예전 구조적 프로그래밍의 원칙은 코드 블록이라는 개념을 합성할 수 있도록 만들어줌으로써 프로그래밍에 대한 혁신을 불러왔다. 그리고 이후 OOP(객체지향 프로그래밍)가 등장했으며, 이 또한 객체들을 합성하는 방법에 대한 이야기를 하고 있다.

    하지만 FP(함수형 프로그래밍)는 이를 넘어 함수와 대수적인 데이터 구조들을 합성할 수 있게 해주고, 심지어 동시성(concurrency) 또한 합성할 수 있도록 해준다. 이는 지금까지의 다른 프로그래밍 패러다임으로는 거의 불가능한 일이다.

    마지막으로 나는 수학을 프로그래머들에게 보다 재미있게 전달할 수 있는 비밀 무기를 하나 가지고 있다.

    만약 당신이 전문적인 수학자라면 모든 가정을 명확하게 정의하고 모든 주장을 정확하게 설명할 수 있어야 하며, 여기서 파생된 증명들은 엄격하게 구성할 수 있어야 한다. 하지만 오히려 이러한 수학의 특징들로 인해 일반인들이 수학과 관련된 논문이나 책을 이해하기란 결코 쉽지 않은 것이 현실이다.

    나는 물리학자 출신이며, 물리학은 이러한 수학의 틀을 벗어난 직관적 사고를 통해 놀라운 발전을 이루어냈다는 말을 먼저 하고 싶다. 수학자들은 위대한 물리학자 P.A.M 디랙이 미분 방정식을 풀기 위해 즉흥적으로 만들어낸 디랙-델타 함수를 보고 비웃었지만, 결국 디랙의 아이디어가 구체적인 형식을 갖춘 뒤 분포 이론이라는 완전히 새로운 미적분 분야로 정립된 이후에 그들은 더 이상 웃지 못했다.

    물론 Hand-waving하게 설명을 할 때는 잘못된 설명을 할 가능성이 있으므로, 이 책에서 나는 직관적인 설명이나 개념 뒤에는 사실 탄탄한 수학적 이론이 함께 존재한다는 것을 이야기해줄 것이다.

    💡 역주

    Hand wave는 “상대방이 이해하기 쉽도록 어려운 것을 간단하게 풀어서 설명한다”는 관용 표현이다.

    물론 이 글은 프로그래머들을 위한 카테고리 이론에 대한 이야기를 하고 있으니, 나는 앞으로 설명할 모든 주요 개념을 컴퓨터 코드와 함께 설명할 것이다.

    아마 여러분도 알고 있겠지만 함수형 언어는 명령형 언어에 비해 수학에 더 가까우며, 더 강력하게 추상화를 할 수 있는 힘을 가져다준다. 그래서 자연스럽게 “카테고리 이론을 이해하려면 Haskell을 배워야해”라고 말하고 싶은 유혹에 빠지게 된다.

    하지만 오히려 이런 생각들이 마치 함수형 프로그래밍 이외의 분야에서는 카테고리 이론이 적용될 수 없다는 오해를 불러일으킬 수도 있기 때문에 나는 가급적이면 많은 C++ 예제를 함께 제공해보려고 한다.

    물론 몇 가지 난해한 문법들을 극복해야할 수도 있고, 장황한 패턴들도 존재할 수 있으며, 높은 레벨의 추상화 대신 복사 붙여넣기를 해야할 수도 있겠지만, 뭐 그게 원래 C++ 프로그래머들이 하는 일이 아닌가?

    하지만 한 가지 알아둬야 할 점은 여러분이 Haskell 프로그래머가 될 필요까지는 없어도 C++로 구현할 아이디어들을 스케치하고 문서화하기 위해서는 결국은 Haskell이 필요하기 때문에 여전히 Haskell이 중요하기는 하다는 것이다.

    사실 이것이 내가 Haskell을 시작했던 이유이다. Haskell의 간결한 문법과 강력한 타입 시스템은 내가 C++의 템플릿, 데이터 구조 그리고 알고리즘을 이해하고 구현하는데에 큰 도움이 된다고 생각한다. 하지만 여러분이 이미 Haskell을 알고 있다고 기대하기는 어렵기 때문에 이런 것들에 대해서는 천천히 소개하고 진행하며 설명해나가려고 한다.

    만약 여러분이 경력직 개발자라면 “지금까지 나는 카테고리 이론이나 함수형 개념같은 것들을 몰라도 코딩하는데는 문제가 없었는데, 도대체 뭐가 변한걸까?”라는 생각이 들 수도 있다. 하지만 이미 여러분은 알게 모르게 기존의 명령형 언어들에 계속 해서 함수형 개념이 도입되고 있다는 사실을 느끼고 있을 것이다.

    객체 지향 프로그래밍의 최후의 보루로 여겨졌던 자바에도 C++의 람다(Lambda)와 같은 개념이 추가되었으며, C++의 람다는 변화하는 세상을 따라잡기 위해 몇 년에 한번씩 새로운 표준이 나올만큼 미친 속도로 발전하고 있다.

    이러한 모든 현상들은 급격한 변화, 흔히 물리학자들이 이야기하는 “상전이(Phase Transition)”를 준비하는 과정이다. 물을 계속 가열하면 결국 끓기 시작하는 것처럼 말이다. 우리는 이제 점점 더 뜨거워지는 물 속에서 계속 헤엄을 칠지, 혹은 다른 대안을 찾아보기를 시작해야할지 결정해야하는 개구리의 입장에 놓여있다.

    1

    이러한 큰 변화를 주도하는 힘 중에 하나는 바로 멀티코어(multicore) 혁명이다. 기존의 주류 프로그래밍 패러다임이었던 객체지향 프로그래밍은 동시성과 병렬성 영역에서 아무런 이점을 제공하지 못 하며, 오히려 위험한 버그를 발생시킬 수 있는 설계를 하게 되기 쉽상이다. 결국 객체지향의 기본 컨셉은 불필요한 정보를 은닉하는 것인데, 이러한 특성이 공유(Share), 변이(Mutation)와 결합되면 결국 데이터 레이스(Data race)가 발생하게 된다.

    💡 역주

    데이터 레이스(Data Race)란 여러 개의 쓰레드나 프로세스가 하나의 자원에 접근하려고 할 때 발생하는 Race Condition을 의미한다.

    물론 뮤텍스(Mutex)와 뮤텍스가 보호할 데이터를 결합하는 것은 좋은 아이디어이지만, 불행하게도 락(Lock)은 합성이 불가능하고 락을 은닉했다가는 데드락(Deadlock)이 발생할 가능성이 커져 디버깅을 더더욱 어렵게 만든다.

    하지만 꼭 이러한 동시성 이슈가 아니더라도, 점점 더 복잡해지는 소프트웨어 시스템이 명령형 패러다임의 확장성의 한계가 어디까지인지를 시험하고 있다. 간단히 이야기하자면 사이드이펙트의 관리가 점점 더 어려워지고 있다.

    사이드이펙트를 발생시키는 함수가 편리하기도 하고 작성하기도 쉽다는 사실은 인정한다. 원칙적으로 이러한 이펙트들은 함수의 이름이나 주석으로 표현될 수 있다. 예를 들어 SetPassword 나 WriteFile 같은 함수들은 명백하게 함수 외부의 상태들은 변경하고 사이드이펙트를 발생시키지만, 이미 우리는 이런 함수들을 다루는 것에 익숙하다.

    하지만 이렇게 사이드이펙트를 발생시키는 함수들을 다른 사이드이펙트를 발생시키는 함수와 합성하다보면 점점 문제가 복잡해진다. 사이드이펙트가 본질적으로 나쁘다는 이야기는 아니지만, 이런 이펙트들은 예측하기가 어렵기 때문에 큰 규모의 어플리케이션에서는 관리하기가 거의 불가능하다는 것이 문제이다. 즉, 모든 명령형 프로그래밍은 사이드이펙트를 피할 수 없지만, 사이드이펙트는 확장이 불가능하다는 것이다.

    하드웨어의 변화, 그리고 점점 더 복잡해지는 소프트웨어의 특성으로 인해 우리는 프로그래밍의 기반을 이루는 것이 무엇인가에 대해 다시 한번 생각해볼 필요가 생겼다.

    마치 유럽의 위대한 고딕 대성당을 짓던 건축가들처럼 우리는 재료와 구조에 대해 한계까지 기술을 연마해왔다. 현재까지도 미완성된 프랑스의 보베 대성당은 이러한 인간의 한계에 대한 투쟁을 잘 보여주는 사례이다. 보베 대성당은 이전에 지어진 그 어떤 성당보다 더 높고 경이로운 성당을 짓기 위해 건설되었지만 몇 차례의 붕괴 사고를 겪었다. 철제와 목재로 지지대를 만들어 계속 붕괴가 진행되는 것은 막았지만 여전히 많은 문제가 있다는 것은 분명하다.

    2 임시 조치로 붕괴를 방지하고 있는 보베 대성당의 모습

    현대적인 관점에서 보면 고딕 구조물이 재료 공학, 컴퓨터 모델링, 유한요소해석, 일반 수학과 물리학의 도움 없이도 성공적으로 완성되었다는 것은 기적에 가깝다. 나는 후대의 사람들도 우리가 복잡한 운영체제, 웹 서버, 그리고 인터넷 인프라를 구축하는 과정에서 사용해왔던 프로그래밍 기술들에 대해서 감탄해주길 바란다.

    아니, 그들은 감탄할 수 밖에 없을 것이다. 왜냐하면 우리는 매우 얄팍한 이론적 기초 위에서 이 모든 것들을 만들어왔기 때문이다. 하지만 우리는 결국 앞으로 더 나아가기 위해 이러한 기초들을 제대로 고쳐야 할 필요가 있다.

    원문 보기

    👉 Category Theory for Programmers

    Evan Moon

    🐢 거북이처럼 살자

    개발을 잘하기 위해서가 아닌 개발을 즐기기 위해 노력하는 개발자입니다. 사소한 생각 정리부터 튜토리얼, 삽질기 정도를 주로 끄적이고 있습니다.