株式会社アカツキでサマーインターンに参加してきました

これは何

8/1から8/23までのおよそ3週間、株式会社アカツキさんでサマーインターンに参加していました。
その時におこなった作業内容や感想などをまとめておこうと思います。

自己紹介

現在東京大学大学院に通っているM1です。情報系の研究室に属しています。
学部2年ごろからプログラミングをはじめ、アルバイトなどを通してWebや自然言語処理など色々な分野を経験してきました。
最近はサーバサイドに興味を持ち、Goを少し前から勉強しています。
また、1年半ほど前から競プロにハマり、最近は暇さえあれば問題を解いています。このブログにも競プロの記事がいくつかあるのでもし興味があれば読んでみてください。

きっかけ

アカツキさんを知ったきっかけは巷で有名の魔法のスプレッドシートでした。
このスプレッドシートにはサマーインターンを開催している企業の募集要項がずらっと並んでいました。
僕はサーバサイドの開発をこの夏にやってみたいと考えたので、自分のやりたい内容にあった企業を探していたところ、アカツキさんから合格の連絡をいただいたので参加することになりました。

開発を行なったプロジェクトの概要

とあるスマホアプリのゲーム内通貨の管理を行うバックエンドのサービスの開発を行いました。ゲーム内通貨とは課金して手に入れることのできるアイテムのことで、よく石などと呼ばれるものです。
この課金アイテムの購入や消費などの取引を正常に行い、チートなどによる悪質な攻撃を未然に防ぐのがこのサービスの目的です。
概要は下図のようになっています。主にGAEやTask Queue、BigQueryなどから構成されています。

f:id:yuji9511yuji:20190822152313p:plain
開発を行なったサービスのアーキテクチャ
このサービスはGoogle Cloud Platform (GCP)上で動作しており、ソースコードは基本的にGoで書かれています。また、CircleCIを用いたCI/CDを活用しているのでこの辺りのノウハウを勉強することもできました。

作業内容

実際に取り組んだIssueをいくつか紹介します。

APIのパスパラメータのvalidation

まず最初のissueとして取り組んだのは、APIのエンドポイントに含まれるフィールド名が適切であるかのvalidationを行うというものでした。入力されたURIをパースしてフィールド名が想定されているものかどうかのチェックを行いました。
とりあえずコードがどのように書かれているかを把握するということで、APIが叩かれてから結果が出力されるまでどのような処理を経ているのかに注目しながら実装を行いました。
そこまでソースコードの規模が大きいわけではありませんでしたが、 実際の開発におけるGoのコードを読むのが初めてということもありソースコードの理解にだいぶ苦戦しました。

また、変更された箇所に関してテストコードの作成も行いました。Goの標準ライブラリであるtestingを用いることで変更後のコードが正常に実行されているかを自動的に確認することが可能となります。僕は今までSeleniumなどの外部ライブラリを用いたテストしか行なったことがなかったため良い勉強になりました。

TQ handlerのエンドポイントを処理ごとに分ける

データベースであるBigQueryへデータを登録する際、まずデフォルトサービスはTask Queue(TQ)と呼ばれるqueueにリクエストを送信します。
TQはFIFOの順でTQ handlerにPOSTを行い、BigQueryへの登録を実行させます。
登録に関する情報は内部パラメータとして渡すため、今までは全ての処理(charge, consumeなど)で同一のエンドポイントを使用していました。
しかし、Stackdriver Loggingなどでログを確認するとなるといちいち内部パラメータを覗く必要があり、可視化の観点では優れていませんでした。
そこで、処理ごとにエンドポイントの名称を変える変更を行い、ログの可読性を高めることを行いました。

しかし、単純に新しいエンドポイントに置き換えてしまうことには問題があります。
このサービスのデプロイはTQ handler -> デフォルトサービス の順で行なっているため、前のエンドポイントを削除してしまったTQ handlerをデプロイしてしまうと現在稼働しているデフォルトサービスのPOSTリクエストを受け取ることができなくなってしまいます。
したがって、まずは新旧両方のPOSTに対応したTQをデプロイし、デフォルトサービスが置き換わったのちに古いものを削除するという二段階の処理が必要になります。図で表すと下のようになります。

f:id:yuji9511yuji:20190823110127p:plain
変更したアプリケーションがデプロイされていく様子。
この部分はしばらく理解するのに手こずってしまいました。

GitHubのブランチ運用の方式を変更する

