LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

LINE公式アカウント友だち追加経路一覧機能開発(インターンレポート)

はじめに

こんにちは。オークランド大学工学部ソフトウェアエンジニアリング科の中根萌花と申します。2024年のサマーインターンシップで4週間にわたり、LINE公式アカウントのサーバーサイドの実開発に参加しました。

今回配属されたのは、LINE Official Account Manager という、LINE公式アカウントの運用管理プラットフォームを担当するチームです。そこで、「友だち追加経路一覧ページ」という新規ページのサーバーサイド開発を担当し、仕様策定から、設計開発、リリースまでを経験させていただきました。

本記事では、私がインターンシップ期間中に取り組んだ内容と学んだことについてご紹介します。

背景・目的

LINE公式アカウントの重要な機能の一つに、今回の案件の対象である「友だち追加経路機能」があります。LINE公式アカウントオーナーは、ポスターやQRコード、URLなど、さまざまな経路から友だちを獲得することができます。これらの方法は「友だち追加経路」と呼ばれ、オーナーは友だちがどの経路から追加されたのかを分析することができます。これにより、オーナーは自身のアカウントの効果的な宣伝方法を見極めることができます。

今回の案件は、オーナーが作成した友だち追加経路を一覧で表示するページを管理画面上に実装することでした。これまでは、管理画面上で経路情報を確認することはできず、オーナーはメモなどの別のツールを使用して経路を管理していました。この方法は保管コストが高く、機能の利便性を低下させていました。今回の一覧ページの実装により、オーナーは友だち追加経路を直接管理画面上で管理できるようになります。

友だち追加経路一覧ページ
図:今回新たに追加された友だち追加経路一覧ページ

行ったこと

今回のページを実現する上で、サーバーサイドとして以下の作業を行いました。

  1. 新規エンドポイントの実装(Kotlin, Spring Boot)
    • 各LINE公式アカウントに一意に付与される oa_id を用いて、友だち追加経路一覧を返す。
      • 検索ワード、作成日時でフィルタリング可
    • 各経路に一意に付与される tracking_route_id を用いて、経路詳細情報を返す。
  2. 既存エンドポイントの内部ロジックの変更(Kotlin, Spring Boot)
    • 新規経路作成のエンドポイント(既存)が呼ばれた際に、渡された経路名が既存の経路名と重複しないかのチェックを行うように変更。
  3. DB設計(MySQL)
    • 新規エンドポイントで経路に紐づく友だち追加URLを返すために、DB上でURLを新たに保管する。(「短縮化URLのDB保管方法の検討」にて後述)

開発の流れ

開発期間を通して、企画、フロントエンド開発者、QA(Quality Assurance)の各担当者とコミュニケーションをとりながら、仕様策定からリリースまでを行いました。各フェーズでサーバーサイドの担当として行ったことや、工夫したことについて書きたいと思います。

1. 仕様策定

企画チームの方が考案した機能や画面構成を基に、サーバーサイドの観点から必要な工数や既存のデータ量を考慮し、以下の機能を今回のリリースで実装するか判断しました。

フィルター機能を実装する必要があるか

アカウントが多くの経路を持つ場合、サーバー側で経路一覧を返す際にフィルター機能を実装する必要があります。逆に、各アカウントの経路作成数が少ない場合はフィルター機能の必要性は低いです。このため、社内のデータプラットフォーム IU(参考: IU開発チームインタビュー)でクエリを実行し、現在の各アカウントの経路作成数を調査しました。

経路作成数が 10 以下のアカウント(ページネーションが10であるため、経路一覧が1ページに収まるアカウント)の割合を調べたところ、これらのアカウントは全体の9割以上を占めることがわかりました。

しかし、アカウントの総数が膨大であるため、それ以外の1割未満であっても無視できない数のアカウントが存在します。また、これらのアカウントの多くは数百単位の経路数を保持していることもわかりました。このように多くの経路を保持するアカウントは、今回の一覧ページを積極的に活用する可能性がより高いことから、フィルター機能は実装するという判断に至りました。

経路作成者を表示するかどうか

もともと経路情報を保存していたテーブルでは、経路の作成者情報を保存していませんでした。そのため、今回の機能で作成者を表⽰するには、テーブル構造の変更やアカウントの複雑な権限設定を考慮した実装が必要となり、今回のリリースでは⼯数の⾯で断念しました。ただ、将来的に経路作成者の表⽰を実装しやすいように、後述のDB設計において経路の作成者に紐づくアカウントIDをテーブル上に保存するようにしました。

2. 設計

