Skip to content
Merged
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
15 changes: 15 additions & 0 deletions docs/seungjun/week8/Q-1-11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Q) 11. ์ƒํƒœ(State)๋ž€ ๋ฌด์—‡์ด๋ฉฐ ์ด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” API๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

Jectpack Compose ์—์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ API ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

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

1. `remember`: ์ดˆ๊ธฐ ์ปดํฌ์ง€์…˜ ๋ฐœ์ƒ์‹œ ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ณ  recomposition ์ด ๋ฐœ์ƒํ•˜๋ฉด ๊ธฐ์กด ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋œ ๊ฐ’์„ ๊บผ๋‚ด์˜ต๋‹ˆ๋‹ค.
2. `rememberSavable`: recomposition ๋ฟ ์•„๋‹ˆ๋ผ, ํ™”๋ฉด ํšŒ์ „๊ณผ ๊ฐ™์€ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์‹œ์—๋„ ํ™”๋ฉด ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. Bundle ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ˜•(`parcelable`) ๋˜๋Š” ๊ทธ ์™ธ ์œ ํ˜•์— ๋Œ€ํ•ด์„œ๋Š” ์ปค์Šคํ…€ saver ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
3. `mutableStateOf`: ๊ฐ€๋ณ€์ ์ธ ์ƒํƒœ๋ฅผ ์˜๋ฏธ, ์ƒํƒœ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ recomposition ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ

### ์‹ค์ „ ์งˆ๋ฌธ

Q) ์ƒํƒœ๋Š” recomposition๊ณผ ์–ด๋–ค ๊ด€๋ จ์ด ์žˆ์œผ๋ฉฐ, recomposition์ด ๋ฐœ์ƒํ•˜๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ•˜๋‚˜์š”?

`mutableStateOf` ๋กœ ์„ค์ •๋œ ๊ฐ’๊ณผ ๊ฐ™์€ ์ƒํƒœ๋Š” ๋ณ€๊ฒฝ์‹œ์— `recomposition` ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜์—ฌ ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ(์ƒํƒœ)์„ UI์— ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๋‹จ์ˆœ `mutableStateOf` ๋ฅผ ์‚ฌ์šฉ์‹œ ๋ฆฌ์ปดํฌ์ง€์…˜ ๋˜๋ฉด์„œ ํ•ด๋‹น ๊ฐ’์„ ์žƒ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๊ฐ’์„ ์žƒ์ง€ ์•Š๊ธฐ ์œ„ํ•ด `remember` ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’์„ ์ €์žฅ ํ•˜๊ณ , ๋ฆฌ์ปดํฌ์ง€์…˜์‹œ์— ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
64 changes: 64 additions & 0 deletions docs/seungjun/week8/Q-1-12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Q) 12. ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…(state hoisting)์œผ๋กœ ์–ด๋–ค ์ด์ ์„
์–ป์„ ์ˆ˜ ์žˆ๋‚˜์š”?

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

๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์›์น™์„ ๋”ฐ๋ผ UI ๋ฅผ ๋” ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

**State** : ๋ถ€๋ชจ ์ปดํฌ์ €๋ธ”์—์„œ ๊ด€๋ฆฌ, ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์„ ์ ์šฉํ•˜๋ ค๋Š” ์ปดํฌ์ €๋ธ”์€ ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์„œ๋Š” ์•ˆ๋œ๋‹ค.

**Events** or **Triggers** : onClick, onValueChange ์™€ ๊ฐ™์€ ์ด๋ฒคํŠธ๋Š” ์ž์‹์—์„œ ๊ฐ’์„ ๋ฐ”๊พธ๊ณ  ์ด๋ฅผ ๋ถ€๋ชจ๋กœ ์ „๋‹ฌ ๋ฐ›๋Š” ํ˜•ํƒœ๋กœ ์—…๋ฐ์ดํŠธ, ์ž์‹ ์ปดํฌ์ €๋ธ”์—์„œ ์ฝœ๋ฐฑ ๋ฐฉ์‹์œผ๋กœ ํ•ด๋‹น ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ `Stateless` ํ•œ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

### ์™œ Stateless ํ•˜๊ฒŒ ์œ ์ง€ํ•ด์•ผํ•˜๋Š”๊ฐ€?

state hoisting ์˜ ์žฅ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

