
ํซ ์คํธ๋ฆผ
- ๋ฐ์ดํฐ๋ฅผ ์๋นํ๋ ๊ฒ๊ณผ ๋ฌด๊ดํ๊ฒ ์์๋ฅผ ์์ฑ
- Coroutines Channel
- ์ปฌ๋ ์ (List, Set)
์ฝ๋ ์คํธ๋ฆผ
- ์์ฒญ์ด ์์ ๋๋ง ์์ ์ ์ํ
- Sequence, Stream
- Flow, RxJava ์คํธ๋ฆผ
Flow
- Flow๋ฅผ ๋ฌด๊ธฐ ์์ดํ ๊ณต์ฅ ์์ ์๋ ์ปจ๋ฒ ์ด์ด ๋ฒจํธ๋ผ๊ณ ์๊ฐ๐จ
- ๊ฐ๊ฐ์ ์์ดํ ๋ค์ ๋ฐ์ดํฐ๋ผ๊ณ ์๊ฐ
- ๋ฌด๊ธฐ ์ ์ฅ๊ณ ์์ ๋ฌด๊ธฐ(๋ฐ์ดํฐ)๋ค์ ๋๋ค ํ๊ฒ ์ค์๊ฐ์ผ๋ก ์์ฑํ๊ณ , ๊ฐ ์ํฉ๋ค์ ์ ์ฅํด ๋ณด์!
sealed class Weapon { class Sword(): Weapon() class Staff(): Weapon() class SpellBook(): Weapon() }
Flow ์์ฑ
val weaponProducer: Flow<Weapon>
- Flow๋ฅผ ์์ฑํ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ โ ์ฝ๋ฃจํด ์ฑ๋์ produce์ ๋น์ทํ ํํ์ ๋น๋ flow ์ ์ธ
- Flow๋ ๊ฐ์ด ํ์ํ ๋๋ง ์์ฑํ๊ธฐ ๋๋ฌธ์,
๋ฐ์ง๊ณ ๋ณด๋ฉด ๋น๋๋ ์๋๊ณcollect() ๊ฐ์ ์ต์ข ์ฐ์ฐ ์ ๋ฐ์ดํฐ๊ฐ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ์ ์ํ ๊ฒ
Emit๊ณผ Collect
- ์๋ก์ด ๋ฌด๊ธฐ(๋ฐ์ดํฐ)๊ฐ ์์ฑ๋ ๋๋ง๋ค weaponProducer๋ emit() ํจ์๋ฅผ ํธ์ถํ๋ค.
- collect()๋ฅผ ํธ์ถํ์ฌ ๋ฌด๊ธฐ(๋ฐ์ดํฐ)๋ฅผ ์์
import kotlinx.coroutines.flow.flow private val weaponProducer: Flow<Weapon> = flow { emit(Weapon.Sword()) emit(Weapon.Staff()) emit(Weapon.SpellBook()) } private val weaponBox = mutableListOf<Weapon>() suspend fun main() { weaponProducer.collect { weapon -> weaponBox.add(weapon) } }

Kotlin Flow์ Operators ์ข ๋ฅ
- Terminal Operators
- Flow์ ์คํ์ ์์ํ๊ฑฐ๋ ์ต์ข ์์ ์ ์ํํ๋ ๋ฐ ์ฌ์ฉ
- collect(), first(), last() ๋ฑ
- Intermediate Operators
- ๋ฐ์ดํฐ๋ฅผ ๋ณํ, ํํฐ๋ง ๋๋ ์กฐ์
- Flow๋ฅผ ์คํํ์ง ์์ผ๋ฉฐ, ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ์ ์
- filter, map, transform ๋ฑ
Intermediate Operators
Filter
- ํน์ ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ ์์๋ฅผ ์ ํ
- ๋ฌด๊ธฐ๊ฐ Sword์ธ ๊ฒฝ์ฐ๋ง collect()
weaponProducer .filter { weapon -> weapon is Sword }.collect()

