Slide 1

Slide 1 text

,PUMJO'FTU ʹ͜͠Γ͞ͿΖʙ!TVCSPI@ ϑϩϯτΤϯυ΋ +FUQBDL$PNQPTFͰॻ͖͍ͨʂ $PNQPTFGPS8FC͸Ϟμϯ8FCΞϓϦέʔγϣϯͷເΛݟΔ͔ʁ 

Slide 2

Slide 2 text

"CPVU.F 📛ʹ͜͠Γ͞ͿΖʙࡔ্੖৴ 🏝౦ژ౎ɾҏ౾େౡग़਎ 🏆৿ཏສ৅Λ,PUMJOͰ࣮૷ͯ͠ ੈք੐෰͕͍ͨ͠ ໺๬  ‎"OESPJEΤϯδχΞ Ϧʔμʔ  ‎8FCΤϯδχΞ 

Slide 3

Slide 3 text

໨࣍  ,PUMJO+4ͷ֓ཁ  ݴޠ͔Βఏڙ͞ΕΔػೳͷ঺հ  ,PUMJO+4ʹΑΔ8FCΞϓϦέʔγϣϯ࣮૷ͷ֓ཁղઆ ͭ   $PNQPTFGPS8FCʹΑΔ8FCΞϓϦέʔγϣϯ։ൃ  ࣄྫɾ࣮૷ͷղઆ  ,PUMJO+4Ͱͷ8FCϑϩϯτΤϯυ։ൃͷ௕ॴɾ୹ॴɺࠓޙͷల๬ 

Slide 4

Slide 4 text

͜ͷηογϣϯͷΰʔϧ 🏁$PNQPTFGPS8FCΛར༻͠ɺ8FCΞϓϦΛ࣮૷ɾϦϦʔεͰ͖Δ  Ϟμϯ͔ͭߴ඼࣭ͳ8FCΞϓϦΛ࣮૷͢ΔͨΊͷ஌ݟڞ༗ 🏁,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ։ൃͷݱঢ়ʹ͍ͭͯڞ༗  ࠓݱࡏԿ͕خͯ͘͠ɺԿ͕ͭΒ͍ͷ͔  աڈͭΒ͔ͬͨ͜ͱ͕Ͳ͏վળ͞Ε͔ͨɺࠓޙͲͷΑ͏ʹਐԽ͢Δ͔ 

Slide 5

Slide 5 text

,PUMJO+4ͷ֓ཁ 

Slide 6

Slide 6 text

,PUMJO+4ͱ͸ʜ 🌈,PUMJO.VMUJQMBUGPSN .11   ,PUMJOͷίʔυΛଞϓϥοτϑΥʔϜ޲͚ʹϏϧυ 
 ʮϩδοΫͷڞ௨ԽʯΛ໨ࢦ͢91MBUϑϨʔϜϫʔΫ  +7./BUJWF+BWB4DSJQUίʔυͷग़ྗʹରԠ 

Slide 7

Slide 7 text

,PUMJO+4ͱ͸ʜ 🌈,PUMJO.VMUJQMBUGPSN .11   ,PUMJOͷίʔυΛଞϓϥοτϑΥʔϜ޲͚ʹϏϧυ 
 ʮϩδοΫͷڞ௨ԽʯΛ໨ࢦ͢91MBUϑϨʔϜϫʔΫ  +7./BUJWF+BWB4DSJQUίʔυͷग़ྗʹରԠ  ͜͜ʹରԠ͢Δ,PUMJOͷػೳ,PUMJO+4

Slide 8

Slide 8 text

ʕ,PUMJOGPS+BWB4DSJQULPUMJOMBOHPSHEPDTKTPWFSWJFXIUNM ,PUMJO+4QSPWJEFTUIFBCJMJUZUPUSBOTQJMFZPVS ,PUMJODPEF UIF,PUMJOTUBOEBSEMJCSBSZ BOE BOZDPNQBUJCMFEFQFOEFODJFTUP+BWB4DSJQU  💡,PUMJO+4͸ɺ,PUMJOͷίʔυɾඪ४ϥΠϒϥϦɺ͓Αͼޓ׵ੑͷ͋Δґଘؔ܎Λ +BWB4DSJQUʹม׵͢ΔػೳΛఏڙ͢Δ

Slide 9

Slide 9 text

8FCϑϩϯτΤϯυ։ൃɺͦ΋ͦ΋Կ͕ඞཁʁ  ˒)5.-$448FCϖʔδͷݟͨ໨Λఆٛ͢Δ ˒+BWB4DSJQUίʔυ8FCϖʔδʹಈ͖Λ͚ͭΔ 㾎ύοέʔδ؅ཧπʔϧ OQN:BSO  㾎Ϟδϡʔϧόϯυϥ 8FCQBDL3PMMVQFTCVJMEFUD   ෳ਺ͷ+4ϞδϡʔϧΛͭʹ·ͱΊΔ  ϞδϡʔϧؒͷґଘੑղܾɺNJOJGZɺίʔυɾϦιʔεͷม׵ ͜ͷ͕ͭ͋Ε͹ ࠷௿ݶ0,🙆 ྫ5ZQF4DSJQUˠ+BWB4DSJQUɺ4BTTˠ$44 Ϟμϯ͔ͭͦΕͳΓͷن໛ͷ 8FCΞϓϦ։ൃʹ͸ ΄΅ඞਢ☝

Slide 10

Slide 10 text

,PUMJO+4͕ఏڙ͢Δػೳ  🛠+BWB4DSJQUίʔυʹม׵Մೳɺ͔ͭ8FC"1*ʹΞΫηεՄೳͳ ,PUMJOඪ४ϥΠϒϥϦ 🛠,PUMJOˠ+BWB4DSJQU΁ͷม׵Λ࣮ߦ͢Δ(SBEMF1MVHJO 🛠:BSO8FCQBDLͷίϚϯυΛ࣮ߦ͢Δ(SBEMF1MVHJO ֤छ+BWB4DSJQU੡ύοέʔδͷϥούʔϥΠϒϥϦ 💡,PUMJOˠ+BWB4DSJQU΁ͷม׵ :BSO8FCQBDLʹΑΔύοέʔδ؅ཧ όϯυϧϑΝΠϧੜ੒ શͯΛ,PUMJOͷੈքͰ׬݁ͤͨ͞ঢ়ଶͰϑϩϯτΤϯυ։ൃΛ࣮ݱʂ

Slide 11

Slide 11 text

,PUMJO+4͕૝ఆ͢ΔϢʔεέʔε  💻8FCΞϓϦέʔγϣϯͷϑϩϯτΤϯυͷ࣮૷ 💻αʔόʔαΠυɾαʔόʔϨεΞϓϦέʔγϣϯͷ࣮૷  ىಈͷߴ଎ԽɾϝϞϦ࢖༻ྔͷ࡟ݮͱ͍ͬͨɺ+BWB4DSJQUϥϯλΠϜͳΒͰ͸ͷϝϦοτΛڗड 💻.11ʹ͓͚Δɺଞͷλʔήοτͱͷڞ༗Λલఏͱͨ͠ίʔυͷ࣮૷  ۀ຿ϩδοΫσʔλϞσϧόϦσʔγϣϯͷϞόΠϧͱͷڞ௨Խ 💻+BWB4DSJQU5ZQF4DSJQUͰ࢖༻͢ΔϥΠϒϥϦͷ࣮૷ ʕ6TFDBTFTGPS,PUMJO+4LPUMJOMBOHPSHEPDTKTPWFSWJFXIUNMVTFDBTFTGPSLPUMJOKT ࠷ऴతͳ੒Ռ෺+4ίʔυ +BWB4DSJQU͕Ͱ͖Δ͜ͱ͸ ཧ࿦্ ͳΜͰ΋Ͱ͖Δ😎

Slide 12

Slide 12 text

💻8FCΞϓϦέʔγϣϯͷϑϩϯτΤϯυͷ࣮૷ 💻αʔόʔαΠυɾαʔόʔϨεΞϓϦέʔγϣϯͷ࣮૷  ىಈͷߴ଎ԽɾϝϞϦ࢖༻ྔͷ࡟ݮͱ͍ͬͨɺ+BWB4DSJQUϥϯλΠϜͳΒͰ͸ͷϝϦοτΛڗड 💻.11ʹ͓͚Δɺଞͷλʔήοτͱͷڞ༗Λલఏͱͨ͠ίʔυͷ࣮૷  ۀ຿ϩδοΫσʔλϞσϧόϦσʔγϣϯͷϞόΠϧͱͷڞ௨Խ 💻+BWB4DSJQU5ZQF4DSJQUͰ࢖༻͢ΔϥΠϒϥϦͷ࣮૷ ,PUMJO+4͕૝ఆ͢ΔϢʔεέʔε  ʕ6TFDBTFTGPS,PUMJO+4LPUMJOMBOHPSHEPDTKTPWFSWJFXIUNMVTFDBTFTGPSLPUMJOKT ,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷ʹ͸ ओʹͭͷํ๏͕ଘࡏ ˞ຊηογϣϯͰ͸ɺͻͨ͢Β͜ͷϢʔεέʔεʹϑΥʔΧε👀

