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

今こそ思い出すGraphQLの特徴

ham
April 21, 2024

 今こそ思い出すGraphQLの特徴

2024/04/19
tsukiji.graphql x ハッカー鮨でLTしたスライドです。
https://tsukiji-graphql.connpass.com/event/314173/

GraphQLを使う際に抑えておいた方が良いポイントをサクッとまとめました。
- 必要なフィールドのみ取得しよう
- 指定していないフィールドの値は取得しない
- N+1対策は遅延ロード
- キャッシュを有効活用しよう

ham

April 21, 2024
Tweet

More Decks by ham

Other Decks in Technology

Transcript

  1. 開発⽣産性が向上する⽅法を探求しているエンジニア! Ruby / Rails / React / TypeScript / AWS

    Agile / DevOps / Developer Productivity / DevEx Stock Investment 浜⽥ 直⼈ Naoto Hamada (ham) @hamchance0215
  2. user(id:$id) { id name } 必要なフィールドのみ取得 - 呼び出し元ではnameしか使わない - 使うフィールドのみ指定

    - 例外としてidフィールドは後に説明する キャッシュのキーとして使⽤するのでキャッ シュを活⽤するなら取得すべき
  3. user(id:$id) { id reviewCount } 無駄な計算 # Ruby code def

    resolve(id:) user = User.find_by(id:) { id: user.id, review_count: user.reviews.count, } end
  4. user(id:$id) { id reviewCount } 無駄な計算 – users select *

    from users where id = 1; – reviews select count(*) from reviews where user_id = 1;
  5. user(id:$id) { id } 無駄な計算 – reviewCountを指定していなくても reviews.countが計算される # Ruby

    code def resolve(id:) user = User.find_by(id:) { id: user.id, review_count: user.reviews.count, } end
  6. user(id:$id) { id } 無駄な計算 – reviewCountを指定していなくても reviews.countが計算される # Ruby

    code def resolve(id:) User.find_by(id:) end # Userモデルのメソッドとして提供して呼ばれ たときだけ取得する def review_count reviews.count end
  7. users { id profile { name } } 遅延ロード –

    id fieldはusersテーブルから取得 – profileはprofilesテーブルから取得 # Ruby code def resolve User.all end
  8. users { id profile { name } } 遅延ロード –

    usersは10件Hit select * from users; – profilesを1件ずつ取得 => N+1問題 select * from profiles where user_id = 1; select * from profiles where user_id = 2; … select * from profiles where user_id = 10;
  9. users { id profile { name } } 遅延ロード –

    usersに対応するprofileを事前ロード # Ruby code def resolve User.all.preload(:profile) end
  10. users { id profile { name } } 遅延ロード –

    usersは10件Hit select * from users; – hitしたusersに対応したprofilesを事前ロード select * from profiles where user_id in (1, 2, …, 10);
  11. users { id } 遅延ロード – usersは10件Hit select * from

    users; – fieldに指定していなくてもprofilesを事前ロー ドしてしまう select * from profiles where user_id in (1, 2, …, 10);
  12. users { id profile { name } } 遅延ロード –

    usersに対応するprofileを遅延ロード # Ruby code def resolve # fieldにprofileがある場合、profile を取得するuser_idを記憶しておき、最後にま とめて取得する User.all end
  13. user(id:$id) { __typename id name } キャッシュの活用 - キャッシュを活⽤することで1度取得した データはバックエンドに問い合わせずに瞬時

    に表⽰できる - ※APOLLOの場合 - https://www.apollographql.com/docs/react/data/ mutations - `__typename`と`id`でデータをキャッシュ
  14. mutation UpdateUser(input:UpdateUserInput!) { updateUser(input:$input) { id name } } -

    Mutationのレスポンスで変更後の値を受け取ることで、キャッシュが更 新される - 明示的にrefetchしなくてもOK キャッシュの活用