DistinctUntilChanged
- ์ฐ์๋ ์ค๋ณต ์์๋ฅผ ํํฐ๋ง
- ์ด์ ๊ฐ๊ณผ ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ง emit ๊ฐ๋ฅ
weaponProducer .distinctUntilChanged() .collect()

Map
- ๊ฐ ์ ๋ ฅ ์์๋ฅผ ๋ณํํ๋ ๋ฐ ์ฌ์ฉ
- ์๋ Flow๋ Collection์ ๋ณ๊ฒฝํ์ง ์๊ณ , ๋ณํ๋ ๊ฐ์ผ๋ก ์๋กญ๊ฒ ๋ง๋ ๋ค.
- ์ผ๋ฐ ๋ฌด๊ธฐ(Weapon)์์ EnchantedWeapons๋ก ๋ณํ
weaponProducer .map { weapon -> mapToEnchantedWeapon(weapon) }.collect()

FlatMap
- Map์ ๊ฐ ์์๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ๋ณํ
- FlatMap์ ๊ฐ ์์๋ฅผ ๋ค๋ฅธ Flow๋ก ๋ณํ ํ ์ด๋ค์ ๋ณํ
Map์ ๋ด๋ถ ๊ตฌํ
inline fun <T, R> Flow<T>.map( crossinline transform: suspend (value: T) -> R ): Flow<R>
FlatMap์ ๋ด๋ถ ๊ตฌํ
inline fun <T, R> Flow<T>.flatMapLatest( crossinline transform: suspend (value: T) -> Flow<R> ): Flow<R>
- ๊ฐ๊ฐ์ ์์๋ฅผ Flow๋ก ๋ฆฌํดํ ํ, ๊ทธ Flow๋ค์ ๋ณํฉ
val weaponTypes: Flow<WeaponType> = queryWeaponTypes() private fun produceWeapons(weaponType: WeaponType): Flow<Weapon> { // Emit weapons of the specified type } weaponTypes .flatMap { type -> produceWeapons(type) }.collect()

- WeaponType์ด ๋ฐฉ์ถ๋๋ฉด์ Flow<Weapon>์ด ์์ฑ
Zip
- ๋ Flow๋ฅผ ๊ฒฐํฉํ์ฌ ๋์ํ๋ ์์๋ค์ Pair๋ก ๋ฌถ์ด ์๋ก์ด ์์๋ฅผ ์์ฑ
- Flow A์ ์ฒซ ๋ฒ์งธ ์์์ Flow B์ ์ฒซ ๋ฒ์งธ ์์๊ฐ ์ง์ ์ด๋ฃจ๊ณ , ๋ ๋ฒ์งธ ์์๋ผ๋ฆฌ ์ง์ ์ด๋ฃจ๊ณ . . .
- enchantments flow์ weapons flow๋ฅผ ๊ฒฐํฉํ์ฌ EnchentedWeapons๋ฅผ ์์ฑ
val enchantments: Flow<Enchantment> = queryEnchantments() val weapons: Flow<Weapon> = queryWeapons() enchantments.zip(weapons) { enchantment, weapon -> createMagicWeapon(enchantment, weapon) }

๊ฒฐ๋ก
Flow๋ฅผ ์๊ฐํํด์ ๋ณผ ์ ์์ด์ ์ฝ๊ณ ์ฌ๋ฐ๊ฒ ์ดํด๊ฐ ๊ฐ๋ฅํ๋ค! ๐
Flow๋ฅผ ์์ ์์ฌ๋ก ์ฌ์ฉํ๋ฉด ์ ๋ง ํธ๋ฆฌํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ฐ์ํ ์ ์์ ๊ฒ ๊ฐ๋ค!!
ํด๋น ํฌ์คํ ์ ์๋ฌธ์ ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Reference
https://medium.com/@robert.baricevicpetrus/kotlin-flows-animated-55640aa48ac9
Kotlin Flows Animated
This article takes a playful approach to explaining Kotlin Flow, using animations that even a six-year-old can grasp.
medium.com