Slide 13

Slide 13 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  %0.Λ௚઀ૢ࡞  ,PUMJOͷඪ४ϥΠϒϥϦ͔Β8FC"1*Λར༻͠ɺ%0.Λ௚઀ૢ࡞͢Δ fun main() { val div = document.createElement("div") div.innerHTML = "Hello, World!" document.body?.appendChild(div) } TBNQMFLU

Slide 14

Slide 14 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  %0.Λ௚઀ૢ࡞  ,PUMJOͷඪ४ϥΠϒϥϦ͔Β8FC"1*Λར༻͠ɺ%0.Λ௚઀ૢ࡞͢Δ createElementϝιουͰEJWཁૉΛੜ੒ ੜ੒ͨ͠EJWཁૉ಺ʹจࣈྻΛ௥Ճ )5.-ͷCPEZʹੜ੒ͨ͠EJWཁૉΛ௥Ճ fun main() { val div = document.createElement("div") div.innerHTML = "Hello, World!" document.body?.appendChild(div) } TBNQMFLU

Slide 15

Slide 15 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  %0.Λ௚઀ૢ࡞  ,PUMJOͷඪ४ϥΠϒϥϦ͔Β8FC"1*Λར༻͠ɺ%0.Λ௚઀ૢ࡞͢Δ DSFBUF&MFNFOUϝιουͰEJWཁૉΛੜ੒ ੜ੒ͨ͠EJWཁૉ಺ʹจࣈྻΛ௥Ճ )5.-ͷCPEZʹੜ੒ͨ͠EJWཁૉΛ௥Ճ function main() { const div = document.createElement('div'); div.innerHTML = 'Hello, World!'; document.body.appendChild(div); } fun main() { val div = document.createElement("div") div.innerHTML = "Hello, World!" document.body?.appendChild(div) } TBNQMFLU TBNQMFKT ಉ͡ಈ࡞Λ͢Δ+BWB4DSJQUίʔυ ,PUMJOίʔυͱͦ͜·Ͱେ͖ͳࠩ͸ͳ͠ ?.͕ͳ͍͘Β͍ 

Slide 16

Slide 16 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  %0.Λ௚઀ૢ࡞ 🙆֎෦ϥΠϒϥϦɾϑϨʔϜϫʔΫ΁ͷґଘΛඇৗʹগͳ͘อͭ͜ͱ͕Ͱ͖Δ 🙅ෳࡶͳϩδοΫ΍ڽͬͨ6*Λ࣮૷͠Α͏ͱ͢Δͱɺίʔυྔ͕๲େʹ 🙅ঢ়ଶ؅ཧͷϩδοΫΛࣗྗͰ࣮૷͢ΔඞཁΞϦ 👉ϩδοΫ͕୯७ Ϧονͳ6*ΛٻΊͳ͍ͳΒɺબ୒ͷ༨஍͋Γ ϥΠϒϥϦͷΞοϓσʔτ࣌ɺ,PUMJO͚ͩέΞ͢Ε͹0,ͳͷ͸ ҙ֎ͱແࢹͰ͖ͳ͍ϝϦοτ

Slide 17

Slide 17 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU  ,PUMJOͷίʔυ͔Β3FBDU"1*Λ࣮ߦ͠ɺ6*Λ࣮૷͢Δ fun main() { val container = document.createElement("div") document.body!!.appendChild(container) createRoot(container).render(HelloWorld.create()) } val HelloWorld = FC { div { +"Hello, World!" } } TBNQMFLU 3FBDU 🚀8FCΞϓϦͷ6*Λએݴతʹ࣮૷ 🚀044Խ͔Β೥͕ܦաɺػೳ͕ચ࿅ ৘ใɾϥΠϒϥϦࢿ࢈΋๛෋ 🚀,PUMJOͷϥούʔϥΠϒϥϦΛ +FU#SBJOT͕ެࣜʹఏڙɺ͜ΕΛར༻ LPUMJOSFBDU+FU#SBJOTLPUMJOXSBQQFSTLPUMJOSFBDU

Slide 18

Slide 18 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU  ,PUMJOͷίʔυ͔Β3FBDU"1*Λ࣮ߦ͠ɺ6*Λ࣮૷͢Δ fun main() { val container = document.createElement("div") document.body!!.appendChild(container) createRoot(container).render(HelloWorld.create()) } val HelloWorld = FC { div { +"Hello, World!" } } TBNQMFLU 3FBDU 🚀8FCΞϓϦͷ6*Λએݴతʹ࣮૷ 🚀044Խ͔Β೥͕ܦաɺػೳ͕ચ࿅ ৘ใɾϥΠϒϥϦࢿ࢈΋๛෋ 🚀,PUMJOͷϥούʔϥΠϒϥϦΛ +FU#SBJOT͕ެࣜʹఏڙɺ͜ΕΛར༻ 3FBDUίϯϙʔωϯτͷੜ੒Օॴ

Slide 19

Slide 19 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU 🙆3FBDU)PPLTΛར༻͠ɺঢ়ଶ؅ཧͷϩδοΫΛεϚʔτʹهड़Ͱ͖Δ ϘλϯΛΫϦοΫ͢Δͱ දࣔ͞Ε͍ͯΔΫϦοΫ਺͕૿͑Δ val Counter = FC { var (count, setCount) = useState { 0 } button { onClick = { setCount(count += 1) } +"Count: $count" } } $PVOUFSLU

Slide 20

Slide 20 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU 🙆3FBDU)PPLTΛར༻͠ɺঢ়ଶ؅ཧͷϩδοΫΛεϚʔτʹهड़Ͱ͖Δ val Counter = FC { var (count, setCount) = useState { 0 } button { onClick = { setCount(count += 1) } +"Count: $count" } } $PVOUFSLU useStateϝιουͰΫϦοΫ਺Λอ࣋͢Δม਺ͱ ม਺Λߋ৽͢ΔͨΊͷؔ਺Λએݴ CVUUPOཁૉͷonClickଐੑͰ ΫϦοΫ਺ߋ৽ͷॲཧΛ࣮ߦ ΫϦοΫ਺ͷදࣔ

Slide 21

Slide 21 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU 🙆3FBDU)PPLTΛར༻͠ɺঢ়ଶ؅ཧͷϩδοΫΛεϚʔτʹهड़Ͱ͖Δ val Counter = FC { var (count, setCount) = useState { 0 } button { onClick = { setCount(count += 1) } +"Count: $count" } } $PVOUFSLU const Counter = () => { const [count, setCount] = useState(0); return ( setCount(count + 1) }> `Count: ${count}` ); } $PVOUFSKTY

Slide 22

Slide 22 text

LPUMJOSFBDU 🙆3FBDU)PPLTΛར༻͠ɺঢ়ଶ؅ཧͷϩδοΫΛεϚʔτʹهड़Ͱ͖Δ const Counter = () => { const [count, setCount] = useState(0); return ( setCount(count + 1) }> `Count: ${count}` ); } $PVOUFSKTY ,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  val Counter = FC { var (count, setCount) = useState { 0 } button { onClick = { setCount(count += 1) } +"Count: $count" } } $PVOUFSLU +49ه๏ɾ'VODUJPOBM$PNQPOFOUͷએݴΛ ΠΠײ͡ʹ࠶ݱ😎

Slide 23

Slide 23 text

LPUMJOSFBDU 🙆ஶ໊ͳϥΠϒϥϦͷҰ෦͸+FU#SBJOT͔Βϥούʔ͕ఏڙ͞Ε͍ͯΔ ,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOXSBQQFST+FU#SBJOTLPUMJOXSBQQFST ˞͜ͷଞʹ΋৭ʑΞϦ

Slide 24

Slide 24 text

LPUMJOSFBDU 🙆ஶ໊ͳϥΠϒϥϦͷҰ෦͸+FU#SBJOT͔Βϥούʔ͕ఏڙ͞Ε͍ͯΔ ,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOXSBQQFST+FU#SBJOTLPUMJOXSBQQFST ˞͜ͷଞʹ΋৭ʑΞϦ FNPUJPO$44JO+4 IJTUPSZηογϣϯཤྺ؅ཧ .6*6*ίϯϙʔωϯτ .BUFSJBM%FTJHO४ڌ QPQQFSਧ͖ग़͠ίϯϙʔωϯτ SFBDU6*ϑϨʔϜϫʔΫ CFBVUJGVMEOE%SBH%SPQ SFBDUSPVUFSϧʔλʔ SFBDUTFMFDUબ୒6* SFEVYঢ়ଶ؅ཧ

Slide 25

