Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions docs/jihyun/week8/Q11_State.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# ์ƒํƒœ(state)๋ž€ ๋ฌด์—‡์ด๋ฉฐ ์ด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” API๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

Jetpack Compose์—์„œ State๋Š” ์•ฑ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ”ํžˆ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์ด์ž, UI์—์„œ ๋™์ ์œผ๋กœ ๋ฐ˜์˜๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ„

ํ”ํžˆ ์‚ฌ์šฉ๋˜๋Š” ์ƒํƒœ:

- ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜์— ๋Œ€ํ•œ Snackbar ๋ฉ”์‹œ์ง€ ๋…ธ์ถœ
- ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋˜๋Š” ์ƒํ˜ธ์ž‘์šฉ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„

์ƒํƒœ๋Š” UI ์—…๋ฐ์ดํŠธ๋ฅผ ์ง์ ‘ ํŠธ๋ฆฌ๊ฑฐ

์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ณ€๊ฒฝ๋œ ์ƒํƒœ๋ฅผ UI์— ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ ๋ Œ๋”๋ง

## State์™€ Composition

UI ์—…๋ฐ์ดํŠธ: ์ปดํฌ์ €๋ธ”์ด ๋ณ€๊ฒฝ๋œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœ๋  ๋•Œ๋งŒ ๋ฐœ์ƒ

์ด๋Ÿฌํ•œ ๋™์ž‘์€ composition ์ƒ๋ช…์ฃผ๊ธฐ์™€ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ด€๋ จ๋จ

- ์ดˆ๊ธฐ Composition: ์ปดํฌ์ €๋ธ”์„ ์‹คํ–‰ํ•˜์—ฌ UI ํŠธ๋ฆฌ๊ฐ€ ์ฒ˜์Œ ์ƒ์„ฑ๋˜๊ณ  ๋ Œ๋”๋ง๋˜๋Š” ํ”„๋กœ์„ธ์Šค
- Recomposition: ์ƒํƒœ ๋ณ€๊ฒฝ ์‹œ ํŠธ๋ฆฌ๊ฑฐ๋˜๋ฉฐ, recomposition์€ ๊ด€๋ จ ์ปดํฌ์ €๋ธ”์„ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฐ˜์˜

Compose Runtime: ์ƒํƒœ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ž๋™์œผ๋กœ ์ถ”์ 

โ†’ ์•ˆ๋“œ๋กœ์ด๋“œ View ์‹œ์Šคํ…œ์—์„œ UI๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” View.invalidate() ๋ฉ”์„œ๋“œ์™€ ์œ ์‚ฌํ•œ ๋™์ž‘์„ ๊ฐœ๋ฐœ์ž ๋Œ€์‹ ํ•˜์—ฌ UI๋ฅผ ์—…๋ฐ์ดํŠธ

Recomposition: ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๋ฅผ ๋ฐ˜์˜ํ•ด์•ผ ํ•˜๋Š” ์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ๋งŒ ํŠธ๋ฆฌ๊ฑฐ

## Compose์—์„œ ์ƒํƒœ ๊ด€๋ฆฌํ•˜๊ธฐ

Jetpack Compose๋Š” ์ƒํƒœ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ API๋“ค์„ ์ œ๊ณต

- remember
- ์ดˆ๊ธฐ ์ปดํฌ์ง€์…˜์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ณ  recomposition์ด ๋ฐœ์ƒํ•˜๋ฉด ๊ธฐ์กด ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋œ ๊ฐ’์„ ๊บผ๋‚ด์˜ด
- API์˜ ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์ƒํƒœ ๊ฐ’์„ ๋ฉ”๋ชจ๋ฆฌ์— โ€˜๊ธฐ์–ตํ•œ๋‹คโ€™๊ณ  ์ดํ•ดํ•˜๋ฉด ๋จ
- rememberSaveable
- recomposition ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ํ™”๋ฉด ํšŒ์ „๊ณผ ๊ฐ™์€ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์‹œ์—๋„ ์ƒํƒœ๋ฅผ ์œ ์ง€
- Bundle์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ˜• ๋˜๋Š” ๊ทธ ์™ธ ์œ ํ˜•์— ๋Œ€ํ•ด์„œ๋Š” ์ปค์Šคํ…€ saver ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Œ
- mutableStateOf
- ๊ฐ€๋ณ€์ ์ธ ์ƒํƒœ๋ฅผ ์˜๋ฏธ
- ์ƒํƒœ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ recomposition์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ

### ์™œ remember์™€ mutableStateOf๊ฐ€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋‚˜์š”?

- remember API๋Š” ๊ฐ์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ
- mutableStateOf๋Š” ์ƒํƒœ๊ฐ’์ด ๋ณ€ํ•  ๋•Œ recomposition์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ธฐ ์œ„ํ•œ ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ API

๋งŒ์•ฝ mutableStateOf๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ์ƒํƒœ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค recomposition์„ ํŠธ๋ฆฌ๊ฑฐ โ†’ ๋ฌธ์ œ๋Š” ํ•ด๋‹น ์ƒํƒœ๊ฐ’ ์ž์ฒด๊ฐ€ recomposition์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜์–ด์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐํ™”๋˜๊ณ , ๊ธฐ๋Œ€ํ–ˆ๋˜ ๋™์ž‘๊ณผ๋Š” ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๊ฒŒ ๋จ

๋”ฐ๋ผ์„œ ์ƒํƒœ ๋˜ํ•œ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ์„ ํ•ด์•ผ ํ•จ
34 changes: 34 additions & 0 deletions docs/jihyun/week8/Q12_State_Hoisting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…(state hoisting)์œผ๋กœ ์–ด๋–ค ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‚˜์š”?

์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…(State hoisting)์€ ์ƒํƒœ๋ฅผ ์ƒ์œ„ ์ˆ˜์ค€์˜ ์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜๋กœ ๋Œ์–ด์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์„ ์˜๋ฏธ

๋”ฐ๋ผ์„œ, ์ƒํƒœ ๊ฐ’๊ณผ ์ƒํƒœ ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ ์ปดํฌ์ €๋ธ” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜๊ณ  ํ•ด๋‹น ๊ฐ’์€ ํ˜„์žฌ ์ปดํฌ์ €๋ธ”์ด ์•„๋‹Œ ๋‹ค๋ฅธ ํ˜ธ์ถœ์ž ์ชฝ์—์„œ ๊ด€๋ฆฌํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ

์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์€ ๊ทผ๋ณธ์ ์œผ๋กœ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์›์น™์„ ๋”ฐ๋ฅด๋ฏ€๋กœ UI๋ฅผ ๋” ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ฆ

### ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์˜ ํŠน์„ฑ

- State: ๋ถ€๋ชจ ์ปดํฌ์ €๋ธ”์—์„œ ๊ด€๋ฆฌ
- ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์„ ์ ์šฉํ•˜๋ ค๋Š” ์ปดํฌ์ €๋ธ”์€ ์ƒํƒœ ์ž์ฒด๋ฅผ ๊ฐ€์ ธ์„œ๋Š” ์•ˆ ๋˜๊ณ , ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ƒํƒœ๋ฅผ ๋ฐ›์•„์„œ๋„ ์•ˆ ๋จ
- Events ๋˜๋Š” triggers
- ์ž์‹์—์„œ ๊ฐ’์„ ๋ฐ”๊พธ๊ณ , ํ•ด๋‹น ๊ฐ’์„ ๋ถ€๋ชจ๋กœ ๋‹ค์‹œ ์ „๋‹ฌ๋ฐ›๋Š” ํ˜•ํƒœ๋กœ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ
- ๋ณดํŽธ์ ์œผ๋กœ ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„˜๊ธฐ๊ณ , ํ•ด๋‹น ์ปดํฌ์ €๋ธ”์„ ํ˜ธ์ถœํ•˜๋Š” ์ชฝ์—์„œ ์—…๋ฐ์ดํŠธ๋œ ๊ฐ’์„ ์ฝœ๋ฐฑ์œผ๋กœ ๋ฐ›์•„ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ์‹œํ‚ค๋Š” ํ˜•ํƒœ๋กœ ๋™์ž‘
- ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ž์‹์—๊ฒŒ ๋‹ค์‹œ ์ „๋‹ฌ๋˜์–ด ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์ƒ์„ฑ

### ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์˜ ์žฅ์ 