仕様が確定した後の設計フェーズでは、新規APIとそれを支えるデータベースの設計を行いました。APIの設計については、仕様をドキュメント化しフロントエンド開発者と認識を統一しました。また、DB設計では、経路情報を保存しているDBが他サービスにも広く利用されているため、他サービスへの影響を最小限に抑えつつ、メンテナビリティを考慮した設計をする必要がありました。

短縮化URLのDB保管方法の検討

  • 背景:

    LINE公式アカウントオーナーが友だち追加経路を作成すると、それに紐づく短縮化URLが⽣成されます。LINEユーザーは、この短縮化URL経由でLINE公式アカウントを友だち追加します。今回実装した一覧ページにはこの短縮化URLも表⽰する必要ありますが、もともとのテーブルにはこのURLは保存されていませんでした。友だち追加経路作成時に都度、短縮化URLを⽣成する仕様だったためです。短縮化URLを⽣成するAPIにはレートリミットが設定されているので、今回新規実装する友だち追加⼀覧ページや詳細ページへの回遊が増えることを考慮すると、表示する度に毎回短縮化URLを⽣成する実装にするとリミットを超える可能性が⾼いです。そのため、URLを都度⽣成するのではなく、DBに保存し、経路情報のAPIが呼ばれた際にDBから取得して返す⽅法が望ましいです。

  • 検討事項:

    どのようにDB上にURLを保存するかを検討しました。経路情報が保存されているDBは、他サービスも広く利用しているDBであるため、影響範囲を考慮する必要があります。

    もともとのテーブル構造: 既存の経路情報を保持するテーブルの構造を以下に⽰します。このテーブルは経路発⾏のログを残す⽬的と、各経路の友だちの流入の分析のための集計で使われていました。

    oa_tracking_route

  • 方法案比較:

    方法案メリットデメリット
    方法(1): 既存テーブルにURLカラム追加
    oa_tracking_route (既存)
    • SQLクエリがシンプルに書ける
    • 当該テーブルにカラムを新たに追加する場合、既存のデータ量的にDB全体に1分間のレプリケーション遅延を引き起こすため、他サービスへの影響が大きく、許容できない。
    方法(2): 新規テーブル追加
    oa_tracking_route (新)
    • 本来の使用方法に影響を与えず、既存サービスに影響を与えない
    • 一つの経路の情報を返すために、二つのテーブルを参照する必要があるため、SQLクエリが複雑になる
    • データ整合性の管理が必要になる。
    方法(3): 既存テーブルの既存カラム使用
    oa_tracking_route (既存)
    • SQLクエリがシンプルに書ける
    • DDLを実行しなくて良いため、レプリケーション遅延による他サービスへの影響が発生しない
    • カラム名がotherとなってしまうため、URLが格納されているとわかりにくい。
  • 結論:

    最終的に方法(3)の既存テーブルの既存カラムを使用することにしました。カラム名が格納データを正しく表現しないというデメリットがありますが、方法(1)は全DBにレプリケーション遅延を引き起こしてしまうため、今回の実装内容には見合わない影響の大きさと範囲です。また、方法(2)に関しても、テーブル構造が複雑化してしまうため避けたいです。そのため、一番デメリットが小さい方法(3)で今回は実装することにしました。また実装時には、このデメリットをカバーするために、コードベース上にドキュメントを残したり、データ型を設定して安全化を図りました。

/** 
 * other 
 * 
 * @property shortenUrl URL 
 * ... 
 */ 
data class TrackingRouteOtherParameter( 
  @get:JsonProperty("shorten_url") 
  @JsonInclude(JsonInclude.Include.NON_NULL) 
  val shortenUrl: URI? = null, 
  // .... 
)

3. リリース

リリース後は、実装したAPIのエラー率や、SQLクエリのレイテンシー、QPS などのメトリクスを Grafana でモニタリングし、挙動やパフォーマンスに問題がないことを確認しました。

Latency

学んだこと・感じたこと

3週間の開発期間を通して学んだこと、感じたことを書きたいと思います。技術面やチーム開発についての学びはもちろん、LINEヤフーのエンジニアの働き方やカルチャーについても理解を深めることができました。

技術面

技術面では、コーディングの段階からセキュリティやパフォーマンスを意識した実装をする、など今までの個人開発や小規模のシステム開発では得られなかった気づきや学びがありました。特に印象的だったのは、システムの規模の大きさと、その大規模システムを支える体制が整っていることです。私が携わったコードベースは、開発者が多く関わるLINEヤフー内でも規模の大きいものでした。その各機能や、過去に起きた問題、実装の仕様などが wiki で管理されており、短いキャッチアップ期間でスムーズに開発に入ることができました。例えば、API設計の際には、過去に発生した問題を参照し、同じ問題を誘発しないようにしました。

