Slide 1

Slide 1 text

2ॏϦΫΤετ׬શ߈ུHANDBOOK Shohei Mitani @ εϚʔτόϯΫ

Slide 2

Slide 2 text

2ॏϦΫΤετ • ޡͬͯෳ਺ճಉ͡ϦΫΤετ͕ૹΒΕɺॏෳͯ͠ॲཧ͕ߦΘΕͯ͠·͏͜ͱ • αϒϛοτϘλϯ͕2ճԡ͞Εͨ • ొ࿥ը໘͕Ϧϩʔυ͞Εͨ • ֎෦αʔϏε͔Βෳ਺ճಉ͡σʔλ͕ૹΒΕͨ • όον͕2ճ࣮ߦ͞Εͨ • 2ॏαϒϛοτͱ͍͏ݴ͍ํ΋͋Δ͕ɺWebϒϥ΢βҎ֎ʹ΋ى͜Γ͏Δ໰୊ Λѻ͍͍ͨͷͰ2ॏϦΫΤετͱݺͿ • 2ճҎ্ϦΫΤετ͢ΔଟॏϦΫΤετ΋2ॏϦΫΤετͱݺͿ͜ͱʹ͢Δ

Slide 3

Slide 3 text

΋͠2ॏϦΫΤετ͕ൃੜͨ͠Β…?? • ܝࣔ൘ʹಉ͡಺༰͕2ճ౤ߘ͞ΕΔ... • ಉ͡঎඼͕2ճߪೖ͞Εͯɺ2ॏͰ࢒ߴ͕ݮΔ͜ͱʹ… • ܾࡁ / ૹۚ / ༧໿ / ग़඼ / ౤ථ / ใु෇༩ / ਃ੥ / etc… • ѱ༻͞Εͯෆਖ਼߈ܸΛड͚ΔηΩϡϦςΟϗʔϧʹ… • Etc…

Slide 4

Slide 4 text

2ॏϦΫΤετͷରࡦ͸ҙ֎ͱ೉͍͠ • ΫϥΠΞϯτͰ੍ޚ͢Ε͹͍͍Μ͡Όͳ͍ͷ͔ʁ • ΫϦοΫ࿈ଧ / ϖʔδ࠶ಡΈࠐΈ / ໭Δˠ࠶ૹ৴ͳͲɺͲ͜·ͰରԠͰ͖Δʁ • ϒϥ΢βͷσϕϩούʔπʔϧͰૢ࡞͞ΕͨΒʁ • ෳ਺λϒʗෳ਺୺຤͔Βಉ࣌ʹૢ࡞͞Εͨ৔߹ʹͰ͖Δରࡦ͸ʁ • ֎෦αʔϏε͔Βͷࣗಈ࠶ૹͳͲɺΫϥΠΞϯτଆΛ੍ޚͰ͖ͳ͍৔߹ʹ͸ʁ • όοΫΤϯυͰςʔϒϧઃܭΛ্ख͘΍Ε͹େৎ෉Ͱ͠ΐ • ϢχʔΫ੍໿͕͚ͭΒΕͳ͔ͬͨΓɺϩοΫ͕औΕͳ͍ঢ়گ΋͋Δ • ҙਤͨ͠ෳ਺ճͷૢ࡞ͱɺࣄނతʹൃੜͨ͠2ॏϦΫΤετΛ൑ผͰ͖Δʁ

Slide 5

Slide 5 text

Θ͟Θ͟Kaigi on RailsͰൃද͢Δ΄Ͳʁ • WebͰݕࡧͯ͠ग़ͯ͘Δํ๏͸Webϒϥ΢βΛલఏͱ ͯ͠΋ͷ͕ଟ͍ • ʮJavaScritptͰʙʯʮ֬ೝμΠΞϩάग़ͯ͠ʙʯ • ʮઈରʹೋॏαϒϛοτΛڐ͞ͳ͍༑ͷձʯͷϒϩά͸Α ͘·ͱ·ͬͯΔ • ݱ࣮ͷΞϓϦέʔγϣϯ͸ෳࡶͰ৭ʑͳέʔε͕͋Δ • ຖճɺରࡦΛௐ΂ͨΓಠࣗʹฤΈग़͢͜ͱʹർΕͨ • ͜Ε͚ͩݟ͓͚ͯ͹େମΧόʔ͞ΕͯΔ΋ͷΛ࡞Γ͍ͨ https://qiita.com/unmelt/items/fb1eff5a2d9bc4da1f7e

Slide 6

Slide 6 text

ࠓ೔ͷൃදςʔϚ • ୭ʹͱͬͯ΋਎ۙͰॏཁͳ2ॏϦΫΤετ໰୊ʹ೰·ͳ͍͍ͯ͘ੈքΛ࡞Δ • 2ॏϦΫΤετͷ໰୊΁ͷཧղ • ༷ʑͳ2ॏϦΫΤετରࡦ΁ͷཧղ • ϢʔεέʔεʹԠͨ͡ϕετϓϥΫςΟεͷ୳ࡧ • ྩ࿨7೥࣌఺Ͱͷ৘ใΛ·ͱΊͨHANDBOOKΛఏڙ • ۀ຿Ͱૺ۰ͨ࣌͠ʹݟฦͤΔࢿྉͱͳΕ͹޾͍ • ଞʹ΋͜͏͍͏ͷ͋ΔΑʂͬͯํ๏͋Ε͹ڭ͍͑ͯͩ͘͞🙌 • ݸʑͷରࡦͷৄࡉ͸ׂѪ͠·͢

Slide 7

Slide 7 text

ࣗݾ঺հ ࡾ୩ ণฏ Έͨʹ ͠ΐ͏΁͍ εϚʔτόϯΫ Engineering Manager / Software Engineer • SIer → Fablic → ָఱ → εϚʔτόϯΫ • ΤϯδχΞྺ11೥໨ɺRailsྺ7೥໨ • Welcome Fintech Community ӡӦ

Slide 8

Slide 8 text

