Refactoring English: Month 1

Michael Lynch

리팩터링 잉글리시: 첫 달

한 줄 요약

책의 첫 번째 챕터를 공개했습니다.

하이라이트

  • 책의 첫 번째 챕터를 공개했는데 반응이 만족스러웠습니다.
  • 책 표지 디자이너를 고용하려던 시도는 실패했습니다.
  • PicoShare에서 대용량 파일을 지원하는 방법을 찾은 것 같습니다.

목표 평가

매달 초에 이루고 싶은 목표를 정합니다. 이번 달 목표 달성 결과는 다음과 같습니다.

Refactoring English 두 챕터 완성하기

  • 결과: 한 챕터를 완성했고 다음 챕터는 75% 진행했습니다.
  • 점수: B

첫 번째 챕터는 계속 고치고 싶은 부분이 나와 예상보다 오래 걸렸습니다. 일주일 정도 쉬면서 두 번째 챕터를 쓰다가 다시 돌아오니 오히려 도움이 되었습니다.

디자이너와 함께 Refactoring English 표지 디자인 완성하기

  • 결과: 표지 디자인을 직접 하기로 했습니다.
  • 점수: C

디자이너와 작업을 어느 정도 진행하다가 방향성이 마음에 들지 않아 중단했습니다. 일단 표지는 직접 만들기로 했습니다.

Refactoring English 첫 번째 챕터를 마치며

Refactoring English의 첫 번째 챕터를 공개했습니다. 챕터 제목은 “소프트웨어 튜토리얼 작성 규칙”이며, 수년간 튜토리얼을 따라 하면서 잘된 점과 아쉬운 점을 관찰한 경험을 바탕으로 썼습니다.

첫 챕터에 대한 긍정적인 반응

챕터에 대한 반응은 기대했던 것보다 훨씬 좋았습니다. 튜토리얼 규칙을 나열한 글이라 인터넷을 뜨겁게 달굴 거라곤 기대하지 않았는데, 잘 맞을 것 같다고 생각한 몇몇 사이트에서 꽤 괜찮은 반응을 얻었습니다.

제가 가장 중요하게 보는 지표는 메일링 리스트 구독자 수입니다. 글을 올린 다음 주에 신규 구독자가 245명 늘었고, 책 메일링 리스트 전체 구독자 수가 31% 증가했습니다.

첫 번째 챕터 공개 후 책 메일링 리스트 구독자 수가 크게 늘었습니다.

글을 공개한 뒤 어떻게 다듬어야 할까?

몇 년 전 Redis의 창시자인 Salvatore Sanfilippo는 프로그래밍을 잠시 멈추고 SF 소설을 썼습니다. 소설을 쓰는 동안 그는 이렇게 말했습니다:

글쓰기와 프로그래밍의 가장 날카로운 차이는, 한 번 쓰고 편집해 완성된 소설은 대체로 불변한다는 점이라고 생각한다.

Salvatore는 이어서 프로그래머가 소설가에게 배워 앱이 완성된 뒤 핵심 로직을 다시 쓰려는 충동을 참아야 한다고 말했습니다. 저는 오히려 정반대 교훈을 얻었습니다. 저자는 프로그래머처럼 책을 더 반복적으로 써야 한다는 것입니다.

Refactoring English에서는 챕터를 거의 완성된 상태로 공개하려고 하지만, 독자 피드백이 글에 반영되도록 하고 싶습니다.

챕터를 계속 수정하면서 공개하니 이전에 겪어보지 못한 문제가 생겼습니다. 댓글 흐름이 꼬이는 것입니다. Hacker News, Lobste.rs, reddit에서 댓글 작성자들은 “조건부 로직은 컴퓨터에게 맡겨라”라는 제 주장에 반박했는데, 그 말이 맞다고 생각합니다. 가장 설득력이 약한 부분이었기 때문에 아예 삭제했습니다.

문제는 그 토론을 읽는 사람이 글에는 없는 주장에 왜 사람들이 반박하는지 의아해한다는 점입니다.

제가 생각한 최선의 해결책은 글 하단에 수정 사항을 알리는 메모를 넣어 아직 책을 수정 중임을 밝히고, 원본 링크와 주요 수정 목록을 함께 제공하는 것입니다.

피드백을 줄 독자를 어떻게 계속 찾을까?

지금까지는 독자 피드백을 바탕으로 반복 개선하려는 계획이 잘 작동하고 있다고 느낍니다.

첫 번째 챕터로 공개한 내용에는 만족하지만, 독자들에게서 수정을 도와줄 깊이 있는 비판도 많이 받았습니다.

‘좋아, 같은 채널에 미리보기 챕터를 계속 공유하면 되겠지’라고 생각했습니다.

