Rails Developers Meetup 2018 https://railsdm.github.io/
҆શ͔ͭߴʹਐΊΔϚΠΫϩαʔϏεԽ3BJMT%FWFMPQFST.FFUVQ!LLVCVO
View Slide
ࣗݾհ• GitHub, Twitter: @k0kubun• Treasure Data ॴଐ• Site Reliability Engineer• Ruby 2.6ͷJITίϯύΠϥ։ൃத
Treasure Data Ͱͷ1ؒ• 2017 1Q: TD APIͷ։ൃ• 2017 2Q: bigdam-queue• 2017 3Q: Fluentd Enterprise• 2017 4Q: Embulk Config Microservice• 2018 1Q: SRE: AutoScaling, Deployment
ࠓ͢͜ͱ1. αʔϏεׂͷલʹߟ͑Δ͖͜ͱ2. ҆શ͔ͭߴʹׂ͢ΔͨΊͷςετख๏3. Railsʹ͓͚ΔϦτϥΠͷ࣮ύλʔϯ4. RailsΞϓϦͷΓग़͠Ͱࠔͳ5. ҆શʹσϓϩΠڥΛվળ͍ͯ͘͠
1. αʔϏεׂͷલʹߟ͑Δ͖͜ͱ
ϚΠΫϩαʔϏεԽͰԿΛղܾ͠·͔͢?Q1.
ฐࣾͷࠓճͷαʔϏεׂͷܦҢ: ࠓճͷΓग़͠ͰͲΕطʹେମղܾࡁͰ͢!!!
Ϟσϧͷ࣮ͷఆ͕ٛYAMLͱͯ͠ผϦϙδτϦʹΓग़͞Ε͍ͯΔ
ຊମͷRailsΞϓϦͱผʹϦϦʔε͢ΔͨΊɺͦͷYAMLΛDBʹͭͬ͜ΜͰಈతʹڍಈΛมߋ+ APIͰͦΕ͕ϦϦʔεͰ͖Δঢ়ଶ
APIʹΑΔYAMLͷϦϦʔεͰϝιουͷఆ͕ٛಈతʹมΘΔͷͰɺϝιουΛݺͼग़͢ʹΫΤϦ͕ඞཁʹͳΓ͍
ͦͦΓग़͞Ε͍ͯͳ͍RailsͷίʔυͱYAML͕ڧ݁߹ͳ͜ͱʹΑΔϦϦʔεॱংґଘͷൃੜͱͦΕʹΑΔো
ຊ1ͭͷϦϙδτϦʹͨ͠ํ͕͍͍ʹܾ·͍ͬͯΔ͕ɺͰ͖ΕΛ໌֬ʹͯ͠νʔϜؒͷίϛϡχέʔγϣϯίετΛԼ͛ͨΓಠཱʹϦϦʔεͨ͠Γ͍ͨ͠
=> YAML͡Όͳͯͪ͘ΌΜͱαʔϏεͱͯ͠͠Α͏
ϚΠΫϩαʔϏεԽͰൃੜ͢Δશͯڐ༰Ͱ͖·͔͢?Q2.
ڥքΛލ͍ͰJOIN͕Ͱ͖ͳ͍
DBΛ͢ΔͱɺͦΕΛލ͙τϥϯβΫγϣϯ͕͔͚ΒΕͣҰ؏ੑ͕୲อͰ͖ͳ͘ͳΔ
ϦιʔεΛऔΔͨΊʹී௨ͷActiveRecordͷίʔυ͕͑ͳ͍
োൃੜݯͷ૿Ճ
αʔϏε͕૿͑Δ͜ͱʹΑΔΠϯϑϥཧ/ӡ༻ίετͷ૿େ
ΤϯυϙΠϯτؙ͝ͱ͢Δ?෦APIʹ͍ͯ͠ΖΜͳॴ͔Βୟ͘?Q3.
ࠓճ෦APIدΓͷɺ͔͠࠷ॳ͔Βͦ͏࡞ΔͷͰͳ్͘தͰΓग़࣌͢ͷΛ͠·͢
2. ҆શ͔ͭߴʹׂ͢ΔͨΊͷςετख๏
ϚΠΫϩαʔϏεԽͷ࠷தͲͷΑ͏ʹςετ͠·͔͢?
ओͳςετͷબࢶ• ϝιουݺͼग़͠୯ҐͰڥքΛશͯελϒ͢Δ• VCRͰ֎෦ͷϦΫΤετΛશͯελϒ͢Δ• ಈ͔͢ίϯϙʔωϯτΛશͯ༻ҙͯ݁͠߹ςετ• Pact Ͱ Consumer Driven Contract Testingࢀߟ: https://medium.com/@copyconstruct/testing-microservices-the-sane-way-9bb31d158c16
ςετͰ۩ମతʹԿΛୡ͍ͨ͠ͷ͔• ୯ͳΔίϐϖͰࡁΈͦ͏ʹͳ͘ɺΓग़͢ॠ͕ؒҰ൪ϦεΫ͕ߴ͍ͷͰɺͲ͏ʹ͔͚ͯͦͩ҆͜͠શʹࡁ·͍ͤͨ• ͔ͱ͍ͬͯઐ༻ͷςετΛҰ͔Βॻ͖·͘Δ΄ͲՋͰͳ͍ͷͰɺۃྗطଘͷςετࢿ࢈Λྲྀ༻͍ͨ͠• ͦͯ͠ଞͷ։ൃΛશ͘ࢭΊͨ͘ͳ͍ͷͰςετ͕ৗʹ༷ͷมߋʹैͰ͖ͳ͍ͱ͍͚ͳ͍
ओͳςετͷબࢶ• ϝιουݺͼग़͠୯ҐͰڥքΛશͯελϒ͢Δ• VCRͰ֎෦ͷϦΫΤετΛશͯελϒ͢Δ• ಈ͔͢ίϯϙʔωϯτΛશͯ༻ҙͯ݁͠߹ςετ• Pact Ͱ Consumer Driven Contract Testing༷มߋʹର͢ΔελϒͷैΛΕͦ͏
ओͳςετͷબࢶ• ϝιουݺͼग़͠୯ҐͰڥքΛશͯελϒ͢Δ• VCRͰ֎෦ͷϦΫΤετΛશͯελϒ͢Δ• ಈ͔͢ίϯϙʔωϯτΛશͯ༻ҙͯ݁͠߹ςετ• Pact Ͱ Consumer Driven Contract Testing୭͕Χηοτߋ৽͢Δͷ? ࣗಈͰߋ৽͢ΔͳΒΧηοτʹͯ͠Δҙຯͳ͘ͳ͍?
ओͳςετͷબࢶ• ϝιουݺͼग़͠୯ҐͰڥքΛશͯελϒ͢Δ• VCRͰ֎෦ͷϦΫΤετΛશͯελϒ͢Δ• ಈ͔͢ίϯϙʔωϯτΛશͯ༻ҙͯ݁͠߹ςετ• Pact Ͱ Consumer Driven Contract Testing͜Εݩ͔Β͋ͬͯɺϝϯςίετߴ͍͕ҰԠͦͷ··͑Δ
ओͳςετͷબࢶ• ϝιουݺͼग़͠୯ҐͰڥքΛશͯελϒ͢Δ• VCRͰ֎෦ͷϦΫΤετΛશͯελϒ͢Δ• ಈ͔͢ίϯϙʔωϯτΛશͯ༻ҙͯ݁͠߹ςετ• Pact Ͱ Consumer Driven Contract Testing༷มߋΛ͢Δਓͨͪʹ͜ΕΛֶशͯ͠Β͏ίετ͕ߴ͗͢Δ + Pact Brokerͷ༻ҙӡ༻ඞཁͳͷͰɺҰճͷΓग़͠Ͱಋೖ͢ΔʹΦʔόʔΩϧ (ظతʹཉ͍͠)
͡Ό͋݁߹ςετ͚ͩΛཔΓʹͰ͖Δͷ͔?• ݱঢ়ɺ݁߹ςετओʹΫϦςΟΧϧͳڍಈʹରͯ͠ͷΈॻ͔Ε͓ͯΓɺͦΕ͚ͩͩͱखബ͍• ͔ͱ͍ͬͯແҋʹ݁߹ςετΛ૿͢ͱอक͕͠ΜͲ͍• ςετࣗମͷอक͕νʔϜʹด͡ͳ͘ͳΔͷͰίϛϡχέʔγϣϯίετ͕ൃੜ• ނো͕ଟͯ͘ෆ҆ఆʹͳΓ͕ͪ (ಛʹCapybaraͱ͔)
Γग़͠ݩΞϓϦͷrspecϓϩηεspec_helper.rbࠓճ༻ͨ͠ςετख๏: Γग़ͨ͠ΞϓϦΛىಈͯ͠ϢχοτςετΛΒͤΔ
Γग़͠ݩΞϓϦͷrspecϓϩηεspec_helper.rbΓग़ͨ͠RailsΞϓϦͷϓϩηεat_exitࠓճ༻ͨ͠ςετख๏: Γग़ͨ͠ΞϓϦΛىಈͯ͠ϢχοτςετΛΒͤΔSpawnKill
Γग़͠ݩΞϓϦͷrspecϓϩηεspec_helper.rbat_exitڞ༗DB(ޙͰΓ͢)ࠓճ༻ͨ͠ςετख๏: Γग़ͨ͠ΞϓϦΛىಈͯ͠ϢχοτςετΛΒͤΔ*_spec.rb FactoryBotΓग़͢࠷த·ͩDB͕ڞ༗͞ΕͯΔ͜ͱΛҰ࣌తʹ׆͔ͯ͠ςετΛಈ͔͢Γग़ͨ͠RailsΞϓϦͷϓϩηε
Γग़͠ݩΞϓϦͷrspecϓϩηεspec_helper.rbat_exitڞ༗DB(ޙͰΓ͢)ࠓճ༻ͨ͠ςετख๏: Γग़ͨ͠ΞϓϦΛىಈͯ͠ϢχοτςετΛΒͤΔ*_spec.rb FactoryBotΓग़ͨ͠RailsΞϓϦͷϓϩηεΓग़͠ݩRailsΞϓϦԿελϒͤͣϦΫΤετ
Γग़͠ݩΞϓϦͷrspecϓϩηεspec_helper.rbat_exitڞ༗DB(ޙͰΓ͢)ࠓճ༻ͨ͠ςετख๏: Γग़ͨ͠ΞϓϦΛىಈͯ͠ϢχοτςετΛΒͤΔ*_spec.rb FactoryBotΓग़ͨ͠RailsΞϓϦͷϓϩηεΓग़͠ݩRailsΞϓϦΓग़ͨ͠DBDBͷΓ͠ʹ͍FactoryBotΛଔۀ͔ΘΓʹAPIͰϦιʔεΛ࡞Δ
͜ͷख๏ͷྑ͍ͱ͜Ζɺѱ͍ͱ͜Ζ• ྑ͍ͱ͜Ζ• ଞͷਓ͕มߋͨ͠ςετΛ΄΅ͦͷ··͑ɺͱʹ͔༷͘มߋʹڧ͍• Կελϒ͠ͳ͍͍ͯ͘ͷͰςετΛॻ͘ͷָ͕• ѱ͍ͱ͜Ζ• Γग़͠ݩͷCIͷ͕࣌ؒ৳ͼΔ• Γग़ͨ͠ΞϓϦΛىಈ͢ΔखஈΛϝϯς͢Δίετ͕͔͔Δ• Γग़ͨ͠ΞϓϦͰյΕͨ࣌ͷσόοάํ๏͕গ͠มΘΔͷͰ໘
ۜͷؙͳ͍ͷͰࣗͨͪͷϑΣʔζཁ݅ʹ߹ΘͤͯॊೈʹղܾࡦΛม͑ଓ͚·͠ΐ͏
3. Railsʹ͓͚ΔϦτϥΠͷ࣮ύλʔϯ
ΤϥʔϋϯυϦϯάͷ؍ͰҙͷAPIΫϥΠΞϯτʹٻΊΒΕΔཁ݅• ඇܾఆతͳΤϥʔʹରͯ͠exponential backoff͖ͭͰϦτϥΠͰ͖Δ• λΠϜΞτΛઃ͚͍ͯΔ (ແݶʹϋϯά͠ͳ͍)• αʔϏε͕མ͍ͪͯΔ͜ͱ͕໌Β͔ͳ߹ɺҰఆظؒϦΫΤετΛεΩοϓͰ͖Δ (Circuit Breaker)
Circuit BreakerύλʔϯͷͨΊͷϥΠϒϥϦ• circuit_breaker.gem• γϯϓϧɺ͚ͩͲmix-inͳͷͰݸਓతʹ͋·Γ͍ͨ͘ͳ͍• expeditor.gem• Circuit Breaker͚ͩͰͳ͘ɺϦτϥΠɺλΠϜΞτɺࣦഊ࣌ͷϑΥʔϧόοΫɺඇಉظԽͳͲ࣮• ਖ਼expeditorʹඇಉظԽ͍Βͳ͔ͬͨΜ͡Όͳ͍͔ͱࢥͬͯΔ͚ͲɺฐࣾͰmakimoto͞Μͱ͕ৄ͍͠ͷͰ͜ΕΛ࠾༻
࣮ࡍͷAPIΫϥΠΞϯτͷྫ (GET)
ϦτϥΠઓུ• exponential backoffΛ͚ͭɺແཧʹෛՙΛ͔͚ͳ͍Α͏ʹ• 5XXͰɺϦτϥΠՄೳͳ͜ͱ͕໌Β͔Ͱͳ͍ΤϥʔઈରϦτϥΠ͠ͳ͍• ΫϥΠΞϯτଆͷϫʔΧʔΛແବʹϒϩοΫͨ͠Γɺαʔόʔଆͷো࣌ʹෛՙΛ͔͚ΑΓঢ়گΛѱԽͤͨ͞Γ͢ΔͨΊ• ྫ͑500NoMethodErrorͱ͔ͩͬͨΓ͢ΔͷͰϦτϥΠ͖͢Ͱͳ͍• ϦτϥΠࠐΈͷશମͷλΠϜΞτͱɺ֤ϦτϥΠͷλΠϜΞτΛઃ͚Δ• ҰॠͰࢮ͵ΤϥʔΛΑΓଟΊʹϦτϥΠ͢ΔͨΊ• ͲͷΤϥʔ͕ϦτϥΠՄೳ͔APIʹΑͬͯҟͳΔ• ֤HTTPϝιου͝ͱʹੑʹؔ͢ΔڍಈΛαʔόʔଆͰ౷Ұ͓ͯ͘͠ͱָ
RailsͰසൟʹ࡞ΒΕͦ͏ͳҎԼͷύλʔϯͰAPIαʔόʔ/ΫϥΠΞϯτΛͲ͏࣮͢Δ͔• GET /embulk_configs (index)• GET /embulk_configs/:id (show)• POST /embulk_configs (create)• PATCH /embulk_configs/:id (update)• DELETE /embulk_configs/:id (destroy)APIͩͱ #new, #edit ࡞Γ·ͤΜΑͶ?
GET /embulk_configs (index)• αʔόʔ• ͨΓલ͚ͩͲGETશͯϩάҎ֎ͷ෭࡞༻͕ͳ͍Α͏ʹ͢Δ• ΫϥΠΞϯτ• ΄΅ϦτϥΠ͠์͚ͩͲɺલड़ͷཧ༝ʹΑΓ404, 422, 500ͱ͔Ί͓͖ͯ·͠ΐ͏• αʔόʔ͕མͪͯΔܥ(502, 503)ͱΫϥΠΞϯτͰλΠϜΞτͨ͠ܥΛϦτϥΠ͢Δ
GET /embulk_configs/:id (show)• GETͳͷͰ#indexͱಉ͡ঢ়ଶʹ͓ͯ͘͠
POST /embulk_configs (create)• αʔόʔ• ࡞ରͷϦιʔεʹunique index͕͋Δ: RecordNotUnique࣌ͷϨεϙϯεΛ۠ผՄೳʹ͢Δ (409ฦ͢ͱ͔)• ͳ͍: ϦΫΤετIDΈ͍ͨͳͷΛΫϥΠΞϯτʹ༻ҙͤ͞ɺͦΕΛ͚࣋ͭͩͷςʔϒϧͷϨίʔυͱ࡞ରͷϦιʔεΛτϥϯβΫγϣϯͰίϛοτ͢Δ• ΫϥΠΞϯτ• 409 Conflictͷ߹ϦτϥΠ͠ͳ͍• ϦΫΤετIDΛ༻ҙ͢Δ߹SecureRandom.uuidͱ͔Λ༻ҙ͠ɺϦτϥΠͷؒͰಉ͕͡ΔΑ͏ʹ͢Δ409ͷͷݩωλ: http://frsyuki.hatenablog.com/entry/2014/06/09/164559
PATCH /embulk_configs/:id (update)• αʔόʔ• ؾ߹Ͱʹ͢Δ• ΞϓϦέʔγϣϯ࣍ୈ͕ͩɺ͘͝γϯϓϧͳཁ݅Ͱ͋ΕʹͳΔΑ͏ʹ࣮͢Δͷ͘͠ͳ͍• ΫϥΠΞϯτ• ʹ͑͞ͳ͍ͬͯΕɺGETͱ͔ͱϦτϥΠ͖͢ΤϥʔมΘΒͳ͍ (ͳͬͯͳ͍ͳΒৗʹϦτϥΠ͠ͳ͍)UPDATEͷੑʹؔͯͪ͜͠Βࢀߟʹ: http://frsyuki.hatenablog.com/entry/2017/08/10/140416
DELETE /embulk_configs/:id (destroy)• αʔόʔ• ඞͣ͠ϦτϥΠͰਖ਼ৗͳϨεϙϯε͕ظͰ͖Δํ๏Ͱͳ͍͕ɺී௨ʹfindͯ͠destroyͨ͠ΒϦιʔεʹର͢Δૢ࡞গͳ͘ͱʹͳΔ• Ͳ͏ͯ͠ʹ͍ͨ͠ͳΒɺཧআ͔ͭաڈʹϨίʔυଘࡏ͚ͨ͠ͲআࡁͰ͋Δ͜ͱ͕Θ͔Δ߹ɺޭΛฦ͍͍͔ͯ͠• ཧআͷ߹ͦͦ࡞ΒΕ͍ͯͳ͔ͬͨ߹ͱผͰ͖ͳ͍ͷͰ404• ΫϥΠΞϯτ• ্هͷڍಈͰ͋ΕGETͱಉ͡ΤϥʔΛϦτϥΠͯ͠Ε͋·ΓࠔΒͳ͍ͣ• طʹআࡁͷ߹(404)ϦτϥΠ͠ͳ͍
4. RailsΞϓϦͷΓग़͠Ͱࠔͳ
Γग़͠ઌʹ͍͚࣋ͬͯͳ͍ΞιγΤʔγϣϯ• ྫ͑Γग़ͦ͏ͱ͍ͯ͠ΔϞσϧ͕ belongs_to :user Λ࣋ͭ߹• ֎෦ʹݟ͑Δܗͱͯ͠αʔϏε͕͔Ε͍ͯΔ߹usersςʔϒϧͷߋ৽ΛPubSubͰ௨ͯ͠Γग़͠ઌʹίϐʔΛ࣋ͭͱ͔• ͋Δ͍ɺDBΛ͢Δ߹Ͳ͏ͬͯҰ؏ੑଛͳΘΕΔͷͰɺׂΓͬͯuser_id͚ͩΓऔΓ͢Δ• JOINͰ͖ͳ͍͠ΧϥϜͷͷҙຯෆ໌ʹͳΔ͕ɺߏγϯϓϧʹอͯΔ
JOINͷඞཁͳιʔτ• A.belongs_to :b ͰBΛผαʔϏεʹΓग़͍͕ͨ͠ɺb.nameͰAΛιʔτ͢ΔAPI͕͋Δ߹• ࢮ͋ΔͷΈ• ͦͦͦΜͳΠϯλʔϑΣʔεΛ࡞ΔͷΛΊΖ• DBͷͷҰ؏ੑΛ͋Δఔ͖͋ΒΊɺb.nameͷίϐʔͰ͋Δa.b_nameΛੜͯ͠ϝϯς͢Δ͔͠ͳ͍• ྫ͑ιʔτʹa.b_nameΛ͏͕b.nameΛฦ͢ͳͲ͢Δɻͨ·ʹॱং͕͓͔͍͠ͷΛڐ༰Ͱ͖ͳ͍ͳΒΓग़͠ఘΊΔ
ؾܰʹղܾͰ͖ͳ͘ͳΔN+1• ActiveRecordͷΫΤϦΛAPIݺͼग़͠ʹͨ͠ॠؒincludes/preload/eager_load ͕͑ͣਏ͍• ઈରʹΊΑ͏: ࢥߟఀࢭΩϟογϡ• ී௨ʹidͷϦετΛऔͬͯฦ͢APIΛੜ͠ɺฦ͖ͬͯͨࢠϦιʔεΛϦιʔεͷΠϯελϯεมʹ২͑Δ͔ɺ{ Ϧιʔε => ࢠϦιʔε } ͳHashΛ࡞Δ• ͍͔ͬͯ͘͠ͳ͍͕ɺ͜ͷൺֱత؆୯ͳํ
ೝূೝՄͲ͏͢Δͷ• ී௨ʹ֎෦ʹݟ͑ͯΔ߹ී௨ʹೝূΛ࣮͢Ε͍͍͚ͩ• ෦Ͱୟ͘APIɺ֎෦͔Βୟ͚ͳ͍Α͏ʹ্ͨ͠Ͱɺཁ݅ʹΑͬͯϕʔγοΫͳೝূೝՄΛεΩοϓͰ͖Δ• ͕ɺΓग़͠ઌͷೝՄʹΓग़͠ݩͷϦιʔε͕ඞཁͳ߹ɺ͕Μͬͯ୲͠Γ͍͔ͯ͘͠͠ͳ͍• ʮେมͰ͢ΑͶɺ͜ΕʯҎ্ͷؾ࣋ͪಛʹͳ͍
࠷ߴͷղܾࡦ:ΈΜͳͰҰͭͷνʔϜʹͳΓશһ͕શͯΛϝϯςͰ͖ΔΑ͏ʹͳΓͦͦϚΠΫϩαʔϏεԽΛෆཁʹ͢Δ·͋ͦΕ͕Ͱ͖ͳ͍͔Β͜Μͳ໘ͳΛղܾ͠ͳ͍ͱ͍͚ͳ͍Θ͚Ͱ͢
5. ҆શʹσϓϩΠڥΛվળ͍ͯ͘͠
ةݥͳσϓϩΠڥΛվળ͍ͯͬͨ͠• ϚΠΫϩαʔϏεಛʹؔͳ͍͚Ͳʮ҆શ͔ͭߴʯʹॏཁͳ෦• ͲΜͳʹஸೡʹ࣮ͯ͠σϓϩΠڥ͕μϝͩͱ҆શʹߴʹਐΊΒΕͳ͍
ਓྨͷσϓϩΠͷจ໌ͷൃల• ssh + git pull σϓϩΠ (capistrano)• ΞʔΧΠϒΛpull͢ΔλΠϓͷσϓϩΠ• DockerίϯςφͷσϓϩΠ• ίϯςφΫϥελͷσϓϩΠ (ECS, k8s)
ਓྨͷσϓϩΠͷจ໌ͷൃల• ssh + git pull σϓϩΠ (capistrano)• ΞʔΧΠϒΛpull͢ΔλΠϓͷσϓϩΠ• DockerίϯςφͷσϓϩΠ• ίϯςφΫϥελͷσϓϩΠ (ECS, k8s)զʑݱࡏͲ͔ͬͪΛਐΊͯΔঢ়ଶ
ϚϧνΫϥυɺDockerԽʹੑೳͷ͋ΔHadoop=> CodeDeploy
ਓࡐ͕ෆ͍ͯ͠Δ͕ͣԿނ͔ཚཱ͢ΔσϓϩΠڥ
CI͕௨͍ͬͯͳͯ͘30ʹҰճChefͰσϓϩΠ͕Δ
CI͕௨͍ͬͯͳͯ͘30ʹҰճChefͰσϓϩΠ͕Δ=> CodeDeploy͔ΒmitamaeΛୟ͘k0kubun/mitamae-plugin-resource-deploy_revisionk0kubun/mitamae-plugin-resource-runitk0kubun/mitamae-plugin-recipe-buildpack
Ͳ͏ͬͯಈ͍ͯΔ͔શ͘Θ͔Βͳ͍heroku-buildpack
खಈͷఀࢭΦϖϨʔγϣϯԿ͕Ͳ͜ʹ͋Δ͔͙͢ࢥ͍ग़ͤͳ͘ͳΔrunit
खಈͷఀࢭΦϖϨʔγϣϯԿ͕Ͳ͜ʹ͋Δ͔͙͢ࢥ͍ग़ͤͳ͘ͳΔrunit=> ࣗಈఀࢭͰ͖Δsystemd service
gemͷόʔδϣϯΛ্͛ΔͱյΕΔ
gemͷόʔδϣϯΛ্͛ΔͱյΕΔ=> αʔϏεΠϯ/αʔϏεΞτԽ
We’re hiring
·ͱΊ• ͦ͜ͰΓग़͢ͷ͕ຊʹྑ͍ͷ͔Α͘ߟ͑·͠ΐ͏• ҠߦதϩʔΧϧͰΞϓϦΛ্ཱͪ͛ͯςετ͢Δͱ͍͏બࢶ༗ޮ• APIʹͳΔΑ͏ઃܭɺແҙຯͳϦτϥΠආ͚Δ• Γग़͠ʹ͓͚Δਏ͍ͱͦͷରԠํΛհ͠·ͨ͠• We’re hiring