- Single source of truth: ๋‹จ์ผ ์ถœ์ฒ˜๋งŒ์„ ๋ณด์žฅํ•˜๊ฒŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ๊ฐ€ ์–ฝํžˆ๋Š” ๊ฒƒ์„ ์˜ˆ๋ฐฉํ•ฉ๋‹ˆ๋‹ค.
- Encapsulated: ์บก์Аํ™”๋ฅผ ํ†ตํ•ด ์ƒํƒœ ์ˆ˜์ •์„ stateful ์ปดํฌ์ €๋ธ”์—์„œ๋งŒ ์กฐ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
- ์ƒํƒœ๊ฐ€ ์—†๋Š” ์ปดํฌ์ €๋ธ”์€ ํ…Œ์ŠคํŠธ๊ฐ€ ๋” ๊ฐ„๋‹จํ•ด์ง‘๋‹ˆ๋‹ค.
- Shareable: ์—ฌ๋Ÿฌ ์ปดํฌ์ €๋ธ”์— ์ƒํƒœ๋ฅผ ๊ณต์œ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

### ์‹ค์ „ ์งˆ๋ฌธ

Q) ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์ด ์™œ ์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ค๋‚˜์š”? ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด์„œ ์„ค๋ช…ํ•ด ์ฃผ์„ธ์š”.

- ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์€ ์ปดํฌ์ €๋ธ”์ด ์ƒํƒœ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ  ๊ฐ’๊ณผ ์ด๋ฒคํŠธ๋งŒ ์ „๋‹ฌ๋ฐ›๊ฒŒ ํ•˜์—ฌ UI ํ‘œํ˜„์—๋งŒ ์ง‘์ค‘ํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.
- ๊ทธ ๊ฒฐ๊ณผ ์ปดํฌ์ €๋ธ”์ด ํŠน์ • ๋กœ์ง์ด๋‚˜ ์ดˆ๊ธฐ๊ฐ’์— ์ข…์†๋˜์ง€ ์•Š์•„ ๋‹ค์–‘ํ•œ ํ™”๋ฉด๊ณผ ์ƒํ™ฉ์—์„œ ์žฌ์‚ฌ์šฉ์ด ์‰ฌ์›Œ์ง„๋‹ค.
- ๋˜ํ•œ ์ƒํƒœ๋ฅผ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์–ด ํ…Œ์ŠคํŠธ ์‹œ ์›ํ•˜๋Š” ์ƒํƒœ๋ฅผ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด ํ…Œ์ŠคํŠธ๊ฐ€ ๋‹จ์ˆœํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

Q) ์–ด๋–ค ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์ปดํฌ์ €๋ธ” ๋‚ด๋ถ€์— ์ƒํƒœ๋ฅผ ๊ฐ–๋„๋ก ํ•˜์‹ค ๊ฑด๊ฐ€์š”? ํ•ด๋‹น ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ์ปดํฌ์ €๋ธ”์— ์ƒํƒœ๋ฅผ ๊ฐ–๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์— ๋น„ํ•ด ์–ด๋–ค ์žฅ์ ์„ ๊ฐ–๋‚˜์š”?

**1๏ธโƒฃ ํ•ด๋‹น ์ƒํƒœ๊ฐ€ UI ๋‚ด๋ถ€์—์„œ๋งŒ ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š” ๊ฒฝ์šฐ**

์˜ˆ๋ฅผ ๋“ค์–ด,

- ๋ฒ„ํŠผ์˜ pressed ์ƒํƒœ
- ํ…์ŠคํŠธ ํ•„๋“œ์˜ ํฌ์ปค์Šค ์—ฌ๋ถ€
- ์ž„์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ง„ํ–‰ ์ƒํƒœ
- ํ† ๊ธ€์˜ ์—ด๋ฆผ/๋‹ซํž˜ ์—ฌ๋ถ€

์ฒ˜๋Ÿผ **์™ธ๋ถ€์—์„œ ์•Œ ํ•„์š”๊ฐ€ ์—†๊ณ , UI ํ‘œํ˜„์—๋งŒ ๊ตญํ•œ๋œ ์ƒํƒœ**๋ผ๋ฉด

๊ตณ์ด ์ƒ์œ„๋กœ ์ƒํƒœ๋ฅผ ๋Œ์–ด์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ  ์ปดํฌ์ €๋ธ” ๋‚ด๋ถ€์—์„œ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

**2๏ธโƒฃ ์žฌ์‚ฌ์šฉ๋˜๊ฑฐ๋‚˜ ๊ณต์œ ๋  ํ•„์š”๊ฐ€ ์—†๋Š” ์ƒํƒœ์ธ ๊ฒฝ์šฐ**