그런데 목차를 다시 보니 첫 번째 챕터를 공유했던 채널에 어울릴 다른 챕터가 없었습니다. 그런 사이트 대부분에는 “코드가 없으면 여기에 올릴 글이 아니다”라는 명문화된 혹은 암묵적인 규칙이 있습니다. 예를 들어 /r/programming에서는 제가 수동태를 왜 그토록 싫어하는지에 대해 열정적으로 쓴 챕터를 반기지는 않을 겁니다.

한 가지 떠오른 아이디어는 다른 작가들을 위해 프리랜서 편집 일을 하면서 그 경험을 Refactoring English에 반영하는 것입니다.

다만 ‘편집’이 제가 잘할 수 있는 일을 정확히 설명하는 말 같지는 않습니다. 사람들은 ‘에디터’라고 하면 제가 대신 글을 다듬어 줄 거라고 생각합니다. 제가 정말 하고 싶은 일은 글의 문제점을 짚어내고, 스스로 개선할 수 있도록 원칙과 기법을 설명해 주는 것입니다. 이걸 뭐라고 불러야 할지 모르겠습니다. 글쓰기 멘토링일까요, 코칭일까요?

어쨌든 이 제안이 흥미롭게 들린다면 연락해 주세요. 블로그 글, 문서, 그 외 소프트웨어 관련 글쓰기라면 무엇이든 도울 수 있습니다. 더 많은 독자를 끌어모으고 글을 더 흥미롭게 만드는 방법을 알려드리겠습니다. 기본적으로 이 블로그에서 제 글쓰기가 마음에 드셨다면, 여기서 사용한 기법을 그대로 알려드릴 수 있습니다.

  • 두 차례 리뷰에 100달러를 받습니다.
    • 초안 리뷰와 피드백을 반영한 수정본 리뷰가 포함됩니다.
  • 글 분량은 최대 2,500단어까지 가능합니다.
  • 비용은 주로 의지를 다지기 위한 장치이므로, 100달러가 부담된다면 다른 방법을 찾아볼 수 있습니다.

Reedsy를 통해 책 표지 디자이너를 고용했던 좋지 않은 경험

11월에 책 작업을 하면서 스스로에게 전문적으로 디자인된 표지가 필요하다고 설득한 것이 작업에 방해가 된 일 중 하나였습니다. 과정은 11월에 시작했지만 실제 작업은 12월에 이루어졌습니다.

디자이너는 Write Useful Books 커뮤니티에서 여러 사람이 추천한 플랫폼인 Reedsy에서 찾았습니다. 대체로 비싸지만 그만한 가치가 있다는 평가였습니다.

원하는 내용을 담은 디자인 브리프를 작성해 Reedsy의 디자이너 네 명에게 보냈습니다. 예산은 350~650달러로 적어 냈습니다. 한 디자이너는 최고 예산보다 20% 높은 금액을 제안하면서 “네, 해드릴 수 있습니다”라는 상투적인 답변만 보냈고 브리프를 읽었다는 흔적은 없었습니다. 다른 한 명은 예산이 너무 낮다며 거절했고, 한 명은 아예 답이 없었습니다.

유일하게 유효한 제안은 Gary에게서 왔는데, 350파운드(약 434달러)에 표지 작업을 하겠다고 했습니다. 그는 제 브리프의 세부 내용을 언급한 정성스러운 메시지를 보냈고, 포트폴리오에는 수십 개의 책 표지가 있었으며 Reedsy에서 평점 5.0 만점을 받고 있었습니다. 한 달 일정에 비용을 세 번에 나누어 결제하자고 제안했고, 괜찮아 보여서 그를 고용했습니다.

Gary와의 작업

일주일이 지났지만 Gary에게서 아무 연락이 없었습니다. 첫 번째 결제가 자동으로 청구된 뒤에야 초기 시안에 대한 일정을 물었고, Gary는 다음 날 컨셉을 보내주겠다고 했고 실제로 그렇게 했습니다.

Reedsy를 통해 고용한 디자이너가 보내온 초기 책 표지 시안들

시안 1은 괜찮아 보였지만, 제가 브리프에서 언급했던 Beautiful Code를 너무 노골적으로 베낀 느낌이었습니다. 나머지는 기대에 못 미쳤지만, 브리프에 더 시간을 들이지 않은 제 탓이라고 생각했습니다.

시안들을 검토하면서 제가 전달하고 싶은 핵심이 ‘신중하고 의도적인 작업’이라는 생각이라는 걸 깨달았습니다. 선 정원 이미지인 시안 6과 점토 틀 이미지인 시안 5가 방향성이 맞다고 느껴 그쪽으로 더 발전시켜 보자고 했습니다. 돌을 조각하는 조각가 이미지를 제안했습니다.

