- 웹 연재가 끝난 뒤에도 Crafting Interpreters는 실제 책이 되기까지 15개월의 추가 작업이 필요했고, 최종적으로 인쇄본·전자책·PDF로 완성됨
- Markdown과 PNG 묶음을 책으로 바꾸려면 Dart 빌드 시스템, InDesign XML 가져오기, JavaScript 자동화, 조판 검증까지 새로 마련해야 했음
- 최종 결과물은 8×10인치, 640페이지, 20만 단어 이상, 코드 스니펫 1,133개와 수백 개의 삽화를 담아 일반 웹 콘텐츠보다 훨씬 까다로운 레이아웃 제약을 가짐
- 전체 재검토 5개월, 전문 카피에디팅, 2개월 조판, 2주 색인 작업, 교정쇄 확인과 PDF 비교 자동화가 이어짐
- 자체 출판 기술서는 글쓰기만으로 끝나지 않으며, 빌드·레이아웃·검증·배포 자동화가 책의 품질과 완성도를 좌우함
웹 콘텐츠 완성 뒤에도 남은 작업
- Crafting Interpreters의 본문은 이미 완성됐지만, 당시 결과물은 Markdown과 PNG 파일을 Python 코드로 웹사이트에 변환하는 형태였음
- 목표는 처음부터 실제 종이책이었고, 웹에 마지막 장을 올린 뒤 약 한 달 동안 휴식함
- 거의 4년 동안 매일 글을 쓴 뒤라 크게 지쳐 있었고, 2020년 초의 상황도 작업을 이어가기 어려운 시기였음
Dart로 다시 만든 빌드 시스템
- 독자들이 GitHub 이슈로 신고한 오타와 오류를 먼저 고침
- 이후 책의 전체 빌드 시스템을 Dart로 다시 작성함
- 첫 책의 빌드 스크립트는 장별 Markdown 파일을 HTML로 렌더링하고 코드 조각을 끼워 넣는 단일 Python 스크립트였음
- Crafting Interpreters는 두 개의 완전한 인터프리터 코드를 30장에 걸쳐 점진적으로 구성해야 해서 더 복잡한 빌드가 필요했음
- 새 빌드 시스템은 특정 장이나 장 내부 특정 지점까지의 인터프리터 코드를 프로그램으로 출력하고, 이를 컴파일해 자동 테스트에 돌릴 수 있게 함
- Python 기반 도구는 저자의 숙련도 기준에서 유지보수 부담이 컸고 속도도 느렸음
- Dart 버전은 원하는 HTML과 구문 강조 코드를 정확히 생성했으며, 기존 Python 버전보다 10배 빠름
- Markdown 처리 제어권이 커진 점은 이후 InDesign용 XML 내보내기에서도 유용했음
책 디자인과 판형 결정
- 책 디자인은 웹 개발이나 게임 개발처럼 먼저 프레임워크를 만들고, 그 안에 콘텐츠를 붓는 작업에 가까웠음
- InDesign에서는 페이지의 여백과 그리드를 정하는 master, 텍스트와 객체의 글꼴·스타일·색상을 정하는 style을 설정함
- Crafting Interpreters는 디자인 난도가 높은 요소가 많았음
- 본문 텍스트가 많음
- 특정 문장, 코드, 삽화를 바로 옆에서 설명하는 긴 aside가 많음
- 코드가 많고, 각 코드 스니펫 옆에 결과 프로그램에서의 위치 설명이 붙음
- 가로 폭은 코드의 긴 줄, aside 영역, 두꺼운 책의 안쪽 여백을 함께 고려해야 했음
- 저자의 책장에 있던 일반적인 CS 교재는 7.5인치 폭이 많았지만, 코드와 aside와 여백을 넣기 어려워 8인치 폭으로 결정함
- 자가 출판에서는 KDP와 IngramSpark가 지원하는 제한된 판형을 써야 했고, 8인치 폭에서 합리적인 선택지는 8×10인치였음
- 세로 방향은 고전적인 12pt baseline grid에 맞춰 텍스트를 정렬함
InDesign으로 옮기기 위한 XML 파이프라인
- InDesign은 Markdown이나 저자의 빌드 시스템을 직접 이해하지 못해 수동 복사·붙여넣기는 현실적이지 않았음
- InDesign은 XML 가져오기와 태그별 스타일 자동 적용을 지원함
- 다만 XML 지원은 중첩 태그 처리에 제약이 있어, HTML처럼 헤더 안에 이탤릭 태그를 중첩하는 방식을 제대로 처리하지 못함
- 저자는 빌드 시스템을 직접 제어할 수 있었기 때문에 InDesign이 받아들이기 쉬운 태그를 생성하는 custom XML exporter를 작성함
InDesign JavaScript 자동화와 한계
- XML 가져오기는 InDesign의 “story”, 즉 메인 텍스트 박스를 따라 이어지는 하나의 연속 텍스트 흐름을 만들어줌
- 본문과 코드 스니펫은 메인 흐름에 들어가지만, aside와 location marker는 옆으로 빼내야 했음
- 이전 책에서는 aside를 수동으로 잘라내 새 텍스트 박스에 붙였지만, 이번 책은 코드 스니펫이 1,133개라 같은 방식이 불가능했음
- InDesign은 JavaScript 스크립팅을 지원하지만 문서와 디버깅 환경이 매우 빈약했음
- 디버거 없음
- 스택 트레이스 없음
- 일반적인 debug print 없음
alert()만 사용할 수 있고 호출 시 스크립트가 멈춤
- JavaScript 스크립트는 aside와 location marker를 찾아 메인 텍스트 흐름에서 빼내고 별도 텍스트 박스로 만들었음
- 위치 지정 자동화는 끝까지 완성하지 못함
- InDesign의 anchor 기능과 Object Style로 배치하려 했으나, 일부 경우 주변 코드 스니펫의 테두리가 사라지는 문제가 생김
- 결국 일부 location tag는 수동으로 위치를 잡아야 했음
편집과 카피에디팅
- 본문 전체를 처음부터 끝까지 다시 읽는 편집 패스를 진행함
- 각 장은 작성 중 이미 세 번의 draft를 거쳤지만, 전체 책의 흐름을 보기 위해 한 번 더 검토함
- 이 작업에는 5개월이 걸렸고, 반복된 농담 대부분을 수정함
- 이후 전문 카피에디터 Kari Somerton을 고용함
- 일반적인 편집 워크플로는 Microsoft Word와 Track Changes가 많지만, 저자는 plaintext와 Git 기반 워크플로를 유지하고 싶어 했음
- Kari Somerton은 Git과 맞춤 빌드 시스템을 익힌 뒤 책 전체를 검토했고, 수백 개의 오류를 찾아냄
- 이미 네 번의 draft와 독자들의 수백 개 이슈가 있었음에도 전문 카피에디터가 많은 문제를 발견함
640페이지 조판의 제약
- 단어를 충분히 다듬은 뒤 InDesign으로 장별 조판을 진행함
- 장별 작업은 다음 흐름으로 반복됐음
- 새 InDesign 파일 생성
- XML 내보내기
- XML을 InDesign으로 가져오기
- JavaScript로 aside와 location marker를 빼내기
- 사이드바 요소 anchor 설정
- 페이지 끝의 공백 조정
- 앞의 다섯 단계는 장당 약 30분이면 처리할 수 있었지만, 마지막 공백 조정이 가장 어려웠음
- 책 조판에는 여러 수직 배치 제약이 있음
- 삽화를 페이지 중간에서 자를 수 없음
- aside는 한 페이지 안에 들어가는 편이 이해하기 쉬움
- 코드 스니펫도 가능하면 페이지를 넘겨 쪼개지 않는 편이 좋음
- 헤더만 페이지 끝에 남는 상황을 피해야 함
- widows and orphans도 피하는 편이 좋음
- InDesign은 이런 상황에서 콘텐츠를 뒤 페이지로 밀어내지만, 그러면 페이지 하단에 큰 흰 공간이 생김
- 삽화와 코드 스니펫은 서로 얽힌 bin-packing 문제처럼 작동했고, 이 때문에 전체 장 조판에 2개월이 걸림
- 공백을 줄이기 위해 코드 스니펫을 둘로 나누거나, 이미지 주변 여백을 조정하거나, 삽화 높이를 바꾸는 작업이 필요했음
삽화, 색인, 앞뒤 부속물
- 삽화는 인쇄 친화적인 흑백 펜 그림으로 선택했고, 처음 스캔할 때 1200 DPI로 가져왔음
- 고해상도 비트맵으로 내보내는 것은 쉬웠지만, 페이지 레이아웃에 배치하는 작업은 어려웠음
- 본문이 “Figure 123 참고” 방식이 아니라 바로 옆의 삽화를 직접 가리키는 문장 구조였기 때문에, 삽화가 가까운 위치에 있어야 했음
- 전문 색인 작성자를 고용하지 않고 직접 2주 동안 모든 장을 다시 훑으며 색인을 만들었음
- InDesign의 색인 기능은 선택한 텍스트를 색인 항목으로 만들고 전체 색인을 생성할 수 있었지만, 항목 추가 자체는 반복적이고 지루한 작업이었음
- 책 뒤에는 색인이 들어갔고, 앞에는 제목 페이지, 저작권 페이지, 헌정, 감사의 글, InDesign이 생성한 목차가 들어감
표지 디자인
- 저자는 기술서 표지의 예술성이 소설만큼 중요하지 않을 수 있다고 봤지만, 교수 지위로 판매를 강제할 수 있는 상황이 아니어서 표지에 시간을 많이 들임
- 처음에는 직접 찍은 사진을 표지에 쓰려 했지만, 적절한 사진을 찾지 못함
- 최종적으로 책의 시각 언어인 펜과 잉크 삽화를 사용하기로 결정함
- 컴파일 과정을 설명하는 산 그림을 더 크고 자세하게 다시 그렸고, 제목 글자도 새로 손글씨 느낌으로 만들었음
- 제목은 Acumin Pro Extra Condensed를 출력해 손으로 따라 그려 불완전한 느낌을 줬고, 1950년대 등사판 스카우트 매뉴얼 같은 색상 팔레트를 골랐음
교정쇄와 PDF 변경 검증
- PDF를 KDP에 업로드하고 교정쇄를 주문했으며, 일주일 뒤 무거운 박스를 받음
- 실물 책을 보고 나서야 프로젝트의 규모를 데이터 파일이 아닌 물리적 물체로 체감함
- 조판 과정에 수작업이 많았기 때문에 교정쇄를 직접 읽으며 오류를 찾고 sticky note로 표시함
- InDesign 파일은 Git 저장소에 넣었지만, 거대한 불투명 바이너리 파일이라 소스 코드처럼 diff를 볼 수 없었음
- InDesign은 실제 변경이 없어 보여도 파일을 바꾸는 경우가 있어, 어떤 변화가 생겼는지 확인하기 어려웠음
- 저자는 Dart script를 작성해 책 PDF의 모든 페이지를 추출하고 하나의 큰 PNG 타일 이미지로 만들었음
- 커밋마다 PDF를 내보내 타일 이미지를 만들고, Photoshop action으로 두 이미지의 다른 픽셀에 빨간 테두리를 그려 변경된 페이지를 찾음
- 이 방식은 세부 변경 내용을 직접 알려주지는 않았지만, 어느 페이지를 시각적으로 점검해야 하는지 알려줬고 예상한 변경만 들어갔는지 확인할 수 있게 함
전자책과 출시
- 인쇄판 교정 수정이 끝난 뒤 Kindle과 EPUB 전자책도 제작함
- 자체 빌드 시스템을 수정해 EPUB이 요구하는 오래된 XHTML, 메타데이터, manifest를 내보낼 수 있게 함
- 몇 가지 명령줄 실행 후 Kindle과 EPUB 전자책을 만들었고, 여러 리더에서 테스트하며 CSS를 조정함
- 최종 파일을 준비한 뒤 책 웹사이트의 첫 페이지를 구매처로 연결하도록 업데이트하고, 사진과 반응형 레이아웃도 정리함
- 스토어 업로드와 사이트 업데이트, 메일링 리스트 안내까지 끝난 뒤 책이 “정말로” 완성된 상태가 됨
이후 계획
- 마지막 장을 끝낸 뒤에도 사람들은 다음 작업이나 다음 책의 주제를 물었음
- 저자는 6년 동안 하나의 프로젝트에 매달린 뒤 당분간 새 책을 계획하지 않으려 함
- 팬데믹 동안 미룬 일도 많았고, 당분간 무엇을 할지 정하지 않은 채 쉬려는 계획임
- 음악 만들기, 낚시, 친구와 가족과 시간 보내기, roguelike 프로젝트 작업 같은 가능성을 언급하지만, 무엇을 할지는 즉시 결정하지 않음
- 언젠가 다시 큰 프로젝트를 하고 싶어질 수는 있지만, 한 프로젝트에 다시 6년을 쓰고 싶지는 않다고 밝힘