์ƒํƒœ๊ฐ€ ๋‹ค๋ฅธ ์ปดํฌ์ €๋ธ”๊ณผ ๊ณต์œ ๋˜์ง€ ์•Š๊ณ 

์™ธ๋ถ€ ๋กœ์ง์ด๋‚˜ ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉฐ ํŠน์ • UI ๊ตฌํ˜„์—๋งŒ ์ข…์†์ ์ธ ๊ฒฝ์šฐ

์ด๋Ÿฐ ์ƒํƒœ๊นŒ์ง€ ํ˜ธ์ด์ŠคํŒ…ํ•˜๋ฉด ์˜คํžˆ๋ ค **๋ถˆํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ์ฆ๊ฐ€์™€ ๊ตฌ์กฐ ๋ณต์žก๋„**๋งŒ ๋†’์•„์ง‘๋‹ˆ๋‹ค.

**3๏ธโƒฃ ์ด ๊ฒฝ์šฐ ์ปดํฌ์ €๋ธ” ๋‚ด๋ถ€ ์ƒํƒœ์˜ ์žฅ์ **

์ด๋Ÿฌํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

- **์ฝ”๋“œ ๋‹จ์ˆœ์„ฑ:** ์ƒ์œ„ ์ปดํฌ์ €๋ธ”์— ๋ถˆํ•„์š”ํ•œ ์ƒํƒœ์™€ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์•„๋„ ๋จ
- **์บก์Аํ™”:** UI ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์„ ์ปดํฌ์ €๋ธ” ๋‚ด๋ถ€์— ์ˆจ๊ธธ ์ˆ˜ ์žˆ์Œ
- **๊ฐ€๋…์„ฑ:** โ€œ์ด ์ƒํƒœ๋Š” ์ด UI์—๋งŒ ์“ฐ์ธ๋‹คโ€๋Š” ์˜๋„๊ฐ€ ์ฝ”๋“œ์—์„œ ๋ช…ํ™•ํ•ด์ง

์ฆ‰, ๋ชจ๋“  ์ƒํƒœ๋ฅผ ํ˜ธ์ด์ŠคํŒ…ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค

**UI ์ „์šฉ ์ƒํƒœ๋Š” ์ปดํฌ์ €๋ธ” ๋‚ด๋ถ€์— ๋‘๋Š” ํŽธ์ด ์˜คํžˆ๋ ค ์œ ์ง€๋ณด์ˆ˜์— ์œ ๋ฆฌ**ํ•ฉ๋‹ˆ๋‹ค.
135 changes: 135 additions & 0 deletions docs/seungjun/week8/Q-1-13.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Q) 13. remember์™€ rememberSaveable์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

### remember

๋ชฉ์ : ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  recomposition ์‹œ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋œ ๊ฐ’์„ ๊บผ๋‚ด ์ƒํƒœ๋ฅผ ์œ ์ง€

์‚ฌ์šฉ: ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ํ›„์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚ ๋ผ๊ฐ€๋„ ๋˜๋Š” ์ƒํƒœ์— ์‚ฌ์šฉ, ์• ๋‹ˆ๋ฉ”์ด์…˜์ด๋‚˜ ์ž„์‹œ์  UI ์ƒํƒœ

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

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

@ComposeCompilerApi
public 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(`updateRememberedValue`) ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ปดํฌ์ง€์…˜ ๋ฐ์ดํ„ฐ ๊ฐ’์„ ์บ์‹œํ•ฉ๋‹ˆ๋‹ค.

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

### rememberSaveable

๋ชฉ์ : ๊ตฌ์„ฑ ๋ณ€๊ฒฝ์‹œ์—๋„ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜์—ฌ ๋” ๋„“์€ ๋ฒ”์œ„์—์„œ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ณต์›, `SDK ์˜ Bundle` ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์— ํ•œํ•ด ์ž๋™์œผ๋กœ ์ €์žฅํ•˜๊ณ  ๋ณต์›

์‚ฌ์šฉ: ์œ ์ € ์ธํ’‹ ์ž…๋ ฅ์ด๋‚˜ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ƒํƒœ์™€ ๊ฐ™์ด ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ํ›„์—๋„ ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š” ์ƒํƒœ์— ์‚ฌ์šฉ

- ๋ณต์žกํ•œ ๊ฐ์ฒด์— ๋Œ€ํ•ด ์ปค์Šคํ…€ Saver ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

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

```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
}
```