또 일주일이 지나 Gary는 선 정원 아이디어를 살짝 변형한 시안을 보냈습니다. 조각가 컨셉도 시도했는데, 끌과 가공되지 않은 돌 사진이었습니다. 돌이 전혀 조각되지 않은 상태라 신중한 작업이라는 느낌을 전하지 못했습니다.

다음 주는 크리스마스 주간이었고, 프로젝트가 12월 30일 마감일까지 끝나지 않을까 걱정이 되기 시작했습니다. Gary는 크리스마스 직전 월요일에 이메일을 보내 12월 27일에 업무에 복귀하니 일정에는 차질이 없다고 했습니다.

27일이 다 가도록 Gary에게서 연락이 없었고, 난처한 상황에 처했다는 걸 깨달았습니다.

제 시간인 미국 동부 시간으로는 금요일 오후 4시였지만, Gary는 영국에 있어 그의 업무 시간은 이미 한참 지나 있었습니다. Reedsy는 월요일 동부 시간 정오에 자동으로 결제를 청구할 예정이었습니다. Reedsy에서 결제에 이의를 제기할 수 있는 마지막 시점은 청구 24시간 전이라, 작업을 마무리할 수 있는 영업일은 하루도 남지 않은 셈이었습니다.

Reedsy 고객 지원에 마지막 결제를 일주일 미뤄달라고 요청했습니다. Gary가 작업을 전달하지 않았다는 이유에서였습니다. Reedsy 측은 Gary와 직접 해결하라고 했습니다. 다음 영업일까지 Gary의 답변을 기다리면 결제를 미루기엔 너무 늦는다고 설명했지만, Reedsy 지원팀은 그래도 Gary와 먼저 해결해 보라고 고집했습니다.

금요일 동부 시간 오후 5시에 Gary에게 이메일을 보냈고, 그는 “회사 근무 시간”대로 일하지 않으니 주말에 작업해서 기한 내에 끝낼 수 있다고 답했습니다. 그는 호의로 결제를 미뤄주었지만, 제가 Reedsy에 불만을 제기한 것에 대해 언짢아하는 기색이었습니다.

반면 저는 가능한 정규 근무 시간을 지키려고 하고, 주말을 Gary와 함께 이 프로젝트를 급히 마무리하는 데 쓰고 싶지 않았습니다. 월요일에 확인해 보니 Gary가 두 컨셉에 대한 업데이트를 보내왔는데, 둘 다 꽤 평범했습니다. 하나는 누가 봐도 AI로 생성한 듯 비현실적이었고, 다른 하나는 제가 요청한 톤을 전혀 담지 못했습니다.

이미지가 AI로 생성된 것인지, 그리고 브리프에서 명시한 라이선스 요구사항을 충족하는지 물었더니, 그때부터 Gary는 말을 얼버무렸습니다. 그래서 프로젝트 취소를 요청했습니다. 이미 지불한 231파운드(약 287달러)는 그대로 가져가되 마지막 결제를 취소하고 프로젝트를 종료하자고 제안했고, 그는 동의했습니다. 그렇게 일단락되었습니다.

Gary에게 모든 항목에 3점 리뷰를 남겼습니다. 끔찍하다고 생각하지는 않았지만, 그저 그럭저럭이었고 일정 공유도 잘 못했습니다. 제 리뷰는 공개되어 있지만, Reedsy는 제가 3점을 줬는데도 Gary가 여전히 평점 5.0 만점이라고 표시합니다. 다른 리뷰는 네 개뿐인데도 말입니다.

제가 Gary에게 3점 리뷰를 남겼음에도 그의 평점은 여전히 리뷰 5개에 평점 5.0 만점으로 표시됩니다.

직접 만든 책 표지

Gary와의 작업이 끝나고 직접 표지를 만들어 보기로 했습니다. Unsplash에서 로열티 프리 이미지 중 조용하고 신중한 작업의 느낌을 담은 사진을 찾아 텍스트를 더했습니다.

아마추어처럼 보이는 건 알지만, Gary의 작업에서 기대했던 만족도의 80% 정도는 충족합니다. 게다가 이건 무료였고 한 시간 만에 만들었습니다. 일단 임시 표지라고 생각하고 있습니다. 나중에 언제든 다른 사람을 고용하거나 더 시간을 투자하면 됩니다.

사이드 프로젝트

PicoShare에서 대용량 파일을 지원하도록 만들기

PicoShare는 제가 몇 년 전에 만든, 인터넷으로 파일을 공유하기 위한 미니멀하고 셀프 호스팅이 쉬운 웹 앱입니다. 지금도 매주 사용하고 있습니다.

