✍️

メイキング - Deep Dive into The Go's Web Server

2021/09/18に公開

この記事について

この記事は、先日公開したZenn本Deep Dive into The Go's Web Serverのメイキングです。
「技術記事ってどうやって書いてるの?」というアウトプット初心者の方々に、あくまで私のやり方ではありますが、メイキング情報をお届けできればと思います。

想定読者

Deep Dive into The Go's Web Serverを読んでいなくてもわかるようにはしていますが、読んでいただいた方がより楽しめるかと思います。

書き始めるまで

突然訪れたネタとの出会い

「Goでのhttpサーバーの中身について書こう」というネタが降ってきたのは、前作であるよくわかるcontextの使い方を書いているときでした。

この本はGoでのcontextパッケージの使用用途をまるっとまとめた本なのですが、contextの機能を実際にフルで使っている例(→第9章)として「httpサーバーとかいいんじゃない?」と思いつきます。
そんなこんなで、Goで実装されたWebサーバーの本質部分だけ抜き出して中身を模倣しようとnet/httpパッケージの中身を漁ります。

私がZenn記事を書いているリポジトリではmemo.mdという名前のマークダウンファイルを一律でgit管理対象外と設定していて、そこに執筆中に気づいたことや、まだ文章としてはまとめきれていない情報をまるっと書き留めていました。
そのため"よくわかるcontextの使い方"のフォルダの中には、以下のようにnet/httpのコードを読み漁り理解した内容についてざっくりとまとめた叩き台が出来上がります。


context本のフォルダにあったnet/httpの内部仕様に関する当時のメモ帳

https://twitter.com/saki_engineer/status/1427627105639145486

書くか書かないか、それが問題だ

この時点で「この内容、いつか何らかの形で世に出すのはありかもなあ」とは思いつつも、「絶対に出すぞ!」とまでは心に決めていませんでした。

というのも、私が理解した内容って「net/httpにそのまま書いてある内容」=「net/http読めば理解できる、わざわざ私が書いてまとめるまでもない内容」なのではないか、という疑惑があったんですね。
そのため、

  • 私が新たにまとめ直すことで追加のバリューが果たして出せるのか?
  • そもそもnet/httpのコードリーディングに需要があるのか?
  • 他の書きたいネタを掘り下げにいったほうが面白くなる?

みたいなところで悩んでいました。

https://twitter.com/saki_engineer/status/1427627519541489675
https://twitter.com/saki_engineer/status/1427628214109753353

そんなことをTwitterでつぶやいていたら、

  • まとめることで、コードを読みにいこうとならない人へリーチできるようになるからいいと思う
  • どういうところを読めばいいのかあたりがつくからまとめる価値はあるよ
  • 自分とはnet/httpの読み方が違うかもしれないからまとめ記事期待

という声をいただいたのものあり、単純な私は「よっしゃ、書くかwww」となります。

執筆開始

とはいえ、ネタ降臨が別の本の執筆中だったこともあり、実際にnet/httpのネタに取り掛かり始めるのはそれが出来上がってからになりました。

ファイル情報から日付を確かめてみたら、

という時間関係でした。

メモからver0.1へ

私が何か記事を書く、となった場合には、まずはざっくりとした章構成から決めることが多いです。

Zennでは1章1マークダウンファイルの構成をとっているため、Zenn本の執筆となった場合には

  1. npx zenn new:bookコマンドでディレクトリを生成
  2. ディレクトリ内に、思いつくだけの章ファイルを作っていく
  3. その中に「現時点でその章にはどういう内容を書くつもりか」という内容を、推敲せずにわーっと書く

という作業をまず最初にすることが多いです。


Deep Dive into the Go's Web Server 3章のver0.1稿

3番の工程では、読みやすい文章だとか誤字脱字だとかを気にせずに、とりあえず内容を俯瞰しやすくするために「とりあえずネタをあるべき位置に配置する」という感覚で作業をしています。
今回のようにネタのメモ帳があった場合は、memo.mdという一つのファイルの内容を、工程2番で作成したファイルの中にコピペ整形するような流れになります。

以下の写真の左側は、memo.md内に書き留めていたとき、右側はZenn本の章ファイルに移したあととの同内容の比較写真です。

左: context本のディレクトリ内のmemo.md 右: そこからZenn本の章原稿マークダウンにネタを写したver0.1

