AI事業本部 小売DX管轄の黒崎です。

今回はインターンに参加して頂いた山﨑さんからの寄稿記事です。


はじめまして、山﨑雅師(@masibw)と申します。
2021年5月の約1ヶ月、サイバーエージェントのAI事業本部で働かせていただきました。その中で取り組んだことや部署について発表させていただきます。

はじめに

期間:5月11日 ~ 27日の「火・水・木」の週3日出勤
部署:AI事業本部 > DX本部 > 小売セクター > アプリ運用センター
貸与PC: 15inch Mac Book Pro USキーボード(快適)
勤務時間: 大体 10 : 00 ~ 19:00
トレーナー: 後藤紳さん
メンター: 黒崎優太さん

部署名がすごく長いんですが、簡単に言うと「小売企業のDX推進を支援」している部署です。小売企業というのは「百貨店」「ホームセンター」「コンビニエンスストア」などのことで、顧客データを集め活用するためのプラットフォームを作ったり、小売企業のアプリ開発などを行っています。
詳しくは先日行われた CA BASE NEXTにて僕のトレーナー・メンターさんが発表されていたので御覧ください。

140兆円の巨大市場、小売業界の再発明に挑む開発プロジェクト
140兆円の巨大市場、小売業界の再発明に挑む開発組織

やったこと

詳しいことは言えませんが、僕は小売企業のアプリ開発に携わらせていただきました。同時期にjoinしたチームメンバーの方と2人で中心に進め、トレーナー・メンターの方にレビューしてもらう形で進みました。
技術選定から実際にアプリのコードを書き始めるところまで、できる限りテンプレートとして採用できるようにアーキテクチャや周辺ツールの選定・設定を行いました。今回はその辺りを書きたいと思います。

使用技術

  • Go
  • Terraform
  • GCP
  • GitHub Actions
  • Docker

ベースとする技術は上記の通りです。その上で幾つか意識した部分について以下で書こうと思います。

Dockerfile

以下の2点を行いました。

  • マルチステージビルド
  • Distrolessイメージの使用

以下に例を示します。細かいところは省いているので環境変数やパスなどは適宜変更してください。


FROM golang AS build #build用イメージ
WORKDIR /go/src/github.com/your-repository/project

COPY go.mod  ./
RUN go mod download

COPY . .
RUN go build .

FROM gcr.io/distroless/static-debian10 AS deploy #本番用イメージ

COPY --from=build /go/src/github.com/your-repository/project/app /
ENTRYPOINT ["/app"]

マルチステージビルドは認知度が高く、多くのプロジェクトで採用されていると思いますが解説しておきます。ビルド用のイメージと本番用のイメージを分け、成果物のみをコピーすることで本番用イメージの容量を大幅に軽減することができます。
Distrolessイメージ

“Distroless” images contain only your application and its runtime dependencies.

とあるように、実行に必要なもののみ含まれたイメージとなります。実行時には不要なツールやソフトウェアを減らすことで脆弱性対応などの負担を減らすことができます。ちなみに、シェルも含まれていないため

ENTRYPOINT “/app”

ではなく

ENTRYPOINT [“/app”]

と記載する必要があります。
なお、buildkitを有効にするなどで更に高速なビルドが見込めるかもしれませんが今回は大きなプロジェクトではないことから調査を行いませんでした。

DBのマイグレーションツール

sqldefを採用しました。ridgepoleから着想を得たツールで、あるべきDBスキーマを定義すればそれに応じたクエリを発行してくれます。rubyなどの依存をインストールする必要もないですし、SQLで書くことができるため非常に馴染みやすいです。作者の方がブログに記事を書かれているのでぜひ読んでみてください。ちなみに、テーブルごとにファイルを分けてスキーマ定義をしたかったので以下のようなスクリプトをMakefileに登録していました。


find ./schemas/ -type f | xargs cat | mysqldef -uroot test

ロギング

ライブラリはzapを使用し、GCPのstack driverへ形式を合わせるため zapdriverを使用しました。
zapはErrorレベルでの出力の場合、自動でstack traceを紐付けてくれますが、あくまで実際にログを吐いたところ基準であり、fmt.Errorfでラップしている場合は元の発生場所まで遡れませんでした。
そこで、xerrorsパッケージを使用することにしました。xerrorsパッケージとはGo2へのエラー関連の提案を先に使えるようにしたものです。これを使うとエラーをラップした場合もstack traceを出すことができます。


errors.New(“hoge error”)

の代わりに


xerrors.new(“hoge error”)

を使用し、


fmt.Errorf(“wrap error: %w”, err)

の代わりに


xerrors.Errorf(“wrap error: %w”)

を使ってエラーをラップ、出力時には


fmt.Errorf(“error: %+v”, err)

を使うことでstack trace付きのエラー出力を行うことができます。

インターンを通して

  • 圧倒的スピード感
  • 目標設定の納得度の高さ
  • 裁量の大きさ

良いところは幾つもあったのですが、特に上記3つが印象に残りました。
インターン初日に早速プロジェクトMTGがあり,終わるとすぐに技術選定の会議が行われました.プロダクトの性質に合った技術を使うことはもちろんですが,挑戦したい技術なども積極的に採用しており裁量の大きさを感じました.裁量が大きいからこそ自分たちで決められる物が多く,スピード感につながっていると感じました.
また,期間中に半期のスローガンを決めるタイミングがあったんですが,今の事業フェーズや今後の目標を提示した上でスローガンを考える時間を取っていました.スローガンは簡潔な方が良いので,自分たちが今大事にすべきこと・目標にすべきことは何なのかをじっくり考え,まとめることができるのでとても良い取り組みだと感じました.

最後になりましたが,1ヶ月間トレーナーの後藤さん,メンターの黒崎さんを始め,人事の方やチームのみなさん,オンラインランチをしてくださった皆さん本当にありがとうございました.

オンラインランチ
フルリモートでのインターンだったのでオンラインランチをした時の写真です