Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

ຐ๏ͷiΒΜͲ

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

GraphQLͱ͸

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

ͳͥGraphQLΛ࠾༻͔ͨ͠

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

ΧΫϤϜ

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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 Λฦ͢෦෼ͷංେԽɾΧΦ εԽ͕༧૝͞Εͨ

Slide 35

Slide 35 text

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 Λฦ͢෦෼ͷංେԽɾΧΦ εԽ͕༧૝͞Εͨ ڞ௨ͷϑΟʔϧυ͕ͩΧΫϤϜͰ ͸ಛघͳՃ޻͕ඞཁ

Slide 36

Slide 36 text

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 Λฦ͢෦෼ͷංେԽɾΧΦ εԽ͕༧૝͞Εͨ ڞ௨ͷϑΟʔϧυ͕ͩΧΫϤϜͰ ͸ಛघͳՃ޻͕ඞཁ ΧΫϤϜͷΈଘࡏ͢ΔϑΟʔϧυ

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

GraphQLͷԸܙ

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

݄ؒ3ԯPV΁ͷඋ͑

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

·ͱΊ

Slide 53

Slide 53 text

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