- ๋” ๋‚˜์€ ์žฌ์‚ฌ์šฉ์„ฑ
- ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์„ ์ ์šฉํ•˜๋ฉด ์ปดํฌ์ €๋ธ”์„ ์ƒํƒœ ์—†๋Š” ํ˜•ํƒœ(stateless) ๋ฐ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ
- ์ƒํƒœ ๋ฐ ์ด๋ฒคํŠธ ์ฝœ๋ฐฑ์„ ์ „๋‹ฌ โ†’ ๋™์ผํ•œ ์ปดํฌ์ €๋ธ”์„ ํŠน์ • ๊ตฌํ˜„์— ์–ฝ๋งค์ด์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ํ™”๋ฉด์ด๋‚˜ ์ปจํ…์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
- ๋‹จ์ˆœํ™”๋œ ํ…Œ์ŠคํŠธ
- ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๋Š” ์ปดํฌ์ €๋ธ”์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋œ ์ƒํƒœ ๊ฐ’์— ์ „์ ์œผ๋กœ ์˜์กด โ†’ ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฌ์›€
- ์ด๋กœ ์ธํ•ด ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ณ  ๋ช…ํ™•ํ•œ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค ๊ฐ€๋Šฅ
- ๋” ๋‚˜์€ ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ
- ์ƒํƒœ ๊ด€๋ฆฌ ๋กœ์ง์„ ๋ถ€๋ชจ ์ปดํฌ์ €๋ธ” ๋˜๋Š” ViewModel๋กœ ์˜ฎ๊น€์œผ๋กœ์จ, UI ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค ๋ Œ๋”๋ง์—๋งŒ ์ง‘์ค‘ํ•˜๋„๋ก ํ•จ
- ์ด๋Ÿฌํ•œ ์—ญํ•  ๋ถ„๋ฆฌ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ UI ์ฝ”๋“œ๋ฅผ ๊ตฌ๋ณ„ํ•˜์—ฌ ์œ ์ง€ ๊ด€๋ฆฌ์„ฑ์„ ํ–ฅ์ƒ
- ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์ง€์›
- ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์€ Jetpack Compose์˜ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์•„ํ‚คํ…์ฒ˜์™€ ์ผ์น˜ํ•˜์—ฌ ์ƒํƒœ๊ฐ€ ๋‹จ ํ•˜๋‚˜์˜ ๊ณต๊ธ‰์›์—์„œ ํ๋ฅด๋„๋ก ๋ณด์žฅ
- ์—ฌ๋Ÿฌ ์†Œ์Šค๊ฐ€ ๋™์ผํ•œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์˜ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ž„
- ํ–ฅ์ƒ๋œ ์ƒํƒœ ๊ด€๋ฆฌ
- ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์„ ์‚ฌ์šฉํ•˜๋ฉด ViewModel ๋˜๋Š” ๋ถ€๋ชจ ์ปดํฌ์ €๋ธ”๊ณผ ๊ฐ™์€ ์ƒ์œ„ ์ˆ˜์ค€ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ƒํƒœ๋ฅผ ์ค‘์•™ ์ง‘์ค‘ํ™”ํ•  ์ˆ˜ ์žˆ์Œ
- ์ด๋ฅผ ํ†ตํ•ด ๋ณต์žกํ•œ UI ํ๋ฆ„์„ ๊ด€๋ฆฌํ•˜๊ณ  ์ธ์Šคํ„ด์Šค ์ƒํƒœ ์ €์žฅ ๋˜๋Š” ์ƒํƒœ ๋ณต์› ๊ด€๋ฆฌ์™€ ๊ฐ™์€ ์ž‘์—…์„ ๋” ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ
184 changes: 184 additions & 0 deletions docs/jihyun/week8/Q13_remember_rememberSaveable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# remember์™€ rememberSaveable์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

์ƒํƒœ ๊ด€๋ฆฌ๋Š” UI๊ฐ€ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋„๋ก ํ•˜๋Š” ํ•ต์‹ฌ์ ์ธ ๊ฐœ๋…

remember์™€ rememberSaveable์€ ๋ชจ๋‘ recomposition๋กœ๋ถ€ํ„ฐ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋„๋ก ํ•˜๋Š” API์ง€๋งŒ ์„œ๋กœ ๋‹ค๋ฅธ ๋ชฉ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

## remember