Slide 25 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU 🙆ஶ໊ͳϥΠϒϥϦͷҰ෦͸+FU#SBJOT͔Βϥούʔ͕ఏڙ͞Ε͍ͯΔ import mui.material.Button import mui.material.ButtonVariant val Counter = FC { val (count, setCount) = useState { 0 } Button { variant = ButtonVariant.contained onClick = { setCount(count + 1) } +"Count: $count" } } ઌఔͷΧ΢ϯλʔΞϓϦΛLPUMJONVJͰ࠶࣮૷ CVUUPOཁૉΛ.6*ͷ#VUUPOίϯϙʔωϯτʹࠩ͠ସ͑

Slide 26

Slide 26 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU 🙆ஶ໊ͳϥΠϒϥϦͷҰ෦͸+FU#SBJOT͔Βϥούʔ͕ఏڙ͞Ε͍ͯΔ import mui.material.Button import mui.material.ButtonVariant val Counter = FC { val (count, setCount) = useState { 0 } Button { variant = ButtonVariant.contained onClick = { setCount(count + 1) } +"Count: $count" } } ৭ɾؙ֯ɾେจࣈԽɾ3JQQMF& ff FDU௥ՃFUD .6*ͷػೳʹΑͬͯϦονͳݟͨ໨ʹ✨

Slide 27

Slide 27 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  LPUMJOSFBDU 🙅ྑ͘΋ѱ͘΋3FBDUͷ࢓༷ʹറΒΕΔͨΊɺจ๏΍࡞๏΁ͷ׳Ε͕ඞཁ 🙅ϥΠϒϥϦΞοϓσʔτ࣌ʹέΞ͢΂͖Օॴ͕ଟ͘ͳΓ͕ͪ  ౰વͳ͕Βɺ+BWB4DSJQU੡ϥΠϒϥϦ͸,PUMJOͷ౎߹ͳͲߟ͑ͣΞοϓσʔτ͞ΕΔ🥺 🙅SE1BSUZͷ+BWB4DSJQUϥΠϒϥϦ͸ѹ౗తʹ5ZQF4DSJQUͷํ͕ѻ͍΍͍͢  ,PUMJOͰѻ͏ͨΊʹ͸ܕఆٛίʔυΛ,PUMJOͰॻ͔ͳ͚Ε͹ͳΒͳ͍🥺  LPUMJOXSBQQFSTʹͳ͍৔߹͸ࣗྗͰ༻ҙͤ͟ΔΛಘͳ͍͜ͱ͕େ൒🥺 5ZQF4DSJQUͷܕఆ͔ٛΒ ࣗಈੜ੒͢Δπʔϧ΋ଘࡏ EVLBU,PUMJOEVLBU ˞࠷৽൛͸SD🤔

Slide 28

Slide 28 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  $PNQPTFGPS8FCͷઆ໌ͷલʹʜ +FUQBDL$PNQPTFʹ͍ͭͯ  "OESPJEΞϓϦͷ6*Λએݴతʹ࣮૷Ͱ͖Δ,PUMJO੡6*ϑϨʔϜϫʔΫ  ೥݄ʹਖ਼ࣜ൛ϦϦʔε  "OESPJEΞϓϦͷ6*։ൃͰ͸ σϑΝΫτʹͳΓͭͭ͋Δ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Column { Text("Android") Text("Jetpack Compose") } } } } .BJO"DUJWJUZLU

Slide 29

Slide 29 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  $PNQPTFGPS8FCͷઆ໌ͷલʹʜ +FUQBDL$PNQPTFʹ͍ͭͯ  "OESPJEΞϓϦͷ6*Λએݴతʹ࣮૷Ͱ͖Δ,PUMJO੡6*ϑϨʔϜϫʔΫ  ೥݄ʹਖ਼ࣜ൛ϦϦʔε  "OESPJEΞϓϦͷ6*։ൃͰ͸ σϑΝΫτʹͳΓͭͭ͋Δ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Column { Text("Android") Text("Jetpack Compose") } } } } .BJO"DUJWJUZLU +FUQBDL$PNQPTFͰ࣮૷͞Ε͍ͯΔՕॴ ͭͷจࣈྻΛॎฒͼͰදࣔ

Slide 30

Slide 30 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  $PNQPTFGPS8FCͷઆ໌ͷલʹʜ +FUQBDL$PNQPTFʹ͍ͭͯ  "OESPJEΞϓϦͷ6*Λએݴతʹ࣮૷Ͱ͖Δ,PUMJO੡6*ϑϨʔϜϫʔΫ  ೥݄ʹਖ਼ࣜ൛ϦϦʔε  "OESPJEΞϓϦͷ6*։ൃͰ͸ σϑΝΫτʹͳΓͭͭ͋Δ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Column { Text("Android") Text("Jetpack Compose") } } } } .BJO"DUJWJUZLU +FUQBDL$PNQPTFͰ࣮૷͞Ε͍ͯΔՕॴ ͭͷจࣈྻΛॎฒͼͰදࣔ 8FCΞϓϦ΋+FUQBDL$PNQPTFͰ ॻ͚ͨΒ࠷ߴͳͷͰ͸ʜʁ ఱ࠽ͷൃ૝ 

Slide 31

Slide 31 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  $PNQPTFGPS8FC  +FUQBDL$PNQPTFͷ,PUMJO.11ରԠ൛Λ+FU#SBJOT͕044Խ😆 DPNQPTFKC+FU#SBJOTDPNQPTFKC ʕ$PNQPTF.VMUJQMBUGPSN'SBNFXPSLKFUCSBJOTDPNKBKQMQDPNQPTFNQQ %FTLUPQ8FCΞϓϦ։ൃʹରԠʂ ˠ+FUQBDL$PNQPTFͱڞ௨ͷ"1*Ͱ 8FCϑϩϯτΤϯυͷ࣮૷͕Ͱ͖Δ🎉 ఱ࠽ͳͷͰ .11ରԠͤ͞ͱ͍ͨͧ😎

Slide 32

Slide 32 text

,PUMJO+4ʹΑΔ8FCϑϩϯτΤϯυ࣮૷  $PNQPTFGPS8FC  +FUQBDL$PNQPTFͷ,PUMJO.11ରԠ൛Λ+FU#SBJOT͕044Խ😆  ೥݄ʹ҆ఆ൛ϦϦʔεࡁΈ🚀 ʕ$PNQPTF.VMUJQMBUGPSN*T(PJOH-JWFc5IF,PUMJO#MPH CMPHKFUCSBJOTDPNLPUMJODPNQPTFNVMUJQMBUGPSNJTHPJOHMJWF DPNQPTFKC+FU#SBJOTDPNQPTFKC طʹຊ൪؀ڥͰͷར༻͕Մೳͳঢ়ଶ🥳 $PNQPTFGPS8FCͰ࡞ͬͯΈΔ͔͠ͳ͍ʂ💪

Slide 33

Slide 33 text

$PNQPTFGPS8FCʹΑΔ 8FCΞϓϦέʔγϣϯ։ൃ 

Slide 34

Slide 34 text

$PNQPTFGPS8FCͰ؆୯ͳΞϓϦΛ࡞Δ 🌏*OUFMMJ+*%&"$&Ͱ਽ܗ࡞੒  /FX1SPKFDU ˠ$PNQPTF.VMUJQMBUGPSN ˠ$PO fi HVSBUJPO4JOHMFQMBUGPSN ˠ1MBUGPSN8FC ˠ$SFBUF ˞/BNFɾ-PDBUJPOɾ(SPVQɾ"SUJGBDU౳͸ ɹ͓޷ΈͰઃఆ

Slide 35

Slide 35 text

🌏*OUFMMJ+*%&"$&Ͱ਽ܗ࡞੒ $PNQPTFGPS8FCͰ؆୯ͳΞϓϦΛ࡞Δ  ˒ੜ੒෺ .BJOLU  6*Λهड़͢Δ,PUMJOίʔυ JOEFYIUNM  +4ม׵ޙͷ,PUMJOίʔυΛϒϥ΢βʹಡΈࠐ·ͤΔ  $44ϞδϡʔϧͷಡΈࠐΈ΍NFUBλάͷهड़ TFUUJOHTHSBEMFLUTCVJMEHSBEMFLUT  ϥΠϒϥϦͷґଘؔ܎ɾ8FCQBDLͷઃఆͷهड़ HSBEMFQSPQFSUJFT  (SBEMFͷઃఆɾϥΠϒϥϦͷόʔδϣϯͷهड़ ੜ੒෺ʹର͠ɺجຊతʹ͸ ௥Ճɾमਖ਼ͷهड़͸ෆཁ

Slide 36

Slide 36 text