ver0.1からver0.5へ

memo.mdからZenn本のファイルにネタを書き移した時点では、内容面ではまだ自分以外が読んで理解することを想定していない状態です。
そこから、「他の人が読んでも理解できるように」行間を埋めていく作業を行います。
この作業の段階で、「きちんとした文章」の大枠が出来上がっていくイメージです。


Deep Dive into the Go's Web Server 3章のver0.5稿

この段階で「あ、この内容、文章だけじゃ無理だ」「図を用意しなきゃ行間埋まんないや」ということに気づきます。

リアルメモ帳にらくがき

簡単な図だったらそのまま画像ファイル形式におこしてしまいますが、今回のnet/httpの場合、処理に様々な構造体・インターフェース・メソッド・関数が入り混じっていたため一旦トライアンドエラーがしやすい紙に落書きすることにしました。

https://twitter.com/saki_engineer/status/1433442440405413896

写真だとかなり書き込みがありますが、落書きする前にこの内容がどれくらい頭にイメージできていたかというと大体7割くらいです。
残りの3割は、頭の中にあった7割のイメージ理解を吐き出して具体化した後に、その上に書き込みをどんどん加えていってクリアにしていく感覚です。

ちなみに使っている紙は、数年前に応用情報技術者試験を受けたときに刷った過去問の裏紙です。

パワーポイントでおえかき

紙に起こして、どういう図を書くべきかかっちり要件が決まったら、今度こそパワポに綺麗にまとめていきます。

https://twitter.com/saki_engineer/status/1434039310240468993

ver0.5からver0.7へ

パワポで図を作ったら、図挿入前のver0.5では埋まっていなかった行間を埋めていきます。

やってる内容としては以下の2つです。

  • Zennの画像アップローダーから取得したURLを、原稿の中に埋めていく
  • 「上記の図のように〜」みたいな、図がないと成立しないような説明文を書く

そのため、図が多い本だとver0.7へのバージョンアップ作業は時間がかかりますし、そうでないならver0.5とver0.7はそう差がなかったりします。

一度全体を俯瞰

ver0.7ができた時点で、一度全体を俯瞰してみてみます。
この時点で出来上がっていたのが、以下の章でした。

  • 2章 ウェブサーバーのHello, World
  • 3章 httpサーバー起動の裏側
  • 4章 デフォルトでのルーティング処理の詳細
  • 5章 ハンドラによるレスポンス返却の詳細

この構成をみて抱いた感想は「んーなんか物足りないんだよなあ」でした。今まで10章越えの本を2冊書いたおかげで感覚が狂っている
5章までがっつりとnet/httpの深い話をしていたあとに、そのまま終わりで「いかがでしたか?」となるのも急だしなあという思いもあり、第6章を追加で入れることにしました。

突然の追加作業

というわけで、やっつけと思いつきで6章を追加することにしたのですが、当然ながら前作を書いていたときのメモにはなかったことなので、そもそもの内容を考えるところから始めました。

当時あった候補は

  • ルーティングアルゴリズムについて:
    「あるパスへのリクエストを、どのハンドラに渡すのか検証するアルゴリズム」については4章で触れていなかったから
  • net/http以外のサードパッケージとの比較:
    標準パッケージ以外の話を2~5章では一切していなかったので、gorilla/muxくらいなら触れてもいいかなとは思っていた

という2つがあったので、とりあえずgorilla/muxの中身について調べて書くかということで作業を始めました。


gorilla/mux章の下書き

ですが、途中まで書いたところで、

  • サードパッケージとの比較というからには、chiとかechoとか他のやつにも手を広げるべき?
  • でもそもそもgorilla/mux以外に使ったことないんだよなあ
  • というかnet/httpのみで薄く作るのが好きなのに、わざわざこの本のためだけに使う予定のないフルスタックパッケージに首を突っ込むのアホらしくない?
  • 一旦書いてみてから気づいたけど、突然サードパッケージに話が飛ぶのも結構な話の飛躍っぷりなのでは

という思いが出てきてしまいました。
そうすると何をまとめて書けばいいのかだんだん分からなくなってきて、あー煮詰まってるなあと感じてきたので、この日は一旦作業を切り上げました。

https://twitter.com/saki_engineer/status/1434454008123461638