- ๋ชฉ์ 
- remember API๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  recomposition์ด ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋œ ๊ฐ’์„ ๊บผ๋‚ด์™€ ์ƒํƒœ๋ฅผ ์œ ์ง€
- ๊ทธ๋Ÿฌ๋‚˜ ํ™”๋ฉด ํšŒ์ „์ด๋‚˜ ํ”„๋กœ์„ธ์Šค ์žฌ์‹œ์ž‘๊ณผ ๊ฐ™์€ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์ค‘์—๋Š” ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š์Œ
- ์œ ์ฆˆ ์ผ€์ด์Šค
- ์ƒํƒœ๊ฐ€ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ํ›„์—๋„ ์œ ์ง€๋  ํ•„์š”๊ฐ€ ์—†์„ ๋•Œ remember์„ ์‚ฌ์šฉ
- e.g., ํ™”๋ฉด์ด ํšŒ์ „๋˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ์–ธ์–ด ์„ค์ • ๋“ฑ์„ ๋ฐ”๊พธ์—ˆ์„ ๊ฒฝ์šฐ, ์ •๋ณด๊ฐ€ ๋‚ ์•„๊ฐ€๋„ ์ƒ๊ด€์—†๋Š” ์ƒํƒœ์˜ ๊ฒฝ์šฐ remember๊ฐ€ ์ ํ•ฉ

## rememberSaveable

- ๋ชฉ์ 
- rememberSaveable API๋Š” ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์‹œ์—๋„ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜์—ฌ remember๋ณด๋‹ค ๋” ๋„“์€ ๋ฒ”์œ„์—์„œ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ณต์›
- ์•ˆ๋“œ๋กœ์ด๋“œ SDK์˜ Bundle์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์— ํ•œํ•˜์—ฌ ์ž๋™์œผ๋กœ ์ €์žฅํ•˜๊ณ  ๋ณต์›
- ์œ ์ฆˆ ์ผ€์ด์Šค
- ์œ ์ € ์ธํ’‹ ์ž…๋ ฅ์ด๋‚˜ ๋‚ด๋น„๊ฒŒ์ด์…˜ ์ƒํƒœ์™€ ๊ฐ™์ด ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ํ›„์—๋„ ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š” ์ƒํƒœ์— ๋Œ€ํ•ด์„œ๋Š” rememberSaveable์„ ์‚ฌ์šฉํ•ด์•ผ ํ•จ

### ๋ฌด์กฐ๊ฑด rememberSaveable์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์€๊ฐ€?

rememberSaveable์€ ๋‚ด๋ถ€์ ์œผ๋กœ remember๋ณด๋‹ค ํ›จ์”ฌ ๋‹ค์–‘ํ•œ ๋‚ด๋ถ€ ์ฒ˜๋ฆฌ ๋ฐ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒ

๋ฌดํ„ฑ๋Œ€๊ณ  ๋ชจ๋“  ์ƒํ™ฉ์— rememberSaveable์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์˜คํžˆ๋ ค ์•ฑ ์„ฑ๋Šฅ์„ ๋–จ์–ด๋œจ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๋ฐฉํ•ดํ•  ์ˆ˜๋„ ์žˆ์Œ

## ์ฃผ์š” ์ฐจ์ด์ 

| ๊ธฐ๋Šฅ | remember | rememberSaveable |
| --- | --- | --- |
| ์ง€์†์„ฑ | ์…˜์žฌ ์ปดํฌ์ง€์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ๋™์•ˆ์—๋งŒ ์ƒํƒœ ์œ ์ง€ | ์ปดํฌ์ง€์…˜ ๋ฐ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์‹œ ์ƒํƒœ ์œ ์ง€ |
| ์ €์žฅ ์œ„์น˜ | ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’ ์ €์žฅ | ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  Bundle์— ์ €์žฅ |
| ์ปค์Šคํ…€ Saver ์ง€์› | ํ•ด๋‹น ์—†์Œ | ๋ณต์žกํ•œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ปค์Šคํ…€ saver ์ง€์› |

## ์‚ฌ์šฉ ์‹œ๊ธฐ