1. ํ‚ค ์ƒ์„ฑ: 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)
}
```

2. ์ƒํƒœ ๋ณต์›: `LocalSaveableStateRegistry` ๋Š” ์ฃผ์–ด์ง„ ํ‚ค์— ๋Œ€ํ•ด ์ด์ „์— ์ €์žฅ๋œ ๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธ ํ›„, ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด Saver ๋ฅผ ํ†ตํ•ด ๋ณต์›๋œ๋‹ค.

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

3. ๊ธฐ๋ณธ๊ฐ’ ์ดˆ๊ธฐํ™”: ๋ณต์›๋œ ๊ฐ’์ด ์—†์œผ๋ฉด init ๋žŒ๋‹ค๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธ๊ฐ’์ด ์ดˆ๊ธฐํ™” ๋œ๋‹ค.

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

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

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

5. ์ž…๋ ฅ ๋ณ€๊ฒฝ ์ฒ˜๋ฆฌ: `rememberSaveable` ์— ๋Œ€ํ•œ ์ž…๋ ฅ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ƒํƒœ๊ฐ€ ๋ฌดํšจํ™” ๋˜๊ณ  ๊ฐ’์ด ๋‹ค์‹œ ์ดˆ๊ธฐํ™” ๋œ๋‹ค.

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

6. ์‚ฌ์ด๋“œ ์ดํŒฉํŠธ: SideEffect ๋ฅผ ํ†ตํ•ด ๋ฆฌ์ปดํฌ์ง€์…˜ ์‹œ ์—…๋ฐ์ดํŠธ๋œ ์ƒํƒœ๊ฐ€ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์ €์žฅ๋œ๋‹ค.

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


๊ธฐ๋ณธ์ ์œผ๋กœ `LocalSaveableStateRegistry` ๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ ๋ณ€๊ฒฝ์‹œ์—๋„ ์ƒํƒœ๋ฅผ ๋ณด์กดํ•˜๊ฒŒ ํ•˜๋Š” ๊ตฌ์กฐ์ด๋‹ค.

### ์‹ค์ „ ์งˆ๋ฌธ

Q) remember์ด ์•„๋‹Œ rememberSaveable๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ๋ฌด์—‡์ด๋ฉฐ, ์–ด๋–ค ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋‚˜์š”?

๊ธฐ๋ณธ์ ์œผ๋กœ rememberSaveable ์€ ์ดˆ๊ธฐํ™” ๋ฐ ์ง๋ ฌํ™” ์—ญ์ง๋ ฌํ™” ๋กœ์ง์ด ์ถ”๊ฐ€์ ์œผ๋กœ ๋“ค์–ด๊ฐ€๊ธฐ์— ํ•ด๋‹น ๋ฆฌ์†Œ์Šค๋ฅผ remember ๋ณด๋‹ค๋Š” ๋” ๋งŽ์ด ๊ฐ€์ ธ๊ฐ„๋‹ค๊ณ  ๋ณผ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ณผ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ์‹œ ์žƒ์–ด๋ฒ„๋ฆฌ์ง€ ์•Š๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ์™ธ ์ค‘์š”ํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ(์žƒ์–ด๋„ ๋˜๋Š” ๋ฐ์ดํ„ฐ๋Š”) remember ๋กœ ๊ฐ€๋ณ๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š”๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Q) ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›๋˜์ง€ ์•Š๋Š” ์ปค์Šคํ…€ ๋น„์›์‹œ(nonโ€‘primitive) ๊ฐ’ ๋กœ ์ €์žฅํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•˜๋‚˜์š”?

`rememberSaveable` ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ **Bundle์— ์ €์žฅ ๊ฐ€๋Šฅํ•œ ํƒ€์ž…๋งŒ** ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์—,

์ปค์Šคํ…€ ๋น„์›์‹œ ํƒ€์ž…์€ **์ง์ ‘ ์ €์žฅยท๋ณต์› ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•œ `Saver`๋ฅผ ๊ตฌํ˜„ํ•ด ์‚ฌ์šฉ** ํ•ฉ๋‹ˆ๋‹ค.
65 changes: 65 additions & 0 deletions docs/seungjun/week8/Q-1-14.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Q) 14. ์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜ ๋‚ด์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„(coroutine scope)๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

๊ธฐ๋ณธ์ ์œผ๋กœ Compose ์—์„œ ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” `rememberCoroutineScope` ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

### rememberCoroutineScope ์‚ฌ์šฉ ์ด์œ 

`rememberCoroutineScope` ๋Š” ์ปดํฌ์ €๋ธ”์ด ์ปดํฌ์ง€์…˜์„ ๋ฒ—์–ด๋‚  ๋•Œ ํ™œ์„ฑ ์ค‘์ธ ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„๋ฅผ ์ž๋™์œผ๋กœ ์ทจ์†Œํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ ์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜์˜ ๋‚ด๋ถ€ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ์ธ์ง€ํ•˜์—ฌ ๋™์ž‘ํ•˜๊ธฐ์— ๊ฐœ๋ฐœ์ž๋Š” ์ˆ˜๋™์œผ๋กœ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

โ†” GlobalScope ์•ฑ ์ „์—ญ์— ์‚ฌ์šฉ๋˜๋Š” Scope๋กœ ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„๋ฅผ ์ˆ˜๋™์œผ๋กœ ๊ด€๋ฆฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ปดํฌ์ €๋ธ”์ด ์‚ฌ๋ผ์ ธ๋„ ์œ ์ง€๋˜์–ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ, viewmodel ์˜ ViewModelScope ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, lifecycleScope ๋ฅผ ์‚ฌ์šฉํ•ด ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ๋ฅผ ๋ณด์žฅํ•˜๋ฉด์„œ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์ž‘์—… ์ทจ์†Œ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

```kotlin
@Composable
public inline fun rememberCoroutineScope(
crossinline getContext: @DisallowComposableCalls () -> CoroutineContext = {
EmptyCoroutineContext
}
): CoroutineScope {
val composer = currentComposer
return remember { createCompositionCoroutineScope(getContext(), composer) }
}

