人事領域に関するプロダクトを多数展開しており、HRTech企業の雄として名高いHRBrain社。年間のリリース回数はなんと1,100回!どうやってそんな開発生産性を実現しているのか、CTOの鈴木悠大さんにお話を伺ってきました。
ブランチデプロイ環境とは
──今日はお話を伺えるのを楽しみにしていました。まずは自己紹介をお願いできますか?
株式会社HRBrainの執行役員CTOをしております鈴木です。技術本部長を務めており、複数プロダクトのテックリードも兼務しています。
──事前に伺っていたところによると、御社では特に開発生産性を高めることに注力されているとか。
そうですね、色んなことをしていますが、まずはリリースのワークフローはかなり工夫しています。一つは、社内で「ブランチデプロイ環境」と呼んでいる環境は、生産性の向上にかなり寄与しているかと思います。
──それはどのようなものですか?
プルリクエストを作成すると、そのブランチ専用の環境が自動で立ち上がるというものです。
具体的には、プルリクに/deploy
というコメントを付けると、そのブランチをデプロイした環境を自動で構築して、専用のURLが発行されます。
こうした環境ができあがる前は、例えば「dev1」から「dev16」くらいまで、あらかじめ環境を用意しておいて、デプロイ先をチームで取り合いながら開発する…という流れで、結構不便を感じていました。
今はブランチデプロイ環境があるおかげで、プルリクごとに検証できる環境が自動で立ち上がるので、プルリクのレビューやQAを依頼するのも、URLを伝えるだけで済みます。特にレビューに関しては、以前はレビュアーがローカルにコードをpullして挙動を確認していたのですが、クラウド上で完結できるようになったのは大きいです。
──すごく便利そうです。開発生産性に寄与している工夫はほかにありますか?
Monorepo化が生産性向上に大きく寄与
開発生産性の向上にすごく効果があったと感じるのは、数年前にMonorepo化したことですね(編注: Monorepoとは、コードをすべて単一のリポジトリで管理する手法)。
──おお、ここでMonorepoの話が出てくるとは意外です。
3~4年前は、サービスごとに別のリポジトリで管理していました。たぶん、30個くらいリポジトリがあったと思います。
でも、そういう状態だと、例えばリリースのワークフローひとつ改善するのも大変なんですよ。全部のリポジトリに対して、同じような内容のプルリクを発行しなきゃいけなかったり。そうなると面倒で、ちょっとした改善はどんどん後回しになってしまう。
これらのリポジトリをひとつにまとめたことで、ちょっとした改善を行うのが億劫じゃなくなり、生産性の改善にも積極的に取り組めるようになりました。
──なるほど、だからMonorepo化が生産性向上にすごく効果があったと感じているんですね。ちなみに、Monorepoに移行すること自体は大変じゃありませんでしたか?
Monorepoへの移行自体は、エンジニアが1人で2,3ヶ月くらいで仕上げてくれたと思います。まあ、そのエンジニアの方がすごく優秀だったのは間違いないんですが。
──20個のリポジトリをまとめるのに1ヶ月…すごいですね。ちなみに、Monorepoってことは、バックエンドからフロントエンドまですべてのコードがまとめられているんだと思いますが、具体的にはどんな言語で書かれていて、どんなふうにリリースされるのでしょうか?
まず、バックエンドはGo言語、フロントエンドはTypeScriptとReactで開発しています。
で、GitHub Actionsでサービスごとに個別にリリースできるようにフローを組んでいます。なので、例えば一つのサービスに不具合があった場合、それを改修してデプロイすれば、対象のサービスのみが正しくデプロイされるようになってます。
──本当に効率的ですね…!
企業・ユーザーの単位で機能のON/OFFを切り替えられる「フィーチャーフラグ」
──一方でMonorepoだと、チーム全員で一つのリポジトリをいじるわけで、大きなコンフリクトが発生してしまって、開発が滞るようなことはないのでしょうか?
そういう事態を避けるため、各ブランチを可能な限り速くmainにマージするようにしています。いわゆるトランクベース開発なのですが、その際にフィーチャーフラグという仕組みが役立っています。
──フィーチャーフラグ?どのような仕組みですか?
端的に言うと、機能のON/OFFを切り替えることのできるフラグと、それを集中管理する仕組みです。
mainにマージされ、リリースされたあとでも、フィーチャーフラグをONにしない限り、その機能は有効化されません。これにより、変更や機能追加がユーザーに及ぼす影響をコントロールできるので、mainにマージするまでのスピードも格段に上がりました。
──大変興味深いです。リリース後も機能ごとにON/OFFできるという仕組みはどのように実現しているんですか?
フラグ自体はyamlで管理していて、機能ごとにON/OFFを切り替えられるようになってます。で、yamlの内容をもとに機能の有効/無効を返すAPIが用意されていて、そのAPIの結果をもとに、プログラムコード中でif文で判定しています。
──なるほど、コードで制御しているんですね。コード制御だと、抜けなどの不具合が心配ではないでしょうか?
そこはコードレビューでしっかり確認する感じですね。
──なるほど。そこで先ほどのブランチデプロイ環境の話につながるのですね。
そうですね。レビューを迅速にできることでマージまでの期間が短くなるのも、コンフリクトを減らせる要因です。
また、フィーチャーフラグはプロダクト品質の向上にも役立ちます。試験的にリリースして反応を見たり、A/Bテスト的に使用したりもできるからです。また、一部の顧客だけにリリースしてフィードバックをもらうなども可能です。
──そうか、機能のON/OFFをAPIで返すようにしているから、「一部の顧客だけに機能を開放する」とか、複雑な条件で機能の有効/無効を切り替えることもできるんですね。
そのとおりです。
──開発生産性向上への執念がすごいですね。ちなみに、生産性の高さを端的に表すような数字とか、もしあったら教えて下さい。
そうですねえ、それでいうと、リリース回数とかはどうでしょうか。昨年1年で1,100回ほどリリースを行いました。弊社は、規模の割にリリース回数はかなり多い方じゃないかなと思います。
──1,100回!それだけ細かく頻繁にリリースができているということですね、素晴らしい。
リモート開発環境の実際
──他に、生産性を高める工夫されている点はありますか?
エンジニアの開発環境は、かなりいろいろ工夫してますね。例えば、ローカル環境の構築はコマンド一発でできるようにしていたり。
──具体的にはどういうことでしょう?
先ほども申し上げたように、弊社はプロダクトやサービスの数がかなり多いんです。しかもそれぞれに依存関係があったりする。サービスの数が多いので、それぞれのサービスにモックを用意するというのも逆に非効率です。
なので、ローカルで開発し、実行して確認するのに、複数のプロダクトを順番通りに立ち上げなくてはなりません。当初はそれらを、 docker compose
を用いて行っていたのですが、それでも複数の docker compose
を、サービスの依存関係に配慮しながら実行する必要がありました。
そこで今は、tiltというサービスを使用しています。これは言ってみれば「docker composeのcompose」のようなもので、Docker composeをさらに取りまとめてくれるイメージですね。たとえば、tilt up <service A>
のように入力すると、Aというサービスとそれに依存しているサービス全部が立ち上がってくれます。
──それで、一発のコマンドで全部のプロダクトを正しく起動できるようになったんですね。tilt、聞いたことありませんでした。
そんなに有名なプロダクトじゃないかもしれませんが、すごく重宝しています。
──しかし、それだけのサービスを一気に立ち上げるとなると、コンピューターのリソースもかなり食いそうですね。
そうなんです。ローカルで3つ4つのプロダクトを立ち上げると50くらいコンテナが立ち上がっちゃうので、すごく重たいです。ただ実は、今はもう、ローカルでの開発はほとんどやっていないんですよね。
──え、どういうことですか?
弊社のチームは、今は徐々にリモート開発に移行してるんです。
──え、全部リモートで開発ですか?先進的…!
去年の末くらいから、Google CloudのCloud Workstationsを導入しまして、ローカルでコンテナを動かす必要がなくなりました。
この環境を構築するにあたっては、Googleの開発促進プログラムであるTAPを利用して、コンサルティングを受けながら進めました。詳細はこちらにまとめています。
──なるほど!完全リモートで開発するというのは、実際いかがですか?
1人1環境(インスタンス)で、起動手順はコマンド化しています。Googleのインスタンスの立ち上げは速いですし、Figmaとか重たいツールを同時に使っても、ストレスなく開発できるくらい軽くなりました。ついでに、ラップトップの充電の持ちもびっくりするくらい良くなりました(笑)
他にもいい点は、新人が来たらインスタンスを発行するだけなので一瞬で開発を開始できることですね。「リードタイムスコアが高いチーム」として、開発生産性についてFindy社から賞も頂きました。(Findy Team+ Award受賞の裏側:GitHub通知の最適活用法 )
──それはすごい。ちなみに利用料金が気になりますが、どうなんでしょう?
使った時間だけ課金されるので、利用時間次第ではあります。なので、エンジニアが帰り際に止めれば課金されませんし、アイドル状態が続いたら自動でシャットダウンするように設定しているので、必要最低限のお金しかかかってないと思います。(編注: 共有ワークステーション クラスタ分の費用は常にかかる。料金 | Cloud Workstations)
テックリード求む!
──最後に、読者にメッセージをお願いできますか?「こんな人が欲しい」とかでも構いませんので!
HRBrainは、人事関連のソフトウェアを開発する企業ですが、作るのが難しいというよりも、「複雑なものを作っている」と感じることが多いんですね。
正解がない中で、お客様の声を聞き、チームで検討を重ねて何が必要かを見極めながら開発してます。
そういう、お客様に提供する価値を考えながら、より良いアプリケーションを作っていきたい…というエンジニアの方にとってはやりがいのある職場じゃないかなと思っています。
──面白そう。ちなみに、どういう職種やエンジニアが対象ですか?
先ほども申し上げましたが、バックエンドがGo言語で、フロントエンドはReactとTypeScriptで開発していますので、それらをフルスタックで扱えるようなテックリードの方だと最高ですね。
今後さらにマルチプロダクト化を推進していければと思っているので、プロダクト開発を牽引出来るテックリードのような方だと最高ですね。
技術的にも、開発生産性の面でも、もっともっと高みを目指していきたいと思っていますし、エンジニアの方にとって裁量の大きな会社だと思いますので、私と一緒にそうした開発を楽しんでいただける方をお待ちしています!
I'm very glad that the map has been improved and optimized. It's obvious that the developers are trying for my escape road.