೔ৗͰ࢖͍ͬͯΔαʔϏεͷཪଆΛެ։Մೳͳܗʹམͱ͠ࠐΜͰൃද͢Δͷ͕޷͖ builderscon 2024 YAPC::Hiroshima 2024 YAPC::Fukuoka 2025 eKYC Χʔυܾࡁ ڝഅ x ػցֶश χον͗ͯ͢ڵຯ࣋ͨΕͳ͍? ެ։͢Δͱڝ߹༏Ґੑࣦ͏? ڪΕͣൃද͢Δ͜ͱͰಘΒΕΔ͜ͱ͸ଟ͍

Slide 9

Slide 9 text

ࠓ೔͸ͬͪ͜ͷ࿩ Kaigi on Rails 2022 Kaigi on Rails 2021 Kaigi on Rails 2023 ։ൃݱ৔Ͱͷ࣮ઓ஌Λந৅Խɾ൚༻తֶͯ͠ͼʹม͍͑ͯ͘׆ಈ΋޷͖ ؂ࢹ ঢ়ଶ؅ཧ ςʔϒϧఆٛมߋ

Slide 10

Slide 10 text

2ॏϦΫΤετ΁ͷ๷ޚࡦ

Slide 11

Slide 11 text

લఏ͢Γ߹Θͤʙ঺հ͢Δ๷ޚࡦͷείʔϓʙ • POST / PUT / DELETE౳ͷߋ৽ܥૢ࡞Λத৺ʹѻ͏ʢGET΁ͷԠ༻͸Մʣ • ૹ৴ऀଆʹѱҙ͸ͳ͍͕ࣄނతʹ2ॏϦΫΤετ͕ൃੜ͢Δ໰୊΁ͷ๷ޚࡦ • αϒϛοτϘλϯ͕Կ౓΋ԡͤΔ౳ͷ࣮૷࿙Ε • όοΫΤϯυͰͷλΠϜΞ΢τʹΑΓɺΫϥΠΞϯτ͔Β࠶ૢ࡞͕Ͱ͖Δέʔε • ૹ৴ऀଆ͕ѱҙΛ࣋ͬͯ2ॏϦΫΤετΛߦ͏Α͏ͳ໰୊΁ͷ๷ޚࡦ • ੬ऑੑΛಥ͍ͨϦϓϨΠ߈ܸ / ෳ਺୺຤Ͱͷಉ࣌ૢ࡞ • ࢓༷ͱͯ͠ಉ͡಺༰ͷૢ࡞͕ڐ༰͞Ε͍ͯΔέʔεͱͷ۠ผ͢Δํ๏ • ಉҰ঎඼ͷߪೖ / ࿈౤౤ߘ

Slide 12

Slide 12 text

ෳ਺ͷ๷ޚ໢Ͱߟ͑Δ 📱 🐟 ΫϥΠΞϯτଆ ๷ޚࡦͷҹ όοΫΤϯυଆ ๷ޚࡦͷҹ

Slide 13

Slide 13 text

ᶃ αϒϛοτϘλϯͷ੍ޚ ᶄ Post-Redirect-Get (PRG) ύλʔϯ ᶅ ഉଞ੍ޚ • Ϧιʔεͷ൵؍ϩοΫ • FIFOʹΑΔॱং੍ޚ • ΞυόΠβϦʔϩοΫ ᶆ ςʔϒϧઃܭ • ঢ়ଶભҠͷϧʔϧԽ • ϢχʔΫ੍໿ ࠓ೔঺հ͢Δ๷ޚࡦͨͪ ᶇ ϨʔτϦϛοτ ᶈ APIΩϟογϡ ᶉ Idempotency-Keyϔομ ᶊ ETag ʴ If-Match ᶋ ϫϯλΠϜτʔΫϯ

Slide 14

Slide 14 text

ᶃ αϒϛοτϘλϯͷ੍ޚ • ࠷΋جຊతͰ࠷ॳʹ஌ΔͰ͋Δ2ॏϦΫΤετ Λ๷͙ํ๏ • ϘλϯΛԡͨ͠Β׬ྃ͢Δ·Ͱඇ׆ੑԽ͢Δ • ΍Βͳ͍ͱ͍͏બ୒ࢶ͸ͳͦ͞͏ʢ?ʣ • ॲཧঢ়ଶΛอ͓͖࣋ͯ͠ɺॲཧதʹૢ࡞͞Εͨ ৔߹ʹϝοηʔδΛදࣔ͢Δ͜ͱ΋Մೳ 📱

Slide 15

Slide 15 text

• ϒϥ΢βͷϦϩʔυʹΑΔ2ॏϦΫΤετΛ๷͙ํ๏ • POSTϦΫΤετͷ׬ྃ࣌ɺ௚઀HTMLΛฦ٫͢ΔͷͰ͸ͳ ͘ɺ݁Ռදࣔϖʔδ΁ϦμΠϨΫτ͢ΔϨεϙϯεΛฦ͢ • ॲཧ׬ྃޙʹϒϥ΢βͰϦϩʔυΛͯ͠΋ɺϦμΠϨΫτઌ΁ ͷGETॲཧͱͳΔͨΊɺݩͷPOSTॲཧͷ2ॏϦΫΤετ͕ى ͖ͳ͍ • ໭ΔϘλϯͰલը໘ʹ໭͔ͬͯΒɺ΋͏Ұ౓αϒϛοτϘλ ϯΛԡ͞ΕΔέʔεʹ͸ແྗͳͷͰɺผରࡦ͕ඞཁ ᶄ Post-Redirect-Get (PRG) ύλʔϯ ΫϥΠΞϯτ αʔόʔ POST REDIRECT GETʢ݁Ռը໘ʣ HTML ϦϩʔυʢGETʣ 🐟

Slide 16

Slide 16 text

