Upgrade to Pro — share decks privately, control downloads, hide ads and more …

システムをあるべき姿から 設計し直してみた

システムをあるべき姿から 設計し直してみた

2025/10/8 「AI開発の実戦メソッドとアーキテクチャ事例 ― toCサービスの高速デリバリを支える技術
」の発表資料です。
https://kauche.connpass.com/event/368490//

Avatar for Jungwon Choi

Jungwon Choi

October 07, 2025
Tweet

More Decks by Jungwon Choi

Other Decks in Programming

Transcript

  1. 崔 井源(ちぇ じょんうぉん) 自己紹介 • 韓国ソウル特別市出身 • 2020年にNAISTで修士課程を修了(ここで理転) • 2020年に株式会社NewsPicksにエンジニアとして新卒入社

    • 2024年くらいまで主にNewsPicksの検索システムの開発やメ ンテナンスを担当(検索データの整形、インフラの開発・メ ンテ、検索機能のUI・UX改善など) • 2025年からプラットフォームエンジニアリングチームで UX・EX・DX改善につながる開発を進めている 2 @jonlpstudy
  2. 抱えていた課題 コンテンツ種別も色々あり、セクション も色々あり、複雑な構造のように見える が、実は下記の並びをどうしているのか に過ぎない(すごい単純化すると)。 • セクション名 • サムネ画像 •

    タイトル • Pick数(コンテンツの人気を表す数 値) 6 NewsPicksの各タブの構成を単純化した図 似たようなことをするのに全部独自の実装がされている
  3. • パターン1 コレクション対応版のメソッドに見せかけて、N+1になっていた fun fetch(targetIds: List<Int>): List<Target> { return targetIds.map

    { someProcess(it) } } 独自の実装が増えていくと、パフォーマンス管理が難しい 抱えていた課題 8 コレクション対応版に見せかけてN+1アクセスする処理の例 val newsModels = newsIds.map { newsRepository.findById(it) } 普通にN+1している例
  4. • パターン2 同じ種別のデータを一気に取得しないので、何回もDBアクセスが発生する 独自の実装が増えていくと、パフォーマンス管理が難しい 抱えていた課題 9 fun findByIds(ids: List<ContentId>): List<Content>

    { val newsIds = ids.filterInstance<NewsId>() val newsModels = newsRepository.findByNewsIds(newsIds).associateWith { it.id } val movieIds = ids.filterInstance<MovieId>() val movieModels = movieRepository.findByMovieIds(movieIds).associateWith { it.id } val additionalNewsIds = newsMovieMappingRepository.findByIds(movieIds) val additionalNewsModels = newsRepository.findByNewsIds(additionalNewsIds).associateWith { it.id } return ... }
  5. あるべき姿 シンプルな問題を定義し、それで検証を行う。 • タブは一つだけ存在し、タブ名は home である • home には3つの異なるデザインのセクションが存在する ◦

    セクション1は、速報「記事」を「リスト」で表示する ◦ セクション2は、人気「動画」を「カルーセル」で表示する ◦ セクション3は、人気「記事」を「ランキング」で表示する • セクションに表示すべきコンテンツは「記事」と「動画」の2種類 のみである ◦ 「記事」には「動画」が紐づかないケースがある ◦ 「動画」には必ず「記事」が紐づく ◦ コンテンツをPickするとPick数が表示される • N+1を許容しないので、必ずそのDBには一回だけリクエストする 13 NewsPicksのアプリの構成
  6. あるべき姿 14 検証後に固まった構成 ポイント • APIとコントローラーは一つだけを用意 し、流用する • タブやセクションの定義はDBで管理し、 クラスが特定のタブに依存しないように

    する • コンテンツ種別ごとに一回だけDBにアク セスする • コンテンツ種別ごとにデータを取得する タイミングでフィルター処理を済ませる ようにし、管理しやすくする より具体化する: 開発者が気にするのはカラーの部分だけ