まず、このプロジェクトで行なっていたブランチ運用を簡単に説明します。開発はdevelopブランチからトピックブランチを切ることで行い、developの変更をmasterブランチにmergeします。CircleCIの設定により、トピックブランチやdevelopではコミット毎にlinterやユニットテスト、統合テストなどが自動的に実行されるようになっています。また、masterではdev環境へのデプロイが実行されるようになっており、masterのコミットに対してreleaseタグを付与することで本番環境にデプロイが実行されます。

この運用の問題点として、「master環境へのコミットの時、デプロイ前にテストが走らない」という問題がありました。万が一テストで問題があってもdev環境へのデプロイが実行されてしまうおそれがあります。

これを解決するため、ブランチ運用をdevelop, master, releaseの3段階に変更する作業を行いました。フローの概要は下図のようになります。

f:id:yuji9511yuji:20190823110131p:plain
変更後の各ブランチの役割
masterブランチでテストを実行し、テストが成功したことを確認した上でreleaseブランチをそこから切ります。releaseブランチは変更を認識するとdev環境へのデプロイを実行します。このようにすることでテストに通過した状態のもののみをデプロイさせることが可能となりました。

実装としては主にCircleCIの設定ファイルであるconfig.ymlをいじる形になります。masterブランチへのプッシュ時に、全てのテストの終了を受けて実行がスタートするジョブ"create_release_branch"を作成します。このジョブではmasterブランチのHEADをチェックアウトし、releaseブランチへのpushを行います。この際、CircleCIにブランチの作成及びpushを行わせるため権限が必要になります。今回はGitHubでデプロイキーを作成し、その秘密鍵をCircleCIのconfigへ登録することで解決しました。

Task Queueに取引情報をPushする時にはPayloadのサイズが大きくなる問題を解決する

BigQueryに登録すべき情報をTask Queueから送信する際、payloadのサイズが大きいことにより処理が失敗することがあるという問題がありました。この原因として、DBへの登録に必要のない情報も含めて送信してしまっていることが挙げられます。そこでDB登録に最低限必要な情報のみを先に作成し、そのデータをpayloadに載せるという変更を行いました。

このIssueではpayloadの送信側と受信側どちらの処理も書き換えなければならず、影響範囲がかなり大きく難易度の高い作業でした。
また、TQを先にデプロイするという先ほどの理由により過去のバージョンのPOSTを受け付ける処理も残したまま変更を加えなければいけないという考慮も必要でした。
Goの型チェックや隅々まで張り巡らされたCIのおかげでなんとか形にはなりましたが、既存の処理を変更しないようにコードを変更していくのはなかなか難しかったです。
こういった変更点がある時にテストを細かい部分まで充実させておくことは重要であると認識することができました。

今回学んだこと・感想など

GoやCircleCIなど、今まであまり触れてこなかった技術を経験することができた

アカツキインターンを選んだ目的として、「サーバサイドの開発経験がほしい、できたらGoに入門してみたい」ということがありました。Goは実務で触ったことがなかったのでインターンの中で習得していきたいという熱意を語ったら採用していただいたのでありがたかったです。Goは型の管理やコーディングの規約が非常にしっかりと固まっているので、ある程度大きな規模のコードを見ても統一感を持って眺めることが可能となっていました。今後も使い続けていきたい言語です。

また、CircleCIの知見を得たことも大きかったです。テストやデプロイなどを自動化させることで人為的ミスやそこにかける工数を削減することができ、機能追加などに集中することができました。
少し前にはGitHubも公式でCI/CDをサポートするとの発表があったのでそちらも楽しみですね。

社内の環境がとても快適だった

3週間という期間ではありますが平日週5で来ることになるので、開発環境がどのようなものか気になっていましたが、とても快適に作業を行うことができました。
ひとチームあたりの人数がそれほど多くないため、意見の疎通もしやすくスピード感のある開発をすることができました。
また社内のイベントやインターン同士の交流なども積極的に開催していただき、たくさんの人とお話ししてたくさん美味しいご飯をいただくことができました。

これからインターンに参加しようと思っている人へ

アカツキの就業型インターンは募集人数こそそこまで多くないですが、その分一人ひとり手厚くサポートなどをしてくれるところがオススメできるポイントです。
手厚いといっても過剰にゲストとしてのもてなしをされるわけではなく、しっかりと実サービス開発のメンバーとして参加することができるので普段どのような段取りで開発が進んでいるのかを間近で体験することができました。
また、ゲーム会社ということで社員さんもゲームに対する愛が強い人が多いため、ゲーム製作に対するモチベーションが高い人にとってはとても良い環境だと思います。
就業型だけではなくUnityでゲームを作るハッカソンのようなコースもあるので、そちらも併せてチェックしてみるといいと思います。

おわりに

3週間という短い期間でしたがとても密度の濃い経験をすることができました。ありがとうございました!