Upgrade to PRO for Only $50/Yearโ€”Limited-Time Offer! ๐Ÿ”ฅ

[KR] Jetpack Compose Structure and Stability

Avatar for Jaewoong Jaewoong
September 04, 2024

[KR] Jetpack Compose Structure andย Stability

Jetpack Compose Structure and Stability

Avatar for Jaewoong

Jaewoong

September 04, 2024
Tweet

More Decks by Jaewoong

Other Decks in Programming

Transcript

  1. G E T S T R E A M .

    I O Jetpack Compose Structure and Stability
  2. G E T S T R E A M .

    I O skydoves @github_skydoves Lead Android Developer Advocate @ Stream Jaewoong Eum
  3. G E T S T R E A M .

    I O Index 1. Compose Structure 2. Declarative UI 3. Composable Functions 4. Stability in Compose
  4. G E T S T R E A M .

    I O Jetpack Compose
  5. G E T S T R E A M .

    I O Jetpack Compose
  6. G E T S T R E A M .

    I O Jetpack Compose Structure Code Transformation In-memory Representation Rendering Layout Trees
  7. G E T S T R E A M .

    I O Jetpack Compose Structure Compose Compiler โ€ข Jetpack Compose ๋‚ด์—์„œ ์ค‘์ถ”์ ์ธ ์—ญํ• ์„ ํ•˜๋Š” ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ โ€ข ์ˆœ์ˆ˜ํ•œ Kotlin์œผ๋กœ ์ž‘์„ฑ๋œ Kotlin ์ปดํŒŒ์ผ๋Ÿฌ ํ”Œ๋Ÿฌ๊ทธ์ธ โ€ข KAPT๋‚˜ KSP์™€ ๊ฐ™์€ annotation processor์™€๋Š” ๋‹ฌ๋ฆฌ, Compose ์ปดํŒŒ์ผ๋Ÿฌ๋Š” FIR ๎‚Frontend Intermediate Representation)์„ ํ†ตํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ์ •์  ๋ถ„์„ ๋ฐ ๋ณ€ํ˜•
  8. G E T S T R E A M .

    I O Jetpack Compose Structure Compose Runtime โ€ข Compose ๋ชจ๋ธ ๋ฐ ์ƒํƒœ ๊ด€๋ฆฌ์˜ ์ดˆ์„ ์—ญํ•  โ€ข Gap Buffer๋ผ๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์—์„œ ํŒŒ์ƒ๋œ Slot Table์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ ์ €์žฅ ๋“ฑ ๋ฉ”๋ชจ๋ฆฌ ์šด์šฉ โ€ข Composable ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์‹ค์งˆ์ ์ธ ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ ๋ฐ UI์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ‘œํ˜„
  9. G E T S T R E A M .

    I O Jetpack Compose Structure Compose UI โ€ข ๊ฐœ๋ฐœ์ž๊ฐ€ Composable ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ ˆ์ด์•„์›ƒ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ ์ œ๊ณต โ€ข ๊ฐ ์ปดํฌ๋„ŒํŠธ๋Š” LayoutNode๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฒฐ๊ณผ์ ์œผ๋กœ Compose ๋ ˆ์ด์•„์›ƒ ํŠธ๋ฆฌ ๊ตฌ์„ฑ์„ ์šฉ์ดํ•˜๊ฒŒ ํ•จ โ€ข Compose Runtime์— ์˜ํ•˜์—ฌ ์†Œ๋น„๋˜๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ ์›์น™
  10. G E T S T R E A M .

    I O Jetpack Compose Structure Compose Compiler ์ปดํฌ์ฆˆ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” Jetpack Compose์˜ ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ๋กœ, Kotlin์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์œผ๋ฉฐ Kotlin Multiplatform์„ ๋Œ€์ƒ์œผ๋กœ ํ•จ. KAPT์™€ KSP ๊ฐ™์€ ์ „ํ†ต์ ์ธ ์–ด๋…ธํ…Œ์ด์…˜ ์ฒ˜๋ฆฌ ๋„๊ตฌ์™€ ๋‹ฌ๋ฆฌ, ์ปดํฌ์ฆˆ ์ปดํŒŒ์ผ๋Ÿฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ FIR๎‚Frontend Intermediate Representation)์„ ์ง์ ‘ ๋‹ค๋ฃธ. Compose Runtime ์ปดํฌ์ฆˆ ๋Ÿฐํƒ€์ž„์€ ์ปดํฌ์ฆˆ์˜ ๋ชจ๋ธ ๋ฐ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์ค‘์ถ”์ ์ธ ์—ญํ• ์„ ์ˆ˜ํ–‰. SlotTable์ด๋ผ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด Composable ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , State(์ƒํƒœ)๋ฅผ ๊ด€๋ฆฌํ•˜์—ฌ Composable ํ•จ์ˆ˜๋ฅผ ์žฌ์‹คํ–‰ ์‹œํ‚ค๋Š” ๋“ฑ ๋Ÿฐํƒ€์ž„ ๋™์ž‘์— ๊ด€์—ฌ. Compose UI ์ปดํฌ์ฆˆ UI๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ Composable ํ•จ์ˆ˜๋กœ UI๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” UI ์ปดํฌ๋„ŒํŠธ๋“ค์˜ ์ง‘ํ•ฉ์ฒด. ์ปดํฌ์ฆˆ UI๋Š” Compose์˜ ๋ ˆ์ด์•„์›ƒ ํŠธ๋ฆฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋‹ค์–‘ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์ด ๋ ˆ์ด์•„์›ƒ ํŠธ๋ฆฌ๋Š” ์ปดํฌ์ฆˆ ๋Ÿฐํƒ€์ž„์— ์˜ํ•ด ์‚ฌ์šฉ๋จ.
  11. G E T S T R E A M .

    I O Declarative UI
  12. G E T S T R E A M .

    I O Declarative UI 1. ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๋กœ ๊ตฌ์„ฑ ์š”์†Œ ์ •์˜ ๊ฐœ๋ฐœ์ž๋Š” ํ•„์ˆ˜ ๊ธฐ๋Šฅ(๋น„์ฆˆ๋‹ˆ์Šค ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋“ฑ)๊ณผ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์š”์†Œ(๋ ˆ์ด์•„์›ƒ)๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋™์‹œ์—, XML๊ณผ Java, Kotlin๊ณผ ๊ฐ™์€ ๋ ˆ์ด์•„์›ƒ ์ •์˜ ๋ถ€๋ถ„๊ณผ ๋„๋ฉ”์ธ ๊ตฌํ˜„ ๊ฐ„์˜ ์–ธ์–ด์  ๊ฒฉ์ฐจ๋ฅผ ์ค„์—ฌ ์›ํ™œํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐœ๋ฐœ์„ ์ด‰์ง„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. Characteristics
  13. G E T S T R E A M .

    I O Declarative UI 1. ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๋กœ ๊ตฌ์„ฑ ์š”์†Œ ์ •์˜ ๊ฐœ๋ฐœ์ž๋Š” ํ•„์ˆ˜ ๊ธฐ๋Šฅ(๋น„์ฆˆ๋‹ˆ์Šค ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋“ฑ)๊ณผ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์š”์†Œ(๋ ˆ์ด์•„์›ƒ)๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋™์‹œ์—, XML๊ณผ Java, Kotlin๊ณผ ๊ฐ™์€ ๋ ˆ์ด์•„์›ƒ ์ •์˜ ๋ถ€๋ถ„๊ณผ ๋„๋ฉ”์ธ ๊ตฌํ˜„ ๊ฐ„์˜ ์–ธ์–ด์  ๊ฒฉ์ฐจ๋ฅผ ์ค„์—ฌ ์›ํ™œํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐœ๋ฐœ์„ ์ด‰์ง„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. 2. ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ƒํƒœ ๊ด€๋ฆฌ ์„ ์–ธ์  UI์—์„œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์—ฌ๊ธฐ์—๋Š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ์ž‘์—…์ด ํฌํ•จ๋œ๋‹ค. ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ƒํƒœ ๋ณ€ํ™”์— ๋”ฐ๋ผ ๊ฐœ๋ฐœ์ž์— ์˜ํ•ด์„œ๊ฐ€ ์•„๋‹ˆ๋ผ ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด์„œ ์—…๋ฐ์ดํŠธ๋˜์–ด์•ผ ํ•œ๋‹ค. Characteristics
  14. G E T S T R E A M .

    I O Declarative UI 1. ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๋กœ ๊ตฌ์„ฑ ์š”์†Œ ์ •์˜ ๊ฐœ๋ฐœ์ž๋Š” ํ•„์ˆ˜ ๊ธฐ๋Šฅ(๋น„์ฆˆ๋‹ˆ์Šค ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋“ฑ)๊ณผ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์š”์†Œ(๋ ˆ์ด์•„์›ƒ)๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋™์‹œ์—, XML๊ณผ Java, Kotlin๊ณผ ๊ฐ™์€ ๋ ˆ์ด์•„์›ƒ ์ •์˜ ๋ถ€๋ถ„๊ณผ ๋„๋ฉ”์ธ ๊ตฌํ˜„ ๊ฐ„์˜ ์–ธ์–ด์  ๊ฒฉ์ฐจ๋ฅผ ์ค„์—ฌ ์›ํ™œํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐœ๋ฐœ์„ ์ด‰์ง„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. 2. ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ƒํƒœ ๊ด€๋ฆฌ ์„ ์–ธ์  UI์—์„œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์—ฌ๊ธฐ์—๋Š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ์ž‘์—…์ด ํฌํ•จ๋œ๋‹ค. ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ƒํƒœ ๋ณ€ํ™”์— ๋”ฐ๋ผ ๊ฐœ๋ฐœ์ž์— ์˜ํ•ด์„œ๊ฐ€ ์•„๋‹ˆ๋ผ ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด์„œ ์—…๋ฐ์ดํŠธ๋˜์–ด์•ผ ํ•œ๋‹ค. 3. ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์„ฑ ์š”์†Œ์— ์ง์ ‘ ๋ฐ”์ธ๋”ฉ ๋ชจ๋ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ค€์—์„œ UI์— ์ง์ ‘์ ์œผ๋กœ ๋ฐ”์ธ๋”ฉํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ ์–ธ์–ด์™€ ๋™์ผํ•œ ์–ธ์–ด์™€ ๋ ˆ๋ฒจ์—์„œ ์˜จ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. Characteristics
  15. G E T S T R E A M .

    I O Declarative UI 1. ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๋กœ ๊ตฌ์„ฑ ์š”์†Œ ์ •์˜ ๊ฐœ๋ฐœ์ž๋Š” ํ•„์ˆ˜ ๊ธฐ๋Šฅ(๋น„์ฆˆ๋‹ˆ์Šค ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋“ฑ)๊ณผ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์š”์†Œ(๋ ˆ์ด์•„์›ƒ)๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋™์‹œ์—, XML๊ณผ Java, Kotlin๊ณผ ๊ฐ™์€ ๋ ˆ์ด์•„์›ƒ ์ •์˜ ๋ถ€๋ถ„๊ณผ ๋„๋ฉ”์ธ ๊ตฌํ˜„ ๊ฐ„์˜ ์–ธ์–ด์  ๊ฒฉ์ฐจ๋ฅผ ์ค„์—ฌ ์›ํ™œํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐœ๋ฐœ์„ ์ด‰์ง„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. 2. ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ƒํƒœ ๊ด€๋ฆฌ ์„ ์–ธ์  UI์—์„œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์—ฌ๊ธฐ์—๋Š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ์ž‘์—…์ด ํฌํ•จ๋œ๋‹ค. ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ƒํƒœ ๋ณ€ํ™”์— ๋”ฐ๋ผ ๊ฐœ๋ฐœ์ž์— ์˜ํ•ด์„œ๊ฐ€ ์•„๋‹ˆ๋ผ ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด์„œ ์—…๋ฐ์ดํŠธ๋˜์–ด์•ผ ํ•œ๋‹ค. 3. ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์„ฑ ์š”์†Œ์— ์ง์ ‘ ๋ฐ”์ธ๋”ฉ ๋ชจ๋ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ปดํฌ๋„ŒํŠธ ์ˆ˜์ค€์—์„œ UI์— ์ง์ ‘์ ์œผ๋กœ ๋ฐ”์ธ๋”ฉํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ ์–ธ์–ด์™€ ๋™์ผํ•œ ์–ธ์–ด์™€ ๋ ˆ๋ฒจ์—์„œ ์˜จ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. 4. ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ฉฑ๋“ฑ์„ฑ ๋ณด์žฅ ์„ ์–ธ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ฉฑ๋“ฑ์„ฑ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค. ์ฆ‰, ํ•จ์ˆ˜๊ฐ€ ๋ช‡ ๋ฒˆ ์‹คํ–‰๋˜์—ˆ๋Š”์ง€์— ๊ด€๊ณ„์—†์ด ๋™์ผํ•œ ์ธํ’‹์— ๋Œ€ํ•ด์„œ ๊ฒฐ๊ณผ๋Š” ํ•ญ์ƒ ๋™์ผํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค. Characteristics
  16. G E T S T R E A M .

    I O Declarative UI @Composable fun Main() { var count by remember { mutableStateOf(0) } CounterButton(count) { count++ } } @Composable fun CounterButton(count: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("Clicked: $count") } } Learn by samples
  17. G E T S T R E A M .

    I O Declarative UI @Composable fun Main() { var count by remember { mutableStateOf(0) } CounterButton(count) { count++ } } @Composable fun CounterButton(count: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("Clicked: $count") } } Compose Compiler์— ์˜ํ•ด ํ•ด์„ ๋ฐ ๋ณ€ํ™˜๋จ Compile 1. ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๋กœ ๊ตฌ์„ฑ ์š”์†Œ ์ •์˜
  18. G E T S T R E A M .

    I O @Composable fun Main() { var count by remember { mutableStateOf(0) } CounterButton(count) { count++ } } @Composable fun CounterButton(count: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("Clicked: $count") } } Declarative UI Runtime Compose Compiler์— ์˜ํ•ด ํ•ด์„ ๋ฐ ๋ณ€ํ™˜๋จ ๋Ÿฐํƒ€์ž„์—์„œ ์ธ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ๋กœ ํ™œ์šฉ
  19. G E T S T R E A M .

    I O Declarative UI 1. ์ƒํƒœ๋Š” Compose Runtime์—์„œ ๊ด€๋ฆฌ๋จ 2. Compose Runtime์€ ๊ฐ ์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์„ ๊ด€๋ฆฌ. Runtime @Composable fun Main() { var count by remember { mutableStateOf(0) } CounterButton(count) { count++ } } @Composable fun CounterButton(count: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("Clicked: $count") } } 2. ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ƒํƒœ ๊ด€๋ฆฌ
  20. G E T S T R E A M .

    I O Declarative UI @Composable fun Main() { var count by remember { mutableStateOf(0) } CounterButton(count) { count++ } } @Composable fun CounterButton(count: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("Clicked: $count") } } ๋ ˆ์ด์•„์›ƒ ๋…ธ๋“œ๋Š” Compose UI ์ปดํฌ๋„ŒํŠธ์— ์˜ํ•ด ์ƒ์„ฑ Rendering UI
  21. G E T S T R E A M .

    I O Declarative UI @Composable fun Main() { var count by remember { mutableStateOf(0) } CounterButton(count) { count++ } } @Composable fun CounterButton(count: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("Clicked: $count") } } Rendering UI 3. ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์„ฑ ์š”์†Œ์— ์ง์ ‘ ๋ฐ”์ธ๋”ฉ 4. ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ฉฑ๋“ฑ์„ฑ ๋ณด์žฅ
  22. G E T S T R E A M .

    I O Declarative vs. Imperative <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal" android:padding="4dp"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Clicked: 0" /> </RelativeLayout>
  23. G E T S T R E A M .

    I O Declarative vs. Imperative <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal" android:padding="4dp"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Clicked: 0" /> </RelativeLayout> @Composable fun CounterButton(count: Int, onClick: () -> Unit) { Button(onClick = onClick) { Text("Clicked: $count") } }
  24. G E T S T R E A M .

    I O Declarative vs. Imperative var counter = 0 binding.button.setOnClickListener { counter++ binding.button.text = counter.toString() } 1. ์ƒํƒœ๋Š” ๊ด€๋ฆฌ๋˜์–ด์•ผ ํ•˜๋ฉฐ UI ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์ˆ˜๋™์œผ๋กœ ๋ฌดํšจํ™”๋˜์–ด์•ผ ํ•จ. 2. ๋ฐ์ดํ„ฐ๋Š” UI ์„ ์–ธ๊ณผ ์ง์ ‘ ๋ฐ”์ธ๋”ฉ๋  ์ˆ˜ ์—†์Œ. <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal" android:padding="4dp"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Clicked: 0" /> </RelativeLayout>
  25. G E T S T R E A M .

    I O Advantages of Declarative UI 1. UI์™€ ๋„๋ฉ”์ธ ๊ฐ„ ์–ธ์–ด์˜ ์ผ๊ด€์„ฑ ๊ฐœ๋ฐœ์ž๋Š” ํ•„์ˆ˜ ๊ธฐ๋Šฅ๊ณผ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์š”์†Œ๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋™์‹œ์—, XML๊ณผ Java, Kotlin๊ณผ ๊ฐ™์€ ๋„ค์ดํ‹ฐ๋ธŒ ์–ธ์–ด ๊ฐ„์˜ ์–ธ์–ด์  ๊ฒฉ์ฐจ๋ฅผ ์ค„์—ฌ ์›ํ™œํ•œ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐœ๋ฐœ์„ ์ด‰์ง„ํ•  ์ˆ˜ ์žˆ๋‹ค. 2. ์ƒํƒœ ๋ฐ UI ๋ฌดํšจํ™”์˜ ์ž๋™ ๊ด€๋ฆฌ ์ƒํƒœ๋Š” Compose Runtime์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋ฉฐ, UI ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜์—ฌ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋œ๋‹ค. 3. ๋ฉฑ๋“ฑ์„ฑ์„ ํ†ตํ•œ ๊ตฌ์„ฑ ์š”์†Œ ์žฌ์‚ฌ์šฉ์„ฑ ๊ฐ•ํ™” ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋™์ผํ•œ ์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•ด ๋ฉฑ๋“ฑ์„ฑ์„ ๊ฐ€์ง€๋ฏ€๋กœ, ์žฌ์‚ฌ์šฉ์„ฑ์ด ๊ทน๋Œ€ํ™”๋œ๋‹ค. 4. ๋„๋ฉ”์ธ ๋ฐ์ดํ„ฐ์™€ UI ์„ ์–ธ์˜ ์ง์ ‘์ ์ธ ์—ฐ๊ฒฐ ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” "์–ด๋–ป๊ฒŒ ํ•  ๊ฒƒ์ธ๊ฐ€"๋ณด๋‹ค๋Š” "๋ฌด์—‡์„ ํ•  ๊ฒƒ์ธ๊ฐ€"์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
  26. G E T S T R E A M .

    I O Compose vs. XML @Composable fun ComposeList(items: List<String>) { LazyColumn { items(items) { item -> ListItem(text = item) } } } @Composable fun ListItem(text: String) { // Render a single list item } Compose XML <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent" /> class MyAdapter(private val items: List<String>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: .. class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { .. recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = MyAdapter(items)
  27. G E T S T R E A M .

    I O Compose Inspiration
  28. G E T S T R E A M .

    I O Composable Functions
  29. G E T S T R E A M .

    I O Composable Functions The meaning @Composable fun Place(name: String) { // composable code } Layout Node Composable tree
  30. G E T S T R E A M .

    I O Composable Functions The meaning @Composable fun Place(name: String) { // composable code }
  31. G E T S T R E A M .

    I O Composable Functions @Composable fun Place(name: String) { Person(name) } @Composable fun Person(name: String) { // composable code } fun place(name: String) { Person(name) } @Composable fun Person(name: String) { // composable code } โœ… โŒ Calling Context
  32. G E T S T R E A M .

    I O Composable Functions Calling Context โ€ข ์ปดํฌ์ฆˆ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” Composable ํ•จ์ˆ˜์˜ ์ค‘๊ฐ„ ํ‘œํ˜„๎‚IR, Intermediate Representation)์„ ๋ณ€ํ™˜ โ€ข ๋ชจ๋“  Composable ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰์— `$composer`๋ผ๋Š” ์ƒˆ๋กœ์šด ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ โ€ข `$composer` ์ธ์Šคํ„ด์Šค๋Š” Composable ํ•จ์ˆ˜์™€ ์ปดํฌ์ฆˆ ๋Ÿฐํƒ€์ž„ ์‚ฌ์ด์—์„œ ์ค‘์žฌ ์—ญํ• ์„ ๋‹ด๋‹น
  33. G E T S T R E A M .

    I O Composable Functions @Composable fun NamePlate(name: String, lastname: String) { Column(modifier = Modifier.padding(16.dp)) { Text(text = name) Text(text = lastname) } } fun NamePlate( name: String, lastname: String, $composer: Composer<*> ) { ... Column(modifier = Modifier.padding(16.dp), $composer) { Text( text = name, $composer ) Text( text = lastname, $composer ) } ... } Calling Context โ‡’ compile
  34. G E T S T R E A M .

    I O Composable Functions vs. suspend function โ€ข Kotlin์€ ์–ธ์–ด ์ˆ˜์ค€์—์„œ ์ฝ”๋ฃจํ‹ด ์ง€์›์„ ์ œ๊ณตํ•˜์—ฌ ๋น„๋™๊ธฐ ๋˜๋Š” ๋…ผ๋ธ”๋กœํ‚น ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์œ ์—ฐํ•˜๊ฒŒ ํ•ด๊ฒฐ โ€ข Suspend ํ•จ์ˆ˜๋Š” ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„๋‚˜ ๋‹ค๋ฅธ suspend ํ•จ์ˆ˜ ๋‚ด์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ โ€ข Kotlin ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ปดํŒŒ์ผ ์‹œ ๊ฐ suspend ํ•จ์ˆ˜์— ๋Œ€ํ•ด Continuation ํƒ€์ž…์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑ suspend fun fetchPlace(name: String): Place { // work.. } fun fetchPlace( name: String, callback: Continuation<Place> ) { // work.. } โ‡’ compile
  35. G E T S T R E A M .

    I O Composable Functions The function coloring @Composable fun Place(name: String) { Person(name) } @Composable fun Person(name: String) { // composable code } setContent { Place(name = "skydoves") } suspend fun fetchPlace(name: String): Place { getPlaceFromDB(name = name) } suspend fun getPlaceFromDB(name: String): Place { // work.. } coroutineScope.launch { fetchPlace(name = "skydoves")
  36. G E T S T R E A M .

    I O Composable Functions Restartable โ€ข Composable ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜ ํ•จ์ˆ˜์™€ ๋‹ฌ๋ฆฌ ๋‹ค์‹œ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋ฅผ ์žฌ๊ตฌ์„ฑ(recomposition)์ด๋ผ๊ณ  ๋ถ€๋ฆ„ โ€ข Recomposition์€ ์ž…๋ ฅ๊ฐ’์ด๋‚˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๋ฐœ์ƒํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์˜ ํ‘œํ˜„์„ ํ•ญ์ƒ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ โ€ข ์ปดํฌ์ฆˆ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ƒํƒœ๋ฅผ ์ฝ๋Š” ๋ชจ๋“  Composable ํ•จ์ˆ˜๋ฅผ ์ฐพ์•„ ๋Ÿฐํƒ€์ž„์ด ์ด๋“ค์„ ์–ด๋–ป๊ฒŒ ๋‹ค์‹œ ์‹œ์ž‘ํ• ์ง€ ์•Œ๋ ค์คŒ
  37. G E T S T R E A M .

    I O Composable Functions Idempotent #Run1 #Run2 ๋™์ผํ•œ ์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•ด์„œ ๋™์ผํ•œ ๊ฒฐ๊ณผ ์ถœ๋ ฅ โ€ข ๋™์ผํ•œ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋”๋ผ๋„ ์ผ๊ด€๋œ UI ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ด์•ผํ•จ โ€ข ์ปดํฌ์ฆˆ ๋Ÿฐํƒ€์ž„์€ ์ด๋Ÿฌํ•œ ๊ฐ€์ •(๋ฉฑ๋“ฑ์„ฑ, Idempotent)์— ์˜์กดํ•˜์—ฌ Recomposition๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. โ€ข Composable ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋Š” ์ด๋ฏธ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ์ปดํฌ์ฆˆ ๋Ÿฐํƒ€์ž„์€ Composable ํ•จ์ˆ˜๊ฐ€ ๋ฉฑ๋“ฑ์„ฑ์„ ๊ฐ–๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์—ฌ ๋™์ผํ•œ ์ž…๋ ฅ์— ๋Œ€ํ•ด ๋‹ค์‹œ ์‹คํ–‰ํ•˜์ง€ ์•Š์Œ
  38. G E T S T R E A M .

    I O Jetpack Compose Internals
  39. G E T S T R E A M .

    I O Stability in Compose
  40. G E T S T R E A M .

    I O Jetpack Compose Histories 80๎‚ Compose Compiler 125๎‚ Compose UI & Runtime versions have been released. Jetpack Compose continues to evolve with steady performance enhancements.
  41. G E T S T R E A M .

    I O Jetpack Compose Histories Compose UI Compose Compiler & Runtime โ€ข Smart Recomposition โ€ข Strong Skipping Mode โ€ข Stability Configuration File
  42. G E T S T R E A M .

    I O Jetpack Compose Phases
  43. G E T S T R E A M .

    I O Jetpack Compose Phases
  44. G E T S T R E A M .

    I O Jetpack Compose Phases
  45. G E T S T R E A M .

    I O Jetpack Compose Phases
  46. G E T S T R E A M .

    I O Understanding Stability โ€ข Composable ํ•จ์ˆ˜๋Š” ํ‘œ์ค€ ํ•จ์ˆ˜์™€๋Š” ๋‹ฌ๋ฆฌ recomposition์„ ํ†ตํ•ด ์žฌ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•จ โ€ข Recomposition์€ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด ํ‘œํ˜„์„ ํ•ญ์ƒ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ž…๋ ฅ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด๋‚˜ ๊ด€์ฐฐ ์ค‘์ธ State์— ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•  ๋•Œ ์ผ์–ด๋‚จ โ€ข Compose ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ƒํƒœ๋ฅผ ๊ด€์ฐฐํ•˜๋Š” ๋ชจ๋“  Composable ํ•จ์ˆ˜๋ฅผ ์ฐพ์•„์„œ Compose ๋Ÿฐํƒ€์ž„์—๊ฒŒ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•จ Restartable
  47. G E T S T R E A M .

    I O Understanding Stability Recomposition 1. ๊ด€์ฐฐ ์ค‘์ธ State์˜ ๋ณ€๊ฒฝ Compose ๋Ÿฐํƒ€์ž„์€ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ๊ด€์ฐฐํ•˜๊ณ  recomposition์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” State๋ผ๋Š” ํšจ์œจ์ ์ธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณต var text by remember { mutableIntStateOf(0) } Text( modifier = Modifier.clickable { text++ }, text = "Clicked $text times" )
  48. G E T S T R E A M .

    I O Understanding Stability Recomposition 1. ๊ด€์ฐฐ ์ค‘์ธ State์˜ ๋ณ€๊ฒฝ Compose ๋Ÿฐํƒ€์ž„์€ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ๊ด€์ฐฐํ•˜๊ณ  recomposition์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” State๋ผ๋Š” ํšจ์œจ์ ์ธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณต 2. Composable ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ Compose ๋Ÿฐํƒ€์ž„์€ equals ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ stableํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•ด ์ž…๋ ฅ๊ฐ’์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ฐ์ง€ํ•จ. ๋งŒ์•ฝ equals ํ•จ์ˆ˜๊ฐ€ false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋Ÿฐํƒ€์ž„์€ ์ด๋ฅผ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ์œผ๋กœ ํ•ด์„ @Composable fun UserProfile(name: String, image: String) { .. }
  49. G E T S T R E A M .

    I O Understanding Stability Stable vs. Unstable @Composable fun Profile(user: User, posts: List<Post>) { // composable code } compile @Composable fun Profile( stable user: User, unstable posts: List<Post>, ) โ€ข Compose ์ปดํŒŒ์ผ๋Ÿฌ๋Š” Composable ํ•จ์ˆ˜์— ์‚ฌ์šฉ๋œ ๋งค๊ฐœ๋ณ€์ˆ˜์—๊ฒŒ stable ํ˜น์€ unstable ํƒ€์ž…์„ ๋ถ€์—ฌ โ€ข Composable ํ•จ์ˆ˜์— unstableํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด recomposition์ด ํ•ญ์ƒ ๋ฐœ์ƒ โ€ข Composable ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋‘ stableํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค๋ฉด recomposition์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๋ถˆํ•„์š”ํ•œ ์ž‘์—… ์ƒ๋žต
  50. G E T S T R E A M .

    I O Understanding Stability Stable vs. Unstable Stable๋กœ ๊ฐ„์ฃผ๋˜๋Š” ์œ ํ˜• โ€ข ์›์‹œ ํƒ€์ž… ๎‚Primitive types) โ€ข ๎‚Int๎‚‚ โ†’ String ์™€ ๊ฐ™์€ ๋žŒ๋‹ค์‹์œผ๋กœ ํ‘œํ˜„๋˜๋Š” ํ•จ์ˆ˜์˜ ์œ ํ˜• (์™ธ๋ถ€๊ฐ’์„ ์บก์ฒ˜ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๊ฐ’์ด stable์ธ ๊ฒฝ์šฐ๋งŒ) โ€ข (data) class์˜ public ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ชจ๋‘ ๋ถˆ๋ณ€์ด๊ฑฐ๋‚˜ stableํ•œ ๊ฒฝ์šฐ โ€ข (data) class์— ๎‚‡Stable ๋ฐ ๎‚‡Immutable ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ stable ํ•˜๋‹ค๊ณ  ํ‘œ๊ธฐ๋œ ๊ฒฝ์šฐ
  51. G E T S T R E A M .

    I O Understanding Stability Stable vs. Unstable Unstable๋กœ ๊ฐ„์ฃผ๋˜๋Š” ์œ ํ˜• โ€ข ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ตฌํ˜„์ฒด๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” Any ์œ ํ˜•๊ณผ ๊ฐ™์€ ์ถ”์ƒ ํด๋ž˜์Šค์™€ List, Map ๋“ฑ์„ ํฌํ•จํ•œ ๋ชจ๋“  ์ธํ„ฐํŽ˜์ด์Šค โ€ข (data) class์˜ public ํ”„๋กœํผํ‹ฐ ์ค‘ ์ตœ์†Œ ํ•˜๋‚˜ ์ด์ƒ์ด ๊ฐ€๋ณ€์ ์ด๊ฑฐ๋‚˜ unstableํ•œ ๊ฒฝ์šฐ
  52. G E T S T R E A M .

    I O Understanding Stability Stable vs. Unstable Stable data class User( val id: Int, val name: String, )
  53. G E T S T R E A M .

    I O Understanding Stability Stable vs. Unstable Stable data class User( val id: Int, val name: String, ) Unstable data class User( val id: Int, var name: String, )
  54. G E T S T R E A M .

    I O Understanding Stability Stable vs. Unstable Stable data class User( val id: Int, val name: String, ) Unstable data class User( val id: Int, var name: String, ) data class User( val id: Int, val images: List<String>, )
  55. G E T S T R E A M .

    I O Understanding Stability Stable vs. Unstable Stable data class User( val id: Int, val name: String, ) @Immutable data class User( val id: Int, val images: List<String>, ) Unstable data class User( val id: Int, var name: String, ) data class User( val id: Int, val images: List<String>, )
  56. G E T S T R E A M .

    I O Understanding Stability Smart Recomposition #Run1 #Run2 recomposition ์ƒ๋žต ๎‚Smart Recomposition) โŒ stableํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์˜ equals()๊ฐ€ true
  57. G E T S T R E A M .

    I O Understanding Stability Smart Recomposition recomposition ์ƒ๋žต ๎‚Smart Recomposition) โŒ stableํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์˜ equals()๊ฐ€ true Recomposition Recomposition Recomposition Skip Recomposition
  58. G E T S T R E A M .

    I O Understanding Stability Smart Recomposition 1. Stability์— ๊ธฐ๋ฐ˜ํ•œ ์˜์‚ฌ๊ฒฐ์ • - ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ stableํ•˜๊ณ  ํ•ด๋‹น ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ (equals() returns true), Compose๋Š” ๊ด€๋ จ UI ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ recomposition ์ž‘์—…์„ ์ƒ๋žต - ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ unstableํ•˜๊ฑฐ๋‚˜ stableํ•˜์ง€๋งŒ ๊ฐ’์ด ๋ณ€๊ฒฝ ๋œ ๊ฒฝ์šฐ (equals() returns false), Compose ๋Ÿฐํƒ€์ž„์€ recomposition์„ ์ˆ˜ํ–‰ํ•˜๊ณ  UI ๋ ˆ์ด์•„์›ƒ์„ invalidateํ•˜์—ฌ ๋‹ค์‹œ ๋žœ๋”๋ง 2. Equality ์ฒดํฌ ์ƒˆ๋กœ์šด stableํ•œ ์œ ํ˜•์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ Composable ํ•จ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋ฉด, equals() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด์ „์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๊ณผ equality(๋™๋“ฑ์„ฑ) ํ™•์ธ์„ ์ˆ˜ํ–‰
  59. G E T S T R E A M .

    I O Inferring Composable Functions โ€ข Restartable โ€ข Skippable โ€ข Movable โ€ข .. @Composable fun NamePlate(name: String, lastname: String) { Column(modifier = Modifier.padding(16.dp)) { Text(text = name) Text(text = lastname) } } Compile Compose ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— Restartable, Skippable, Movable๊ณผ ๊ฐ™์€ Composable ํ•จ์ˆ˜์˜ ํŠน์„ฑ์„ ์ถ”๋ก ํ•˜๊ณ  Compose ๋Ÿฐํƒ€์ž„์—๊ฒŒ ํ•ด๋‹น ์ •๋ณด๋ฅผ ์ „๋‹ฌ
  60. G E T S T R E A M .

    I O Inferring Composable Functions Restartable #Run1 #Run2 ์ž…๋ ฅ๊ฐ’์ด ๋‹ฌ๋ผ์ง€๋ฉด, Composable ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ์šด ์ž…๋ ฅ๊ฐ’์œผ๋กœ ์žฌ์‹คํ–‰ ๋Œ€๋ถ€๋ถ„์˜ Composable ํ•จ์ˆ˜๋Š” Restartable(์žฌ์‹คํ–‰ ๊ฐ€๋Šฅ)ํ•˜๊ณ  ๋ฉฑ๋“ฑ์„ฑ์˜ ์„ฑ์งˆ์„ ๊ฐ€์ง
  61. G E T S T R E A M .

    I O Inferring Composable Functions Skippable โŒ #Run1 #Run2 Composable ํ•จ์ˆ˜๊ฐ€ stableํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ฒฝ์šฐ, recomposition์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋Š” Skippable๋กœ ๋ถ„๋ฅ˜ recomposition ์ƒ๋žต ๎‚Smart Recomposition) stableํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์˜ equals()๊ฐ€ true
  62. G E T S T R E A M .

    I O Inferring Composable Functions Compose Compiler Metrics stable class StreamShapes { stable val circle: Shape stable val square: Shape stable val button: Shape stable val input: Shape stable val dialog: Shape stable val sheet: Shape stable val indicator: Shape stable val container: Shape } restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun Avatar( stable modifier: Modifier? = @static Companion stable imageUrl: String? = @static null stable initials: String? = @static null stable shape: Shape? = @dynamic VideoTheme.<get-shapes>($composer, 0b0110๎‚‚.circle stable textSize: StyleSize? = @static StyleSize.XL stable textStyle: TextStyle? = @dynamic VideoTheme.<get-typography>($composer, 0b0110๎‚‚.titleM stable contentScale: ContentScale? = @static Companion.Crop stable contentDescription: String? = @static null
  63. G E T S T R E A M .

    I O Inferring Composable Functions Compose Compiler Metrics subprojects { tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().all { kotlinOptions.freeCompilerArgs += listOf( "๎‚ˆP", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + project.buildDir.absolutePath + "/compose_metrics" ) kotlinOptions.freeCompilerArgs += listOf( "๎‚ˆP", "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + project.buildDir.absolutePath + "/compose_metrics" ) } } ๐Ÿ’ป bit.ly/3V2Q1wB Kotlin 1.9.x Kotlin 2.0.0 + Compose Plugin composeCompiler { reportsDestination = layout.buildDirectory.dir("compose_compiler") }
  64. G E T S T R E A M .

    I O Stability Annotations Compose Runtime ๎‚‡Immutable ๎‚‡Stable Compose ๋Ÿฐํƒ€์ž„์€ ๎‚‡Immutable๊ณผ ๎‚‡Stable ์ด๋ผ๋Š” ๋‘ ๊ฐ€์ง€ stability ์–ด๋…ธํ…Œ์ด์…˜์„ ์ œ๊ณตํ•˜์—ฌ ํŠน์ • ํด๋ž˜์Šค๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ stableํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•  ์ˆ˜ ์žˆ์Œ
  65. G E T S T R E A M .

    I O Stability Annotations ๎‚‡Immutable @Immutable ์–ด๋…ธํ…Œ์ด์…˜์€ Compose ์ปดํŒŒ์ผ๋Ÿฌ์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ์•ฝ์†์ด๋ฉฐ, class์˜ ๋ชจ๋“  public ํ”„๋กœํผํ‹ฐ์™€ ํ•„๋“œ๊ฐ€ ์ดˆ๊ธฐํ™” ๋œ ์ดํ›„์— ์ ˆ๋Œ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก(๋ถˆ๋ณ€) ๋ณด์žฅ @Immutable ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๋‘ ๊ฐ€์ง€ ๊ทœ์น™: 1. ๋ชจ๋“  public ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•˜์—ฌ val keyword๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ถˆ๋ณ€์ž„์„ ํ™•์ธ 2. ์ปค์Šคํ…€ setter ์‚ฌ์šฉ์„ ํ”ผํ•˜๊ณ , ๋ชจ๋“  public ํ”„๋กœํผํ‹ฐ์— ๊ฐ€๋ณ€์„ฑ์ด ์—†๋Š”์ง€ ํ™•์ธ
  66. G E T S T R E A M .

    I O Stability Annotations ๎‚‡Immutable public data class User( public val id: String, public val nickname: String, public val profileImage: String, ) Stable
  67. G E T S T R E A M .

    I O Stability Annotations ๎‚‡Immutable public data class User( public val id: String, public val nickname: String, public val profileImage: String, ) Stable Unstable public data class User( public val id: String, public val nickname: String, public val profileImages: List<String>, )
  68. G E T S T R E A M .

    I O Stability Annotations ๎‚‡Immutable public data class User( public val id: String, public val nickname: String, public val profileImage: String, ) Stable Unstable public data class User( public val id: String, public val nickname: String, public val profileImages: List<String>, ) @Immutable public data class User( public val id: String, public val nickname: String, public val profileImages: List<String>, )
  69. G E T S T R E A M .

    I O Stability Annotations ๎‚‡Stable โ€ข ๎‚‡Stable ์–ด๋…ธํ…Œ์ด์…˜ ๋˜ํ•œ Compose ์ปดํŒŒ์ผ๋Ÿฌ์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ์•ฝ์†์ด์ง€๋งŒ, ๎‚‡Immutable ๋ณด๋‹ค๋Š” ์กฐ๊ธˆ ๋А์Šจํ•œ ์•ฝ์†์„ ์˜๋ฏธ โ€ข ๋ฌธ๋งฅ์ ์œผ๋กœ "Stable(์•ˆ์ •์ )"์ด๋ผ๋Š” ์šฉ์–ด๋Š” ํ•จ์ˆ˜๊ฐ€ ๋™์ผํ•œ ์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•ด ์ผ๊ด€๋˜๊ฒŒ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ, ์ž ์žฌ์ ์ธ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋™์ž‘์„ ๋ณด์žฅํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธ โ€ข ๎‚‡Stable ์–ด๋…ธํ…Œ์ด์…˜์€ public ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ถˆ๋ณ€์ธ ํด๋ž˜์Šค ํ˜น์€ ์ธํ„ฐํŽ˜์ด์Šค์— ๊ฐ€์žฅ ์ ํ•ฉํ•˜์ง€๋งŒ, ํด๋ž˜์Šค ์ž์ฒด๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ์•ˆ์ •์ ์ด์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉ๋จ
  70. G E T S T R E A M .

    I O Stability Annotations ๎‚‡Stable ๎‚‡Stable interface State<out T> { val value: T } ๎‚‡Stable interface MutableState<T> : State<T> { override var value: T operator fun component1(): T operator fun component2(): ๎‚T) โ†’ Unit }
  71. G E T S T R E A M .

    I O Stability Annotations ๎‚‡Immutable vs. Stable ๎‚‡Immutable public data class User( public val id: String, public val nickname: String, public val profileImages: List<String>, ) ๎‚‡Immutable ๎‚‡Stable ๎‚‡Stable interface UiState<T ๎‚’ Result<T>> { val value: T? val exception: Throwable? val hasSuccess: Boolean get() = exception == null }
  72. G E T S T R E A M .

    I O ๎‚‡Composable ๎‚‡NonRestartableComposable fun LaunchedEffect( key1๎‚’ Any?, block: suspend CoroutineScope.() โ†’ Unit ) { .. } @NonRestartableComposable โ€ข Composable ํ•จ์ˆ˜์— ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ Restartable ์†์„ฑ์„ ๋ถ€์—ฌํ•˜์ง€ ์•Š๊ณ  recomposition์„ ์ƒ๋žต โ€ข Recomposition์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜๊ธฐ์— ์ ํ•ฉ โ€ข e.g, Composable ํ•จ์ˆ˜ ๋‚ด ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ ์ฒ˜๋ฆฌ ๋ฐ ํ‘œ์ค€ ํ•จ์ˆ˜๋งŒ์„ ํ˜ธ์ถœํ•˜๋Š” ์‚ฌ๋ก€ Stability Annotations ๎‚‡NonRestartableComposable
  73. G E T S T R E A M .

    I O Stabilize Composable Functions Immutable Collections internal var mutableUserList: MutableList<User> = mutableListOf() public val userList: List<User> = mutableUserList @Composable fun Profile(images: List<String>) { .. } Unstable
  74. G E T S T R E A M .

    I O Stabilize Composable Functions Immutable Collections internal var mutableUserList: MutableList<User> = mutableListOf() public val userList: List<User> = mutableUserList Replace with: - kotlinx.collections.immutable (ImmutableList and ImmutableSet) - guava's immutable collections @Composable fun Profile(images: List<String>) { .. } @Composable fun Profile(images: ImmutableList<String>) { .. } Unstable Stable, Skippable
  75. G E T S T R E A M .

    I O Stabilize Composable Functions Immutable Collections Compose Compiler: KnownStableConstructs.kt object KnownStableConstructs { val stableTypes = mapOf( // Guava "com.google.common.collect.ImmutableList" to 0b1, "com.google.common.collect.ImmutableSet" to 0b1, .. // Kotlinx immutable "kotlinx.collections.immutable.ImmutableCollection" to 0b1, "kotlinx.collections.immutable.ImmutableList" to 0b1, .. ) }
  76. G E T S T R E A M .

    I O Stabilize Composable Functions Wrapper Class ๎‚‡Immutable data class ImmutableUserList( val user: List<User>, val expired: java.time.LocalDateTime, ) ๎‚‡Composable fun UserAvatars( stable modifier: Modifier, stable userList: ImmutableUserList, ) ๎‚‡Composable fun UserAvatars( stable modifier: Modifier, unstable user: List<User>, unstable expired: java.time.LocalDateTime, ) Non-Skippable Skippable
  77. G E T S T R E A M .

    I O Stabilize Composable Functions Stability Configuration File kotlinOptions { freeCompilerArgs += listOf( "๎‚ˆP", "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" + "${project.absolutePath}/compose_compiler_config.conf" ) } compose_compiler_config.conf // Consider LocalDateTime stable java.time.LocalDateTime // Consider kotlin collections stable kotlin.collections.* // Consider my datalayer and all submodules stable com.datalayer.** // Consider my generic type stable based off it's first type parameter only com.example.GenericClass<*,_> // Consider our data models stable since we always use immutable classes com.google.samples.apps.nowinandroid.core.model.data.*
  78. G E T S T R E A M .

    I O Blog Post Jetpack Compose ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ Stability ์ดํ•ดํ•˜๊ธฐ velog.io/@skydoves/compose-stability
  79. G E T S T R E A M .

    I O Thank you.