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

Hatena Engineer Seminar #14 GraphQL編

Hatena Engineer Seminar #14 GraphQL編

サブタイトル: 〜ユーザーも開発者も快適なサービスであるために〜

魔法のiらんどでは、クライアント・サーバー間のインターフェースとしてGraphQLを採用しました。この技術選択は、はてなの技術スタックのモダン化を進め、ユーザーと開発に携わるエンジニア双方の体験が快適であることを目指したものです。この発表では、魔法のiらんどリニューアルを成功に導いたGraphQLの強みと、月間3億PVをさばくためのパフォーマンス面の検討について紹介します。

Yuu Igarashi

July 15, 2020
Tweet

More Decks by Yuu Igarashi

Other Decks in Programming

Transcript

  1. GraphQLฤ
    ʙϢʔβʔ΋։ൃऀ΋շదͳαʔϏεͰ͋ΔͨΊʹʙ
    Hatena Engineer Seminar #14
    2020/07/15 id:yigarashi

    View full-size slide

  2. ࣗݾ঺հ
    • id:yigarashi
    • ৽ଔ2೥໨
    • WebΞϓϦέʔγϣϯΤϯδχΞ
    • ڵຯ
    • ։ൃϓϩηεɺϓϩδΣΫτ؅ཧ
    • ϓϩάϥϛϯάݴޠཧ࿦

    View full-size slide

  3. ຐ๏ͷiΒΜͲ

    View full-size slide

  4. γεςϜͷ֓؍
    /FYUKT
    αʔόʔαΠυϨϯμϦϯά
    (SBQI2-"1*
    σʔλϕʔε

    View full-size slide

  5. γεςϜͷ֓؍
    /FYUKT
    αʔόʔαΠυϨϯμϦϯά
    (SBQI2-"1*
    σʔλϕʔε
    ͍·͔Β͜͜ͷ࿩Λ͠·͢

    View full-size slide

  6. GraphQLฤ - ໨࣍
    • GraphQLͱ͸
    • ͳͥGraphQLΛ࠾༻͔ͨ͠
    • GraphQLͷԸܙ
    • ݄ؒ3ԯPV΁ͷඋ͑

    View full-size slide

  7. GraphQLͱ͸
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ

    View full-size slide

  8. GraphQLͱ͸
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View full-size slide

  9. GraphQLͱ͸
    {
    me {
    name
    interests
    }
    }
    ΫΤϦ
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View full-size slide

  10. GraphQLͱ͸
    {
    me {
    name
    interests
    }
    }
    ΫΤϦ
    {
    "me": {
    "name": "yigarashi",
    "interests": [
    "։ൃϓϩηε",
    "ϓϩάϥϛϯάݴޠཧ࿦",
    ]
    }
    }
    ฦΓ஋ʢ+40/ʣ
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View full-size slide

  11. GraphQLͱ͸
    {
    me {
    name
    interests
    }
    }
    ΫΤϦ
    {
    "me": {
    "name": "yigarashi",
    "interests": [
    "։ൃϓϩηε",
    "ϓϩάϥϛϯάݴޠཧ࿦",
    ]
    }
    }
    ฦΓ஋ʢ+40/ʣ
    ΫΤϦͱಉ͡ܗͷ
    +40/͕ฦ͞ΕΔ
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View full-size slide

  12. ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ

    View full-size slide

  13. ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ

    View full-size slide

  14. ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ
    type Query { me: Me }
    type Me {
    name: String
    interests: List[String]
    }
    εΩʔϚͷྫ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ

    View full-size slide

  15. ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ
    type Query { me: Me }
    type Me {
    name: String
    interests: List[String]
    }
    εΩʔϚͷྫ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ
    {
    me {
    name
    interests
    }
    }

    View full-size slide

  16. ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ
    type Query { me: Me }
    type Me {
    name: String
    interests: List[String]
    }
    εΩʔϚͷྫ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ
    {
    me {
    name
    interests
    }
    }

    View full-size slide

  17. type Query { me: Me }
    type Me {
    name: String
    interests: List[String]
    }
    ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ
    εΩʔϚͷྫ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ

    View full-size slide

  18. type Query { me: Me }
    type Me {
    name: String
    interests: List[String]
    }
    ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ
    εΩʔϚͷྫ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ
    {
    me {
    name
    interests
    age
    }
    }

    View full-size slide

  19. type Query { me: Me }
    type Me {
    name: String
    interests: List[String]
    }
    ॏཁͳ֓೦(1) - εΩʔϚ
    ϥϯλΠϜ͕ͲΜͳσʔλΛฦͤΔ͔هड़ͨ͠΋ͷ
    εΩʔϚͷྫ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ
    {
    me {
    name
    interests
    age
    }
    }

    View full-size slide

  20. ॏཁͳ֓೦(2) - Ϧκϧό
    ϥϯλΠϜʹ͓͍ͯϑΟʔϧυͷ஋Λܭࢉ͢Δؔ਺

    View full-size slide

  21. ॏཁͳ֓೦(2) - Ϧκϧό
    ϥϯλΠϜʹ͓͍ͯϑΟʔϧυͷ஋Λܭࢉ͢Δؔ਺
    {
    me {
    name
    interests
    }
    }

    View full-size slide

  22. ॏཁͳ֓೦(2) - Ϧκϧό
    ϥϯλΠϜʹ͓͍ͯϑΟʔϧυͷ஋Λܭࢉ͢Δؔ਺
    {
    me {
    name
    interests
    }
    }
    యܕతͳ࣮ߦ

    View full-size slide

  23. ॏཁͳ֓೦(2) - Ϧκϧό
    ϥϯλΠϜʹ͓͍ͯϑΟʔϧυͷ஋Λܭࢉ͢Δؔ਺
    {
    me {
    name
    interests
    }
    }
    • meΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • DB͔ΒmeʹରԠ͢ΔΦϒδΣΫτMeΛऔಘ
    యܕతͳ࣮ߦ

    View full-size slide

  24. ॏཁͳ֓೦(2) - Ϧκϧό
    ϥϯλΠϜʹ͓͍ͯϑΟʔϧυͷ஋Λܭࢉ͢Δؔ਺
    {
    me {
    name
    interests
    }
    }
    • meΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • DB͔ΒmeʹରԠ͢ΔΦϒδΣΫτMeΛऔಘ
    • nameΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • Me.nameΛฦ͢
    యܕతͳ࣮ߦ

    View full-size slide

  25. ॏཁͳ֓೦(2) - Ϧκϧό
    ϥϯλΠϜʹ͓͍ͯϑΟʔϧυͷ஋Λܭࢉ͢Δؔ਺
    {
    me {
    name
    interests
    }
    }
    • meΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • DB͔ΒmeʹରԠ͢ΔΦϒδΣΫτMeΛऔಘ
    • nameΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • Me.nameΛฦ͢
    • interestsΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • Me.interests͕idͷྻʹͳ͍ͬͯΔͷͰDB͔Βऔಘ͢Δ
    యܕతͳ࣮ߦ

    View full-size slide

  26. ॏཁͳ֓೦(2) - Ϧκϧό
    ϥϯλΠϜʹ͓͍ͯϑΟʔϧυͷ஋Λܭࢉ͢Δؔ਺
    {
    me {
    name
    interests
    }
    }
    • meΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • DB͔ΒmeʹରԠ͢ΔΦϒδΣΫτMeΛऔಘ
    • nameΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • Me.nameΛฦ͢
    • interestsΛܭࢉ͢ΔϦκϧόΛ࣮ߦ
    • Me.interests͕idͷྻʹͳ͍ͬͯΔͷͰDB͔Βऔಘ͢Δ
    • ࠷ޙʹ׬੒ͨ͠஋ΛJSONʹͯ͠ฦ͢
    యܕతͳ࣮ߦ

    View full-size slide

  27. ͳͥGraphQLΛ࠾༻͔ͨ͠

    View full-size slide

  28. Ϣʔβʔମݧɾ։ൃޮ཰Λ޲্͢Δ
    • Ϣʔβʔମݧ
    • SPA(Single Page Application) + APIͷߏ੒ʹ͢Δ͜ͱͰɺϞμϯͳ
    ΞϓϦతͳମݧΛ࣮૷͠΍͘͢͢Δ
    • ։ൃޮ཰
    • ΫΤϦݴޠ͕ڧྗͰը໘ͷมߋʹڧ͍
    • Ϟμϯͳٕज़Λ࠾༻͢Δ͜ͱͰϞνϕʔγϣϯ޲্
    • ͔ͦ͠͠Ε͚ͩͰ͸ͳ͍……

    View full-size slide

  29. ຐ๏ͷiΒΜͲϦχϡʔΞϧͷϙΠϯτ
    • ΧΫϤϜͷίΞϩδοΫΛ࢖ͬͯAPIΛ࣮૷͢Δ
    • ྫ: ࡞඼ʹؔ͢ΔCRUDૢ࡞
    • ൓ରʹɺຐ๏ͷiΒΜͲͷͨΊʹ࣮૷ͨ͠APIΛΧΫϤϜͰ΋࢖͑ΔΑ
    ͏ʹ͓ͯ͘͠
    ΧΫϤϜͱίʔυϕʔεΛڞ༗͠ɺ։ൃɾӡ༻ίετͷ࡟ݮΛૂ͏

    View full-size slide

  30. ঢ়گΛ෼ੳ͢Δ
    • খઆΛॻ͘ɺಡΉɺڞ༗͢Δͱ͍͏େے͸͔֬ʹࣅ͍ͯΔ
    • ࡉ෦͕ͪΐͬͱͣͭҧ͏
    • ϑΟʔϧυͷ༗ແ
    • ຐ๏ͷiΒΜͲʹ͋Δ͕ΧΫϤϜʹ͸ͳ͍ɺٯ΋વΓ
    • ஋Λฦͨ͢Ίͷॲཧͷҧ͍

    View full-size slide

  31. REST API ͸ͭΒ͍
    ίΞϩδοΫΛ࢖ͬͯJSON
    Λฦ͢෦෼ͷංେԽɾΧΦ
    εԽ͕༧૝͞Εͨ

    View full-size slide

  32. REST API ͸ͭΒ͍ sub example_handler {
    my $common_field = get_common_field;
    if (is_kakuyomu) {
    $common_field =
    kakuyomu_specific_operation($common_field);
    }
    my $kakuyomu_field = undef;
    if (is_kakuyomu) {
    $kakuyomu_field = get_kakuyomu_field;
    }
    ...
    }
    ίΞϩδοΫΛ࢖ͬͯJSON
    Λฦ͢෦෼ͷංେԽɾΧΦ
    εԽ͕༧૝͞Εͨ

    View full-size slide

  33. REST API ͸ͭΒ͍ sub example_handler {
    my $common_field = get_common_field;
    if (is_kakuyomu) {
    $common_field =
    kakuyomu_specific_operation($common_field);
    }
    my $kakuyomu_field = undef;
    if (is_kakuyomu) {
    $kakuyomu_field = get_kakuyomu_field;
    }
    ...
    }
    ίΞϩδοΫΛ࢖ͬͯJSON
    Λฦ͢෦෼ͷංେԽɾΧΦ
    εԽ͕༧૝͞Εͨ
    ڞ௨ͷϑΟʔϧυ͕ͩΧΫϤϜͰ
    ͸ಛघͳՃ޻͕ඞཁ

    View full-size slide

  34. REST API ͸ͭΒ͍ sub example_handler {
    my $common_field = get_common_field;
    if (is_kakuyomu) {
    $common_field =
    kakuyomu_specific_operation($common_field);
    }
    my $kakuyomu_field = undef;
    if (is_kakuyomu) {
    $kakuyomu_field = get_kakuyomu_field;
    }
    ...
    }
    ίΞϩδοΫΛ࢖ͬͯJSON
    Λฦ͢෦෼ͷංେԽɾΧΦ
    εԽ͕༧૝͞Εͨ
    ڞ௨ͷϑΟʔϧυ͕ͩΧΫϤϜͰ
    ͸ಛघͳՃ޻͕ඞཁ
    ΧΫϤϜͷΈଘࡏ͢ΔϑΟʔϧυ

    View full-size slide

  35. GraphQLͰղܾ
    ϑΟʔϧυ͝ͱʹϦκϧ
    όΛఆٛ͢ΔͷͰɺॲཧ
    ͷৼΓ෼͚Λॊೈ͔ͭ៉
    ྷʹߦ͏͜ͱ͕Ͱ͖Δ

    View full-size slide

  36. GraphQLͰղܾ
    GraphQL::Type::Object->new(
    name => 'Example',
    fields => +{
    common_field => is_kakuyomu ?
    kakuyomu_resolver :
    maho_resolver,
    (is_kakuyomu ? (
    kakuyomu_field => kakuyomu_field_resolver
    ) : ())
    ...
    }
    )
    ϑΟʔϧυ͝ͱʹϦκϧ
    όΛఆٛ͢ΔͷͰɺॲཧ
    ͷৼΓ෼͚Λॊೈ͔ͭ៉
    ྷʹߦ͏͜ͱ͕Ͱ͖Δ

    View full-size slide

  37. GraphQLͰղܾ
    GraphQL::Type::Object->new(
    name => 'Example',
    fields => +{
    common_field => is_kakuyomu ?
    kakuyomu_resolver :
    maho_resolver,
    (is_kakuyomu ? (
    kakuyomu_field => kakuyomu_field_resolver
    ) : ())
    ...
    }
    )
    ϑΟʔϧυ͝ͱʹϦκϧ
    όΛఆٛ͢ΔͷͰɺॲཧ
    ͷৼΓ෼͚Λॊೈ͔ͭ៉
    ྷʹߦ͏͜ͱ͕Ͱ͖Δ
    ݺͼग़͢ϦκϧόΛৼΓ෼͚Δͩ
    ͚Ͱྑ͍

    View full-size slide

  38. GraphQLͰղܾ
    GraphQL::Type::Object->new(
    name => 'Example',
    fields => +{
    common_field => is_kakuyomu ?
    kakuyomu_resolver :
    maho_resolver,
    (is_kakuyomu ? (
    kakuyomu_field => kakuyomu_field_resolver
    ) : ())
    ...
    }
    )
    ϑΟʔϧυ͝ͱʹϦκϧ
    όΛఆٛ͢ΔͷͰɺॲཧ
    ͷৼΓ෼͚Λॊೈ͔ͭ៉
    ྷʹߦ͏͜ͱ͕Ͱ͖Δ
    ݺͼग़͢ϦκϧόΛৼΓ෼͚Δͩ
    ͚Ͱྑ͍
    αʔϏε͝ͱʹඞཁͳϑΟʔϧυ
    ͚ͩ࿐ग़͢Δ

    View full-size slide

  39. ࠾༻ཧ༝ͷ·ͱΊ
    • SPA + API ʹΑΔϞμϯͳϢʔβʔମݧͷ࣮ݱ
    • ։ൃޮ཰ͷ޲্
    • ΧΫϤϜͱͷίʔυϕʔεͷڞ༗
    ҎԼͷͭͷधཁΛ͏·͘ຬͨ͢ͷ͕(SBQI2-ͩͬͨ

    View full-size slide

  40. GraphQLͷԸܙ

    View full-size slide

  41. Ըܙ(1) - ϑϩϯτΤϯυ։ൃମݧͷ޲্
    • ύϫϑϧͳΫΤϦݴޠʹΑΔॊೈͳσʔλऔಘ
    • Τϐιʔυ --> ࡞඼ --> ࡞ऀͱ͍ͬͨωετͨ͠σʔλ΋αʔόʔ
    ͷมߋͳ͠ʹ؆୯ʹऔಘͰ͖Δ
    • Apollo ClientͷԸܙ
    • Reactͱ࿈ܞ͢ΔGraphQLΫϥΠΞϯτͷσϑΝΫτ
    • ߥ࡟Γͳ෦෼΋͋Δ͕ϞμϯͳUIΛ࡞ΔͨΊͷػೳ͕๛෋

    View full-size slide

  42. Ըܙ(2) - API։ൃͷޮ཰Խ
    • ࠷ॳʹશͯͷը໘Λਫ਼ࠪͯ͠1000ߦ͍ۙεΩʔϚΛઃܭͨ͠
    • εΩʔϚϑΝʔετͳ։ൃ
    • εΩʔϚઃܭΛ௨ͯ͠ϓϩμΫτ΁ͷཧղ͕ਂ·ͬͨ
    • ΤϯδχΞ8ਓͷେॴଳ͕͏·͘ػೳ͢Δ͖͔͚ͬʹ
    • εΩʔϚத৺ͷίϛϡχέʔγϣϯͰԿΛ࡞Δ͔ͷೝ͕ࣝἧͬͨ
    • type ΍ mutation ୯Ґͷ෼୲Ͱߴ౓ͳฒྻ։ൃ͕Մೳʹ

    View full-size slide

  43. Ըܙ(3) - ։ൃϞνϕʔγϣϯͷ޲্
    • ϦϦʔεޙͷ;Γ͔͑ΓͰʮϞνϕʔγϣϯΛߴ͘อͯͨʯͱͷ੠
    • ϕςϥϯ΋஌Βͳ͍͜ͱ͕ͨ͘͞Μ͋Γܹࢗతͳ೔ʑ
    • ແҋʹ৽ٕज़Λ࢖͏ͷ͸ةݥ͕ͩɺద੾ʹऔΓೖΕΔͷ͸ॏཁ
    • ྲྀߦ͍ͬͯΔٕज़͸৘ใ΋ଟ͍

    View full-size slide

  44. Ըܙ(4) - ΧΫϤϜͱͷίʔυϕʔεڞ༗
    • ೉͍͠෦෼΋ଟ͕͋ͬͨ֓͘Ͷ៉ྷʹ࣮૷Ͱ͖ͨ
    • ॲཧΛ෼͚͍ͨ৔߹ͷΈαʔϏε͝ͱͷϦκϧόΛఆٛ
    • αʔϏε͝ͱʹεΩʔϚ͕͋ΔͷͰϑΟʔϧυͷࠩ෼΋໌Β͔

    View full-size slide

  45. ݄ؒ3ԯPV΁ͷඋ͑

    View full-size slide

  46. ݄ؒ3ԯPVͷڪා
    • ࣄલͷݟੵ΋Γ͸ϐʔΫ࣌Ͱຖඵ350ϦΫΤετ
    • طଘαʔϏεͷϦϓϨΠε
    • ϦϦʔεͨ͠௚ޙ͔ΒେྔͷΞΫηε͕΍ͬͯ͘Δ
    • ҆શ͔ͭద੾ʹඋ͑Δඞཁ͕͋Δ
    • Πϯϑϥඅ༻͸༗ݶ

    View full-size slide

  47. ࡞ઓ
    • N+1໰୊ͷରࡦͳͲجຊతͳ͜ͱ͸΍Δ
    • Ωϟογϡ͕೉͍͠ͷΛͲ͏͢Δ͔
    • ΤϯυϙΠϯτ͕ /graphql ʹू໿͞Εͯ͠·͏
    • ΞϓϦέʔγϣϯϨΠϠʔͰͷΩϟογϡ͸࣮૷ίετ͕ߴ͍
    • ຊ౰ʹΩϟογϡ͕ඞཁ͔ෛՙࢼݧΛߦͬͯ໌Β͔ʹ͢Δ
    • ਪଌ͢ΔͳɺܭଌͤΑ

    View full-size slide

  48. ෛՙࢼݧ - 1ճ໨ͷ݁Ռ
    • Ωϟογϡͱؔ܎ͳ͘ϨΠςϯγ͕ҟৗʹѱ͍
    • ͔͠΋ϨεϙϯεαΠζʹൺྫͯ͠ϨΠςϯγ͕ѱԽ͍ͯ͠Δ…
    • ϓϩϑΝΠϦϯάͯ͠ௐࠪ
    • ࣮ߦ࣌ͷܕνΣοΫϥΠϒϥϦ͕ɺ֤ϑΟʔϧυͷϦκϧόݺͼग़
    ͠͝ͱʹݺ͹Ε͍ͯͨͷ͕ݪҼ
    • production؀ڥͰܕνΣοΫΛແޮʹ͢ΔύονΛ౰ͯͯ࠶τϥΠ

    View full-size slide

  49. ෛՙࢼݧ - 2ճ໨ͷ݁Ռ
    • ര଎
    • ฏۉϨΠςϯγ͸100msۙ͘
    • ݱ࣮తͳΠϯϑϥͰຊ൪૝ఆΛେ্͖͘ճΔෛՙʹ଱͑ΒΕͨ
    • ݁࿦: Ωϟογϡͳ͠ͰϦϦʔεޙͷෛՙʹ଱͑ΒΕΔ
    • ϦϦʔεޙɺෛՙͷ໰୊ͰαʔϏεμ΢ϯ͢Δ͜ͱ͸ͳ͔ͬͨ
    • ܭଌʹΑͬͯඞཁे෼ͳରࡦΛߦ͑ͨ

    View full-size slide

  50. • ຐ๏ͷiΒΜͲͰ͸ GraphQL Λ࠾༻͠·ͨ͠ɹ
    • ϞμϯͳϢʔβʔମݧͷ࣮ݱʹߩݙ
    • ։ൃޮ཰ɾ։ൃϞνϕʔγϣϯ͕޲্
    • ΧΫϤϜͱͷϩδοΫڞ༗ͱ͍͏೉͍͠ཁٻʹϚον
    • ύϑΥʔϚϯε໘΋ཱ྆
    • ͸ͯͳͱGraphQL
    • ϋϚΔͱ͜ΖͰ࠾༻͞ΕΔ͜ͱ͕૿͖͑ͯͨ
    • ͜Ε͔Β΋ϓϥΫςΟεͷ஝ੵɾڞ༗ΛਐΊ͍͖ͯ·͢ʂ

    View full-size slide