🌏*OUFMMJ+*%&"$&Ͱ਽ܗ࡞੒ $PNQPTFGPS8FCͰ؆୯ͳΞϓϦΛ࡞Δ  kotlin.version=1.7.20 compose.version=1.2.1 ,PUMJOͱ$PNQPTFͷόʔδϣϯ͸ ࠷৽ʹ͓ͯ͘͠ͱ޾ͤ👍 HSBEMFQSPQFSUJFT ˞Ҏલͷ,PUMJO+4͕ݹ͍/PEFKTʹґଘ ɹ"QQMF4JMJDPOͷ.BDͰϏϧυ͕མͪΔ🥺 ˒ੜ੒෺ .BJOLU  6*Λهड़͢Δ,PUMJOίʔυ JOEFYIUNM  +4ม׵ޙͷ,PUMJOίʔυΛϒϥ΢βʹಡΈࠐ·ͤΔ  $44ϞδϡʔϧͷಡΈࠐΈ΍NFUBλάͷهड़ TFUUJOHTHSBEMFLUTCVJMEHSBEMFLUT  ϥΠϒϥϦͷґଘؔ܎ɾ8FCQBDLͷઃఆͷهड़ HSBEMFQSPQFSUJFT  (SBEMFͷઃఆɾϥΠϒϥϦͷόʔδϣϯͷهड़

Slide 37

Slide 37 text

$PNQPTFGPS8FCͰ؆୯ͳΞϓϦΛ࡞Δ 🌏(SBEMFίϚϯυΛ࣮ߦ  $ ./gradlew :jsBrowserRun MPDBMIPTUͰ Χ΢ϯλʔΞϓϦ্ཱ͕͕ͪΔ🎉

Slide 38

Slide 38 text

 fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { padding(25.px) } }) { Button(attrs = { onClick { count -= 1 } }) { Text("-") } Span({ style { padding(15.px) } }) { Text("$count") } Button(attrs = { onClick { count += 1 } }) { Text("+") } } } } .BJOLU 🛠࣮૷ৄࡉ

Slide 39

Slide 39 text

 fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { padding(25.px) } }) { Button(attrs = { onClick { count -= 1 } }) { Text("-") } Span({ style { padding(15.px) } }) { Text("$count") } Button(attrs = { onClick { count += 1 } }) { Text("+") } } } } .BJOLU 🛠࣮૷ৄࡉ mutableStateOfϝιουͰ஋ͷঢ়ଶ؂ࢹ͕ Մೳͳม਺Λఆٛ ˞ͨͩͷ*OUͩͱɺ6*ͷ࠶ඳը͕࣮ߦ͞Εͳ͍

Slide 40

Slide 40 text

 fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { padding(25.px) } }) { Button(attrs = { onClick { count -= 1 } }) { Text("-") } Span({ style { padding(15.px) } }) { Text("$count") } Button(attrs = { onClick { count += 1 } }) { Text("+") } } } } .BJOLU 🛠࣮૷ৄࡉ id="root"ͷ)5.-ཁૉʹ $PNQPTFͰߏஙͨ͠6*Λඳը͢ΔΑ͏ʹࢦఆ Sample
JOEFYIUNM

Slide 41

Slide 41 text

 fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { padding(25.px) } }) { Button(attrs = { onClick { count -= 1 } }) { Text("-") } Span({ style { padding(15.px) } }) { Text("$count") } Button(attrs = { onClick { count += 1 } }) { Text("+") } } } } .BJOLU 🛠࣮૷ৄࡉ $PNQPTFʹΑΔ6*ͷߏஙՕॴ )5.-λάΛ+FUQBDL$PNQPTFͷจ๏ʹԊͬͯ એݴతʹهड़͢Δ

Slide 42

Slide 42 text

 fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { padding(25.px) } }) { Button(attrs = { onClick { count -= 1 } }) { Text("-") } Span({ style { padding(15.px) } }) { Text("$count") } Button(attrs = { onClick { count += 1 } }) { Text("+") } } } } .BJOLU 🛠࣮૷ৄࡉ 6*ͷݟͨ໨͸$44Ͱهड़͢Δ $PNQPTFGPS8FCʹ.PEJ fi FS͸ొ৔͠ͳ͍🙅  $44͸$PNQPTFGPS8FC͕%4-Λఏڙ ܕ҆શ͔ͭαδΣετΛޮ͔ͤͳ͕Βهड़👍

Slide 43

Slide 43 text

 fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { padding(25.px) } }) { Button(attrs = { onClick { count -= 1 } }) { Text("-") } Span({ style { padding(15.px) } }) { Text("$count") } Button(attrs = { onClick { count += 1 } }) { Text("+") } } } } .BJOLU 🛠࣮૷ৄࡉ )5.-λάͷଐੑ஋΁ͷ஋୅ೖɾϝιουઃఆ͸ attrsҾ਺ʹϥϜμࣜͷܗͰ౉͢ countม਺͕.VUBCMF4UBUFܕͰએݴ͞Ε͍ͯΔ countͷ஋͕ߋ৽͞ΕΔͱ6*ͷ࠶ඳը͕ࣗಈతʹ૸Δ🏃

Slide 44

Slide 44 text

