「エンジニアが技術的な意思決定に携わること」は、キャリアにおいて重要な意味を持ちます。特定の技術がどのような思想のもとに作られていて、利点や欠点は何か。そして、その技術が自社の求めるニーズに合致しているかなど、複数の観点に基づき決断を下す必要があります。では、各企業で活躍するエンジニアたちは、これまでどのような技術的な意思決定に携わってきたのでしょうか。
今回インタビューしたのは、2023年4月にサービス提供開始10年を迎えたアプリプラットフォーム「Yappli(ヤプリ)」を開発・提供する株式会社ヤプリ。同社の取締役執行役員CTOである佐藤源紀さんとサーバーサイドのエンジニアリングマネージャーである鬼木悠貴さんに、ヤプリの開発チームが取り組んできた技術的な意思決定の事例を伺いました。
――過去に取り組んだ技術的意思決定のなかで印象に残るものや、そこから得た学びを話していただきたいです。
鬼木:CMSのシステム基盤刷新の事例からお話をさせてください。これはアプリプラットフォーム「Yappli」のエンドユーザーが、コンテンツの情報を管理するためのCMSになります。このCMSはバックエンドがPHP、フロントエンドはJavaScriptで書かれており、開発にフレームワークを使用していませんでした。
ビジネスの成長に伴って、さらにシステム開発に力を入れる必要がありました。しかし、CMSのコードにはメンテナンス性やパフォーマンスの課題があり、より多くの人数で大きなシステムを作っていくことが難しい状態だったんです。そこで、新しいアーキテクチャの導入を検討し、今後の開発速度やユーザー体験向上のためフロントエンドのUIも含めて刷新を行いました。
――システム刷新を行うにあたって、採用するプログラミング言語にもさまざまな選択肢があります。バックエンドの言語を選ぶ基準は何でしたか?
鬼木:前提条件としては、今後のビジネス拡大に耐えられるように保守性やパフォーマンスに優れていること。それからエンジニアが増えていくことを見越して、大規模なチームでも開発がしやすいことを意識しました。当時はバックエンドエンジニアが7~8名ほど在籍していたのですが、採用する言語のアイデアを各々が持ち寄って、一緒に議論しました。
その過程で、Goが有力であるとわかってきました。もともとGoは、Googleが大規模な開発プロジェクトを推進するにあたって直面していた課題を解消するために生まれたという背景があり、パフォーマンスも優れています。それから、ちょうどGoが言語として成長しており日本でも人気が出ていました。
またGoの利点として、良い意味での表現力の低さが挙げられます。使用できる文法が限られているため、コードを書く際に迷いが少ないですし、他の人が書いたコードもレビューしやすいです。そうした利点から、バックエンドの言語としてGoを採用しました。フロントエンドはVue.js+Nuxt.js、通信方式はgRPCを使う方針になりました。
佐藤:このプロジェクトでは、インフラのアーキテクチャもリプレイスをしました。以前はAmazon EC2のインスタンス上にアプリケーションを載せ、AWS OpsWorksを使ってデプロイをしていたんです。しかし、運用の工数が大きくサーバーのスケールアウトが難しいという課題がありました。
そこで、Dockerを導入しAmazon ECS(on Fargate)を用いて、アプリケーションのデプロイを効率化しました。また、手動で行っていたデプロイを自動化して、継続的インテグレーションを実現するためにCI/CDのプロセスを整備しました。AWS OpsWorksを使っていたのを、CircleCIへとリプレイスしています。
この移行プロジェクトは長期間に及ぶことが予想されたため、新しい技術を選ぶときに気にしたのは「選んだ技術が安定しており長くメンテナンスが続きそうか」「上昇志向の強いエンジニアが興味を持ってくれそうか」「社内のエンジニアにとって程よくチャレンジングでモチベーションが上がりそうか」といった点でした。
――CMSの刷新を進めていく上で、工夫されたことや大変だったことはありますか?
鬼木:まず、大規模な刷新であったことや、GoやgRPCなど新しい技術をふんだんに使っていたことから、設計やコーディングルールの方針を決めるのにかなりの時間がかかりました。そのため、開発の初速を出すのに苦労しました。ただ、このフェーズで時間をかけて決めておいたことで後々に負債が生じることを防げたため、エンジニア同士の議論には価値があったと感じます。
また、今のヤプリはドキュメントを書く文化が浸透していますが、当時はそうではなかったため同じ機能要件を満たす新システムを構築することの難易度が高かったです。当時はメンバー全員がオフラインで働いていたこともあり、ディレクターやデザイナー、エンジニア同士が密にコミュニケーションをとりながら、旧システムと新システムを同じ機能にするように工夫しました。
システム移行に際しての工夫としては、新システムのリリースと同時に旧システムの機能を閉じるのではなく、両方使える状態にしながら段階的に出していったことが挙げられます。何か問題があった場合には、旧システムの側を使ってもらうことでユーザーにクリティカルな影響を出さないようにしました。
――Goに不慣れなエンジニアも多かったと思うのですが、コードの品質を高めるための取り組みはありましたか?
鬼木:実はちょうどプロジェクトが始まったくらいのタイミングで佐藤が入社しましたが、佐藤はかなりGoに習熟したエンジニアです。そこで、佐藤の持っている知見をなるべくメンバーに共有しながら、コードの品質を高めていきました。
佐藤:開発チームに参画してから、最初にGoのlintを入れましたね。それから、変数名やメソッド名などの名前の付け方にチーム内でブレがあったので、認識を合わせるためのミーティングを開催するなどして、メンバーに知見を共有していきました。
――CMS刷新のプロジェクトを終えての感想や読者の方々に伝えたいことはありますか?
鬼木:いま動いているシステムの仕様や設計、開発のポリシーなどを後から変更するのには、かなりのコストがかかります。インシデントが発生するリスクもあります。だからこそ、システムを構築する際にはプロジェクト初期の段階でいかに重要事項を決めておくか、懸念事項を洗い出すかといったことが重要になります。このプロジェクトでも、初期の方針策定に時間がかかりましたが、入念に調査や議論をして進められたのが良かったと思っています。
佐藤:このプロジェクトはトータルで2年以上かかったんですよね。根気がいりましたし、社内の調整も大変でした。ですが、エンジニアたちはシステムが抱える課題の大きさやプロジェクトの重要性をよく理解していたからこそ、最後まで粘り強く取り組んでくれました。プロジェクトの途中で入社を決めたメンバーも、その難しさややりがいを理解して入ってくれました。プロジェクトを完遂したときの達成感は大きかったです。
――そのプロジェクトの次の事例についてもお聞かせください。
鬼木:アプリプラットフォーム「Yappli」では、プッシュ通知の配信基盤が存在しています。「Yappli」上では800種類くらいのアプリが運用されているのですが、特に人気の高いアプリはエンドユーザーが数百万人ほどになります。1日あたり、合計で数千万ものデバイスに対して膨大な量のプッシュ通知を送っています。
旧来のプッシュ通知の基盤はPHPで作られており、まだサービスの規模がそれほど大きくなかった頃は問題なく運用できていました。しかし、事業の成長に伴ってメモリリークやネットワークエラーなどの問題が発生するようになっていたんです。また、コードのメンテナンス性もそれほど良い状態とは言えませんでした。そこで、システムの刷新を行うことで障害対策や配信速度の改善などを目指しました。
――どのような技術を採用しましたか?
鬼木:プログラミング言語に関しては、このシステムでもGoを採用しました。また、1つのリポジトリで先ほど述べたCMSのバックエンドとプッシュ配信のバックエンドを統合しており、共通のインフラストラクチャー層などを流用できるようにしています。
インフラとしては、複数のAmazon ECSのタスク+Amazon SQSを組み合わせた構成を採用しています。特定のAmazon ECSのタスクが完了したら、後続のタスクへとAmazon SQSのジョブキューでリレー方式に情報を受け渡していくようなアーキテクチャです。Amazon SQS経由の疎結合なアーキテクチャになっているため、特定のタスクを増やすことやインフラのスケーリングも容易です。
Amazon SQSの機能でエラー発生時のリトライなどを賄うことで、アプリケーションコードは対象者抽出や配信といったビジネスロジックに集中できます。また、このアーキテクチャでは大規模データの取り扱いに伴って発生するメモリ枯渇などの問題に対処するため、件数の多いデータの場合は分割して処理するような方法を採用しています。
配信基盤としては、メルカリ社が開発したプッシュ通知用のOSSであるgaurunを採用しました。このOSSはCPUとメモリリソースを効率的に使用して、配信速度を最大限に向上させてくれます。自社のユースケースに対応するためにforkして修正を行ったのですが、自社でゼロから配信基盤を作成するよりも大幅にコスト削減が実現できました。また、gaurunはGoで書かれているため社内のエンジニアがメンテナンスしやすいのも良かったです。
――このプロジェクトにおいて、工夫されたことや大変だったことはあるでしょうか?
鬼木:システム移行時の初期の段階では、いくつかの障害が発生しました。プッシュ通知に関連する障害は発生時の影響範囲が大きいため、精神的にもかなり過酷な部分がありましたね。また、本番環境でしか再現しないようなエラーも発生していたため、「どうやって本番相当のデータでテストを行うか」が重要でした。
そこで、課題解決のために本番同等の負荷で検証できるような、プッシュ通知専用のレビュー環境を構築しました。本番環境で予約されているプッシュ通知の情報をもとに、配信のdry runができる環境です。これにより、システムが高負荷の場合に発生する問題についても、本番環境へのリリース前に検知できるようにしました。
また、プッシュ配信は配信量が多いほどエラーの発生リスクが大きくなるため、新システムはアプリごとのカナリアリリースにすることで、障害発生時の影響を可能な限り抑えました。
――他の事例についてもお聞きします。
佐藤:BaaS(Backend as a Service)の活用事例についてお話しさせてください。ヤプリでは常に、新規事業を生み出すための努力を続けています。業務のなかで、メンバー同士でディスカッションをしたり、企画書を作ったりするんですが、それだけでは「プロダクトの体験や価値のイメージがつかめない」「技術的なハードルを測りにくい」などの課題があります。そこで、簡単なモックレベルのプロダクトをなるべくスピーディーに作りたいというモチベーションがありました。
モック作成の段階では、フロントエンドが一定以上実装できていれば、プロダクトで実現できる体験・価値は把握できます。そこで、フロントエンド側はそのまま本番リリースのプロダクトにもコードを流用できるようにNuxt.jsによって手厚く作り、バックエンド側はBaaSを使うことで実装の工数を削減する方針を選びました。
世の中にBaaSは数多くありますが、クラウド上で環境を構築するサービスは最小限のアプリを作るだけでもそれなりの手間がかかってしまいます。そこで、ローカル環境で動作して無料で使えるBaaSとして、Appwriteを活用しました。Appwriteはインターフェースが整っており、開発者体験も良いです。また、シンプルな機能を提供するWeb APIならすぐにできますし、細かいカスタマイズも可能です。
ただ、Appwriteはまだpublic betaでありサービス仕様に破壊的変更が入る可能性があることに注意しなければなりません。私たちの事例でも、特定の機能がある時点で使えなくなってしまったことがありました。
――どのような開発プロジェクトの場合、Appwriteを使用することをおすすめしますか?
佐藤:私たちがそうであるように、新規事業のアイデアがたくさんあってプロトタイプをたくさん作らなければならないケースに向いています。バックエンドでそれほど複雑な処理を行う必要がなく、ユーザーの認証とデータのCRUDさえあればよいようなパターンですね。
一方で、バックエンドで複雑な処理をさせることが必要な場合には、Appwriteはあまり向いていません。私たちの場合も、「プロダクトの初期フェーズではAppwriteのバックエンドをそのまま使えないだろうか」と考えていましたが、やはり厳しいことがわかりGoで作り直そうとしています。
――チャレンジングな事例をたくさん紹介していただきましたが、こうしたプロジェクトを推進するにはエンジニアのマインドも重要です。ヤプリではどのようなマインドの人が活躍できると思われますか?
鬼木:ヤプリでは複雑度の高いサービスを扱っています。また、モバイルエンジニアやフロントエンドエンジニア、サーバーサイドエンジニア、ディレクター、QAなど、複数の職種のメンバーと仕事をする機会も多いです。その環境のなかで、全体最適を考えられることが大事です。それは、他の人たちとの協調という意味でもそうですし、システムを俯瞰的に見て方針を考えるという意味でもそうです。その視点があることは、サービスを長期的にグロースさせられるエンジニアの条件だと思います。
佐藤:私たちは上場して企業として大きくなってきましたが、まだまだ解決できていない課題がたくさん転がっています。その課題を積極的に拾って解決できる人ですかね。そういう人が成長していますし、周囲からも評価されています。
――「what we use」で掲載するインタビューやコラムは「技術的な意思決定」をテーマにしています。このテーマに関連して、最後にまとめのコメントをいただけますか?
鬼木:自分自身、技術選定を行う機会をもっと増やしたいですし、システム基盤の構築にもチャレンジしたいと思っています。そして、新しいシステムを構築する際には「どのような意図に基づいてその技術を採用するのか」を、きちんと深掘りして言語化できるようになっておきたいと思っています。加えて、エンジニアリングマネージャーとしてメンバーが技術選定に携わる機会や考えを深めて言語化する機会を、より増やしていきたいです。
佐藤:今回のインタビューでは3つの事例を紹介しました。前半2つはビジネスとして成功しているシステムのリプレイスになるので、万が一失敗すればその影響がクリティカルになります。こういう場合は、技術選定としては手堅く行くべきです。長く使える技術を選ぶべきですし、設計も慎重に行うべきだと思います。
3つ目は、基本的にはスクラップ&ビルドすることが前提のシステムなので、ある程度リスキーな選択をしても後から取り返しがつきます。この場合はフットワークの軽さを重視したほうがよいです。いずれの場合でも、扱うビジネスやプロダクトの特性を踏まえて技術選定をすべきだと思います。
そして、エンジニアがモチベーション高く仕事に取り組めるように、愛着を持って接することができる技術を選ぶことも大切です。もちろん、それが行き過ぎると独りよがりになるので、ビジネス要件を満たせるか、開発の生産性を高められるかなどのバランスを取りながら、自分たちにマッチした技術を選んでください。
取材・執筆:中薗昴
撮影:山辺恵美子
提供:株式会社Haul
株式会社ヤプリの技術スタックをチェック
無料で技術スタックを掲載する
このページをシェア
技術スタック・ツールのデータベースサービス
© 2024 Haul inc.
技術スタック・ツールのデータベースサービス
© 2024 Haul inc.