PicoShare에 대해 살짝 부끄러운 점은 대용량 파일에서 확장성이 떨어진다는 것입니다. 공유 CPU와 256MB RAM을 쓰는 VM에서는 약 1GB까지의 파일은 문제없이 잘 작동합니다. 1GB보다 큰 파일을 업로드하려고 하면 대개 RAM이 고갈되어 충돌합니다. 하드웨어를 더 투입하면 해결할 수 있지만, PicoShare가 크기 제한 없이 큰 파일 업로드를 지원하면 더 좋을 것입니다.

이 문제를 몇 번 파고들어 봤는데, 제 강한 추측으로는 성능 문제가 PicoShare가 모든 파일 데이터를 SQLite에 저장하기 때문이라는 것입니다. 흔한 선택은 아니지만, 이렇게 하면 파일 데이터를 포함한 앱의 전체 상태가 SQLite 데이터에 담기게 됩니다. 그래서 PicoShare가 방대한 데이터를 SQLite에 쓰려다 RAM이 고갈되어 죽는 것으로 보입니다.

SQLite의 스트리밍 I/O API를 사용하면 데이터베이스에 더 효율적으로 쓸 수 있을 것 같아 관심이 있었습니다. 하지만 PicoShare를 Go로 작성했고, 제가 쓰던 Go용 SQLite 드라이버는 스트리밍 I/O API를 지원하지 않았습니다.

다행히 Nuno Cruces가 스트리밍 I/O를 지원하는 Go용 새 SQLite 드라이버를 공개했고, PicoShare를 그의 라이브러리로 포팅하는 것을 도와주겠다고 제안했습니다. 9월에 그와 함께 작업을 조금 진행해 어느 정도 진전이 있었지만, 스트리밍 I/O를 써도 여전히 PicoShare가 대용량 파일에서 메모리를 고갈시킨다는 걸 알게 되었습니다.

Nuno는 파일을 나눠 청크 단위로 SQLite에 쓰면 RAM 사용량을 줄일 수 있을 거라고 제안했습니다. 사실 현재 구현에서도 이미 그렇게 하고 있습니다만, 스트리밍 I/O의 의미 체계가 달라 섬세한 코드를 대거 다시 써야 했습니다. 그래서 그때는 기력이 떨어져 작업을 잠시 접어 두었습니다.

12월에 스트리밍 I/O 문제를 다시 새로운 시각으로 들여다봤습니다. 청크 처리 문제가 생각보다 간단하다는 걸 깨달았습니다. PicoShare는 대용량 파일을 읽을 때는 RAM이 고갈되지 않고 쓸 때만 고갈되었습니다. 그래서 더 효율적인 스트리밍 API로 쓰기 부분만 다시 구현하면 되었습니다.

스트리밍 I/O로 파일을 청크 단위로 쓰는 작업은 SQLite 기본 API로 구현했던 것보다 더 간단했습니다. 처음에는 SQLite 데이터베이스를 io.Writer 객체로 추상화해 io.Copy로 데이터를 밀어 넣는 게 가장 쉬운 방법이라고 생각했습니다. 하지만 이번에는 io.Copy를 거치지 않고 직접 모든 쓰기를 수행하는 편이 더 쉽다는 걸 깨달았습니다.

스트리밍 I/O 버전은 제한적인 테스트에서는 안정적으로 동작했지만, 더 광범위한 테스트가 필요합니다. 문제는 집 인터넷의 업로드 속도가 너무 느리다는 것이어서, fly.io에서 데스크톱 OS를 실행해 VNC로 원격 접속하는 방법을 마련 중입니다.

마무리

무엇을 해냈나?

배운 점

  • 그래픽 디자이너 고용 시 교훈
    • 전문가를 고용하기 전에 직접 임시 버전을 만들어 볼 것을 고려하기.
    • 대금은 날짜가 아니라 프로젝트 마일스톤에 연동하기.
    • 디자이너가 AI 생성 이미지나 AI 보조 이미지 합성을 사용하는 것이 괜찮은지 명확히 밝히기.
    • 사진이나 폰트 같은 서드파티 에셋의 라이선스 정보를 반드시 확인해야 함을 명확히 하기.
      • 브리프에서 모든 에셋이 호환 가능한 라이선스를 가져야 한다고 적었습니다.
      • 계약자가 라이선스를 준수한다는 구두 약속만 하는 것이 아니라 라이선스 정보를 직접 전달해야 한다고 명시하는 편이 더 좋았을 것입니다.
    • 크리스마스 직후에 끝나도록 프로젝트 일정을 짜지 않기.
    • Reedsy는 의뢰인보다 계약자에게 크게 유리하도록 경험이 설계되어 있습니다.

다음 달 목표

  • 2024년 연간 회고 블로그 글 게시하기.
  • 책의 다음 챕터 한 개 완성하기.
  • 독자 피드백을 바탕으로 튜토리얼 챕터 수정하기.

도움이 필요한 부분

원문은 Michael Lynch님이 에 게재했습니다.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.