$PNQPTFGPS8FCͰ؆୯ͳΞϓϦΛ࡞Δ 💅ݟͨ໨Λ΋ͬͱϦονʹ͍ͨ͠ʜʂ  ࣗྗͰ$44Λؤுͬͯॻ͘👹  SE1BSUZ੡ͷ+BWB4DSJQUϑϨʔϜϫʔΫ$44ϞδϡʔϧΛ׆༻͢Δ☺  ࢼ͠ʹ͜ͷ࣭ૉͳΧ΢ϯλʔΞϓϦΛ NBUFSJBMJ[FDTTͰϦονʹվ଄🔨 NBUFSJBMJ[FDTT%PHGBMPNBUFSJBMJ[F

Slide 45

Slide 45 text

 🛠NBUFSJBMJ[FDTTͰαϯϓϧΞϓϦͷݟͨ໨Λվ଄ JOEFYIUNM  ˞ৄ͘͠͸NBUFSJBMJ[FDTTͷެࣜυΩϡϝϯτΛࢀরNBUFSJBMJ[FDTTDPN JOEFYIUNMʹ$%/΁ͷϦϯΫΛ௥Ճ NBUFSJBMJ[FDTTͷ$44+4ϑΝΠϧΛಡΈࠐΈ💿

Slide 46

Slide 46 text

 🛠NBUFSJBMJ[FDTTͰαϯϓϧΞϓϦͷݟͨ໨Λվ଄  ˞ৄ͘͠͸NBUFSJBMJ[FDTTͷެࣜυΩϡϝϯτΛࢀরNBUFSJBMJ[FDTTDPN @Composable fun FloatingActionButton( icon: String, attrs: AttrBuilderContext? = null, ) = Button(attrs = { classes("btn-floating", "waves-effect", "waves-light") attrs?.invoke(this) }) { I(attrs = { classes("material-icons") }) { Text(icon) } } 'MPBUJOH"DUJPO#VUUPOLU 'MPBUJOH"DUJPO#VUUPO༻ͷ$PNQPTBCMFؔ਺Λ௥Ճ

Slide 47

Slide 47 text

 🛠NBUFSJBMJ[FDTTͰαϯϓϧΞϓϦͷݟͨ໨Λվ଄  ˞ৄ͘͠͸NBUFSJBMJ[FDTTͷެࣜυΩϡϝϯτΛࢀরNBUFSJBMJ[FDTTDPN @Composable fun FloatingActionButton( icon: String, attrs: AttrBuilderContext? = null, ) = Button(attrs = { classes("btn-floating", "waves-effect", "waves-light") attrs?.invoke(this) }) { I(attrs = { classes("material-icons") }) { Text(icon) } } 'MPBUJOH"DUJPO#VUUPOLU 'MPBUJOH"DUJPO#VUUPO༻ͷ$PNQPTBCMFؔ਺Λ௥Ճ CVUUPOλάͷଐੑ஋Λઃఆ͢ΔϥϜμࣜ ΫϦοΫϦεφʔ΍$44ͷ্ॻ͖Λ֎෦͔ΒͰ͖ΔΑ͏ʹ typealias AttrBuilderContext = AttrsScope.() -> Unit

Slide 48

Slide 48 text

 🛠NBUFSJBMJ[FDTTͰαϯϓϧΞϓϦͷݟͨ໨Λվ଄  ˞ৄ͘͠͸NBUFSJBMJ[FDTTͷެࣜυΩϡϝϯτΛࢀরNBUFSJBMJ[FDTTDPN @Composable fun FloatingActionButton( icon: String, attrs: AttrBuilderContext? = null, ) = Button(attrs = { classes("btn-floating", "waves-effect", "waves-light") attrs?.invoke(this) }) { I(attrs = { classes("material-icons") }) { Text(icon) } } 'MPBUJOH"DUJPO#VUUPOLU 'MPBUJOH"DUJPO#VUUPO༻ͷ$PNQPTBCMFؔ਺Λ௥Ճ attrsϒϩοΫ಺ͷclassesϝιουͰ $44Ϋϥε໊Λઃఆ

Slide 49

Slide 49 text

fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { display(DisplayStyle.Flex) padding(25.px) } }) { FloatingActionButton("remove") { onClick { count -= 1 } } Span({ style { padding(12.px) } }) { Text("$count") } FloatingActionButton("add") { onClick { count += 1 } } } } }  🛠NBUFSJBMJ[FDTTͰαϯϓϧΞϓϦͷݟͨ໨Λվ଄  ˞ৄ͘͠͸NBUFSJBMJ[FDTTͷެࣜυΩϡϝϯτΛࢀরNBUFSJBMJ[FDTTDPN αϯϓϧΞϓϦͷϘλϯඳըՕॴΛ ௥Ճͨ͠'MPBUJOH"DUJPO#VUUPOʹஔ͖׵͑ .BJOLU

Slide 50

Slide 50 text

fun main() { var count: Int by mutableStateOf(0) renderComposable(rootElementId = "root") { Div({ style { display(DisplayStyle.Flex) padding(25.px) } }) { FloatingActionButton("remove") { onClick { count -= 1 } } Span({ style { padding(12.px) } }) { Text("$count") } FloatingActionButton("add") { onClick { count += 1 } } } } }  🛠NBUFSJBMJ[FDTTͰαϯϓϧΞϓϦͷݟͨ໨Λվ଄  ˞ৄ͘͠͸NBUFSJBMJ[FDTTͷެࣜυΩϡϝϯτΛࢀরNBUFSJBMJ[FDTTDPN .BJOLU Ϙλϯͷݟͨ໨͕Ϧονʹ🎉 3JQQMF& ff FDU΋ͭͧ͘💪

Slide 51

Slide 51 text

 🧗$44ͷಡΈࠐΈ Ԡ༻ฤ   8FCQBDLͷػೳΛར༻ͯ͠$44ΛಡΈࠐΉ͜ͱ΋Մೳ  ˞8FCQBDLʹ͍ͭͯਂງΓ͍ͨਓ͸ެࣜυΩϡϝϯτΛࢀরXFCQBDLKTPSH CVJMEHSBEMFLUTͱಉ͡֊૚ʹ XFCQBDLDPO fi HEͱ͍͏σΟϨΫτϦΛ࡞੒ XFCQBDLDPO fi HEҎԼͷ+4ϑΝΠϧͰ ௨ৗͷ8FCϑϩϯτ։ൃͱಉ͡Α͏ʹ 8FCQBDLͷઃఆΛࣗ༝ʹهड़͢Δ͜ͱ͕Մೳ😆

Slide 52

Slide 52 text

 🧗$44ͷಡΈࠐΈ Ԡ༻ฤ   8FCQBDLͷػೳΛར༻ͯ͠$44ΛಡΈࠐΉ͜ͱ΋Մೳ  ˞8FCQBDLʹ͍ͭͯਂງΓ͍ͨਓ͸ެࣜυΩϡϝϯτΛࢀরXFCQBDLKTPSH const sass = require('sass'); config.entry.main.push(path.resolve(rootPath, 'web/app/src/jsMain/resources/app.scss')); config.module.rules.push({ test: /\.scss$/, use: [ { loader: 'sass-loader', options: { implementation: sass, webpackImporter: false, sassOptions: { includePaths: [nodeModulePath], }, }, }, ], }); XFCQBDLDPO fi HETBTTKT 4BTTͰهड़ͨ͠ελΠϧγʔτΛಡΈࠐΈ $44ʹίϯύΠϧ͢ΔͨΊʹඞཁͳઃఆ

Slide 53

Slide 53 text

🧗$44ͷಡΈࠐΈ Ԡ༻ฤ   8FCQBDLͷػೳΛར༻ͯ͠$44ΛಡΈࠐΉ͜ͱ΋Մೳ const sass = require('sass'); config.entry.main.push(path.resolve(rootPath, 'web/app/src/jsMain/resources/app.scss')); config.module.rules.push({ test: /\.scss$/, use: [ { loader: 'sass-loader', options: { implementation: sass, webpackImporter: false, sassOptions: { includePaths: [nodeModulePath], }, }, }, ], });   ˞8FCQBDLʹ͍ͭͯਂງΓ͍ͨਓ͸ެࣜυΩϡϝϯτΛࢀরXFCQBDLKTPSH XFCQBDLDPO fi HETBTTKT 8FCQBDLΛར༻͢Δ࠷େͷར఺͸ 4BTT΍-FTT౳ͷ$44ͷϝλݴޠΛ௚઀ར༻Ͱ͖Δ͜ͱ💪 ֎෦Ϟδϡʔϧ͔ΒඞཁͳελΠϧఆٛͷΈΠϯϙʔτ͠ ίϯύΠϧޙͷ$44ͷαΠζΛ࡟ݮ͢Δ͜ͱ΋Ͱ͖Δ💪

Slide 54

Slide 54 text

$PNQPTFGPS8FCͰ؆୯ͳΞϓϦΛ࡞Δ 🚀࡞ͬͨ8FCΞϓϦΛެ։͍ͨ͠ʜʂ - ϏϧυίϚϯυ./gradlew jsBrowserWebpackΛ࣮ߦ  ੜ੒͞Εͨ)5.-ɾ+4ɾͦͷଞϦιʔεΛΑ͠ͳʹϗεςΟϯά  αϯϓϦΞϓϦΛͦͷ··Ϗϧυ͢Δͱ CVJMEEJTUSJCVUJPOTҎԼʹϑΝΠϧ͕ੜ੒͞ΕΔ ϦϦʔε🚀

Slide 55

Slide 55 text

؆୯ɾγϯϓϧͳ8FCΞϓϦ͸ ࣮૷ ϦϦʔε͕Ͱ͖ΔΑ͏ʹͳͬͨ🎉 

Slide 56

Slide 56 text

ෳࡶɾେن໛ͳ8FCΞϓϦ͸ Ͳ͜·Ͱ࣮૷Ͱ͖ΔͷͩΖ͏͔🤔 

Slide 57

Slide 57 text

$PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ 👨🎓ࣄྫ঺հ$0-03.!45&3  ΞΠυϧϚελʔʹొ৔͢ΔΞΠυϧΛݕࡧ ΠϝʔδΧϥʔϓϨϏϡʔ  ͍ͭͲ͜Ͱ΋εϚϗΛϖϯϥΠτԽʂ😆  63-JNBTDPMPSNBTUFSXFCBQQ (JU)VCTVCSPIDPMPSNBTUFS

Slide 58

Slide 58 text

$PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ 👨🎓ࣄྫ঺հ$0-03.!45&3  ΞΠυϧϚελʔʹొ৔͢ΔΞΠυϧΛݕࡧ ΠϝʔδΧϥʔϓϨϏϡʔ  ͍ͭͲ͜Ͱ΋εϚϗΛϖϯϥΠτԽʂ😆  ϦϦʔε౰ॳ͸,PUMJO .6* 3FBDU Ͱ࣮૷ ೥݄ʹ$PNQPTFGPS8FCʹϑϧϦϓϨΠε🕺 63-JNBTDPMPSNBTUFSXFCBQQ (JU)VCTVCSPIDPMPSNBTUFS ˞ॳճϦϦʔε͸೥݄

Slide 59

Slide 59 text

$PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ 👨🎓$0-03.!45&3Ͱ࣮ݱͨ͜͠ͱ ػೳ໘   ը໘ભҠͷεϜʔζͳ41"  ͔ͳΓਅ໘໨ʹ ϨεϙϯγϒରԠ  μʔΫςʔϚɾଟݴޠ +"&/ ରԠ  (PPHMFΞΧ΢ϯτͱͷ࿈ܞ 
 ਪ͠ͷΞΠυϧͷొ࿥ɾӾཡΛ࣮ݱ  μʔΫςʔϚ μʔΫςʔϚ ӳޠදࣔ ࢒ΓͰ͖͍ͯͳ͍ͷ͸ɺ443ͷಋೖʹΑΔ ॳظඳըͷߴ଎Խɾ4&0ڧԽ͘Β͍ʜʁ🧐

Slide 60

Slide 60 text

$PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ ɹ$0-03.!45&3Ͱར༻͍ͯ͠ΔϥΠϒϥϦ  ,UPS)UUQΫϥΠΞϯτ  LPUMJOYTFSJBMJ[FS+40/γϦΞϥΠβσγϦΞϥΠβ  LPUMJOYDPSPVUJOFTඇಉظॲཧ  LPJO%FQFOEFODZ*OKFDUJPOϥΠϒϥϦ  +FUQBDL$PNQPTF $PNQPTFGPS8FC 6*ϑϨʔϜϫʔΫ  %FDPNQPTFϧʔςΟϯά ۀ຿ϩδοΫίϯϙʔωϯτͷ੾Γ෼͚  ,PUFTUςετϑϨʔϜϫʔΫ  ˞$0-03.!45&3Ͱ͸ϧʔςΟϯάػೳͷΈ࢖༻ શͯͷϥΠϒϥϦ͕.11ʹެࣜରԠ😎

Slide 61

Slide 61 text

ɹ$0-03.!45&3Ͱར༻͍ͯ͠ΔϥΠϒϥϦ  NBUFSJBMDPNQPOFOUTXFC.BUFSJBM%FTJHO४ڌͷ6*ϑϨʔϜϫʔΫ  JOFYUݴޠϦιʔε੾Γସ͑  'JSFCBTF+44%,(PPHMFΞΧ΢ϯτ࿈ܞ 'JSFTUPSFΫϥΠΞϯτ  XFCQBDLDEOQMVHJOIUNMXFCQBDLQMVHJOόϯυϧαΠζ࡟ݮ $PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  +BWB4DSJQU੡ϥΠϒϥϦ΁ͷґଘ͸جຊ͜Ε͚ͩ .11ରԠͷϥΠϒϥϦΛϑϧ׆༻͢Ε͹ɺ+BWB4DSJQUͷࢿ࢈ʹཔΒͣͱ΋ ͦΕͳΓͷن໛ͷ8FCΞϓϦ͸࣮૷Ͱ͖Δ👍

Slide 62

Slide 62 text

$PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  👨🎓$0-03.!45&3ͷ࣮૷ղઆ  :sharedϞδϡʔϧҎԼͷσΟϨΫτϦߏ੒

Slide 63

Slide 63 text

👨🎓$0-03.!45&3ͷ࣮૷ղઆ  :sharedϞδϡʔϧҎԼͷσΟϨΫτϦߏ੒ 🗂EBUB  🗂BQJΠϯϑϥ૚ˠ֎෦αʔϏεͱͷ઀ଓ෦෼ͷ࣮૷  📦BVUIFOUJDBUJPOˠ(PPHMFϩάΠϯͷ࣮૷  📦 fi SFTUPSFˠ'JSFTUPSFΫϥΠΞϯτ  📦JNBTQBSRMˠJN!TQBSRMΫϥΠΞϯτ  📦KT fi SFCBTFBQQˠ'JSFCBTF+44%,ͷܕఆٛ  📦NPEFM  📦SFQPTJUPSZ ΞΠϚεͷ༷ʑͳ৘ใΛΫΤϦݴޠɾ41"32-Ͱ ݕࡧͰ͖ΔϑΝϯϝΠυͷ֎෦αʔϏε )1TQBSRMDSTTOLZYZ[JNBT (JUIVCJNBTJNBTQBSRM $PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  ϓϥοτϑΥʔϜຖͷࠩҟΛٵऩ͠ɺ υϝΠϯɾΞϓϦέʔγϣϯ૚ͱ ֎෦αʔϏεΛૄ݁߹ͳঢ়ଶʹอͭ ˞ ˞

Slide 64

Slide 64 text

👨🎓$0-03.!45&3ͷ࣮૷ղઆ  :sharedϞδϡʔϧҎԼͷσΟϨΫτϦߏ੒ 🗂EBUB  🗂BQJ  📦BVUIFOUJDBUJPO  📦 fi SFTUPSF  📦JNBTQBSRM  📦KT fi SFCBTFBQQ  📦NPEFMυϝΠϯ૚ˠۀ຿ϩδοΫදݱ༻ͷΫϥεఆٛ  📦SFQPTJUPSZυϝΠϯ૚ˠ$36%ૢ࡞ͷఆٛɾந৅Խ $PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  ϓϥοτϑΥʔϜʹґଘ͠ͳ͍ EBUBDMBTTɾϩδοΫͷఆٛ Ұ෦ྫ֎Λআ͖ɺcommonMainʹͷΈ ίʔυ͕ଘࡏ͢Δঢ়ଶͱͳΔ

Slide 65

Slide 65 text

👨🎓$0-03.!45&3ͷ࣮૷ղઆ  :sharedϞδϡʔϧҎԼͷσΟϨΫτϦߏ੒ 🗂EBUB  🗂BQJ  📦BVUIFOUJDBUJPO  📦 fi SFTUPSF  📦JNBTQBSRM  📦KT fi SFCBTFBQQ  📦NPEFM  📦SFQPTJUPSZ $PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  💡,PUMJO.11ͷίϯηϓτͰ͋Δ ۀ຿ϩδοΫͷڞ௨ԽΛ ࣮ݱ͍ͯ͠ΔྖҬ

Slide 66

Slide 66 text

👨🎓$0-03.!45&3ͷ࣮૷ղઆ  :sharedϞδϡʔϧҎԼͷσΟϨΫτϦߏ੒ 🗂DPNQPOFOUT  📦DPSF 🗂GFBUVSFT  📦IPNF  📦NZJEPMT  📦QSFWJFX  📦TFBSDI $PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  ͦͷଞʹ΋ڞ௨Խίʔυ͕ଘࡏ🤔

Slide 67

Slide 67 text

👨🎓$0-03.!45&3ͷ࣮૷ղઆ  :sharedϞδϡʔϧҎԼͷσΟϨΫτϦߏ੒ 🗂DPNQPOFOUTओʹ%*पΓͷίʔυఆٛ  📦DPSF 🗂GFBUVSFT  📦IPNF  📦NZJEPMT  📦QSFWJFX  📦TFBSDI $PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  .11ରԠͷ%*ϥΠϒϥϦɾ,PJOʹΑΔ Πϯϑϥ૚ɾυϝΠϯ૚ͷΫϥεͷ ґଘੑ஫ೖॲཧΛهड़ ΞϓϦέʔγϣϯ૚͔Β υϝΠϯ૚ͷίʔυͷΈࢀরՄೳͳ ঢ়ଶΛอͭͨΊʹ༻ҙ👍 LPJO*OTFSU,PJO*0LPJO

Slide 68

Slide 68 text

👨🎓$0-03.!45&3ͷ࣮૷ղઆ  :sharedϞδϡʔϧҎԼͷσΟϨΫτϦߏ੒ $PNQPTFGPS8FCͰෳࡶͳΞϓϦΛ࡞Δ  🗂DPNQPOFOUT  📦DPSF 🗂GFBUVSFTϓϨθϯςʔγϣϯ૚  📦IPNF  📦NZJEPMT  📦QSFWJFX  📦TFBSDI ΞϓϦέʔγϣϯ͕ఏڙ͢Δػೳຖʹ 6*ϩδοΫΛఆٛɾ࣮૷ $PNQPTF.VMUJQMBUGPSNΛར༻͠ 6*ϩδοΫ·Ͱڞ௨Խ💪

Slide 69

Slide 69 text

 🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷத਎ @Composable fun rememberSearchIdolsUseCase( params: SearchParams, language: Languages = CurrentLocalLanguage(), koinApp: KoinApplication = CurrentLocalKoinApp(), ): State { val scope = rememberCoroutineScope() val repository: IdolColorsRepository by remember(koinApp) { mutableStateOf(koinApp.koin.get()) } return produceState( initialValue = LoadState.Initialize, params, ) { val job = scope.launch(start = CoroutineStart.LAZY) { runCatching { repository.search(params, language) } .onSuccess { value = LoadState.Loaded(it) } .onFailure { value = LoadState.Error(it) } } value = LoadState.Loading job.start() } } 4FBSDI*EPMT6TF$BTFLU ྫ໊લ͔ΒΞΠυϧΛݕࡧ͢ΔϩδοΫ ˞commonMain಺Ͱͷ࣮૷ίʔυ

Slide 70

Slide 70 text

🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷத਎ @Composable fun rememberSearchIdolsUseCase( params: SearchParams, language: Languages = CurrentLocalLanguage(), koinApp: KoinApplication = CurrentLocalKoinApp(), ): State { val scope = rememberCoroutineScope() val repository: IdolColorsRepository by remember(koinApp) { mutableStateOf(koinApp.koin.get()) } return produceState( initialValue = LoadState.Initialize, params, ) { val job = scope.launch(start = CoroutineStart.LAZY) { runCatching { repository.search(params, language) } .onSuccess { value = LoadState.Loaded(it) } .onFailure { value = LoadState.Error(it) } } value = LoadState.Loading job.start() } }  4FBSDI*EPMT6TF$BTFLU paramsݕࡧΫΤϦ จࣈྻΛอ࣋͢ΔEBUBDMBTT  languagesݱࡏͷݴޠઃఆ koinAppLPJOͷίϯςφΠϯελϯε

Slide 71

Slide 71 text

🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷத਎ @Composable fun rememberSearchIdolsUseCase( params: SearchParams, language: Languages = CurrentLocalLanguage(), koinApp: KoinApplication = CurrentLocalKoinApp(), ): State { val scope = rememberCoroutineScope() val repository: IdolColorsRepository by remember(koinApp) { mutableStateOf(koinApp.koin.get()) } return produceState( initialValue = LoadState.Initialize, params, ) { val job = scope.launch(start = CoroutineStart.LAZY) { runCatching { repository.search(params, language) } .onSuccess { value = LoadState.Loaded(it) } .onFailure { value = LoadState.Error(it) } } value = LoadState.Loading job.start() } }  4FBSDI*EPMT6TF$BTFLU LPJOͷίϯςφΠϯελϯε͔Β 3FQPTJUPSZͷΠϯελϯεΛऔಘ

Slide 72

Slide 72 text

🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷத਎ @Composable fun rememberSearchIdolsUseCase( params: SearchParams, language: Languages = CurrentLocalLanguage(), koinApp: KoinApplication = CurrentLocalKoinApp(), ): State { val scope = rememberCoroutineScope() val repository: IdolColorsRepository by remember(koinApp) { mutableStateOf(koinApp.koin.get()) } return produceState( initialValue = LoadState.Initialize, params, ) { val job = scope.launch(start = CoroutineStart.LAZY) { runCatching { repository.search(params, language) } .onSuccess { value = LoadState.Loaded(it) } .onFailure { value = LoadState.Error(it) } } value = LoadState.Loading job.start() } }  4FBSDI*EPMT6TF$BTFLU produceStateϝιου ˠҾ਺params͕มԽͨ࣌͠ʹϒϩοΫ಺ͷTVTQFOEؔ਺Λ࣮ߦ͠ ঢ়ଶΛࣗಈߋ৽͢Δ4UBUFܕͷΠϯελϯεΛฦ͢ ˞4UBUFͱ͸ʁ +FUQBDL$PNQPTF͕ఏڙ͢Δ ঢ়ଶ؅ཧ༻ͷΠϯλʔϑΣʔε SFGEFWFMPQFSBOESPJEDPNSFGFSFODFLPUMJOBOESPJEYDPNQPTFSVOUJNF4UBUF

Slide 73

Slide 73 text

🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷத਎ @Composable fun rememberSearchIdolsUseCase( params: SearchParams, language: Languages = CurrentLocalLanguage(), koinApp: KoinApplication = CurrentLocalKoinApp(), ): State { val scope = rememberCoroutineScope() val repository: IdolColorsRepository by remember(koinApp) { mutableStateOf(koinApp.koin.get()) } return produceState( initialValue = LoadState.Initialize, params, ) { val job = scope.launch(start = CoroutineStart.LAZY) { runCatching { repository.search(params, language) } .onSuccess { value = LoadState.Loaded(it) } .onFailure { value = LoadState.Error(it) } } value = LoadState.Loading job.start() } }  4FBSDI*EPMT6TF$BTFLU ݕࡧΫΤϦͷQPTU ݁ՌͷऔಘΛ࣮ߦ͢ΔTVTQFOEͳؔ਺ ݕࡧΫΤϦ͕มԽ͢Δ౓ʹɺ͜ͷؔ਺͕ࣗಈ࣮ߦ͞ΕΔ -PBE4UBUFΫϥεˠඇಉظॲཧͷঢ়ଶΛද͢ sealed class LoadState { object Initialize : LoadState() object Loading : LoadState() data class Loaded(val value: T) : LoadState() data class Error(val error: Throwable) : LoadState() }

Slide 74

Slide 74 text

🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷݺͼग़͠ํ  @Composable fun FrontLayerContent( params: SearchParams, coroutineScope: CoroutineScope, backdropScaffoldState: BackdropScaffoldState, snackbarHostState: SnackbarHostState, launchPreviewScreen: (ScreenType, List) -> Unit, ) { val idolColorLoadState by rememberSearchIdolsUseCase(params) val items = idolColorLoadState.getValueOrNull() ?: listOf() Column { SearchStateLabel( params, idolColorLoadState, // 検索結果の表示UIの描画 // ...略 ) } } @Composable fun FrontLayer( backdropState: MutableState, isSignedIn: Boolean, params: SearchParams, ) { // ...略 val idolColorLoadState by rememberSearchIdolsUseCase(params) SearchResultList( isSignedIn, idolColorLoadState, // 検索結果の表示UIの描画 // ...略 ) } 'SPOU-BZFSLU 'SPOU-BZFS$POUFOULU

Slide 75

Slide 75 text

🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷݺͼग़͠ํ  @Composable fun FrontLayerContent( params: SearchParams, coroutineScope: CoroutineScope, backdropScaffoldState: BackdropScaffoldState, snackbarHostState: SnackbarHostState, launchPreviewScreen: (ScreenType, List) -> Unit, ) { val idolColorLoadState by rememberSearchIdolsUseCase(params) val items = idolColorLoadState.getValueOrNull() ?: listOf() Column { SearchStateLabel( params, idolColorLoadState, // 検索結果の表示UIの描画 // ...略 ) } } @Composable fun FrontLayer( backdropState: MutableState, isSignedIn: Boolean, params: SearchParams, ) { // ...略 val idolColorLoadState by rememberSearchIdolsUseCase(params) SearchResultList( isSignedIn, idolColorLoadState, // 検索結果の表示UIの描画 // ...略 ) } 'SPOU-BZFSLU 'SPOU-BZFS$POUFOULU ݕࡧ݁Ռͷऔಘ 8FC ݕࡧ݁Ռͷऔಘ "OESPJE 💡ϒϦοδͷίʔυΛ༻ҙ͢Δ͜ͱͳ͘ ࠷খݶͷهड़Ͱ6*ϩδοΫ ঢ়ଶ؅ཧʹΞΫηε😎 ˠϓϥοτϑΥʔϜݻ༗ͷ෦෼΋ಉ͡ϑϨʔϜϫʔΫΛར༻ ϒϦοδͷͭΒΈΛղফ🎉ݻ༗෦෼ͷ࣮૷ʹΑΓਂ͘஫ྗ🎉

Slide 76

Slide 76 text

🛠ڞ௨Խ͞Εͨ6*ϩδοΫͷݺͼग़͠ํ  @Composable fun FrontLayerContent( params: SearchParams, coroutineScope: CoroutineScope, backdropScaffoldState: BackdropScaffoldState, snackbarHostState: SnackbarHostState, launchPreviewScreen: (ScreenType, List) -> Unit, ) { val idolColorLoadState by rememberSearchIdolsUseCase(params) val items = idolColorLoadState.getValueOrNull() ?: listOf() Column { SearchStateLabel( params, idolColorLoadState, // 検索結果の表示UIの描画 // ...略 ) } } @Composable fun FrontLayer( backdropState: MutableState, isSignedIn: Boolean, params: SearchParams, ) { // ...略 val idolColorLoadState by rememberSearchIdolsUseCase(params) SearchResultList( isSignedIn, idolColorLoadState, // 検索結果の表示UIの描画 // ...略 ) } 'SPOU-BZFSLU 'SPOU-BZFS$POUFOULU ݕࡧ݁Ռͷऔಘ 8FC ݕࡧ݁Ռͷऔಘ "OESPJE 💡ϒϦοδͷίʔυΛ༻ҙ͢Δ͜ͱͳ͘ ࠷খݶͷهड़Ͱ6*ϩδοΫ ঢ়ଶ؅ཧʹΞΫηε😎 ˠϓϥοτϑΥʔϜݻ༗ͷ෦෼΋ಉ͡ϑϨʔϜϫʔΫΛར༻ ϒϦοδͷͭΒΈΛղফ🎉ݻ༗෦෼ͷ࣮૷ʹΑΓਂ͘஫ྗ🎉 ,PUMJO΍ͬͺΓఱ࠽͔ʜʁ🥰 ΋͏ੈքͷશͯΛ,PUMJOͰॻ͚͹ ͑͑ͷͰ͸ʜʁ🤔 ओޠσΧൃݴ

Slide 77

Slide 77 text

,PUMJO+4ʹΑΔ 8FCϑϩϯτΤϯυ։ൃͷ௕ॴɾ୹ॴ ࠓޙͷల๬ 

Slide 78

Slide 78 text

,PUMJO+4Ͱͷ8FCϑϩϯτ։ൃ௕ॴ 👍ϩδοΫͷڞ௨ԽΛ޿ൣғͰ࣮ݱͰ͖Δ  $PNQPTF.VMUJQMBUGPSNͷొ৔ʹΑΓɺ6*ϩδοΫͷڞ௨Խ΋ݱ࣮తʹ  ʮ8FCͰͱΓ͋͑ͣϦϦʔεˠ࢖ΘΕͦ͏ͳͷͰϞόΠϧΛ࣮૷ʯͷ 
 ϏδωεϓϩμΫτཁٻʹૉૣ͘ରԠ͢Δ͜ͱ͕Ͱ͖Δ 👍,PUMJOͷ๛෋ͳදݱྗ +7.ͷܕγεςϜͰ8FCΞϓϦΛ࣮૷Ͱ͖Δ  ϩδοΫͱ6*͕ಉ͡ݴޠͰ࣮૷ˠίϯςΩετεΠονͷ੾Γସ͕͑ෆཁ  5ZQF4DSJQUͷܕγεςϜʹ͸ͳ͍ԸܙΛಘΔ͜ͱ͕Ͱ͖Δ   5ZQF4DSJQUͷܕγεςϜ ਖ਼௚͋·Γͬ͘͠Γ͖ͯͳ͍ʜ😇 ˞ݸਓͷײ૝Ͱ͢

Slide 79

Slide 79 text

,PUMJO+4Ͱͷ8FCϑϩϯτ։ൃ୹ॴ 😢ݟͨ໨෦෼ͷ࣮૷ʹ$44ͷ஌ࣝΛཁٻ͞ΕΔ  $PNQPTFGPS8FCͰ͸.PEJ fi FS͸ݪଇ࢖༻ෆՄ˞QSFWJFXͷػೳͰ͸ར༻Մೳɺޙड़ 😢+BWB4DSJQU੡Ϟδϡʔϧͷར༻ʹͻͱख͔͔ؒΔ  +BWB4DSJQUͷΦϒδΣΫτɾϝιουͷར༻ʹ͸,PUMJOͰͷܕఆ͕ٛඞཁ  .11ରԠͷ,PUMJO੡ϥΠϒϥϦͳΒ˕ɺ͔͠͠ࢿ࢈ͷྔ͸ 😢ෳࡶͳ͜ͱΛ͠Α͏ͱͨ࣌͠ɺ8FCQBDLͷઃఆΛ͍͡Δඞཁ͕͋Δ  ϏϧυγεςϜͷ஌ࣝΛ਎ʹண͚Δͷ͸ɺجຊͲͷྖҬͰ΋ϋʔυ  "OESPJEΤϯδχΞʹͱͬͯ ࠷େͷࢀೖোน😖

Slide 80

Slide 80 text

,PUMJO+4ͷաڈ ḪΔ͜ͱ೥ʜ  ,PUMJO'FTUͰ ,PUMJO 3FBDUͰͷ8FCΞϓϦ࣮૷ ʹ͍ͭͯ঺հ

Slide 81

Slide 81 text

,PUMJO+4ͷաڈ ḪΔ͜ͱ೥ʜίʔυҎ֎Կ΋ͳ͔ͬͨ😇  ೥݄࣌఺ͰެࣜͷυΩϡϝϯτ͸ϖʔδ ެࣜͷϋϯζΦϯ͸ͭ΋ͳ͠🥺 *OUFMMJ+*%&"Ͱ਽ܗ࡞ͬͯ΋ ίϚϯυൃͰಈ͔ͳ͍🥺

Slide 82

Slide 82 text

,PUMJO+4ͷաڈ ḪΔ͜ͱ೥ʜίʔυҎ֎Կ΋ͳ͔ͬͨ😇  +BWB4DSJQU੡ϥΠϒϥϦͷϥούʔूCZ+FU#SBJOT .6*΍#PPUTUSBQͷϥούʔͳ͍Μ͔ʜ😢 ೥݄࣌఺  ࢓ํͳ͘ .6*ͷϥούʔΛࣗΒ࣮૷ ϥΠϒϥϦͱͯ͠ެ։ ˞ϝϯς͠ΜͲ͔ͬͨ😇

Slide 83

Slide 83 text

,PUMJO+4ͷݱࡏ ೥ؒͷ,PUMJO+4ͷਐԽ ൈਮ  ,PUMJO🚀  ,PUMJO+4OFX*3DPNQJMFSЋ൛ϦϦʔεɻόϯυϧαΠζͷେ෯ͳ࡟ݮ 5ZQF4DSJQUͷܕఆٛϑΝΠϧੜ੒ɻ  (SBEMF%4-΁ͷػೳ௥Ճɻbinaries.executable()cssSupport(dev|optional|peer)Npm౳ɻ ,PUMJO🚀  (SBEMF%4-΁ͷػೳ௥Ճɻpackage.jsonΛ(SBEMFεΫϦϓτ಺ͰΧελϚΠζͰ͖ΔΑ͏ʹɻ ,PUMJO🚀  ϑϨʔϜϫʔΫɾϥΠϒϥϦ޲͚ͷϏϧυͰOFX*3DPNQJMFS͕ར༻Մೳʹɻ ,PUMJO🚀  ,PUJO+4OFX*3DPNQJMFSЌ൛ϦϦʔεɻ8FCϑϩϯτ։ൃʹ͓͚Δσόοάػೳͷվળɻ ,PUMJO🚀  importจʹΑΔ+BWB4DSJQUϞδϡʔϧͷಈతಡΈࠐΈʹରԠɻOFX*3DPNQJMFSͷύϑΥʔϚϯεվળɻ  $PNQPTFGPS8FCςΫχΧϧϓϨϏϡʔ൛ϦϦʔε $PNQPTF.VMUJQMBUGPSNЋ൛ˠЌ൛ˠ4UBCMF൛ϦϦʔε $PNQPTF.VMUJQMBUGPSNϦϦʔε (dev|optional|peer)Npm͸ ͕௥Ճ😎 ,PUMJOຊମͷϦϦʔεͷ౓ʹ ຖճԿ͔͠Βͷػೳ௥Ճɾվળ͕͞Ε͍ͯΔ✨

Slide 84

Slide 84 text

,PUMJO+4ͷݱࡏ ެࣜυΩϡϝϯτͷॆ࣮  ެࣜυΩϡϝϯτ ೥݄ϖʔδˠ೥݄ϖʔδ😆 ެࣜͷϋϯζΦϯ΋௥Ճ😆 -JOLQMBZLPUMJOMBOHPSHIBOETPOPWFSWJFX

Slide 85

Slide 85 text

,PUMJO+4ͷݱࡏ ϥΠϒϥϦͷॆ࣮  +BWB4DSJQU੡ϥΠϒϥϦͷϥούʔूCZ+FU#SBJOT ೥݄ݸˠ೥݄ݸ🤩 .6*ͷϥούʔϥΠϒϥϦ΋௥Ճ🥳 💡,PUMJO.11ͷߏ੒ཁૉͷͭͱͯ͠ண࣮ʹΞοϓσʔτ ,PUMJO+4ʹΑΔ8FCϑϩϯτ։ൃͷମݧ͸ ೔ʑ޲্͠ଓ͚͍ͯΔ😎

Slide 86

Slide 86 text

,PUMJO+4ͷࠓޙͷల๬ 💫OFX*3DPNQJMFSͷ4UBCMF൛ϦϦʔε  όϯυϧαΠζ࡟ݮɺ+4ίʔυ΁ͷτϥϯεύΠϧߴ଎Խʹେ͖͘ߩݙ  ΠϯΫϦϝϯλϧίϯύΠϧ +4ͱͷ૬ޓӡ༻ੑʹ஫ྗ͠ɺ҆ఆԽ  ͜ͷλεΫ͕׬ྃ͢Δͱɺ&4ରԠ͕࠶։͞ΕΔ ͸ͣ  💫$PNQPTFGPS8FCͷ4LJBରԠ  $PNQPTFGPS8FCͰ΋.PEJ fi FSΛ࢖ͬͨ 
 6*࣮૷͕Մೳʹ  ˞,PUMJO࣌఺Ͱ͸Ќ൛ ˞$PNQPTF.VMUJQMBUGPSN࣌఺Ͱ͸1SFWJFX൛ ཁνΣοΫʂ 😉 Ϟμϯ+4ͱͷ૬ޓӡ༻ੑ͕ େ͖͘ߴ·Δ ͸ͣ 

Slide 87

Slide 87 text

·ͱΊ 🐦,PUMJO+4ʹΑΔϞμϯͳ8FCΞϓϦ։ൃͷखॱɾ࣮ྫΛ঺հ  LPUMJOSFBDU$PNQPTFGPS8FCΛར༻͢Δ͜ͱͰ࣮ݱՄೳ  ϞόΠϧͱͷ޿ൣғʹٴͿίʔυڞ௨ԽʹΑΓɺແೋͷԸܙΛಘΒΕΔ 🐦,PUMJO+4ͷΞοϓσʔτཤྺɾࠓޙͷల๬Λ঺հ  OFX*3DPNQJMFS$PNQPTFGPS8FCʹΑΓɺ։ൃऀମݧ͕େ෯ʹ޲্  ਐԽΛ଴ͭஈ֊͔ΒಋೖࣄྫΛ૿΍͢ஈ֊ʹ طʹೖΓ࢝Ί͍ͯΔͷͰ͸ʜʁ🤔

Slide 88

Slide 88 text

·ͱΊ 🐦,PUMJO+4ʹΑΔϞμϯͳ8FCΞϓϦ։ൃͷखॱɾ࣮ྫΛ঺հ  LPUMJOSFBDU$PNQPTFGPS8FCΛར༻͢Δ͜ͱͰ࣮ݱՄೳ  ϞόΠϧͱͷ޿ൣғʹٴͿίʔυڞ௨ԽʹΑΓɺແೋͷԸܙΛಘΒΕΔ 🐦,PUMJO+4ͷΞοϓσʔτཤྺɾࠓޙͷల๬Λ঺հ  OFX*3DPNQJMFS$PNQPTFGPS8FCʹΑΓɺ։ൃऀମݧ͕େ෯ʹ޲্  ,PUMJOͰ8FCϑϩϯτΤϯυͷੈքΛ೷͖ɺֶͿͷ͸ͱͯ΋ָ͍͠ʂ ੋඇ͋ͳͨ΋ɺ,PUMJO+4ͰΞΠσΟΞΛܗʹͯ͠Έ·ͤΜ͔ʁ☺ 5IBOLZPVGPSMJTUFOJOH