原点回帰 - ver0.7からver0.9へ

サードパーティーパッケージに手を出して難航したので、ここで一旦「何のために6章を追加したんだっけ」という原点に立ち返って考えてみます。

5章までがっつりとnet/httpの深い話をしていたあとに、そのまま終わりで「いかがでしたか?」となるのも急だしなあという思いもあり、第6章を追加で入れることにしました。

実際、今はnet/httpの中身を理解するには、3〜5章を通しで読まないとわからないということと、そこで説明してきた内容が下図のように結構入り組んでいたのですね。

3~5章の詳細説明で使っていた図

ここまで図が密になっているのは、インターフェースとそれを実装している具体型の行ったり来たりを全て正確にのせてしまっているからです。
私は作図者本人なので、これが何を意味しているのか100%理解していますが、他の人がこれをパッとみて「全部理解した」となるかは、あらためて見るとうーんという気持ちになりました。

そのため、第6章では

  • 3〜5章で詳細を述べた内容を、1つの章にまとめる
  • その際には、理解に必要な本質部分のみを抽出する

という方針を決めなおしました。そんな経緯でgorilla/mux章はめでたく(?)お蔵入りとなったわけです。

方針を決めてしまったら話は早くて、まずは本質部分だけ抽出した概略図を新たに作成し、それを説明する文章をばーっと書いていくだけです。


6章での本質部分抽出のために、大事なところだけ抜き出した図

「おわりに」を書く

本論部分が出来上がったら、あとはイントロとAppendixを書くだけです。
私はAppendixは「おわりに」という名前で書くように全部で統一しています。

「おわりに」については、執筆中に参照した参考文献リストを常にappendix.md上に更新し続けているのもあり、作業としては

  • 各参考文献がそれぞれどういう文章なのか、についての詳細紹介文を書く
  • いい感じの幕引き文を書く

という2点です。

いい感じの幕引き文を書くのってどうしてこんなに難しいんですかね。誰かエモいまとめ文をパッとかける方法を教えて欲しいです。

実際にできた記事はこちら

「はじめに」を書く

私はイントロは「はじめに」という名前で書くように統一しています。

イントロに書く内容については以下4点です。

  • いい感じのイントロ文 :
    大体「なぜこの本を書くことになったのか」「書こうと思った動機」「この本でわかるようになること」を書きます。
  • 本の構成 :
    各章の内容を3行でまとめた内容をここに一旦載せておいて、本全体の見通しが良くなるようにしています。
  • 使用する環境・バージョン
  • 読者に要求する前提知識 :
    自分が初学者時代に困ったこと第一位がこれです。「わからないことを記事で調べる → その記事で出てきたわからない事柄をまた調べる → ...」の無限ループの末に結局混乱してわからなくなるということが多かったので、「何を既知とした議論をしているのか」ということを絶対に明示するようにしています。

バージョンについては今回は大丈夫でしたが、前作context本のときには「記事公開当日にGo1.17がHomebrewに入ったことに気づく」ということがあったため、急いでbrew upgrade goをして、書いたコードの動作確認を1.17でし直すという割り込み作業がここでありました。
Goの新バージョン公開 → Homebrewでインストール可能になるまでにはある程度のタイムラグがあり、brewでGoを入れていた私は1.17リリースの後でもしばらく1.16を使いながら対応待ちをしていたがための事態でした。泣きそうだった。

summaryを書こう


Zennの本を読むときに最初に表示されるページ
この部分を書く作業です。

いい感じのイントロ文は「はじめに」で絞り尽くされてネタ切れだよと思いながら記事を紹介されるときに真っ先に目に付く大事な文章になるので、なるべく簡潔に、かつ読みたいと思ってもらえるような要約文を書いていきます。

タイトルを決めよう

私の場合、タイトルを決めるのは一番最後です。本の中身が全て決まってからじゃないと「中身を的確に表したタイトル」というのは決められないと思っています。

とはいえ、この段階になると「本文も書けたしイントロ文とか幕引き文みたいな大変なところも全て書けたし、残作業はさっさと終わらせて早く公開したい〜〜〜」という気持ちになっているので、一番大事なところでもあるにもかかわらず適当であることが多いです。自分のこういうところ本当良くないと思います