ᶅ ഉଞ੍ޚ • ͋ΔϓϩηεͷΈ͕ϦιʔεͷΞΫηεݖΛಠ઎͢Δ͜ͱͰɺ ಉ࣌ʹૢ࡞Ͱ͖ΔϓϩηεΛҰͭʹ੍ݶ͢Δ࢓૊Έ • 2ॏϦΫΤετ͕ൃੜͯ͠΋αʔόʔଆͰ҆શʹॲཧͯ͠๷ޚ ͢Δํ๏ • ಉ࣌ʹಉ͡ϦιʔεΛૢ࡞͢Δͱσʔλͷෆ੔߹͕ى͖΍͍͢ • ϩετΞοϓσʔτ౳ͷ໰୊ • ಉ࣮࣌ߦΛ๷͙͜ͱͰɺॲཧ಺෦Ͱߟྀ͠ͳ͚Ε͹ͳΒͳ͍͜ͱ͕ ݮΒͤΔ 🐟 Table READ BLOCK READ

Slide 17

Slide 17 text

ᶅ ഉଞ੍ޚʙϦιʔεͷ൵؍తϩοΫʙ • RDBΛར༻͍ͯ͠Δ৔߹ʹ࠷΋؆୯ʹར༻Ͱ͖Δͷ͸൵؍తϩοΫ • User. fi nd(1).with_lock { … } • ૢ࡞ର৅ʹରͯ͠ɺద੾ͳϩοΫΛऔΕΔϦιʔε͕ଘࡏ͠ͳ͍৔߹΋͋Δ • ΞυόΠβϦʔϩοΫͷར༻ʢMySQL: GET _LOCK / PostgreSQL: pg_advisory_lockʣ • ActiveRecord::Base.connection.get_advisory_lock(“UserID#{user_id}:Payment”) • ϩοΫઐ༻ͷςʔϒϧ΍RedisΛ࢖͏౳ߟ͑ΒΕΔ • ඇಉظతʹॲཧΛͯ͠ྑ͍৔߹ʹ͸FIFOΩϡʔΛ࢖͏͜ͱ΋ • FIFOʢFirst-in, First-outʣͷΩϡʔΛ࢖͏͜ͱͰɺΩϡʔ୯ҐͰॱ൪ʹॲཧ͕ߦΘΕΔ ͨΊɺϩοΫΛऔಘͨ࣌͠ͱಉ͡Α͏ʹഉଞ੍ޚ͞ΕΔ 🐟

Slide 18

Slide 18 text

ᶅ ഉଞ੍ޚʙ஫ҙ఺ʙ • ഉଞ੍ޚ͸ಉ࣌ʹૢ࡞͞ΕΔ͜ͱΛ๷͍Ͱ͍Δ͚ͩͳͷͰɺϩοΫղ์͞Εͨ ޙͷॲཧ΁ͷରԠ͸ผ్ߟ͑Δඞཁ͕͋Δ • ଈ࣌Τϥʔʹ͢ΔͳΒ : User. fi nd(1).with_lock(“FOR UPDATE NOWAIT”) { … } • ଈ࠲Τϥʔ΋ɺಉ࣌ʹϩοΫΛऔಘͨ͠৔߹ʹݶΔͷͰɺλΠϜϥά͕͋ͬͯ2ॏϦΫ Τετ͕དྷͨ࣌ͷ͜ͱΛߟ͑Δඞཁ͕͋Δ • ϩοΫͷऔಘൣғʹ͸஫ҙ͕ඞཁ • 2ॏϦΫΤετΛ๷͍͗ͨAPIҎ֎ͰϩοΫղ์଴͕ͪൃੜ͠ɺϨεϙϯελΠϜ͕ѱ Խ͢Δͷ͸͋Δ͋Δͳ໰୊ 🐟

Slide 19

Slide 19 text

ᶆ ςʔϒϧઃܭ • 2ॏϦΫΤετ͕ൃੜͯ͠΋σʔλͷ੔߹ੑΛอͯΔΑ͏ςʔϒϧઃܭ͓ͯ͘͠ ͜ͱͰ๷ޚ͢Δํ๏ • ഉଞ੍ޚͱҟͳΓɺಉ࣌ʹϦΫΤετ͕དྷͳ͍έʔεͰ͋ͬͯ΋ɺ͋Δ΂͖σʔλͷ ͕࢟อͨΕΔΑ͏ʹ͢Δ • ςʔϒϧઃܭͷํ๏͸ଟछଟ༷ʹ͋ΓɺશͯΛ঺հ͢Δ͜ͱ͸Ͱ͖ͳ͍ͷͰɺ ݸਓతʹΑ͘࢖͏ํ๏Λ2ͭ঺հ 🐟

Slide 20

Slide 20 text

ᶆ ςʔϒϧઃܭʙঢ়ଶભҠͷϧʔϧԽʙ • ঢ়ଶؒͷભҠϧʔϧΛఆٛ͢Δ͜ͱͰɺ2ॏϦΫΤετ Λड͚औͬͨࡍʹঢ়ଶભҠΤϥʔΛൃੜͤ͞Δ • ӈͷྫͩͱɺ஫จঢ়ଶͱ͍͏ENUMͷΧϥϜʹঢ়ଶભ ҠͷϧʔϧΛఆٛ͢Δ • ʮΩϟϯηϧঢ়ଶ͸஫จঢ়ଶ͔Β͔͠ભҠͰ͖ͳ͍ʯ • ʮ੥ٻঢ়ଶ͸஫จঢ়ଶ͔Β͔͠ભҠͰ͖ͳ͍ʯ • ʮൃૹঢ়ଶ͸੥ٻঢ়ଶ͔Β͔͠ભҠͰ͖ͳ͍ʯ • RailsͩͱAASMͷgem͕͋Δ 🐟

Slide 21

Slide 21 text

ᶆ ςʔϒϧઃܭʙϢχʔΫ੍໿ʙ • ϢχʔΫ੍໿Λ͚ͭΔ͜ͱͰɺ2ॏϦΫΤετ Λड͚औͬͨࡍʹঢ়ଶભҠΤϥʔΛൃੜͤ͞Δ • ӈͷྫͩͱɺ஫จͷঢ়ଶຖʹςʔϒϧΛ෼ׂ ͠ɺ஫จIDʹϢχʔΫ੍໿ʢUQʣΛ͚ͭΔ • ΠϛϡʔλϒϧσʔλϞσϧ • https://scrapbox.io/kawasima/ΠϛϡʔλϒϧσʔλϞσϧ 🐟

Slide 22

Slide 22 text

ঢ়ଶભҠͷϧʔϧԽ vs ϢχʔΫ੍໿ • ঢ়ଶભҠͷϧʔϧԽͰ͸ɺϩετΞοϓσʔτ΁ͷ஫ҙ͕ඞཁ • ผτϥϯβΫγϣϯͷ಺༰͕ಡΈऔΕͳ͍ͨΊɺӈਤͩͱ੥ٻ → ੥ٻ΁ͷঢ়ଶมߋΛNGͱ͢ΔΑ͏ͳϧʔϧ͸͢Γൈ͚ΒΕΔ • τϥϯβΫγϣϯΛషΔ৔߹ʹ͸ഉଞ੍ޚͱηοτͰߟ͑Δ΂͖ • ޙ͔Βॲཧͨ͠಺༰Ͱ্ॻ͖ͯ͠໰୊ͳ͍࢓༷Ͱ͋Ε͹ෆཁ • ϢχʔΫ੍໿ͷ৔߹ɺτϥϯβΫγϣϯΛίϛοτͨ͠λΠϛ ϯάͰΤϥʔ͕ൃੜ͢ΔͨΊɺϩοΫ͸ෆཁͳར఺͕͋Δ • σʔλϕʔεͷ੍໿͸ศར TRN1 TRN2 *%  ঢ়ଶ ஫จ ೔࣌ ࣌෼ Table Table Table *%  ঢ়ଶ ੥ٻ ೔࣌ ࣌෼ *%  ঢ়ଶ ੥ٻ ೔࣌ ࣌෼ 🐟

Slide 23

Slide 23 text

ᶇ ϨʔτϦϛοτ • ഉଞ੍ޚ / ঢ়ଶભҠͷϧʔϧԽ / ϢχʔΫ੍໿͸͍ͣΕ΋ΞϓϦέʔγϣϯ಺Ͱσʔλ ͷ੔߹ੑΛอͭͨΊͷΞϓϩʔν • ΫϨδοτΧʔυʹਃ͠ࠐΉͳͲɺݱ࣮ͱͯ͠ࢦఆظؒʹෳ਺ૢ࡞͞Εͳ͍ͱ࢓্ׂ༷ Γ੾ΕΔػೳͰ͋Ε͹ɺΑΓ্ҐϨΠϠʔͰͷ๷ޚ͕Մೳ • ϨʔτϦϛοτ : γεςϜ΁ͷա౓ͳෛՙΛ๷͙ͨΊʹɺҰఆظؒ಺ʹॲཧͰ͖Δ ϦΫΤετ΍τϥϑΟοΫͷྔΛ੍ݶ͢Δख๏ͷ͜ͱ • ϢʔβʔIDͳͲΛΩʔʹAPIʹϨʔτϦϛοτΛಋೖ͠ɺҰఆظؒ͸1ճ͔͠ϦΫΤε τͰ͖ͳ͍Α͏ʹ͢Δ౳ 🐟

Slide 24

Slide 24 text

ϨʔτϦϛοτͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'/PU&YJTU  ঎඼ͷϩοΫ  ߪೖঢ়ଶ΁ͷมߋ  &UDʜ σʔλετΞ 🎁ߪೖ׬ྃ 🐟 1045QBZNFOUT nJUFN@JEJUFN@ 1BZNFOUJUFN $IFDL 63-1045QBZNFOUT *UFN*%JUFN@ 4BWF 63-1045QBZNFOUT *UFN*%JUFN@ 55-

Slide 25

Slide 25 text

ϨʔτϦϛοτͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ σʔλετΞ 🐟 1045QBZNFOUT nJUFN@JEJUFN@ ❌'PSCJEEFO $IFDL 63-1045QBZNFOUT *UFN*%JUFN@ 💀ߪೖࣦഊ ⚙*'&YJTU$PVOU  Τϥʔॲཧ

Slide 26

Slide 26 text

• Amazon API GatewayͳͲͷඪ४ػೳʢεϩοτϦϯάʣΛར༻͢Δ͜ͱ΋Մೳ • εϩοτϦϯάͷద༻ൣғʢϦʔδϣϯ / APIΩʔ/ϝιουʣͷઃܭ࣍ୈ • ྫ: toB޲͚αʔϏεͷΫϥΠΞϯτຖʹAPI KeyΛൃߦ͠ɺͦͷKeyϨϕϧͰಛఆ ΤϯυϙΠϯτͷϦΫΤετΛ1ճʹߜΔͳͲ • ࡉ͔͍୯ҐͰ੍ޚ͕ඞཁͳ৔߹͸ࣗલߏங͢Δඞཁ͋Γ • rack-attack gem / throttling gem ͋ͨΓ͕ࢀߟʹͳΔ͔΋ • Rails 8͔Βඪ४ͰϨʔτϦϛοτͷػೳ͕ೖͬͨ ϨʔτϦϛοτͷิ଍ 🐟

Slide 27

Slide 27 text

ᶈ APIΩϟογϡ • Ұ౓ड͚෇͚ͨϦΫΤετͷϨεϙϯεΛอଘ͓͍ͯͯ͠ɺಉҰϦΫΤετ͕ དྷͨ৔߹ʹ͸Ωϟογϡͨ͠ϨεϙϯεΛฦ٫͢Δ͜ͱͰႈ౳ੑΛ୲อ͢ΔΞ ϓϩʔν • ΫϥΠΞϯτଆ͔ΒݟΔͱ2ॏͰૹ৴ͨ͠ࡍɺͲͪΒ΋੒ޭѻ͍ͱͯ͠ϋϯυϦϯά Ͱ͖ΔʢϨʔτϦϛοτͱͷҧ͍ʣ • Amazon API GatewayͳͲͷػೳΛར༻͢Δ͜ͱʹΑΓɺΞϓϦέʔγϣϯͷ ֎ଆͰ2ॏϦΫΤετΛ๷ޚ͢Δ͜ͱ͕Մೳ 🐟

Slide 28

Slide 28 text

APIΩϟογϡͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'/PU&YJTU  ঎඼ͷϩοΫ  ߪೖঢ়ଶ΁ͷมߋ  &UDʜ σʔλετΞ 🎁ߪೖ׬ྃ 🐟 1045QBZNFOUTJUFN@ 1BZNFOUJUFN $IFDL ,FZ1045QBZNFOUTJUFN@ 4BWF ,FZ1045QBZNFOUTJUFN@ 3FTQPOTF#PEZYYYY 55-

Slide 29

Slide 29 text

APIΩϟογϡͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'&YJTU  3FTQPOTF#PEZͷऔಘ σʔλετΞ 🎁ߪೖ׬ྃ 🐟 1045QBZNFOUTJUFN@ 1BZNFOUJUFN DBDIFE $IFDL ,FZ1045QBZNFOUTJUFN@

Slide 30

Slide 30 text

• ΩϟογϡΛ࢖͏͜ͱͷҰൠతͳࠔ೉͞ʹཱͪ޲͔͏ඞཁ͕͋Δ • ΩϟογϡͷKeyΛͲ͏͢Δ͔ʁ • ΩϟογϡͷTTLΛͲ͏͢Δ͔ʁ • ΩϟογϡͰ͖ΔαΠζͷݶք஋ • GET͸·ͩ͠΋ɺPOSTܥͷAPIΛΩϟογϡͯ͠ྑ͍ͷ͔ʁ • Ωϟογϡ͕อଘ͞ΕΔ·Ͱͷؒʹൃੜ͢Δ2ॏϦΫΤετ͸ແྗ APIΩϟογϡͷิ଍ 🐟

Slide 31

Slide 31 text

• ΫϥΠΞϯτ͕ϦΫΤετΛҰҙʹࣝผͰ͖Δ৘ใʢIdempotency KeyʣΛ HTTPϔομʹ෇༩͢Δ͜ͱʹΑΓႈ౳ͳAPIΛߏங͢ΔΞϓϩʔν ᶉ Idempotency-Keyϔομ 🐟 📱 https://speakerdeck.com/ohbarye/safe-retry-with-idempotency-key-header https://speakerdeck.com/ohbarye/my-favorite-protocol-idempotency-key-header

Slide 32

Slide 32 text

Idempotency-Keyϔομͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'/PU&YJTU  ঎඼ͷϩοΫ  ߪೖঢ়ଶ΁ͷมߋ  &UDʜ σʔλετΞ 🎁ߪೖ׬ྃ 1045QBZNFOUT nJUFN@JEJUFN@= )t*EFNQPUFODZ,FZYZ[u 1BZNFOUJUFN $IFDL ,FZYZ[ 4BWF ,FZYZ[ 3FTQPOTF#PEZYYYY 55- 🐟 📱 🪏,FZ࠾൪

Slide 33

Slide 33 text

Idempotency-Keyϔομͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'&YJTU  3FTQPOTF#PEZͷऔಘ σʔλετΞ 🎁ߪೖ׬ྃ 1BZNFOUJUFN DBDIFE 🐟 📱 1045QBZNFOUT nJUFN@JEJUFN@= )t*EFNQPUFODZ,FZYZ[u 🪏,FZ࠾൪ $IFDL ,FZYZ[

Slide 34

Slide 34 text

APIΩϟογϡ vs Idempotency-Keyϔομ • Idempotency Keyϔομ͸APIΩϟογϡΑΓෳࡶ͕Ώ͑ʹॊೈ͔ͭݎ࿚ʹႈ౳ͳAPIαʔ όʔΛ࡞ΕΔ • ΫϥΠΞϯτ͕஋Λ࠾൪ͯ͠ઃఆ͢ΔͨΊɺႈ౳ͷൣғ͕APIΩϟογϡΑΓ΋ݫີ • ಉҰ୺຤Ͱͷૢ࡞Λ൑ผ͢Δ͜ͱ͕Ͱ͖Δ • ಉҰ୺຤ͰͷϦτϥΠૢ࡞ͱɺ1͔Βͷ΍Γ௚͠ͷૢ࡞΋൑ผͰ͖Δ • ະॲཧ / ॲཧத / ॲཧࡁΈͱࡉ͔͘ॲཧεςʔλεΛ؅ཧͰ͖Δ • ةݥͳߋ৽ܥͷૢ࡞ʹରͯ͠΋҆શʹႈ౳ੑΛ࣋ͨͤΔͨΊʹ͸ɺAPIΩϟογϡΑΓ΋ Idempotency-Keyϔομͷํ͕༏Ε͍ͯΔ • ෭࡞༻͕গͳ͍؆қతͳૢ࡞Ͱ͋Ε͹APIΩϟογϡͰे෼ͳέʔε΋ 🐟 📱

Slide 35

Slide 35 text

ᶊ ETag ʴ If-Match • ETagʢEntity Tagʣͱ͍͏ߋ৽ର৅ͷόʔδϣϯΛλά؅ ཧ͠ɺIf-MatchϔομͰ৚݅෇͖ߋ৽ϦΫΤετΛૹΔ͜ ͱͰ2ॏϦΫΤετΛ๷͙ํ๏ʢָ؍తϩοΫʣ • αʔόʔଆͰ͸ɺΫϥΠΞϯτ͔ΒૹΒΕͨETagͷ஋Λ ൺֱ͠ɺόʔδϣϯ͕Ұகͨ͠ΒॲཧΛߦ͍ɺෆҰகͷ৔ ߹ʹ͸412 Precondition FailedΛฦ٫͢Δ • ӈͷྫͩͱόʔδϣϯΧϥϜΛETagͱͯ͠ར༻͢Δ͜ͱ΋ Ͱ͖Δ͠ɺ಺༰ͷtext͔ΒHash஋ΛٻΊͯETagͱ͢Δ͜ ͱ΋Մೳ 🐟 📱

Slide 36

Slide 36 text

ETag ʴ If-Matchͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'7FSTJPO.BUDI  ঎඼ͷϩοΫ  &UDʜ σʔλετΞ 🎁ߪೖ׬ྃ 1045QBZNFOUT nJUFN@JEJUFN@= )t*G.BUDIu 1BZNFOUJUFN (FU*UFN 7FSTJPO 🐟 📱 (&5JUFNTJUFN@ &5BH 6QEBUF*UFN 7FSTJPO $IFDL $VSSFOU7FSTJPO

Slide 37

Slide 37 text

ETag ʴ If-Matchͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'7FSTJPO/PU.BUDI  Τϥʔॲཧ σʔλετΞ 1045QBZNFOUT nJUFN@JEJUFN@= )t*G.BUDIu ❌1SFDPOEJUJPO'BJMFE (FU*UFN 7FSTJPO 🐟 📱 (&5JUFNTJUFN@ &5BH $IFDL $VSSFOU7FSTJPO 💀ߪೖࣦഊ

Slide 38

Slide 38 text

• ָ؍తϩοΫͰ๷͍Ͱ͍Δํ๏ͳͨΊɺมߋ͞Ε΍͍͢Ϧιʔε΁ͷಋೖʹ͸ෆ޲͖ • ྫ͑͹ECαΠτͷ঎඼ߪೖͳͲɺෳ਺ਓ͕ಉ࣌ߪೖ͢Δέʔεʹ͸޲͍͍ͯͳ͍ • ϢʔβʔͷϓϩϑΟʔϧߋ৽ͳͲɺ1ਓ͔͠ฤू͠ͳ͍έʔεʹ޲͍͍ͯΔ • ΫϥΠΞϯτ͕ϔομΛ෇༩͢Δ͜ͱͰ2ॏϦΫΤετ΁ͷରࡦΛ͍ͯ͠Δ఺Ͱ ͸Idempotency-Keyϔομͱಉ͕ͩ͡ɺ໨తʹҧ͍͕͋Δ • Idempotency-Key : ϔομͷKey৘ใΛ࢖ͬͯɺႈ౳ͳAPIΛఏڙ͢Δ • ETag ʴ If-Match : ָ؍తϩοΫͰҟͳΔΫϥΠΞϯτؒͰͷಉ࣌ߋ৽Λ๷͙ ETag ʴ If-Matchͷิ଍ 🐟 📱

Slide 39

Slide 39 text

• 1౓ͷΈ࢖༻ՄೳͳτʔΫϯΛൃߦ͢Δ͜ͱͰ2ॏϦΫΤετΛ๷͙Ξϓϩʔν • 2ॏϦΫΤετͷ໨తҎ֎ʹɺਖ਼౰ͳϦΫΤετͰ͋Δ͜ͱΛอূͯ͠վ͟Μ౳Λ๷͍ ͩΓɺ༗ޮظݶΛઃ͚Δ͜ͱͰΑΓηΩϡΞʹ͢ΔͳͲෆਖ਼ରࡦ໨తͰ΋࢖ΘΕΔ • τϥϯβΫγϣϯτʔΫϯνΣοΫͱ͍͏ݴ༿Ͱ঺հ͞ΕΔ͜ͱ΋ • CSRFτʔΫϯ΋τʔΫϯΛ࢖ͬͯϦΫΤετΛνΣοΫ͍ͯ͠ΔͷͰࣅ͍ͯΔ͕ɺ CSRFରࡦͷจ຺Ͱ͸τʔΫϯ͕ϫϯλΠϜͰ͋Δ͜ͱ͸ඞਢͰ͸ͳ͍ ᶋ ϫϯλΠϜτʔΫϯ 🐟 📱

Slide 40

Slide 40 text

ϫϯλΠϜτʔΫϯͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'5PLFOJT7BMJE  ঎඼ͷϩοΫ  &UDʜ σʔλετΞ 🎁ߪೖ׬ྃ 1045QBZNFOUT nJUFN@JEJUFN@= nUPLFOYZ[ 1BZNFOUJUFN *TTVF UPLFOYZ[ 🐟 📱 1045UPLFOT 5PLFOYZ[ %FMFUF5PLFO $IFDL UPLFOYZ[

Slide 41

Slide 41 text

ϫϯλΠϜτʔΫϯͷϑϩʔ 📱ΫϥΠΞϯτ 🐟αʔόʔ ⚙*'5PLFOJT*OWBMJE  Τϥʔॲཧ σʔλετΞ 1045QBZNFOUT nJUFN@JEJUFN@= nUPLFOYZ[ ❌'PSCJEEFO *TTVF UPLFOYZ[ 🐟 📱 1045UPLFOT 5PLFOYZ[ %FMFUF5PLFO $IFDL UPLFOYZ[ 💀ߪೖࣦഊ

Slide 42

Slide 42 text

๷ޚࡦͷ·ͱΊ

Slide 43

Slide 43 text

ᶃ αϒϛοτϘλϯͷ੍ޚ ᶄ Post-Redirect-Get (PRG) ύλʔϯ ᶅ ഉଞ੍ޚ • Ϧιʔεͷ൵؍ϩοΫ • FIFOʹΑΔॱং੍ޚ • ΞυόΠβϦʔϩοΫ ᶆ ςʔϒϧઃܭ • ঢ়ଶભҠͷϧʔϧԽ • ϢχʔΫ੍໿ ঺հͨ͠๷ޚࡦͨͪ ᶇ ϨʔτϦϛοτ ᶈ APIΩϟογϡ ᶉ Idempotency-Keyϔομ ᶊ ETag ʴ If-Match ᶋ ϫϯλΠϜτʔΫϯ

Slide 44

Slide 44 text

αϒϛοτϘλϯͷ੍ޚ ๷ޚࡦͷάϧʔϐϯά Idempotency-Keyϔομ ETag ʴ If-Match ϫϯλΠϜτʔΫϯ ΫϥΠΞϯτͰͷ๷ޚࡦ ΫϥΠΞϯτͱόοΫΤϯυͰͷ๷ޚࡦ όοΫΤϯυͰͷ๷ޚࡦ Post-Redirect-Get (PRG) ύλʔϯ ഉଞ੍ޚ ςʔϒϧઃܭ ϨʔτϦϛοτ APIΩϟογϡ 🐟 📱 🐟 📱

Slide 45

Slide 45 text

ൃදऀͷߟ͑ • جຊ͸αϒϛοτϘλϯͷ੍ޚ / PRGύλʔϯ / ഉଞ੍ޚ + ςʔϒϧઃܭΛߦ ͳ͍ͬͯΕ͹े෼ͳέʔε͕ଟ͍ • σʔλͷ੔߹ੑ͕֬อ͞ΕΔΑ͏ςʔϒϧઃܭΛ͍ͯ͠Ε͹க໋తͳ໰୊͸ى͖ͳ͍ • 2ॏϦΫΤετࣗମɺશମͷϦΫΤετ͔ΒݟΔͱΤοδέʔεʹ౰ͨΔͷͰɺ2ॏϦ ΫΤετ͕ൃੜͨ͠ࡍͷඃ֐΍ಘΒΕΔϝϦοτΛ૝ఆͯ͠ɺద੾ͳΞϓϩʔνΛબ ୒͢΂͖ • ϫϯόϯΫͰ࣮ࡍʹར༻͍ͯ͠Δ๷ޚࡦΛཧ༝ͱͱ΋ʹ঺հ

Slide 46

Slide 46 text

ϓϦϖΠυΧʔυ / ೖۚ / ग़ۚ Citadel / ֎෦αʔϏεґଘ

Slide 47

Slide 47 text

Idempotency-Keyϔομ • ΫϥΠΞϯτଆͰ࠾൪ͨ͠KeyΛ࢖ͬͯႈ౳ͳAPIΛߏங ͢Δํ๏ • ֎෦αʔϏε΁ͷॏཁͳૢ࡞Λߦ͏ॲཧͰଟ͘ར༻ • ίϯϏχ / ϖΠδʔͳͲͷೖۚ৘ใΛൃߦ͢Δॲཧ • ΫϨδοτΧʔυೖۚΛ͢Δࡍͷ3DSೝূॲཧ • ۜߦޱ࠲͔ΒҾ͖མͱ͠ॲཧ

Slide 48

Slide 48 text

Idempotency-Keyϔομ • ֎෦αʔϏεͱͷ࿈ܞॲཧ͸ෳࡶʹͳΓ͕ͪ • ෳ਺ͷDB τϥϯβΫγϣϯ͕ඞཁͰഉଞ੍ޚ͕ෳࡶʹͳΔ • ࣗαʔϏεଆͱ֎෦αʔϏεଆͷ྆ํͰσʔλෆ੔߹͕ൃ ੜ͢ΔՄೳੑ͕͋ΓɺϦΧόϦॲཧ͕େม • Idempotency-KeyϔομΛར༻ͯ͠ຊॲཧͷલஈͰ2ॏ ϦΫΤετ΁ͷରࡦΛߦ͏͜ͱͰɺσʔλෆ੔߹͕ൃ ੜ͢ΔϦεΫΛݮΒ͢͜ͱ͕Ͱ͖Δ ֎෦αʔϏε ݺͼग़͠ લॲཧ τϥϯβΫγϣϯ ޙॲཧ τϥϯβΫγϣϯ ֎෦αʔϏεݺͼग़͠ॲཧ Idempotency-Key ϔομʹΑΔ๷ޚ

Slide 49

Slide 49 text

Idempotency-Keyϔομ • ࣄނతͳ2ॏϦΫΤετͱҙਤతͳผϦΫΤετΛ۠ผ͢Δ͜ͱ͕Ͱ͖Δͷ΋ັྗత • ྫ͑͹ϓϦϖΠυΧʔυ΁ͷೖۚॲཧ͸୹࣌ؒͰෳ਺ճߦΘΕͯ΋͓͔͘͠ͳ͍ • Key͕ಉ͡ = ࣄނతͳϦΫΤετɺKey͕ҟͳΔ = ҙਤతͳϦΫΤετͱ۠ผͰ͖Δ • ҰํɺKeyͷνΣοΫॲཧ΍ొ࿥ॲཧͳͲͷΦʔόʔϔου͕૿͑ͨΓɺΫϥΠΞϯτଆ ͰͷKey࠾൪ॲཧͷ࣮૷ͳͲ࣮૷ίετ͕͔͔ΔͨΊɺಋೖՕॴ͸ݶఆత

Slide 50

Slide 50 text

ϫϯλΠϜτʔΫϯ • ΞϓϦͷதͰ΋ಛʹॏཁͳॲཧͰ࢖༻ • ύείʔυͷొ࿥ / ࠶ઃఆ • Χʔυ൪߸ͷදࣔ • ͋ͱ͹Β͍νϟʔδ΍ۜߦޱ࠲Ҿ͖མͱ͠ͳͲͷೖۚ ॲཧ

Slide 51

Slide 51 text

ϫϯλΠϜτʔΫϯ • Ϣʔβʔͷࣄނతͳ2ॏϦΫΤετΛ๷ࢭ͢Δ໨తͰ͸ͳ͘ɺϦΫΤετ಺༰ͷ౪ௌͳͲ ʹΑΔϦϓϨΠ߈ܸΛ๷͙໨తͷͨΊʹ࢖༻ • ϦϓϨΠ߈ܸ : αΠόʔ߈ܸͷҰछͰɺ௨৴ͰҰ౓ૹ৴͞Εͨਖ਼نͷσʔλΛ๣ड͠ɺͦ ͷ··࠶ૹ৴͢Δ͜ͱͰɺෆਖ਼ͳಈ࡞Λ༠ൃ͢Δ߈ܸ • ೖۚॲཧ͕౪ௌ͞ΕͯԿ౓΋ෆਖ਼ೖۚ͞ΕΔͳͲͷ߈ܸΛ๷͙ • ࣄނతͳ2ॏϦΫΤετΛ๷͙ͨΊɺIdempotency-Keyϔομͱ૊Έ߹Θ࣮ͤͯ૷͍ͯ͠ ΔAPI΋ଟ͍ • τʔΫϯऔಘϑϩʔͳͲ࣮૷ίετ΍ɺϢʔβʔͷख͕ؒൃੜ͢Δํ๏ͳͷͰɺ࣮૷Օॴ ͸ηΩϡϦςΟڧ౓Λ্͍͛ͨՕॴͷΈ

Slide 52

Slide 52 text

ϨʔτϦϛοτ • όʔνϟϧΧʔυͱ͍͏෺ཧతͳΧʔυ͸ൃߦ͞ΕͣΧʔυ ൪߸͚ͩೖखͰ͖ΔػೳͷൃߦॲཧͰར༻ • όʔνϟϧΧʔυ͸Կ౓Ͱ΋࠶ൃߦͰ͖Δ͕ɺ୹࣌ؒʹԿ౓ ΋࠶ൃߦ͢Δ͜ͱ͸ਖ਼ৗͳঢ়ଶͰ͸ͳ͍ • ؒҧ͑ͯΧʔυൃߦ͕ى͖ͨࡍ͸֎෦αʔϏεଆͷमਖ਼΋ඞ ཁͰӡ༻ίετ͕ߴ͍ • Χʔυൃߦ͸2ͭͷαʔϏεʹލͬͯॲཧ͞ΕΔ͕ɺΧʔυൃ ߦଆͰϩοΫΛऔಘͰ͖Δద౰ͳϦιʔε͕ଘࡏ͠ͳ͔ͬͨ • Ϣʔβʔຖͷൃߦճ਺Λอଘ͠ɺࢦఆճ਺Λ௒͑ͨΒΤϥʔ ൃੜ͢Δ࢓༷ʹ ϞόΠϧΞϓϦ #'' *TTVJOH"1* $PSF"1* ֎෦αʔϏε

Slide 53

Slide 53 text

ϨʔτϦϛοτ • ഉଞ੍ޚͰ͖ΔΑ͏ʹطଘͷ࢓૊ΈΛमਖ਼ͨ͠ΓɺΞυ όΠβϦʔϩοΫ΋ݕ౼͕ͨ͠ίεύ؍఺Ͱෆ࠾༻ • ϨʔτϦϛοτͷ੍ޚ͸ςʔϒϧΛҰͭ௥Ճ͢Δఔ౓Ͱ࣮ݱ Մೳ • Idempotency-Keyϔομͷಋೖ΋ݕ౼͕ͨ͠ɺΧʔυൃߦ αʔϏεଆʹ͸ͦͷ࢓૊Έ͕੔͍ͬͯͳ͔ͬͨͨΊෆ࠾༻ • ໓ଟʹൃੜ͠ͳ͍͕ɺ΋͠ൃੜͨ͠Βσʔλमਖ਼౳ͷӡ ༻ίετ͕ߴ͍໰୊Λ௿ίετͰղܾ https://blog.smartbank.co.jp/entry/2025/03/19/123000

Slide 54

Slide 54 text

ςʔϒϧઃܭ + Ωϟογϡ • ίϯϏχ / ϖΠδʔͳͲͷೖۚํ๏Ͱ͸ɺϢʔβʔ͕ϨδͰ͓ۚ Λࢧ෷ͬͨޙʹ׬ྃ৘ใ͕WebhookͰૹΒΕΔ • Webhookʹ͸ϦτϥΠػೳ͕ఏڙ͞Ε͍ͯΔ͜ͱ͕ଟ͍ • λΠϜΞ΢τ͕ൃੜ͢Δͱ֎෦αʔϏεଆʹ͸Τϥʔ൑ผ͞Εͨ ͚Ͳ࣮ࡍʹ͸੒ޭঢ়ଶͱ͍͏σʔλෆ੔߹͕ൃੜ͢Δ • ϦτϥΠ࣌ʹɺςʔϒϧઃܭͰ੔߹ੑΛอ͍ͬͯΔ͔ΒͱΤϥʔ ൃੜͤ͞ΔͱΤϥʔϧʔϓ͕ൃੜ͢Δ • ֎෦αʔϏεΛར༻͍ͯ͠Δͱ͖͸ɺIdempotency-Keyϔομͳ ͲͷΫϥΠΞϯτଆͷมߋ͕Ͱ͖ͳ͍ ֎෦ αʔϏε αʔόʔ POST TIMEOUT RETRY ? DB Table SAVE SUCCESS

Slide 55

Slide 55 text

ςʔϒϧઃܭ + Ωϟογϡ • ςʔϒϧઃܭ্͸Ұҙ੍໿ΛೖΕΔͳͲͰ੔߹ੑΛ֬อ͓ͯ͠ ͖ɺWebhookΛड͚औͬͨࡍʹ͸ର৅Ϧιʔεͷঢ়ଶΛ֬ೝ ͠ɺॲཧ׬͍ྃͯͨ͠Β੒ޭΛฦ͢͜ͱͰႈ౳ʹ͢Δ • ͨͩ͠ႈ౳ʹ͢ΔϦΫΤετΛಛఆͰ͖ΔIDͳͲؚ͕·Ε͍ͯͳ ͍ͱ࣮ݱͰ͖ͳ͍ͷͰɺ֎෦αʔϏεͷ࢓༷࣍ୈ ֎෦ αʔϏε αʔόʔ POST TIMEOUT RETRY SUCCESS DB Table SAVE FETCH SUCCESS

Slide 56

Slide 56 text

·ͱΊ

Slide 57

Slide 57 text

·ͱΊ • ୭ʹͱͬͯ΋਎ۙͰॏཁͳ2ॏϦΫΤετ໰୊ʹ೰·ͳ͍͍ͯ͘ੈքΛ࡞Δ • 2ॏϦΫΤετ͕ͲͷΑ͏ͳ໰୊ͳͷ͔આ໌ • 2ॏϦΫΤετͷ๷ޚ๏Λ9ݸ঺հ • ϫϯόϯΫͰͷϢʔεέʔεͱ࠾༻͍ͯ͠Δ๷ޚ๏Λ঺հ • ۀ຿ͰʮͲ͏͠Α͏ʯͱͳͬͨ࣌ʹͥͻݟฦ͍ͯͩ͘͠͞ʂ • ࠓ೔ൃදͨ͠ύλʔϯΛ୯ಠ or ૊Έ߹ΘͤΔ͜ͱͰͳΜͱ͔ͳΔέʔε͕ଟ͍͸ͣ

Slide 58

Slide 58 text

No content