@PublishedApi
@OptIn(InternalComposeApi::class)
internal fun createCompositionCoroutineScope(
coroutineContext: CoroutineContext,
composer: Composer,
): CoroutineScope =
if (coroutineContext[Job] != null) {
CoroutineScope(
Job().apply {
completeExceptionally(
IllegalArgumentException(
"CoroutineContext supplied to " +
"rememberCoroutineScope may not include a parent job"
)
)
}
)
} else {
val applyContext = composer.applyCoroutineContext
RememberedCoroutineScope(applyContext, coroutineContext)
}
```

`createCompositionCoroutineScope` ๋ฅผ ํ†ตํ•ด ์ฃผ์–ด์ง„ ์ฝ”๋ฃจํ‹ด ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•ด ์ƒˆ ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

**์ƒ์œ„ Job ์ œํ•œ**: ์ œ๊ณต๋œ `CoroutineContext` ์—์„œ Job ์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. `rememberCoroutineScope` ๊ฐ€ ๊ธฐ์กด์˜ ์ƒ์œ„ Job ์— ์ข…์†๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋…๋ฆฝ์  ์Šค์ฝ”ํ”„๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

**Job ๊ด€๋ฆฌ**:์Šค์ฝ”ํ”„๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Job ์ด ์ฝ”๋ฃจํ‹ด ์ปจํ…์ŠคํŠธ์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

**Composer ํ†ตํ•ฉ**: `composer.applyCoroutineContext` ๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑ๋œ Job ๊ณผ ๊ฒฐํ•ฉํ•ด ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

### ์‹ค์ „ ์งˆ๋ฌธ

Q) ์ปดํฌ์ €๋ธ” ๋‚ด์—์„œ ์ง์ ‘ ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹œ์ž‘ํ•˜๋ฉด ์–ด๋–ค ์œ„ํ—˜์„ฑ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‚˜์š”? `rememberCoroutineScope`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?

`rememberCoroutineScope()`๋Š” **Composable์˜ Composition ์ƒ๋ช…์ฃผ๊ธฐ์— ๋ฌถ์ธ ์Šค์ฝ”ํ”„**๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๊ฐ™์€ Composition ๋™์•ˆ์€ **์Šค์ฝ”ํ”„๊ฐ€ ์žฌ์‚ฌ์šฉ**๋˜์–ด ๋ฆฌ์ปดํฌ์ง€์…˜๋งˆ๋‹ค ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š์•„์š”. Composable์ด Composition์—์„œ ์ œ๊ฑฐ๋˜๋ฉด **์ž๋™์œผ๋กœ cancel**๋˜์–ด ๋ˆ„์ˆ˜/๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…์„ ์ค„์ž…๋‹ˆ๋‹ค.

์ฆ‰, UI ์ด๋ฒคํŠธ(๋ฒ„ํŠผ ํด๋ฆญ ๋“ฑ)๋กœ โ€œ์ฆ‰์‹œ ์‹คํ–‰ํ•˜๋Š” ์ž‘์—…โ€์„ ์•ˆ์ „ํ•˜๊ฒŒ launchํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
Loading