2024年の振り返り
By kkoudev
去年は結局ブログを1つも書かなかったのですが、
理由としてはあまり自分が関心を持てる技術を最近使っていないというところにもあります。
mocriのサービス終了後からは社内のとあるSNSを作る事業部で主にエンジニアやPjMとして働いています。
このサービスは自分が参入するよりも1年ほど前から開発が開始していたので途中参加となります。
そのため、自分の関心のあるアーキテクチャーにはなっていないというのがいちばんの理由です。
もちろん自分で好きな技術選定をできるケースというのはそれ自体が珍しいかもしれませんが、
自分は割とそういう状況にここ10年ほどいたためちょっと違うなと感じるところがいくつかあったとは思ってます。
その上で、学べる点もあるかなとは最初は思ったのですが、
1年経ってみると過去やったことを繰り返しただけで特に新しく学べるような要素はなかったかも・・・というのが正直なところになります。
とはいえ、敢えて触れてこなかった部分に触れたことで改めてわかったこともあったので、
一応ここ1年で技術的にどういうことをやったのか、また仕事的に何をやってたのかを振り返ってみようかなと思います。
技術的なこと
ECSとデプロイ
ECSを自分でサービス開発で採用した経験はなく、2018年のmocri開始時にはKubernetesを採用していました。
ECSを避けていた理由は当時よく聞いていたFargateにおけるCPUガチャ問題が気になったというところと、
AWS謹製のサービスはあまり使い勝手的に良くないということを経験上知っているため、(例:Amplify)
EC2を除けば運用的にプラスになるRDSやElastiCacheくらいしか使わないようにしていたというのが理由です。
で、今回新たに参入したサービスではECSが採用されていたのですが、以下の点で自分はKubernetes (EKS)の方が使いやすいと思いました。
- ALBやECSサービス、セキュリティグループをTerraformで構築するのが基本となっている
- デプロイツールがecspresso以外はあまり筋が良くない。アプリケーション運用を考慮しているのは ecspresso 以外はあまり適していない
1がまず結構面倒に感じました。
Kubernetesを使う上ではTerraformで管理するのはNodeとなるEC2サーバやRDSやEKSクラスタといった基盤となるインスタンスがほとんどで、
ALBのようなロードバランサーもアプリケーションサービスとなるServiceやDeploymentといったものも、
Kubernetesのマニフェストをkubectl applyするだけですぐに反映することができます。
それに比べれば、1つサービスを追加するためだけにTerraformの設定を作るというのはかなり面倒でした。
2についても同じです。
私がチームへ参入した当初はデプロイがまともにできていないような状況でした。
全てをTerraformで実施してたり、ビルドにCodePipelineを使っていたりと、
色々と筋が悪くリリース後のメンテナンスが考えられていないような状態だったため、
ビルドをGitHub Actionsへ置き換えつつ、ecspressoを使ったデプロイに切り替えました。
なぜTerraformでうまく管理ができないのかといえば、
いちばんの理由はECSタスクのリビジョンの管理、コンテナの定義がJSONでその中の要素単位では差分管理ができない、
といったようにTerraformで全てを上手く管理するのが難しいからです。
これはECSの仕組み上の問題になります。
これがあるからこそ ecspresso のようなデプロイツールが利用されているケースが多いというわけです。
ecspresso 自体は素晴らしいツールで、これらのECSの使い勝手の悪い仕組みを
上手くアプリケーション運用がしやすい形にできるようにサポートできるツールになっています。
Terraformの tfstate を読み込んでセキュリティグループのIDなどを読み込む仕組みもあったりして、
初期構築はTerraform、以降の運用はecspressoといった形をうまく実現できるものになっていたりします。
とはいえ、こういうのはECSが元からアプリケーション運用をもっと考慮したような設計になっていればよかったという話でもあります。
Kubernetesに比べるとどうしてもアプリケーションサービスの追加のしづらさや、
ecspressoを使っても、ecspressoがサポートしているjsonnet形式のコンフィグを駆使してある程度スクリプトを自作する必要はあるところもECSそのものの使いづらさの一旦を表しているように感じています。
(ecspresso自体が素晴らしいだけに、その裏を返すと・・・という意味です)
この辺は好みの問題はあるかもしれませんが、
Kubernetesに比べるとどうしても運用のし辛さを感じてしまいます。
ここは慣れれば慣れるほどその印象が強くなってきました。
とはいえ、Kubernetesはクラスタアプデが最大の運用時の難所ではあるので、そこが上手く構築できないくらいならECSを選ぶ気持ちもわかるといえばわかります。
Flutterの辛いところ
参入したチームではiOS/Androidアプリケーション作成にFlutterが採用されていたのですが、このFlutterがとにかく辛いです。
5年ほどReact Nativeを使ってきた自分からみるととにかく周辺ツールの貧弱さが際立つと感じています。
特に辛いと感じた具体的なポイントは以下です。
- Dartの表現力(nullable checkが特に)が低すぎて、TypeScriptに遥かに劣る
- Linterである dart analysis が遅すぎる。ESLintと比較しても遅すぎる。custom_lint はそれ以上に遅い
- context.mounted を非同期処理内で都度チェックしないといけなくて大変。忘れるとクラッシュエラーにつながる
- 内部実装がキャンバスへ描画する仕組みなので、MethodChannelでネイティブを呼び出してもネイティブそのものにならない
- Flutter Engineのテキスト入力サポートが弱い。iOSのコピペでペースト許可のアラートが出る (v3.24以降は回避可能)
- Flutterそのものにパッチを当てるのが大変。Flutter Engineはビルドするのに30分ほどかかる
この辺りが代表的な理由ですが、特に1番目と2番目が辛いところです。
やはりDartが辛い・・・。
言語なんて最低限の機能さえ揃えば大して変わりはないツールの一種だとは思っていますが、Dartは近年よく使われる言語の中でも残念ながらその最低限を満たせていません。
例えば if で nullチェックをしても、クラスメンバであるとそのチェックは考慮されずに force unwrapped が必要になるなど、
TypeScriptでは考慮されることすらDartでは考慮されなかったりします。
ローカル変数に一度代入してチェックしたり、 if case を使えば上手くできますが、どれもとっつきにくいです。
その上、Linterが遅いところも想像以上に負担になるため、遅すぎるLinterのせいで横着して実行しない人まで出てきてしまうくらいです。(結局CIのチェックでひっかかるようにはしていますが…、pre-commitやpre-pushでのチェックは遅すぎて無理というレベル)
また、描画がキャンバスベースなのも辛いところの1つで、画面が謎にフラッシュしてしまうケースがあったりしますし、(Flutterのバグっぽいですが) MethodChannelでネイティブそのものを表示しているようで実際はキャンバスに描画されたネイティブコンポーネントを表示しているという手順が内部的にあったりして、それが要因かCPU負荷が上がるケースもありました。
極めつけには、React Nativeと違ってFlutterそのものに問題があるときに、気軽にパッチを当てることも大変(運用上難しい)です。(Flutter Engineのビルドに時間がかかりすぎるため)
悪いところばかり挙げてしまいましたが、強いて良い点といえば
React Nativeと違ってiOSビルドはかなり速い、という点でしょうか。
CocoaPodsベースの部分が大半を占めるReact Nativeは常に本体のソースのビルドも走るために遅くなりやすい傾向があります。
FlutterアプリであればGitHub Actionsでキャッシュを効かせればある程度大きなプロジェクトでも10分以内にはビルドを完了させられます。
ただ、個人的にはそれくらいしかアドバンテージがないと思っているので、それだけでは大きな価値とは言いづらいと思っています。
Flutter利用者は日本だと多いですが、より良いアプリを作ると考えた時、
その最低限の品質を保つための土台が十分に整っていないため、まだまだ厳しいと思うところがあります。
Dartがめちゃくちゃ進歩するか、LinterをRustなどで書き直すような動きがあればまだ可能性はありそうですが、
他にも理由の中に挙げた context.mounted を非同期処理内でチェックする必要があるような点も設計上の問題を実装者に押し付けているようにも思えてそこまで好きになれなかったりします。
CIやビルドまわりはかなり自分で処理を作り直したのでだいぶ改善はできたものの、
フレームワークそのものはさすがに難しいところですし、やりすぎれば使う理由もなくなってしまいます。
色々理由を挙げましたが、今後2〜3年あれば改善される可能性もあるので、それくらい経てば評価も変わるかもしれません。
App RouterがPages Routerよりも良い
新規参入したサービスではWeb基盤を作ったことがある人がいなかったので自分が作ることにしたのですが、
そこで採用した技術として Next.js の App Router と、CSS in JSとして vanilla-extract を採用しました。
vanilla-extractは何年か前に副業で使ってみてCSS Modulesを使うよりも型チェックが効く点は良いと感じたので採用しました。
あとは、stylelintのルールが頻繁に変わるのがとにかく運用上辛いことが多かったので、生CSSやSCSSは使わずTypeScript化することで
Property Order以外のルールはある程度TypeScriptの構文チェックとして担保できると考えたことも理由の1つです。
また、vanilla-extract自体はデザイントークンを定義する上でも使いやすいので、CSS Modulesを使ってやるよりも優位に働きやすいというのが設計上はあります。
App Routerを本格採用したのは初めてでしたが、
App Routerのキャッシュ問題は回避策があるし、(今の最新版v15系ではデフォルト無効になりましたし)
Pages Routerではなかった layout ファイルを作れるところ、
OGPを含めたMetadata生成できる仕組みがあるところはかなり良いポイントだと思いました。
特にOGPの画像生成は以前(Pages Router利用時)はAPI側で生成したものを使うようにしてたこともあったので、
Node.js側で用意された仕組みの中でできるのはかなり簡単にできてよかったポイントです。
JetBrains AI Assistantが良くなった
会社だとGitHub Copilotを満足に使わせてもらえないため自分で課金したJetBrains AI Assistantですが、
当初はあまり使い物にならない、ChatGPTくらいの立ち位置だったのですが、ここ半年以内からかなり進化して
コード補完もかなり正確にやってくれるようになりました。
単体テストコードくらいであれば生成したものを少し直すだけで結構正確に動いてくれるので、だいぶ重宝しています。
使い物になるかどうかを1年で見極めるためにサブスクを購入しましたが、もう1年延長しそうです。
仕事面について
PjMのお仕事
特に今まで意識してきたわけではないですが、自分はPjMとして動くケースが多く今回もそのような動きをしていました。
特別なことをしているわけではないと思っているのですが、タスクをしっかり管理してそれらの影響範囲まで考慮しようとするモチベのある人が世の中には意外にいないことが多いです。
そういう意味で、人がやらないことをやってきたというだけなのだとは思ってるのですが、これをやるかやらないかだけでも随分プロジェクトの進捗や成果は変わるというのを経験上知ってます。
リリース目処が全くなかったプロジェクトも体系的にタスク管理をするだけで目処が見えることが殆どです。
要するに目的の設定とそれに対するチーム内の認識を揃えること、かつタスクがその目的に紐づいていること、
これを可視化してレールを敷くことがタスク管理の目的です。
それらが考慮されない中で、GitHub IssuesやNotionでいたずらにタスクを発行しているだけではタスク管理にはならないことが多いです。
また、一般的なエンジニアやプランナーに特に多いのですが、手段(How)ベースで何もかもを決めようとする傾向のある流れが生まれやすいので、そういうのを防ぐのもPjMとしての役割なのかなと思います。
プロダクトを作る上でも同じです。
機能ベースで開発をすると手段だけをみてしまう傾向があり、
例えば技術的に難易度が高いから音声サーバーを導入することに挑戦したい、みたいなエンジニアのやりたいことかつ手段ベースでタスクを決めたりし、プロダクトを使う側のユーザー体験を一切考慮しないような流れは実際に何度かありました。
Howだけを考えず、Whyを考えるという昔そーだいさんが書かれたブログの内容は本当にそのとおりで、
いたずらに目的から逸れる仕事を増やすような動きをさせないことが非常に大事です。
ふとしたときにこれを振り返るのが非常に大事なのだと思って今でもこれを心がけるようにしています。
副業を始めた
今までスポットでLP制作やアプリ制作をお願いされたことはあったものの、
継続的な副業を始めたのは今回が初でした。
理由としては単純にお金の問題もありましたが、1つの企業に長いこといて自分でアーキテクチャー選定をやってたりすると
本当に自分がやっていることは正しいのかと思うケースが多々出てきます。
そのため、外の世界も知っておきたいというのも理由の1つになります。
結果的にはその考え通りになったので始めてみてよかったと思ってます。
特にGraphQLを本採用した現場は始めてだったのと、そこでのスキーマ管理が非常に合理的に体系化されていて
こういう知見が欲しかったとまさに思ったのが理由の1つです。
命名規則やDDDやクリーンアーキテクチャーに寄りすぎない、無駄を排除した合理的な設計も非常に参考になりました。
Flutterを触る機会も副業で増えましたが、なんだかんだ日本では需要がある技術なので自分の経験としては良い経験になってると考えてます。
名前が有名なサービスのリリースに立ち会えた
これも1つの経験としては良かったなと思ってます。
もちろんリリースしたら終わりではなく、ここからがサービスとしては重要な局面なので楽観視は出来ないものの
新規登録数も1週間で結構な数を超えたのはなかなか得られない経験だったのでそれ自体は良かったと思ってます。
ただ、現時点ではほぼ名前だけで初回の登録数を稼いだに過ぎず、プロダクトの完成度としてはまだまだだと感じてますので、
ここをどう作っていけるのかどうかは今後のプロダクトおよびプロジェクトの運用にかかっているかと思います。
そしてこれは過去の自分も何度か言ってきたのですが、とにかく名前は大事です!
名前1つで平凡な機能も別機能に見られたり、そのサービスとしての色になったりします。
サービス名なら尚更で、名前というものがどれだけ大事なのかというのは今後も意識していくべきことだとは思いました。
立ち位置を考えることが増えた
一方でPjMという立ち位置とエンジニアとしての立ち位置にはどちらに軸足を置くべきかということには悩むことが増えました。
基本的にはどちらか一方を優先するということはなく、必要な方を状況に応じて優先するという形なのですが、
恐らくこのバランス感覚が自分の思うバランスには現状なっていないのだろうとは感じており、今もどうするべきかを日々考えています。
どういう動き方が今後自分がやりたいことに繋がっていけるかは考えていこうかとは思っています。
今年やりたいこと
プロダクトをグロースする具体的な手法をいくつか実践してみる
プロダクトを作っていくことに関しては一通り完璧ではないにしても経験として得ることができたので、
次は実際にどのようにグロースさせていくかをもう少し具体的な手法に落として実践するということに挑戦してみたいと考えています。
これはmocriをやっていた頃はほぼコロナ特需で広がっていったこともあってグロースに重きを置いた施策に殆ど手をつけられない状態だったのですが、
実際のところはプロダクト自体の品質以上にどうやって広めるかも同じかそれ以上に大事です。
よくあるバケツの穴理論(人を集めても使えるものになっていなければユーザーは離れる一方)に囚われて品質だけに重きを置いてしまうと、
グロースするタイミングを見失ってしまうということは私が過去に失敗した経験の1つです。
ある程度は口コミだけでも広がっていきますが、そのある程度の先の大きな広がりは口コミだけでは起こせないというのは当時の経験からも感じているので、
その口コミよりも先の広がりとなる起点なのか波なのかをどうやって起こすかをもう少し体系的に実践できる体制が作れたらいいなと考えています。
E2Eテストを本気でやってみる
今まであまりE2Eテストに本気で取り組んでこなかったのですが、
QAコストを下げるにはやっぱりE2Eテストが有用だと感じてきました。
これは副業でお世話になっている会社がQA実施者を採用せずにエンジニアがE2Eテストを作って担保するような体制をとっていて、
CIもその仕組みもめちゃくちゃこだわって作られているのをみて感銘を受けたことが大きいです。
なんとなくコストがかかるとか、単体テストでユーティリティークラスくらいはテストを書こうとか、その程度の甘い認識で進めることが多かったのですが、その認識が大きく変わる出来事でした。
なのでE2Eテストをやっていこうというところなのですが、
その中でも事例がそこまでないモバイルアプリのE2Eテストをまずはやってみたいと考えています。
去年はMagicPodというツールを社内で使っているプロダクトが多かったのでQAのメンバーに試しに導入してもらったのですが、
GUIベースのためどうもとっつきにくかったり、変更の多いプロダクトだとシナリオの修正が非常に手間になったりということがあったので、
今年は別のツールを使ってみようと考えています。
いくつかサービス案を考えて実際に作ってみたい
副業までし出したのでそんな時間は取れそうにも無いとは思いつつも、
自分が今の仕事をするようになった原点に一度立ち戻ってみたいと考えることが増えました。
何かしらエンジニアリング関連のツールを作ることも考えましたが、必要に迫られないとどうしても作ろうとしない性分のようなので、
それなら何か簡単なWebサービスでも考えて時間がかかってでも作ってみようかなと考えています。
特に何か当てるとか当てないとか、そういう思考は一旦すべて捨て去って、やりたいことをやってみたときに何ができるのかという感じで気楽に実践できればという考えでやってみます。
まとめ
そんな感じで、今年も頑張ろうと思ったのですが、
思えば去年のやりたいこと(Vercelへブログを移す)は結局何1つ手をつけませんでした。
あまり優先度の低いことはやらない傾向が強そうです。
今年こそどれか1つはやってみたいと思います!