日本語のタイトルだと「よくわかるGoのWebサーバー」みたいな前作と同じような感じになって面白くないな、ということで、英語で"Deep Dive into The Go's Web Server"と捻り出しました。1分で考えた割にはいい感じになっているんじゃないでしょうか。

表紙を作ろう

Zenn本の表紙を作るのにはCanvaというサービスがおすすめです。
絵が書けない人でも、いい感じの背景を選ぶだけでエモい表紙が作れます。

私の場合デザインセンスが皆無なので、いい感じのきらきら背景を選んだらあとは帯とタイトルと自分の名前を入れるだけで無難に終わらせます。
自分の著作の中で統一感を出すという意味も込めて、多分このスタイルはしばらく変えないと思います。冒険しないだけ

個人的にnet/httpは赤やピンクのような系統の色をしてるなと思っていたので、とりあえずまずは赤系統のキラキラした背景を選んで表紙を作ってみました。


表紙第一案

……なんか全然Deep Diveしている感じがしない。
あとは背景に白い光が思った以上に多く、パッと見でどこにタイトル文字列が入っているのかがわかりにくいなあという感想を抱きました。

というわけで、

  • 星やオーロラみたいなきらきら光る感じがあるけど
  • 落ち着いた感じの
  • 赤系統(赤、ピンク、紫…)

という条件で新しく背景を探したところ、最終的にここに落ち着きました。


表紙最終案

赤系統というかは紫っぽいかも。
ただ、この黒紫-赤オレンジのグラデーションは

  • (上→下)わからない夜の闇から、本を読んでわかるようになって夜明けを迎える
  • (下→上)net/httpの深海にDeep Diveしていく

という二種類の見方ができそうな感じだなあと後から思いました。普通に気に入っています。

公開まで

告知

表紙が出来上がった時点で夜の10時近かったため、本の公開は翌日に持ち越すことにしました。

やっぱり頑張って書いたものなのでなるべくたくさんの人の目に触れて欲しい!ということで、私は公開時間は意図的に夜9時や夜10時にしています。仕事が終わってみんながTwitterとかしてそうな時間ですね。

というわけで、告知のための写真を撮ります。

お気づきだろうか…?

この写真を撮った時点で「タイトルのtheに大文字・小文字の表記ゆれがある」ということに気づきます。
タイトルという超重要部分のミスだったため放置できず、泣く泣く表紙を修正しました。

https://twitter.com/saki_engineer/status/1435224110452260866

告知文に「何もなければ」というセルフハンディキャップが入っているのは、

  • 我が家の生活リズム的にこの時間帯に夕飯になって、リリース作業ができないかもしれない
  • もしも別の大きいイベントにぶつかっていて、PV数が見込めないようであれば延期したい

という事情があるからです。
実際、公開予定日が東京五輪の開会式と被っていることに直前で気づいたためリリースを1日後にずらしたということもありました。

https://twitter.com/saki_engineer/status/1418549673535500291

公開

今回は特にイベント被りも大事故もなかったため、予告通りの日時に公開することができました。
https://twitter.com/saki_engineer/status/1435588964522414089

根がチキンハートなので公開してすぐは反響が怖くて1時間くらいネット断ちして別のことをして、そろそろ読み終わった人がいるかな?って段階で反応をチラ見して喜んでることが多いです。

まとめ

https://twitter.com/saki_engineer/status/1435911841830477827

読んでくださった皆様のおかげもあり、ネタ元となった本と並んでZennトップページに2つ揃ってランクインというなかなか嬉しいことを経験することができました。本当にありがとうございます。

というわけで、Zenn本メイキング記事をお届けしましたがいかがでしたでしょうか。
この執筆裏側で私が伝えたいことは以下3つです。

  • 「書こうかな?」と迷ったら書いた方がいい。
    その記事の需要を決めるのは自分じゃなくて他の人たちだから、自分で「わざわざ書くまでもないよな…」と決めつけない。
  • 一発で「公開していいクオリティの文章」を書こうとするのは、よほどの文才がないと無理。
    まずはver0.1みたいなラフでもメモでもいいから書いてみて、そこから推敲していけばいい。
  • summaryとタイトルは大事だから手を抜いちゃダメ

みんな技術記事を書こう!

今回メイキングしたZenn本はこちらです

https://zenn.dev/hsaki/books/golang-httpserver-internal

Discussion