- ์• ๋‹ˆ๋ฉ”์ด์…˜์ด๋‚˜ ์ž„์‹œ์ ์ธ UI ์ƒํƒœ์™€ ๊ฐ™์ด ํ˜„์žฌ ์ปดํฌ์ง€์…˜์„ ๋„˜์–ด์„œ ์œ ์ง€๋  ํ•„์š”๊ฐ€ ์—†๋Š” ์ผ์‹œ์ ์ธ ์ƒํƒœ์—๋Š” remember๋ฅผ ์‚ฌ์šฉ
- ์‚ฌ์šฉ์ž ์ž…๋ ฅ, ์„ ํƒ ์ƒํƒœ ๋˜๋Š” ์–‘์‹ ๋ฐ์ดํ„ฐ์™€ ๊ฐ™์ด ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์‹œ์—๋„ ์œ ์ง€๋˜์–ด ๋” ๋‚˜์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ์—์„œ๋Š” rememberSaveable์„ ์‚ฌ์šฉ

## remember ๋ฐ rememberSaveable ๋‚ด๋ถ€ ๊ตฌ์กฐ

### remember ๋‚ด๋ถ€ ๊ตฌ์กฐ

```kotlin
@Composable
inline fun <T> remember(crossinline calculation: @DisallowComposableCalls () -> T): T =
currentComposer.cache(false, calculation)
```

remember๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ Composer ์ธ์Šคํ„ด์Šค์—์„œ cache ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ

cache ํ•จ์ˆ˜ ๊ตฌํ˜„ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Œ

```kotlin
@ComposeCompilerApi
inline fun <T> Composer.cache(invalid: Boolean, block: @DisallowComposableCalls () -> T): T {
@Suppress("UNCHECKED_CAST")
return rememberedValue().let {
if (invalid || it === Composer.Empty) {
val value = block()
updateRememberedValue(value)
value
} else it
} as T
}
```

Compose ์ปดํŒŒ์ผ๋Ÿฌ ํ”Œ๋Ÿฌ๊ทธ์ธ API์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜์—ฌ ์ปดํฌ์ง€์…˜ ๋ฐ์ดํ„ฐ์— ๊ฐ’์„ ์บ์‹œ

๊ตฌ์ฒด์ ์œผ๋กœ, ๊ฐ’์ด ์œ ํšจํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜๋Š”์ง€(Composer.Empty) ํ™•์ธ

- ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ œ๊ณต๋œ ๋ธ”๋ก ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ณ  ์ปดํฌ์ง€์…˜ ๋ฐ์ดํ„ฐ์— ์ €์žฅํ•œ ๋‹ค์Œ ๋ฐ˜ํ™˜
- ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ด์ „์— ๊ธฐ์–ต๋œ ๊ฐ’์„ ๋‹จ์ˆœํžˆ ๋ณต์›ํ•˜์—ฌ ๋ฐ˜ํ™˜

โ‡’ ์ค‘๋ณต์ ์ธ ๊ณ„์‚ฐ์„ ํ”ผํ•˜๋ฉด์„œ recomposition์ด ๋ฐœ์ƒํ•ด๋„ ๊ฐ’์ด ํšจ์œจ์ ์œผ๋กœ ์œ ์ง€๋˜๋„๋ก ๋ณด์žฅ

### rememberSaveable ๋‚ด๋ถ€ ๊ตฌ์กฐ

```kotlin
@Composable
public fun <T : Any> rememberSaveable(vararg inputs: Any?, init: () -> T): T {
// TODO(mgalhardo): We're planning to support both `autoSaver` and `serializer` in this base
// variant, where neither is explicitly passed. To avoid potential method signature conflicts,
// we're not using default parameters for `saver`.
// This introduces a direct dependency between Compose Runtime and KTX Serialization, which is
// currently under discussion at go/ktx-serialization-in-savedstate.
@Suppress("DEPRECATION")
return rememberSaveable(*inputs, saver = autoSaver(), key = null, init = init)
}
```

```kotlin
@Composable
public fun <T : Any> rememberSaveable(
vararg inputs: Any?,
saver: Saver<T, out Any> = autoSaver(),
key: String? = null,
init: () -> T,
): T {
val compositeKey = currentCompositeKeyHashCode
// key is the one provided by the user or the one generated by the compose runtime
val finalKey =
if (!key.isNullOrEmpty()) {
key
} else {
compositeKey.toString(MaxSupportedRadix)
}
@Suppress("UNCHECKED_CAST") (saver as Saver<T, Any>)

val registry = LocalSaveableStateRegistry.current

val holder = remember {
// value is restored using the registry or created via [init] lambda
val restored = registry?.consumeRestored(finalKey)?.let { saver.restore(it) }
val finalValue = restored ?: init()
SaveableHolder(saver, registry, finalKey, finalValue, inputs)
}

val value = holder.getValueIfInputsDidntChange(inputs) ?: init()
SideEffect { holder.update(saver, registry, finalKey, value, inputs) }

return value
}
```