CI/CD、Grafana、アラートシステムなど、システムを安全に運用するための体制も整っていました。私が既存のコードを改定した際には、毎日2回自動で実行される統合テストで問題を発見し、見落としていた他サービスへの影響を未然に防ぐことができました。また、リリース作業を見学する機会があったのですが、自動化された運用フローや、複数の監視ツールを用いて安全にリリースできる体制が整っていることがわかりました。これまで知識として理解していたこのようなツールや体制の重要性を、実際に体験することができました。

また、開発していく上で大規模データベースならではの考慮事項についても理解を深めました。実装方法を決める際には、APIのレートリミットやデータ量による制約を考え、実装方法を選定しました。また、今回は開発日数の関係でできなかったのですが、経路一覧ページを実装するにあたって、経路情報を保管するテーブルにインデックスを貼ることを検討していました。かなりのデータ量があるため、いくつかのカラムにインデックスを貼ることでさらなるパフォーマンスの向上が期待できたと考えます。

チーム開発

企画、開発、QAなどさまざまな職種に分かれ、システムを開発するのが初めての経験でした。この過程で、メンバー間の役割や知識の違いを考慮しながらのコミュニケーションや、認識の擦り合わせを行う過程で、エンジニアとして多くの学びを得ました。特に、企画から提示される機能や仕様に対して、開発側としてリソースや工数、運用コストを考慮して意見を述べるという経験ができたのはとても良かったです。

また、現行チームに飛び込んで開発を進める中で、開発において不明点が生じた際にそれが自身の技術不足なのか、組織やシステム独自の仕様によるものなのか判断が難しい状況も経験しました。短いインターンシップ期間を有効なものにするために、「20分以上自分で調べても解決できない場合はチームに質問する」というルールを設けました。質問する際は、何がわからないのか、何を試したのかを明確にし、簡潔かつ効果的な質問を心掛けました。

LINEヤフーについて

インターンシップを通じて、LINEヤフーのカルチャーについても大きく理解が深まりました。エンジニアやQA、企画などの職種にかかわらず、全員がユーザーに良いものを届けようという思いが伝わってきました。印象的に残っているのが、私が企画の方にUIに関する提案をした際に、真剣に考慮していただいたことです。エンジニアとしての役割だけに限定されず、サービスを良くするために主体的に行動できる文化がとても魅力的だと感じました。また、私が配属された部署のエンジニアの皆様は、技術への追求心がとても高く、年次にかかわらず技術について楽しそうにディスカッションされていた姿が印象的で、私自身とても刺激になりました。


おわりに

このインターンシップに参加したのは、大規模なシステムの開発工程を経験してみたい、またそれを通してエンジニアとして成長したい、という思いからでした。今回携わった機能は、実際にエンドユーザーであるLINE公式アカウントオーナーに以前から望まれていた機能だったそうです。学生でありながら、堅牢かつ大規模なコードベースの開発に参加させていただいただけでなく、エンドユーザーの体験をより便利にする機能の開発に携わることができ、大変貴重な経験となりました。実際にリリースされた画面を見たときは感動もひとしおでした。

この経験を通して、技術的な学びや会社理解はもちろん、自身のことやエンジニアとして働く心構えについても理解を深めることができました。

また、期間中はたくさんの社員の皆様にお世話になりました。友だち追加経路一覧のチームの方々、配属先のチームの皆様をはじめ、他にも交流させていただいた社員の皆様のおかげで、非常に楽しく、学びの多い4週間にすることができました。心から感謝申し上げます。

メンターからの一言

中根さんのメンターを務めた嶋崎修功(社内通称はLong)です。普段はLINE公式アカウントのサーバーサイド開発を担当しています。

今回のインターンシップでは、友だち追加経路一覧機能の開発をお願いしました。この機能は、オーナーが友だち獲得する経路を効率よく把握し、より効果的に運用するために重要なものです。ただし、既存のデータベースに新しい機能を追加するにあたり、拡張方法や設計の工夫が求められ、課題も多い内容でした。

中根さんは、開発に取り組む前から企画やQAなどの関係者としっかり意見交換を行い、オーナーが求めるニーズをできる限り実現するために丁寧に準備を進めていました。特に、データベースの拡張では既存システムへの影響を最小限に抑えながら、どのように必要な機能を追加するかという難しい課題に向き合い、複数の選択肢を比較検討していました。その結果、合理的で現実的な解決策を導き出せたことは、とても印象的でした。

短いインターン期間ながら、問題の本質をしっかり理解し、自分の考えを持って開発に取り組む姿勢に感心しました。この経験が中根さんの今後の成長に繋がることを願っています。またお会いできる日を楽しみにしています!