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

みんなで育てる GraphQL スキーマ, それを支える Protobuf / GraphQL and Protobuf #tech_stand

みんなで育てる GraphQL スキーマ, それを支える Protobuf / GraphQL and Protobuf #tech_stand

Masayuki Izumi

March 03, 2022
Tweet

More Decks by Masayuki Izumi

Other Decks in Programming

Transcript

  1. ©2021 Wantedly, Inc.
    ΈΜͳͰҭͯΔ(SBQI2-εΩʔϚ ͦΕΛࢧ͑Δ1SPUPCVG
    GraphQL Gateway in Wantedly
    TECH STAND #7
    Mar 2, 2022 - Masayuki Izumi (@izumin5210)

    View full-size slide

  2. ©2021 Wantedly, Inc.
    ͜Ε·Ͱͷ͋Β͢͡
    8IZʹ͍ͭͯ࿩ͨ͠ผΠϕϯτͷ಺༰͓͞Β͍

    View full-size slide

  3. ©2021 Wantedly, Inc.

    View full-size slide

  4. ©2021 Wantedly, Inc.
    (SBQI2-#''΍ΊΔ
    ˞׬શҠߦ͸ͯ͠ͳ͍
    ‣ ͬ͘͟Γݴ͏ͱ

    #''͕8BOUFEMZͷશମͷΞʔΩςΫνϟʹ

    ͋·ΓϚονͯ͠ͳ͔ͬͨ
    ‣ ˞͜ͷl#''z͸ʮ͋ΔϑϩϯτΤϯυઐ༻ͷɺ
    ϑϩϯτΤϯυ͕ΦʔφʔγοϓΛ࣋ͭ"1*
    TFSWFSʯ͘Β͍ͷχϡΞϯε
    ͜Ε·Ͱͷ͋Β͢͡
    @izumin5210, GraphQL ಋೖͷ൓লͱ࠶௅ઓ, JSConf JP 2021
    @Altech, ٕज़Λతʹ౰ͯΔٕज़ʹ͍ͭͯ - GraphQL ΛೖΕ௚ͨ͠࿩, ٢঵ࣉ.pm28

    View full-size slide

  5. ©2021 Wantedly, Inc.
    (SBQI2-(BUFXBZ
    ͸͡Ί·ͨ͠
    ˞׬શҠߦ͸ͯ͠ͳ͍
    ‣ ͬ͘͟Γݴ͏ͱ
    1SPUPCVG͔Β(SBQI2-εΩʔϚΛੜ੒͢Δ
    શΞϓϦͰಉ͡(SBQI2-εΩʔϚɾαʔόΛ
    ࢖͏
    ‣ ࠓ೔͸(SBQI2-(BUFXBZͷઃܭɾ࣮૷ͳͲΛ
    ঺հ͠·͢
    ͜Ε·Ͱͷ͋Β͢͡
    @izumin5210, GraphQL ಋೖͷ൓লͱ࠶௅ઓ, JSConf JP 2021
    @Altech, ٕज़Λతʹ౰ͯΔٕज़ʹ͍ͭͯ - GraphQL ΛೖΕ௚ͨ͠࿩, ٢঵ࣉ.pm28

    View full-size slide

  6. ©2021 Wantedly, Inc.
    @izumin5210
    ‣ "SDITRVBE8BOUFEMZ *OD
    #BDLFOE 8FC'SPOUFOEͷ5FDI-FBEతͳ͜ͱ΋͍ͯ͠·͢
    ୅ද࡞
    HSBQJ(PͷH31$TFSWFS༻ϚΠΫϩϑϨʔϜϫʔΫ
    6*σβΠϯγεςϜͷ3FBDU࣮૷ͷઃܭ
    (SBQI2-(BUFXBZͷઃܭɾ࣮૷ ˡࠓ೔͸͜ͷ࿩ʣ
    ‣ ؾʹͳΔ(SBQI2-4QFD3'$͸$MJFOUDPOUSPMMFEOVMMBCJMJUZPQFSBUPS
    IUUQTHJUIVCDPNHSBQIRMHSBQIRMTQFDJTTVFT
    %JSFDUJWFೖΕΔ࿩͔ͱࢥͬͨΒɺ4ZOUBYͷ֦ுͩͬͨ

    View full-size slide

  7. ©2021 Wantedly, Inc.
    લఏͷ࿩
    8BOUFEMZͷΞʔΩςΫνϟͱओཁٕज़

    View full-size slide

  8. ©2021 Wantedly, Inc.
    8BOUFEMZͷΞʔΩςΫνϟɾओཁٕज़
    https://speakerdeck.com/wantedly/for-engineers?slide=22

    View full-size slide

  9. ©2021 Wantedly, Inc.
    8BOUFEMZͷΞʔΩςΫνϟɾओཁٕज़
    https://speakerdeck.com/wantedly/for-engineers?slide=22
    όοΫΤϯυͷαʔϏεؒ௨৴Ͱ͸H31$Λར༻
    1SPUPCVGΛத৺ʹͨ͠։ൃ

    View full-size slide

  10. ©2021 Wantedly, Inc.
    8BOUFEMZͷΞʔΩςΫνϟɾओཁٕज़
    https://speakerdeck.com/wantedly/for-engineers?slide=22
    όοΫΤϯυͷαʔϏεؒ௨৴Ͱ͸H31$Λར༻
    1SPUPCVGΛத৺ʹͨ͠։ൃ
    https://www.wantedly.com/companies/wantedly/post_articles/309513

    View full-size slide

  11. ©2021 Wantedly, Inc. @izumin5210, GraphQL ಋೖͷ൓লͱ࠶௅ઓ, JSConf JP 2021

    View full-size slide

  12. ©2021 Wantedly, Inc.
    (SBQI2-#''΍ΊΔ
    ˞׬શҠߦ͸ͯ͠ͳ͍
    ‣ ͬ͘͟Γݴ͏ͱ

    #''͕8BOUFEMZͷશମͷΞʔΩςΫνϟʹ

    ͋·ΓϚονͯ͠ͳ͔ͬͨ
    ‣ ˞͜ͷl#''z͸ʮ͋ΔϑϩϯτΤϯυઐ༻ͷɺ
    ϑϩϯτΤϯυ͕ΦʔφʔγοϓΛ࣋ͭ"1*
    TFSWFSʯ͘Β͍ͷχϡΞϯε
    <࠶ܝ>͜Ε·Ͱͷ͋Β͢͡
    @izumin5210, GraphQL ಋೖͷ൓লͱ࠶௅ઓ, JSConf JP 2021
    @Altech, ٕज़Λతʹ౰ͯΔٕज़ʹ͍ͭͯ - GraphQL ΛೖΕ௚ͨ͠࿩, ٢঵ࣉ.pm28

    View full-size slide

  13. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    8BOUFEMZͷόοΫΤϯυ
    ϚΠΫϩαʔϏεΞʔΩςΫνϟͰ͋Δ

    QSPUPʹυϝΠϯ஌͕ࣝϞσϦϯά͞Ε͍ͯΔ
    8BOUFEMZʹ͓͚Δ(SBQI2-ӡ༻্ͷ՝୊
    QSPUP্ͷ஌ࣝ(SBQI2-ʹಉظ͞Εͳ͍
    ϑϩϯτΤϯυΤϯδχΞ͕QSPUPΛࢀর͠ʹ͍͘ྗֶ͸ಇ͔ͳ͍
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ

    View full-size slide

  14. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    8BOUFEMZͷόοΫΤϯυ
    ϚΠΫϩαʔϏεΞʔΩςΫνϟͰ͋Δ

    QSPUPʹυϝΠϯ஌͕ࣝϞσϦϯά͞Ε͍ͯΔ
    8BOUFEMZʹ͓͚Δ(SBQI2-ӡ༻্ͷ՝୊
    QSPUP্ͷ஌ࣝ(SBQI2-ʹಉظ͞Εͳ͍
    ϑϩϯτΤϯυΤϯδχΞ͕QSPUPΛࢀর͠ʹ͍͘ྗֶ͸ಇ͔ͳ͍
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ
    ˠ1SPUPCVG͔Β0QFO"1* 4XBHHFS
    ͷεΩʔϚΛు͚ΔͷͰɺ
    (SBQI2-Ͱ͋Δඞཁ͕ͳ͍ʜ

    View full-size slide

  15. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    8BOUFEMZͷόοΫΤϯυ
    ϚΠΫϩαʔϏεΞʔΩςΫνϟͰ͋Δ

    QSPUPʹυϝΠϯ஌͕ࣝϞσϦϯά͞Ε͍ͯΔ
    8BOUFEMZʹ͓͚Δ(SBQI2-ӡ༻্ͷ՝୊
    QSPUP্ͷ஌ࣝ(SBQI2-ʹಉظ͞Εͳ͍
    ϑϩϯτΤϯυΤϯδχΞ͕QSPUPΛࢀর͠ʹ͍͘ྗֶ͸ಇ͔ͳ͍
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ
    ˠ1SPUPCVG͔Β0QFO"1* 4XBHHFS
    ͷεΩʔϚΛు͚ΔͷͰɺ
    (SBQI2-Ͱ͋Δඞཁ͕ͳ͍ʜ
    )PXOPUUPMFBSO(SBQI2-5IF(VJME#MPH
    IUUQTXXXUIFHVJMEEFWCMPHIPXOPUUPMFBSOHSBQIRM

    View full-size slide

  16. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    8BOUFEMZͷόοΫΤϯυ
    ϚΠΫϩαʔϏεΞʔΩςΫνϟͰ͋Δ

    QSPUPʹυϝΠϯ஌͕ࣝϞσϦϯά͞Ε͍ͯΔ
    8BOUFEMZʹ͓͚Δ(SBQI2-ӡ༻্ͷ՝୊
    QSPUP্ͷ஌ࣝ(SBQI2-ʹಉظ͞Εͳ͍
    ϑϩϯτΤϯυΤϯδχΞ͕QSPUPΛࢀর͠ʹ͍͘ྗֶ͸ಇ͔ͳ͍
    (SBQI2-ͷϝϦοτ
    ʢ࠶ར༻Մೳͳ ʣΦϒδΣΫτάϥϑͷߏங બ୒తσʔλऔಘ
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    ෳ਺ϚΠΫϩαʔϏε͔ΒσʔλΛू໿͢Δ(SBQI2-αʔόΛ࡞Γɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ

    View full-size slide

  17. ©2021 Wantedly, Inc.
    1SPUPCVGͱ(SBQI2-ͷڞଘ
    8BOUFEMZͷ(SBQI2-(BUFXBZͰ͸Ͳ͏ͯ͠Δ͔

    View full-size slide

  18. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    ෳ਺ϚΠΫϩαʔϏε͔ΒσʔλΛू໿͢Δ(SBQI2-αʔόΛ࡞Γɺʜ
    ࡞Βͳ͍ͱ͍͚ͳ͍ߟ͑ͳ͍ͱ͍͚ͳ͍΋ͷ
    1SPUP͔Β(SBQI2-ͷܕΛͲ͏΍ͬͯੜ੒͢Δ͔
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔

    View full-size slide

  19. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    ࡞Βͳ͍ͱ͍͚ͳ͍ߟ͑ͳ͍ͱ͍͚ͳ͍΋ͷ
    1SPUP͔Β(SBQI2-ͷܕΛͲ͏΍ͬͯੜ੒͢Δ͔
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔

    View full-size slide

  20. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2- ܕͷੜ੒
    GraphQL
    Protobuf
    // ブログ投稿を表すオブジェクト。


    message Post {


    // Required.


    uint64 id = 1;


    // Required. 投稿のタイトル。


    string title = 2;


    // Required. 記事の状態。


    State state = 3;


    enum State {


    STATE_UNSPECIFIED = 0;


    // 下書き


    STATE_DRAFT = 1;


    // 公開済み


    STATE_PUBLISHED = 2;


    }


    }
    Generate
    # ブログ投稿を表すオブジェクト。


    type Post {


    # Required.


    id: String!


    # Required. 投稿のタイトル。


    title: String!


    # Required. 記事の状態。


    state: State!


    }


    enum PostState {


    # 下書き


    DRAFT


    # 公開済み


    PUBLISHED


    }

    View full-size slide

  21. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2- ܕͷੜ੒
    GraphQL
    Protobuf
    // ブログ投稿を表すオブジェクト。


    message Post {


    // Required.


    uint64 id = 1;


    // Required. 投稿のタイトル。


    string title = 2;


    // Required. 記事の状態。


    State state = 3;


    enum State {


    STATE_UNSPECIFIED = 0;


    // 下書き


    STATE_DRAFT = 1;


    // 公開済み


    STATE_PUBLISHED = 2;


    }


    }
    Generate
    # ブログ投稿を表すオブジェクト。


    type Post {


    # Required.


    id: String!


    # Required. 投稿のタイトル。


    title: String!


    # Required. 記事の状態。


    state: State!


    }


    enum PostState {


    # 下書き


    DRAFT


    # 公開済み


    PUBLISHED


    }
    ίϝϯτΛ൓өͯ͠Δͷ΋ॏཁͳϙΠϯτ

    View full-size slide

  22. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2-/FYVT
    GraphQL Nexus
    const Post = objectType({


    name: "Post",


    definition(t) {


    t.field("title", {


    type: nonNull("String"),


    description: "...",


    resolver(root) {


    // .proto から生成した message


    return root.getTitle();


    }


    });


    // ...


    }


    });
    Generate
    ܕͷੜ੒ίʔυͷੜ੒
    Protobuf
    // ブログ投稿を表すオブジェクト。


    message Post {


    // Required.


    uint64 id = 1;


    // Required. 投稿のタイトル。


    string title = 2;


    // Required. 記事の状態。


    State state = 3;


    enum State {


    STATE_UNSPECIFIED = 0;


    // 下書き


    STATE_DRAFT = 1;


    // 公開済み


    STATE_PUBLISHED = 2;


    }


    }

    View full-size slide

  23. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2-/FYVT
    GraphQL Nexus
    const Post = objectType({


    name: "Post",


    definition(t) {


    t.field("title", {


    type: nonNull("String"),


    description: "...",


    resolver(root) {


    // .proto から生成した message


    return root.getTitle();


    }


    });


    // ...


    }


    });
    Generate
    ܕͷੜ੒ίʔυͷੜ੒
    Protobuf
    // ブログ投稿を表すオブジェクト。


    message Post {


    // Required.


    uint64 id = 1;


    // Required. 投稿のタイトル。


    string title = 2;


    // Required. 記事の状態。


    State state = 3;


    enum State {


    STATE_UNSPECIFIED = 0;


    // 下書き


    STATE_DRAFT = 1;


    // 公開済み


    STATE_PUBLISHED = 2;


    }


    }
    8BOUFEMZͰ͸
    (SBQI2-/FYVT 5ZQF4DSJQU
    Λར༻

    View full-size slide

  24. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2-/FYVT
    GraphQL Nexus
    const Post = objectType({


    name: "Post",


    definition(t) {


    t.field("title", {


    type: nonNull("String"),


    description: "...",


    resolver(root) {


    // .proto から生成した message


    return root.getTitle();


    }


    });


    // ...


    }


    });
    Generate
    ܕͷੜ੒ίʔυͷੜ੒
    Protobuf
    // ブログ投稿を表すオブジェクト。


    message Post {


    // Required.


    uint64 id = 1;


    // Required. 投稿のタイトル。


    string title = 2;


    // Required. 記事の状態。


    State state = 3;


    enum State {


    STATE_UNSPECIFIED = 0;


    // 下書き


    STATE_DRAFT = 1;


    // 公開済み


    STATE_PUBLISHED = 2;


    }


    }
    8BOUFEMZͰ͸
    (SBQI2-/FYVT 5ZQF4DSJQU
    Λར༻
    1SPUPUP(SBQI2-ͷม׵ίʔυ΋ੜ੒

    View full-size slide

  25. ©2021 Wantedly, Inc.
    Generate
    GraphiQL
    VSCode
    Android Studio
    .proto

    View full-size slide

  26. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2-/FYVT (SBQIJ2-্Ͱͷݟ͑ํ
    QSPUPʹ.BSLEPXOͰυΩϡϝϯτΛॻ͚͹ɺ
    (SBQIJ2-ͷ%PDVNFOUBUJPO&YQMPSFSͰ͍͍ײ͡ʹ֬ೝͰ͖Δ

    View full-size slide

  27. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2- (SBQI2-/FYVT
    ࢓༷ͱ࣮૷͸ͦΕͧΕ044ʹ͍ͯ͠·͢
    IUUQTHJUIVCDPNQSPUPHSBQIRMQSPUPHSBQIRM
    IUUQTHJUIVCDPNQSPUPHSBQIRMQSPUPOFYVT
    ʢHRMHFO༻ͷ࣮૷΋్த·Ͱ΍ͬͨ΍͕ͭQVCMJDSFQPʹ͋Γ·͢😇ʣ

    View full-size slide

  28. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    ࡞Βͳ͍ͱ͍͚ͳ͍ߟ͑ͳ͍ͱ͍͚ͳ͍΋ͷ
    1SPUP͔Β(SBQI2-ͷܕΛͲ͏΍ͬͯੜ੒͢Δ͔
    ˠม׵ͷϧʔϧͱɺͦͷ࣮૷Ͱ͋Δίʔυੜ੒πʔϧΛࣗ࡞
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔
    ˠ

    View full-size slide

  29. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    ࡞Βͳ͍ͱ͍͚ͳ͍ߟ͑ͳ͍ͱ͍͚ͳ͍΋ͷ
    1SPUP͔Β(SBQI2-ͷܕΛͲ͏΍ͬͯੜ੒͢Δ͔
    ˠม׵ͷϧʔϧͱɺͦͷ࣮૷Ͱ͋Δίʔυੜ੒πʔϧΛࣗ࡞
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔
    ˠ

    View full-size slide

  30. ©2021 Wantedly, Inc.
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏங
    Ͳ͏͍͏ΞʔΩςΫνϟͰ࣮ݱ͢Δʁ
    1SPEVDUJPO3FBEZ(SBQI2-ͱ͍͏ຊͰ͸ɺ(SBQI2-(BUFXBZͷ࣮૷ύλʔϯͱͯ͠ҎԼͷͭΛ঺հ͍ͯ͠Δ
    ʢεϖʔεͷؔ܎Ͱઆ໌͕ࡶͳͷͰɺਖ਼֬ͳ৘ใ͸ຊಡΉ͔άά͍ͬͯͩ͘͞🙏ʣ
    ‣ 5IFl4JNQMFzXBZ୯७ͳϓϩΩγͱͯ͠ৼΔ෣͏ɻεΩʔϚ͸ޙΖͷ31$ͷܗʹͳΔʢάϥϑʹͳΒͳ͍ʣ
    ‣ 4DIFNB4UJUDIJOHෳ਺ͷ(SBQI2-εΩʔϚΛ߹੒ɻؔ࿈͸FYUFOEͰఆٛ SFTPMWFS͸(BUFXBZʹ࣮૷ɻ
    ‣ "QPMMP4DIFNB'FEFSBUJPOσΟϨΫςΟϒΛ͏·͘࢖ͬͯɺεΩʔϚΛ·͍ͨͩؔ࿈Λهड़Ͱ͖ͨΓ͢Δɻ
    ‣ 4JOHMF4DIFNB(BUFXBZ
    ʢ্͕ͭ4DIFNB͝ͱ%FDFOUSBMJ[F͢Δͷʹରͯ͠ʣ$FOUSBMJ[Fͳ··ѻ͏
    ϏδωεϩδοΫ͸όοΫΤϯυͷαʔϏε܈Ͱ࣋ͪɺ(BUFXBZʹ͸άϧʔίʔυͷΈهड़͢Δ
    1SPUPCVG(SBQI2-
    Production Ready GraphQL ͸ GraphQL ʹؔ͢Δ࠷΋ྑ͍ࢿྉͷҰͭͳͷͰɺͥͻಡΈ·͠ΐ͏


    https://book.productionreadygraphql.com/

    View full-size slide

  31. ©2021 Wantedly, Inc.
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏங
    Ͳ͏͍͏ΞʔΩςΫνϟͰ࣮ݱ͢Δʁ
    1SPEVDUJPO3FBEZ(SBQI2-ͱ͍͏ຊͰ͸ɺ(SBQI2-(BUFXBZͷ࣮૷ύλʔϯͱͯ͠ҎԼͷͭΛ঺հ͍ͯ͠Δ
    ʢεϖʔεͷؔ܎Ͱઆ໌͕ࡶͳͷͰɺਖ਼֬ͳ৘ใ͸ຊಡΉ͔άά͍ͬͯͩ͘͞🙏ʣ
    ‣ 5IFl4JNQMFzXBZ୯७ͳϓϩΩγͱͯ͠ৼΔ෣͏ɻεΩʔϚ͸ޙΖͷ31$ͷܗʹͳΔʢάϥϑʹͳΒͳ͍ʣ
    ‣ 4DIFNB4UJUDIJOHෳ਺ͷ(SBQI2-εΩʔϚΛ߹੒ɻؔ࿈͸FYUFOEͰఆٛ SFTPMWFS͸(BUFXBZʹ࣮૷ɻ
    ‣ "QPMMP4DIFNB'FEFSBUJPOσΟϨΫςΟϒΛ͏·͘࢖ͬͯɺεΩʔϚΛ·͍ͨͩؔ࿈Λهड़Ͱ͖ͨΓ͢Δɻ
    ‣ 4JOHMF4DIFNB(BUFXBZ
    ʢ্͕ͭ4DIFNB͝ͱ%FDFOUSBMJ[F͢Δͷʹରͯ͠ʣ$FOUSBMJ[Fͳ··ѻ͏
    ϏδωεϩδοΫ͸όοΫΤϯυͷαʔϏε܈Ͱ࣋ͪɺ(BUFXBZʹ͸άϧʔίʔυͷΈهड़͢Δ
    1SPUPCVG(SBQI2-
    Production Ready GraphQL ͸ GraphQL ʹؔ͢Δ࠷΋ྑ͍ࢿྉͷҰͭͳͷͰɺͥͻಡΈ·͠ΐ͏


    https://book.productionreadygraphql.com/
    On GraphQL Schema Stitching & API Gateways | by Marc-André Giroux | Medium


    https://xuorig.medium.com/on-graphql-schema-stitching-api-gateways-5dcb579fa90f


    ͜ͷهࣄ͸ Wantedly ࣾ಺Ͱͷ Production Ready GraphQL ྠಡձͰڞ༗͞Ε·ͨ͠
    4JOHMF4DIFNB(BUFXBZͷΠϝʔδਤ
    1SPEVDUJPO3FBEZ(SBQI2-ஶऀͷϒϩά͔ΒҾ༻
    4JOHMF4DIFNB(BUFXBZͱ͍͏୯ޠ͸ग़ͯͳ͍͕ɺ
    ಉ͡΋ͷΛࢦ͍ͯͦ͠͏
    8BOUFEMZͰ͸4JOHMF4DIFNB(BUFXBZΛ࠾༻
    ௕ظతʹͲ͏ͳΔ͔͸Θ͔Βͳ͍͕ɺ
    4UJUDIJOH΍'FEFSBUJPOͰதԝूݖԽΛճආͰ͖ΔϝϦοτΑΓɺ
    ॳखͰ͸ߏ੒͕ෳࡶʹͳΔσϝϦοτͷ΄͏͕େ͖͍ͱ൑அͨ͠ɻ
    ʢ·ͣ1SPUPˠ(SBQI2-ͷ໰୊ղܾʹूத͍ͨ͠ͷͰɺ
    ଞͷ໰୊Λ૿΍͢ͷΛආ͚͍ͨͱ͍͏ͷ΋͋Δʣ

    View full-size slide

  32. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2- ؔ࿈ͷఆٛʢάϥϑͷߏஙʣ
    GraphQL
    Protobuf
    Generate
    message Post {


    // ...


    // Required. 投稿したユーザの ID。


    uint64 author_id = 11;


    }
    type Post {


    # ...


    # Required. 投稿したユーザの ID。


    authorId: String!


    }
    Protobuf
    message User {


    // ...


    }
    GraphQL
    type User {


    # ...


    }
    Generate

    View full-size slide

  33. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2- ؔ࿈ͷఆٛʢάϥϑͷߏஙʣ
    GraphQL
    Protobuf
    Generate
    message Post {


    // ...


    // Required. 投稿したユーザの ID。


    uint64 author_id = 11;


    }
    type Post {


    # ...


    # Required. 投稿したユーザの ID。


    authorId: String!


    }
    Protobuf
    message User {


    // ...


    }
    GraphQL
    type User {


    # ...


    }
    Generate
    GraphQL
    extend type Post {


    # 投稿したユーザ


    author: User


    }
    ΦϒδΣΫτͷؔ࿈͸
    (SBQI2-(BUFXBZଆͰఆٛ

    View full-size slide

  34. ©2021 Wantedly, Inc.
    1SPUPCVG(SBQI2-/FYVT
    GraphQL Nexus
    /FYVTͰ͸FYUFOE5ZQFͰܕͷ֦ு͕Մೳ
    ͜͜Ͱؔ࿈Λද͢ϑΟʔϧυΛఆٛ͠ɺ
    SFTPMWFSʹσʔλऔಘΛ࣮૷͢Δ
    ؔ࿈ͷఆٛʢάϥϑͷߏஙʣ
    const addAuthorToPost = extendType({


    type: "Post",


    definition(t) {


    t.field("author", {


    type: nullable("User"),


    resolver(root, _args, ctx, _info) {


    // root.getAuthorId() から Author 取得


    // ctx から gRPC クライアントを取り出して RPC 叩く


    // DataLoader を使うことも多い


    }


    });


    }


    });

    View full-size slide

  35. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    ࡞Βͳ͍ͱ͍͚ͳ͍ߟ͑ͳ͍ͱ͍͚ͳ͍΋ͷ
    1SPUP͔Β(SBQI2-ͷܕΛͲ͏΍ͬͯੜ੒͢Δ͔
    ˠม׵ͷϧʔϧͱɺͦͷ࣮૷Ͱ͋Δίʔυੜ੒πʔϧΛࣗ࡞
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔
    ˠ(BUFXBZͷίʔυ্Ͱ4DIFNBΛFYUFOE͠ σʔλऔಘΛ࣮૷

    ʢ4JOHMF4DIFNB(BUFXBZ1BUUFSOʣ

    View full-size slide

  36. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    ࡞Βͳ͍ͱ͍͚ͳ͍ߟ͑ͳ͍ͱ͍͚ͳ͍΋ͷ
    1SPUP͔Β(SBQI2-ͷܕΛͲ͏΍ͬͯੜ੒͢Δ͔
    ˠม׵ͷϧʔϧͱɺͦͷ࣮૷Ͱ͋Δίʔυੜ੒πʔϧΛࣗ࡞
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔
    ˠ(BUFXBZͷίʔυ্Ͱ4DIFNBΛFYUFOE͠ σʔλऔಘΛ࣮૷

    ʢ4JOHMF4DIFNB(BUFXBZ1BUUFSOʣ
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    ෳ਺ϚΠΫϩαʔϏε͔ΒσʔλΛू໿͢Δ(SBQI2-αʔόΛ࡞Γɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ

    View full-size slide

  37. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    ࡞Βͳ͍ͱ͍͚ͳ͍ߟ͑ͳ͍ͱ͍͚ͳ͍΋ͷ
    1SPUP͔Β(SBQI2-ͷܕΛͲ͏΍ͬͯੜ੒͢Δ͔
    ˠม׵ͷϧʔϧͱɺͦͷ࣮૷Ͱ͋Δίʔυੜ੒πʔϧΛࣗ࡞
    1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔
    ˠ(BUFXBZͷίʔυ্Ͱ4DIFNBΛFYUFOE͠ σʔλऔಘΛ࣮૷

    ʢ4JOHMF4DIFNB(BUFXBZ1BUUFSOʣ
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    ෳ਺ϚΠΫϩαʔϏε͔ΒσʔλΛू໿͢Δ(SBQI2-αʔόΛ࡞Γɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ


    View full-size slide

  38. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    ෳ਺ϚΠΫϩαʔϏε͔ΒσʔλΛू໿͢Δ(SBQI2-αʔόΛ࡞Γɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ
    8BOUFEMZʹ͓͚Δ(SBQI2-ӡ༻্ͷ՝୊
    QSPUP্ͷ஌ࣝ(SBQI2-ʹಉظ͞Εͳ͍
    ϑϩϯτΤϯυΤϯδχΞ͕QSPUPΛࢀর͠ʹ͍͘ྗֶ͸ಇ͔ͳ͍

    View full-size slide

  39. ϖʔδλΠτϧ ϖʔδαϒλΠτϧ
    ©2021 Wantedly, Inc.
    QSPUP͔Β(SBQI2-ͷܕΛੜ੒͠ɺ
    ෳ਺ϚΠΫϩαʔϏε͔ΒσʔλΛू໿͢Δ(SBQI2-αʔόΛ࡞Γɺ
    8FCϑϩϯτɺϞόΠϧ͔Βར༻Ͱ͖Ε͹ɺ
    1SPUPCVGΛࡴͣ͞(SBQI2-΋׆͖ΔͷͰ͸ʁ
    8BOUFEMZʹ͓͚Δ(SBQI2-ӡ༻্ͷ՝୊
    QSPUP্ͷ஌ࣝ(SBQI2-ʹಉظ͞Εͳ͍
    ˠಉظ͞ΕΔΑ͏ʹͳͬͨ✅
    ϑϩϯτΤϯυΤϯδχΞ͕QSPUPΛࢀর͠ʹ͍͘ྗֶ͸ಇ͔ͳ͍
    ˠʢ8FCϑϩϯτɺϞόΠϧ͕(SBQI2-Λར༻͢Ε͹ʣಁաతʹࢀর͞ΕΔ͜ͱʹͳΔ✅

    View full-size slide

  40. ©2021 Wantedly, Inc.
    ΈΜͳͰҭͯΔ(SBQI2-εΩʔϚ ͦΕΛࢧ͑Δ1SPUPCVG

    View full-size slide

  41. ©2021 Wantedly, Inc.
    ΈΜͳͰҭͯΔ(SBQI2-εΩʔϚ ͦΕΛࢧ͑Δ1SPUPCVG
    όοΫΤϯυɾ8FCϑϩϯτɾϞόΠϧͷ։ൃऀ͕

    ΈΜͳಉҰͷ(SBQI2-εΩʔϚΛݟͯ։ൃ͢ΔΑ͏ʹͳΔ
    ˠΈΜͳ͕εΩʔϚɾυΩϡϝϯτͷվળʹؔΘΔϞνϕ͕Ͱ͖Δʂ
    (SBQI2-εΩʔϚ͸େ෦෼͸1SPUPCVG*%-͔Βੜ੒͞ΕΔ
    1SPUPCVG͸௨ৗͷϓϩάϥϛϯάݴޠͷߏ଄ମఆٛʹ͍ۙϝϯλϧϞσϧͰ
    ಡΈॻ͖͕Ͱ͖Δ
    ˠεΩʔϚ͕એݴతʹ؅ཧͰ͖ɺͦͷߋ৽ʹಛผͳ஌ࣝ΋ཁٻ͞Εͳ͍ʂ

    View full-size slide

  42. ©2021 Wantedly, Inc.
    ·ͱΊ ΈΜͳͰҭͯΔ(SBQI2-εΩʔϚ ͦΕΛࢧ͑Δ1SPUPCVG
    ‣ όοΫΤϯυͰར༻͍ͯͨ͠ࢿ࢈ʢ1SPUPCVGʣΛ׆͔ͭͭ͠ɺ(SBQI2-ͷϝϦοτ΋ڗड͍ͨ͠
    (SBQI2-ͷϝϦοτಛʹ࠶ར༻ՄೳͳΦϒδΣΫτάϥϑͷߏங ͦͷଞ͍Ζ͍Ζ
    ͦͷͨΊʹɺͭͷ໰୊ʹऔΓ૊Μͩ
    ‣ QSPUP͔Β(SBQI2-ͷܕΛੜ੒͍ͨ͠
    ੜ੒͢Δ࢓༷Λఆٛ͠ɺ(SBQI2-/FYVTͷίʔυΛੜ੒͢Δ࣮૷Λ࡞ͬͨ
    ‣ 1SPUP͔Βͷσʔλू໿ɾάϥϑߏஙΛͲ͏ఆٛɾهड़͢Δ͔
    4JOHMF4DIFNB(BUFXBZΞʔΩςΫνϟΛ࠾༻ͨ͠
    (SBQI2-ͷAFYFOEAͷ࢓૊ΈΛར༻͠ɺ1SPUP͔Βੜ੒ͨ͠(SBQI2-0CKFDUͷάϥϑΛఆٛ͢Δ
    ‣ 1SPUPCVG͔Β࠶ར༻ՄೳͳΦϒδΣΫτάϥϑͱͯ͠ͷ(SBQI2-TDIFNB͕Ͱ͖ͨ
    8FCϑϩϯτɾϞόΠϧΤϯδχΞͱڞ௨ݴޠͱͯ͠ར༻͢Δ͜ͱͰɺΈΜͳͰεΩʔϚΛҭͯΒΕΔ؀ڥͱͳ͍ͬͯ͘

    View full-size slide