Web API に秩序を与える Protocol Buffers / Protocol Buffers for Web API #builderscon

2b4f9f20b554d4c77c46fe6a9930d6fe?s=47 Nao Minami
August 30, 2019

Web API に秩序を与える Protocol Buffers / Protocol Buffers for Web API #builderscon

builderscon tokyo 2019 で「Web API に秩序を与える Protocol Buffers」というタイトルで発表した資料です。

Protocol Buffers を利用して Web API の Schema 管理をするという観点で、豊富な実例とともにその手法やメリット・デメリットについて話しました。

cf. https://builderscon.io

追記: 61ページ目で Protocol Buffers を利用する際の注意点として後方互換性が壊れるケースの話をしましたが、自分たちが経験したのは gRPC + grpc-gateway 構成特有のケースだったので記述を修正しました。

2b4f9f20b554d4c77c46fe6a9930d6fe?s=128

Nao Minami

August 30, 2019
Tweet

Transcript

  1. ©2019 Wantedly, Inc. 8FC"1*ʹடংΛ༩͑Δ 1SPUPDPM#VGGFST 30.Aug.2019 - Nao Minami (@south37)

    Wantedly, Inc. builderscon tokyo 2019
  2. ©2019 Wantedly, Inc. /BP.JOBNJ *OGSBTUSVDUVSF&OHJOFFS 8BOUFEMZ (JU)VCTPVUI 5XJUUFSTPVUI  43&ͱͯ͠ͷ໾ׂ

     ։ൃج൫ͱͯ͠ͷ໾ׂ 1SPUPDPM#V⒎FSTΛར༻ͨ͠ ϚΠΫϩαʔϏε։ൃʹऔΓ૊Ή
  3. ©2019 Wantedly, Inc. ͸͡Ίʹ

  4. ©2019 Wantedly, Inc. ಥવͰ͕͢ 8FC"1*ͷ4DIFNB؅ཧΛ ͍ͯ͠·͔͢ʁ

  5. ©2019 Wantedly, Inc. 4DIFNBͱ͸ "1*ͷৼΔ෣͍Λهड़ͨ͠΋ͷ w QBUI΍ϝιουɺSFRVFTUSFTQPOTFͷ಺༰ͳͲΛએݴతʹهड़ w ͍͔ͭ͘ͷํ๏͕஌ΒΕ͍ͯΔ w

    FH0QFO"1* +40/"1* 1SPUPDPM#V⒎FST FUD
  6. ©2019 Wantedly, Inc. Ͳ͏͍ͬͨ࣌ʹ 4DIFNB؅ཧΛͨ͘͠ͳΔͷ͔ʁ

  7. ©2019 Wantedly, Inc. 4DIFNB%SJWFO%FWFMPQNFOU 4DIFNBΛ࠷ॳʹఆٛͯ͠։ൃ w 8FC"1*ͷ4DIFNBΛఆ͔ٛͯ͠Βɺ4DIFNBΛຬͨ͢TFSWFSɺ ར༻͢ΔDMJFOUΛಉ࣌ʹ։ൃ w 4DIFNB͕ʮ৴པͰ͖ΔυΩϡϝϯτʯͱͳΓίϛϡχέʔγϣϯ

    ͷ伴ͱͳΔ ߴ͍ੜ࢈ੑͰ։ൃՄೳ 4DIFNB 4FSWFS։ൃ $MJFOU։ൃ
  8. ©2019 Wantedly, Inc. .JDSPTFSWJDFT"SDIJUFDUVSF .JDSPTFSWJDFͷৼΔ෣͍Λ؅ཧ͍ͨ͠ w .JDSPTFSWJDFT"SDIJUFDUVSFͰ͸ଟ਺ͷ.JDSPTFSWJDF "1* ͕ଘࡏ w

    ૄ݁߹ੑΛߴΊɺ࠶ར༻͠΍͘͢͢ΔͨΊʹ΋4DIFNBͷએݴతهड़ ͕ॏཁ 3BJMT (P 5ZQF4DSJQU
  9. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻ͯ͠ 4DIFNB؅ཧΛ͢Δํ๏ʹ͍ͭͯ ࿩͠·͢

  10. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTͱ͸ʁ

  11. ©2019 Wantedly, Inc.

  12. ©2019 Wantedly, Inc. (PPHMF੡ͷ4FSJBMJ[BUJPO-JCSBSZ  *OUFSGBDF%FpOJUJPO-BOHVBHF *%-  w *%-Ͱ"1*4DIFNBΛهड़͠ɺTFSJBMJ[BUJPOEFTFSJBMJ[BUJPOίʔυ

    Λࣗಈੜ੒ w *%-Ͱهड़ͨ͠಺༰ʢQSPUPpMFʣ͸ɺ"1*ʹର͢Δ੩తܕ෇͚ͱͳΔ w 1SPUPDPM#V⒎FSTίϯύΠϥʢQSPUPDʣ͸QMVHJOͰ༷ʑͳػೳ֦ு ͕Մೳ w TXBHHFSKTPOͷੜ੒ H31$ར༻ FUD w ༷ʑͳݴޠͰར༻Մೳ w $$ (P +BWB 1ZUIPO 3VCZ /PEF FUD 1SPUPDPM#VGGFSTͱ͸ʁ
  13. ©2019 Wantedly, Inc. ྫͱͯ͠A(&5CPPLTJEAͱ͍͏ "1*ͷ4DIFNBΛ QSPUPpMFʹهड़ͯ͠ΈΔ

  14. ©2019 Wantedly, Inc. service BookService { rpc getBook (getBookRequest) returns

    (Book) { option (google.api.http) = { get: "/api/books/{id}" }; } } message getBookRequest { int64 id = 1; } message Book { int64 id = 1; string title = 2; } #PPL"1*ͷ4DIFNBΛQSPUPGJMFʹهड़
  15. ©2019 Wantedly, Inc. QSPUPDͰίʔυࣗಈੜ੒ w ͦΕͧΕͷNFTTBHFΛTFSJBMJ[FEFTFSJBMJ[F͢ΔSVOUJNFMJCSBSZ ͷίʔυΛࣗಈੜ੒ ྫQSPUPGJMF͔Βίʔυࣗಈੜ੒ Google::Protobuf::DescriptorPool.xxx do

    add_message "books.GetBookRequest" do optional :id, :int64, 1 end add_message "books.Book" do optional :id, :int64, 1 optional :title, :string, 2 end end module Books GetBookRequest = XXX(“books.GetBookRequest”).msgclass Book = XXX(“books.Book").msgclass end message getBookRequest { int64 id = 1; } message Book { int64 id = 1; string title = 2; } QSPUPpMF 3VCZ
  16. ©2019 Wantedly, Inc. [1] book = Book.new(id: 2, title: "Hello,

    Book") => <Book: id: 2, title: "Hello, Book"> [2] book.to_proto => "\b\x02\x12\vHello, Book” [3] book.to_json => "{\"id\":2,\"title\":\"Hello, Book\”}" [4] Book.decode("\b\x02\x12\vHello, Book") => <Book: id: 2, title: "Hello, Book"> 3VCZ message Book { int64 id = 1; string title = 2; } QSPUPpMF
  17. ©2019 Wantedly, Inc. ࣗಈੜ੒ίʔυͰCJOBSZ΍+40/ͷ 4FSJBMJ[F%FTFSJBMJ[FΛ࣮ݱ

  18. ©2019 Wantedly, Inc. service BookService { rpc getBook (getBookRequest) returns

    (Book) { option (google.api.http) = { get: "/api/books/{id}" }; } } TXBHHFSQMVHJOͰ+40/Λࣗಈੜ੒ w HSQDHBUFXBZQSPUPDHFOTXBHHFSQMVHJOΛར༻ w ҎԼͷQSPUPpMFͷ಺༰Λ൓өͨ͠TXBHHFSKTPOΛੜ੒ ྫQSPUPGJMF͔ΒTXBHHFSKTPOΛࣗಈੜ੒
  19. ©2019 Wantedly, Inc. { "swagger": “2.0", …, "paths": { "/api/books/{id}":

    { "get": { "operationId": "GetBook", "responses": { "200": { "description": … "schema": { "$ref": "#/definitions/booksBook" } } }, “parameters": [ { "name": "id", "in": "path", "required": true, "type": "string", "format": "int64" } ], "tags": … } } }, "definitions": { "booksBook": { "type": "object", "properties": { "id": { "type": "string", "format": "int64" }, "title": { "type": "string" } } } } }
  20. ©2019 Wantedly, Inc. ͦͷ΄͔ʹ΋ɺQSPUPpMFΛ TJOHMFTPVSDFPGUSVUIͱͯ͠ ༷ʑͳίʔυࣗಈੜ੒͕Մೳ

  21. ©2019 Wantedly, Inc. ͳͥ1SPUPDPM#VGGFSTΛ ར༻͢Δͷ͔ʁ

  22. ©2019 Wantedly, Inc. ͳͥ1SPUPDPM#VGGFSTΛར༻͢Δͷ͔ʁ  ࣗಈੜ੒ίʔυར༻ʹΑΔ"1* 4DIFNBͷอূ  4FSJBMJ[FS%FTFSJBMJ[FSͷػೳ 

    QSPUPDͷ๛෋ͳQMVHJO
  23. ©2019 Wantedly, Inc. ͳͥ1SPUPDPM#VGGFSTΛར༻͢Δͷ͔ʁ  ࣗಈੜ੒ίʔυར༻ʹΑΔ"1* 4DIFNBͷอূ w QSPUPpMFΛਖ਼֬ʹ൓өͨ͠4FSJBMJ[FS%FTFSJBMJ[FSΛར༻͢ΔͷͰ ʮ࣮૷ͱ4DIFNBͷڍಈ͕ͣΕΔʯͱ͍͏ࣄ͕ݪཧతʹൃੜ͠ͳ͍

    w 4XBHHFSͷ༷ʹUFTU΍WBMJEBUJPOͰ୲อ͢ΔͷͰ͸ͳ͘ɺͨͩ QSPUPD͕ੜ੒͢ΔίʔυΛར༻͢Ε͹ྑ͍ ʮੜ͖ͯΔυΩϡϝϯτʯΛ؆୯͔࣮ͭ֬ʹ࡞Δ͜ͱ͕Ͱ͖Δ
  24. ©2019 Wantedly, Inc. 4FSJBMJ[FS%FTFSJBJM[FSͷػೳ w pFMEͷ௥Ճ΍ϦωʔϜ͸ޙํޓ׵ੑΛյ͞ͳ͍ w ݹ͍QSPUPpMF͔Βੜ੒ͨ͠%FTFSJBMJ[FSͰ΋৽͍͠ CJOBSZΛ%FTFSJBMJ[FͰ͖Δɻͦͷٯ΋વΓɻ ෳ਺ϚΠΫϩαʔϏεͷಉ࣌EFQMPZͳͲΛۃྗݮΒͤΔ

    w CJOBSZGPSNBU͸+40/ΑΓ΋TFSJBMJ[FEFTFSJBMJ[F͕ૣ͘ɺ EBUBTJ[F΋খ͍͞ 4FSJBMJ[FS%FTFSJBMJ[FSͷػೳ͕༏Ε͍ͯΔ ͳͥ1SPUPDPM#VGGFSTΛར༻͢Δͷ͔ʁ
  25. ©2019 Wantedly, Inc. ͳͥ1SPUPDPM#VGGFSTΛར༻͢Δͷ͔ʁ QSPUPDͷ๛෋ͳQMVHJO w QMVHJOʹΑ༷ͬͯʑͳػೳ֦ு͕Մೳ w FHTXBHHFSKTPOͷੜ੒ w

    FHQSPUPpMFͷ಺༰Λ+40/ܗࣜ΁ม׵ w FHH31$ HSQDHBUFXBZͷར༻ w ಛʹɺTXBHHFSKTPO͸ݩʑ8FC'SPOUFOE .PCJMF"QQνʔϜͱͷ ίϛϡχέʔγϣϯʹར༻͍ͯͨ͠ͷͰɺԸܙ͕େ͖͔ͬͨ w QSPUPDQMVHJOΤίγεςϜ͕࡞ΒΕ͖͍ͯͯΔ
  26. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛ Ͳ͏ར༻͍ͯ͠Δͷ͔ʁ

  27. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛͲ͏ར༻͍ͯ͠Δͷ͔ʁ #SPXTFS .PCJMF"QQ ϚΠΫϩαʔϏεͷ಺ଆͱ֎ଆ ྆ํͷ௨৴ʹ1SPUPDPM#VGGFSTΛར༻ QSPUPpMFͷ಺༰Λ൓өͨ͠ +40/PWFS)551

    1SPUPDPM#V⒎FSTPWFS)551 PS QSPUPpMFͷ಺༰Λ൓өͨ͠ +40/PWFS)551
  28. ©2019 Wantedly, Inc. ϚΠΫϩαʔϏε։ൃͰ͸ ओʹ(Pͱ3VCZΛར༻

  29. ©2019 Wantedly, Inc. (PΛར༻ͨ͠ϚΠΫϩαʔϏεͰ͸ Ͳ͏͍ͯ͠Δ͔ʁ

  30. ©2019 Wantedly, Inc.

  31. ©2019 Wantedly, Inc. HSBQJΛར༻ w HSBQJ"TVSQSJTJOHMZFBTZ"1*TFSWFSBOEHFOFSBUPSJOH31$ BOE(P w ฐࣾΤϯδχΞ!J[VNJO࡞ͷϑϨʔϜϫʔΫ w

    H31$ HSQDHBUFXBZͷߏ੒Ͱ(PαʔόʔΛ؆୯ʹߏஙՄೳ (PΛར༻ͨ͠ϚΠΫϩαʔϏε։ൃ
  32. ©2019 Wantedly, Inc. (PPHMF੡31$ϑϨʔϜϫʔΫ w QSPUPpMFʹهड़ͨ͠TFSWJDFEFpOJUJPO͔ΒDMJFOUTFSWFS ίʔυ͓ΑͼTFSJBMJ[FSEFTFSJBMJ[FSίʔυΛࣗಈੜ੒ 4DIFNBͱ࣮૷ͷҰகΛอূ H31$ͱ͸ʁ

  33. ©2019 Wantedly, Inc. H31$ͱ3&45GVM)551"1*ͷม׵Λ ߦ͏3FWFSTF1SPYZ(FOFSBUPS w H31$TFSWFSͷલஈʹཱͪɺ+40/"1*TFSWFSͱͯ͠ৼΔ෣͏ ಋೖͷϋʔυϧ͕௿͍ HSQDHBUFXBZͱ͸ʁ

  34. ©2019 Wantedly, Inc. HSBQJΛར༻ͯ͠ɺ1SPUPDPM#VGGFST ͷϝϦοτΛڗड w QSPUPpMFΛॻ͘ͱɺH31$ HSQDHBUFXBZͷίʔυΛࣗಈੜ੒ 4DIFNBΛݫີʹຬͨ͢"1*TFSWFSΛ؆୯ʹ࡞੒Մೳ w

    QSPUPDQMVHJOͰTXBHHFSKTPOΛੜ੒ 4XBHHFS6*ͳͲɺ4XBHHFSΤίγεςϜΛ׆͔ͤΔ w ৄࡉ͸ҎԼͷϦϯΫΛࢀর (PΛར༻ͨ͠ϚΠΫϩαʔϏε։ൃ IUUQTTQFBLFSEFDLDPNJ[VNJOHSBQJCVMEJOHKTPOBQJ TFSWFSXJUIHSQDHBUFXBZGPSNJDSPTFSWJDFT
  35. ©2019 Wantedly, Inc. Ͱ͸ɺ3VCZΛར༻ͨ͠ ϚΠΫϩαʔϏε։ൃ͸ʁ

  36. ©2019 Wantedly, Inc. 3VCZPO3BJMT 1SPUPDPM#VGGFSTͷ 4FSJBMJ[FS%FTFSJBMJ[FSΛར༻ w 3BJMTͰ"1*Λ։ൃ w ͨͩ͠ɺSFRVFTUSFTQPOTFͷQBZMPBEʹ1SPUPDPM#V⒎FSTͷ

    CJOBSZGPSNBUΛར༻ 3VCZΛར༻ͨ͠ϚΠΫϩαʔϏε։ൃ
  37. ©2019 Wantedly, Inc. > PATCH /api/books/2 HTTP/1.1 > Accept: application/protobuf

    > Content-Type: application/protobuf > > \x08\x02 < HTTP/1.1 200 OK < Content-Type: application/protobuf < < \x08\x02\x12\x0BHello, Book [1] book = Book.new(id: 2, title: "Hello, Book") => <Book: id: 2, title: "Hello, Book"> [2] book.to_proto => "\b\x02\x12\vHello, Book” 3VCZ )551SFRVFTUSFTQPOTF
  38. ©2019 Wantedly, Inc. Mime::Type.register "application/protobuf", :protobuf ActionController::Renderers.add :protobuf do |obj,

    _| send_data obj.to_proto, type: Mime[:protobuf] end 3VCZPO3BJMTJOJUJBMJ[FS def show req = GetBookRequest.decode(request.body.read) … book = Book.new(id: xxx, title: yyy) render protobuf: book end 3VCZPO3BJMTDPOUSPMMFS
  39. ©2019 Wantedly, Inc. 3BJMTΛར༻͠ͳ͕Βɹ 1SPUPDPM#VGGFSTͷϝϦοτΛڗड

  40. ©2019 Wantedly, Inc. Ұ෦Ͱ͸5ZQF4DSJQU͔Β΋ 1SPUPDPM#VGGFSTΛར༻

  41. ©2019 Wantedly, Inc. #BDLFOE'PS'SPOUFOE #'' ͱͳΔ 5ZQF4DSJQUαʔόʔ͕ଘࡏ w #SPXTFSͱ͸(SBQI2-Ͱ௨৴͠ɺ#BDLFOE4FSWFSͱͷ௨৴ʹ͸ 1SPUPDPM#V⒎FSTΛར༻

    5ZQF4DSJQU͔Βͷ1SPUPDPM#VGGFSTར༻ #SPXTFS .PCJMF"QQ 5ZQF4DSJQU (SBQI2- 1SPUPDPM#V⒎FST
  42. ©2019 Wantedly, Inc. (SBQI2-ͱ1SPUPDPM#VGGFSTΛ దࡐదॴͰ࢖͍෼͚͍ͯΔ

  43. ©2019 Wantedly, Inc. ࣮ࡍʹ1SPUPDPM#VGGFSTΛར༻ͯ͠ ײͨ͡ϝϦοτ

  44. ©2019 Wantedly, Inc. ૝૾Ҏ্ʹྑ͍෦෼͕ ଟ਺͋ͬͨʂ

  45. ©2019 Wantedly, Inc. ࣮૷ΑΓ΋ৼΔ෣͍ʹूதͰ͖Δ w QSPUPpMFͷ಺༰͸γϯϓϧͰಡΈ΍͘͢ཧղ͠΍͍͢ w QSPUPpMFΛݟΔ͚ͩͰɺϚΠΫϩαʔϏεͷৼΔ෣͍͕෼͔Δ w υϝΠϯϞσϧΛQSPUPpMFͷதʹએݴతʹهड़Ͱ͖Δ

    ʮ࣮૷ʯΑΓ΋ʮৼΔ෣͍ʯʹूதͯٞ͠࿦ɾઃܭ͕Ͱ͖Δ 1SPUPDPM#VGGFSTΛར༻ͯ͠ײͨ͡ϝϦοτ
  46. ©2019 Wantedly, Inc.

  47. ©2019 Wantedly, Inc.

  48. ©2019 Wantedly, Inc. (PPHMFͷ"1*%FTJHO(VJEFͷଘࡏ w (PPHMF$MPVE"1*TͳͲ(PPHMFͷެ։"1*͸QSPUPpMFͰهड़ ͞Ε͓ͯΓɺͦΕ͕४ڌ͢Δ"1*%FTJHO(VJEF΋ެ։͞Ε͍ͯΔɹ w DGIUUQTHJUIVCDPNHPPHMFBQJTHPPHMFBQJT w

    DGIUUQTDMPVEHPPHMFDPNBQJTEFTJHO w (PPHMF"1*T͸༏Ε࣮ͨྫͱͳ͍ͬͯΔ w "1*%FTJHO(VJEF͸"1*ઃܭͷࢀߟʹͰ͖Δ w ඪ४తͳܕͳͲ΋(PPHMFʹΑͬͯଟ਺ఆٛ͞Ε͍ͯͯར༻Ͱ͖Δ 1SPUPDPM#VGGFSTΛར༻ͯ͠ײͨ͡ϝϦοτ
  49. ©2019 Wantedly, Inc. ੩తಈతݴޠ྆ํ͔Βѻ͍΍͍͢ w QSPUPpMF͸"1*ʹର͢Δ੩తܕ෇͚ͱͯ͠ػೳ͢Δ w (Pͷ༷ͳ੩తܕ෇͚ݴޠ͔Β΋ѻ͍΍͍͢ɻQBZMPBEΛ੩తܕ෇͚ ͞ΕͨTUSVDU΁NBSTIBMVONBSTIBMͰ͖Δɻ w

    3VCZͷ༷ͳಈతܕ෇͚ݴޠͰ΋ѻ͍΍͍͢ɻpFME໊ͷUZQPͳͲΛ ߟ͑ͳͯ͘ྑ͍ɻ 1SPUPDPM#VGGFSTΛར༻ͯ͠ײͨ͡ϝϦοτ
  50. ©2019 Wantedly, Inc. 5FTU%SJWFO%FWFMPQNFOU 5%%  ͕΍Γ΍͍͢ w QSPUPpMFͱͯ͠"1*ͷৼΔ෣͍Λઌʹఆٛ͢ΔͷͰɺͦΕΛຬͨ͢ 5FTUΛ࣮૷ΑΓ΋ઌʹॻ͘͜ͱ͕ग़དྷΔ

    w ࣗવͳܗͰ5%%Λ࣮ફग़དྷΔ 1SPUPDPM#VGGFSTΛར༻ͯ͠ײͨ͡ϝϦοτ
  51. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTͷԸܙΛड͚ͯ ։ൃΛਐΊΔ͜ͱ͕Ͱ͖ͨ

  52. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻͢ΔதͰ ݟ͖͑ͯͨ஫ҙ఺

  53. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻͢ΔதͰݟ͖͑ͯͨ஫ҙ఺ QSPUPpMFͷڞ༗ํ๏͸੔උ͕ඞཁ w 1SPUPDPM#V⒎FST͸$MJFOU 4FSWFS྆ํ͕ಉ͡QSPUPpMFΛࢀর͢Δ ඞཁ͕͋Δɻ 3FQPTJUPSZ͕෼͔Ε͍ͯΔ৔߹ɺQSPUPpMFͷڞ༗͕ඞཁ

    w ڞ༗ํ๏͝ͱͷϝϦοτɾσϝϦοτΛߟ͑Δඞཁ͕͋Δ w ୯७ͳίϐʔʜ࣮ݱ͕؆୯͕ͩɺQSPUPpMFͷมߋ௥ै͕೉͍͠ w QSPUPEFQ౳ͷπʔϧʜ$MJFOU͔ΒWFSTJPOࢦఆ͕Մೳ w QSPUPpMFू໿SFQPTJUPSZʜSFQPTJUPSZʹQSPUPpMFΛू໿ɻ ίʔυੜ੒ͯ͠MJCSBSZͱͯ͠഑৴ɻEFQFOEBCPUͰมߋΛ௨஌ɻ w 8BOUFEMZͰ͸ϓϩδΣΫτ͝ͱʹόϥόϥ͕ͩɺQSPUPpMFू໿ SFQPTJUPSZͷར༻͕૿Ճத
  54. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻͢ΔதͰݟ͖͑ͯͨ஫ҙ఺ 1SPUPDPM#VGGFSTίϯύΠϥ QSPUPD  ͷWFSTJPOʹ஫ҙ͢Δ w QSPUPDWFSTJPOͷҧ͍ʹΑͬͯɺࣗಈੜ੒ͨ͠ίʔυ಺༰͕มΘΔ

    w ޓ׵ੑ͸΄ͱΜͲյΕͳ͍͸͕ͣͩɺಛʹ(PͰݟͨ໨ͷEJ⒎͕ େ͖͘WFSTJPOΛ্͛ͮΒ͔ͬͨ w ։ൃऀͦΕͧΕ͕QSPUPDͰίʔυੜ੒͢Δ৔߹ɺQSPUPDWFSTJPO Λἧ͑Δඞཁ͋Γ VCFSQSPUPUPPMͳͲΛར༻ͯ͠WFSTJPOΛݻఆ͢Δͱྑ͍
  55. ©2019 Wantedly, Inc.

  56. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻͢ΔதͰݟ͖͑ͯͨ஫ҙ఺ ݴޠʹΑͬͯ͸4FSJBMJ[BUJPO-JCSBSZ ͷػೳ͕ශऑ w +BWB4DSJQUpFMEͷTFU͸TFUUFSNFUIPEΛར༻͢Δඞཁ͕͋Δ w FHTFU*E

    TFU/BNF FUD w 3VCZSFQFBUFEpFME͸"SSBZMJLF͕ͩඍົʹ࢖͍উख͕ҧ͏ w ୯७ͳTFU͸ग़དྷͣɺSFQMBDF͕ඞཁ w "DUJWF3FDPSEͷXIFSFʹͦͷ··౉ͤͳ͍
  57. ©2019 Wantedly, Inc. [1] book = Book.new(id: 1) => <Book:

    id: 1, authors: []> [2] book.authors => [] [3] book.authors.class => Google::Protobuf::RepeatedField [4] book.authors = [Author.new(id: 2)] Google::Protobuf::TypeError: Expected repeated field array from (pry):4:in `method_missing’ [5] book.authors.replace([Author.new(id: 2)]) => [<Author: id: 2, name: "">] [6] book.authors => [<Author: id: 2, name: "">]
  58. ©2019 Wantedly, Inc. [1] req = ListBookRequest.new(ids: [1, 2, 3])

    => <ListBookRequest: ids: [1, 2, 3]> [2] req.ids.class => Google::Protobuf::RepeatedField [4] Book.where(id: req.ids).to_sql => "SELECT \"books\".* FROM \"books\" WHERE \"books\".\"id\" = NULL" [3] Book.where(id: req.ids.to_a).to_sql => "SELECT \"books\".* FROM \"books\" WHERE \"books\".\"id\" IN (1, 2, 3)"
  59. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻͢ΔதͰݟ͖͑ͯͨ஫ҙ఺ 1SPUPDPM#VGGFST8FMMLOPXO5ZQFT ͷѻ͍͸গ͠໘౗ w 1SPUPDPM#V⒎FST্Ͱ࣌ؒΛදݱ͢ΔHPPHMFQSPUPCVG5JNFTUBNQ w ݴޠ͝ͱͷ5JNF࣮૷ͱ͸ผͳͷͰຖճXSBQVOXSBQ͢Δඞཁ͋Γ

    w 4USJOH7BMVF *OU7BMVFͳͲͷOVMMBCMFUZQFT w TUSJOH JOUͳͲΛOVMMBCMFʹ͢Δҝʹར༻ w ͜Ε΋XSBQVOXSBQͷख͕͔͔ؒΔ
  60. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻͢ΔதͰݟ͖͑ͯͨ஫ҙ఺ CJOBSZGPSNBUͷՄࢹԽํ๏Λߟ͑Δ ඞཁ͋Γ w MPHʹ࢒͢ࡍͳͲɺCJOBSZGPSNBUͷ··Ͱ͸ղऍͮ͠Β͍ ྫ͑͹MPHΛར༻͢ΔλΠϛϯάͰ%FTFSJBMJ[F͢Δ w

    SFRVFTUSFTQPOTFͷ಺༰֬ೝʹ͸ɺՄࢹԽ͕ඞཁ +40/ͱ1SPUPDPM#V⒎FST྆ํΛฦ͢αʔόʔͱͯ͠։ൃ
  61. ©2019 Wantedly, Inc. 1SPUPDPM#VGGFSTΛར༻͢ΔதͰݟ͖͑ͯͨ஫ҙ఺ H31$ HSQDHBUFXBZߏ੒ͷ࣌ มߋʹΑͬͯ͸ޙํޓ׵ੑ͕յΕΔ w QSPUPpMFͷFOVN஋Λ૿΍ͨ͠ࣄʹΑͬͯɺSFRVFTUQBSBNFUFS Ͱ͋Δ+40/ͷ%FTFSJBMJ[FͰFSSPS͕ى͖ͨέʔε͕͋ͬͨ

    w H31$ HSQDHBUFXBZߏ੒ͷ࣌͸ɺ҆શͳมߋ͔ෆ҆ͳ࣌͸ڍಈΛ ֬ೝͨ͠΄͏͕ྑ͍
  62. ©2019 Wantedly, Inc. ͍͔ͭ͘ͷ఺ʹ͸஫ҙ͠ͳ͕Β 1SPUPDPM#VGGFSTΛར༻͠Α͏

  63. ©2019 Wantedly, Inc. ·ͱΊ

  64. ©2019 Wantedly, Inc. ·ͱΊ 1SPUPDPM#VGGFSTΛ"1*ͷ4DIFNB ؅ཧʹར༻͢Δͱଟ͘ͷར఺͕͋Δ w QSPUPpMFͱͯ͠"1*ͷৼΔ෣͍Λએݴతʹهड़ w ࣗಈੜ੒ͨ͠ίʔυʹΑͬͯ4DIFNBͱ࣮૷ͷҰகΛอূ

    w ੩తಈతܕ෇͚ݴޠ྆ํ͔Βѻ͍΍͍͢ w TXBHHFSKTPOͷੜ੒ͳͲɺQSPUPDQMVHJOͷΤίγεςϜΛ׆༻Մೳ ϝϦοτΛڗड͠ੜ࢈ੑߴ͘։ൃ͠Α͏ʂ
  65. ©2019 Wantedly, Inc. "QQEFOEJYH31$ʹ͍ͭͯ H31$΋ݱࡏݕূத w LTDMVTUFS಺ͷϚΠΫϩαʔϏεʹରͯ͠FOWPZ͕TJEFDBSQSPYZ ͱͯ͠EFQMPZ͞ΕΔ༷ʹͳͬͨ )551MPBECBMBODJOH͕Մೳʹͳͬͨ w

    HSQDHBUFXBZΛ௨ͣ͞ʹ(PͷH31$αʔόʔͱ௨৴ͨ͠Γɺ৽͍͠ 3VCZαʔόʔΛH31$αʔόʔͱͯ͠։ൃ͢ΔࢼΈΛ͍ͯ͠Δ 1SPUPDPM#V⒎FSTͷԸܙΛड͚ͭͭɺUSBOTQPSU΋ޮ཰Խ
  66. ©2019 Wantedly, Inc. 1IPUP$SFEJU w "MFYXPOHIUUQTVOTQMBTIDPNQIPUPTM5[WBMDQT