rememberSaveable ํ•จ์ˆ˜๋Š” ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ๋ฐ ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ ์‹œ์—๋„ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ณต์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€์ ์œผ๋กœ ์ง€์› โ†’ remember ๋ณด๋‹ค ๋” ๋„“์€ ์Šค์ฝ”ํ”„์—์„œ์˜ ๋ฐ์ดํ„ฐ ๋ณต์›์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ

- ํ‚ค ์ƒ์„ฑ(Key Generation)
- key ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ปค์Šคํ…€ ํ‚ค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Œ
- ์ œ๊ณต๋˜์ง€ ์•Š์œผ๋ฉด ํ˜„์žฌ ์ปดํฌ์ง€์…˜ ํ•ด์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณตํ•ฉ ํ‚ค๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋จ

```kotlin
val compositeKey = currentCompositeKeyHashCode
// key is the one provided by the user or the one generated by the compose runtime
val finalKey =
if (!key.isNullOrEmpty()) {
key
} else {
compositeKey.toString(MaxSupportedRadix)
}
```

- ์ƒํƒœ ๋ณต์›(State Resotration)
- LocalSaveableStateRegistry๋Š” ์ฃผ์–ด์ง„ ํ‚ค์— ๋Œ€ํ•ด ์ €์žฅ๋œ ๊ฐ’์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ
- ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ์ œ๊ณต๋œ Saver๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์›๋จ

```kotlin
val registry = LocalSaveableStateRegistry.current
val restored = registry?.consumeRestored(finalKey)?.let { saver.restore(it) }
```

- ๊ธฐ๋ณธ๊ฐ’ ์ดˆ๊ธฐํ™”(Default Vlaue Initialization)
- ๋ณต์›๋œ ๊ฐ’์ด ์—†์œผ๋ฉด init ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ๊ฐ’์ด ์ดˆ๊ธฐํ™”๋จ

```kotlin
val finalValue = restored ?: init()
```

- Saveable Holder
- ์ƒํƒœ, saver, ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋ฐ ์ž…๋ ฅ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด SaveableHolder๊ฐ€ ์ƒ์„ฑ๋จ

```kotlin
SaveableHolder(saver, registry, finalKey, finalValue, inputs)
```

- ์ž…๋ ฅ ๋ณ€๊ฒฝ ์ฒ˜๋ฆฌ(Input Change Handling)
- rememberSaveable์— ๋Œ€ํ•œ ์ž…๋ ฅ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ƒํƒœ๊ฐ€ ๋ฌดํšจํ™”๋˜๊ณ  ๊ฐ’์ด ๋‹ค์‹œ ์ดˆ๊ธฐํ™”๋จ

```kotlin
val value = holder.getValueIfInputsDidntChange(inputs) ?: init()
```

- ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ(Side Effects)
- SideEffect๋Š” recomposition ์ค‘์— ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๊ฐ€ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์ €์žฅ๋˜๋„๋ก ๋ณด์žฅ

```kotlin
SideEffect { holder.update(saver, registry, finalKey, value, inputs) }
```


โ‡’ remember์™€ ๋‹ฌ๋ฆฌ LocalSaveableStateRegistry๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™”๋ฉด ํšŒ์ „๊ณผ ๊ฐ™์€ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์‹œ์—๋„ ์ƒํƒœ๋ฅผ ๋ณด์กดํ•จ์œผ๋กœ์จ ์ƒํƒœ์˜ ๋ณต์› ๋ฒ”์œ„๋ฅผ ๋„“ํž˜. ๋˜ํ•œ saver ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ์ปค์Šคํ…€ ์ง๋ ฌํ™” ๋ฐ ์—ญ์ง๋ ฌํ™” ๋กœ์ง์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์–ด ๋ณต์žกํ•œ ๊ฐ์ฒด๋ฅผ ์›ํ™œํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