Redux: ์ œ์•ˆ: "์ €์žฅ์†Œ" ์ด๋ฆ„์„ "๋ฆฌ๋“€์„œ"๋กœ ๋ณ€๊ฒฝ

์— ๋งŒ๋“  2015๋…„ 06์›” 18์ผ  ยท  54์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: reduxjs/redux

๋‚ด ๊ธฐ์–ต์ด ๋งž๋‹ค๋ฉด @gaearon , Redux๊ฐ€ ๋ณ„ 500๊ฐœ๋ฅผ ๋‹ฌ์„ฑํ•˜๋ฉด ์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ ์šฉํ•˜๊ฒ ๋‹ค๊ณ  ๋ง์”€ํ•˜์…จ์Šต๋‹ˆ๋‹ค. :)

๋˜ํ•œ ๋ฌธ์„œ์˜ "์šฉ์–ด" ์„น์…˜์ด ์žˆ์–ด ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํŠนํžˆ ์šฐ๋ฆฌ๊ฐ€ ํ˜„์žฌ _์ ์–ด๋„_ ์„ธ ๊ฐ€์ง€ ๋‹ค๋ฅธ ๊ฒƒ์„ ์–ธ๊ธ‰ํ•˜๊ธฐ ์œ„ํ•ด "๋””์ŠคํŒจ์ฒ˜"๋ผ๋Š” ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

discussion docs

๋ชจ๋“  54 ๋Œ“๊ธ€

-1 ์ด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ํ•™์Šต ๊ณก์„ ์€ ์ด๋ฏธ ๊ฐ€ํŒŒ๋ฅด๊ฒŒ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ํ”Œ๋Ÿญ์Šค ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ ์ƒˆ๋กœ์šด ์šฉ์–ด๋ฅผ ๋„์ž…ํ•˜์—ฌ ๋” ๊ฐ€ํŒŒ๋ฅด๊ฒŒ ๋งŒ๋“ค์ง€ ๋ง™์‹œ๋‹ค.

๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋ฆฌ๋“€์„œ๋ผ๊ณ  ๋ถ€๋ฅผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ณต๊ฐœ์ ์œผ๋กœ ์ €์žฅ์†Œ๋กœ ์œ ์ง€ํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์†”์งํžˆ ์ง€๊ธˆ์ด ๋” ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๊ฒƒ ๊ฐ™์•„์š”. ์™„์ „ํžˆ ์ผํ™”์ง€๋งŒ IRL์ด "์ƒ์ "์ด ๋ฌด๊ตญ์ ์ž๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์„ ์—‰๋ง์œผ๋กœ ๋งŒ๋“  ์‚ฌ๋žŒ์ด ๋ช‡ ๋ช… ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ „ํ†ต์ ์ธ Flux์—์„œ "์ €์žฅ์†Œ"์˜ ์ฃผ์š” ํŠน์ง•์€ 1) ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ  2) ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค Redux์—์„œ๋Š” ์‚ฌ์‹ค์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์šฉ์–ด๋ฅผ ๋ช…ํ™•ํžˆ ํ•ด์•ผ ํ•˜๊ณ  ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๋” ๋‚˜์€ ์ด๋ฆ„์„ ์ฐพ์•„์•ผ ํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.
์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋กœ JSDoc์ด ์žˆ์–ด์•ผ ํ•˜๊ณ  ์šฉ์–ด ์„น์…˜๋„ ๋„์›€์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
์ผ๋ฐ˜์ ์œผ๋กœ ์ผ์ • ์ˆ˜์ค€์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

FP์ฒ˜๋Ÿผ ๋“ค๋ฆฌ์ง€ ์•Š์ง€๋งŒ "์ƒ์ "๋„ ์•„๋‹Œ ์šฉ์–ด๊ฐ€ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.
๋„๋ฉ”์ธ?

OTOH๋Š” ์ด๋ฏธ Redux๋ผ๊ณ  ๋ถˆ๋ฆฌ๋ฏ€๋กœ ์ ์–ด๋„ "๋ฆฌ๋“€์„œ"๋Š” ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒํƒœ๋ฅผ ํ•œ ๋‹จ๊ณ„ ์•ž์œผ๋กœ ์ด๋™์‹œํ‚ค๋Š” "๋‹จ๊ณ„ ์—…๋ฐ์ดํŠธ" ๋˜๋Š” "์Šคํ…Œํผ"๋Š” ์–ด๋–ป์Šต๋‹ˆ๊นŒ? step , update ๋˜๋Š” next ๋ผ๋Š” ํ•จ์ˆ˜๊ฐ€ ์žˆ๋Š” Elm ๋ฌธํ—Œ์—์„œ ์ด๊ฒƒ์ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ์—๋Š” node.js ์ˆ˜ํ•˜๋ฌผ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ๋“ค์€ ๊ธฐ๋Šฅํ•˜๋Š” ๋ฐฉ์‹์˜ ์ €์žฅ์†Œ๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ํ”Œ๋Ÿญ์Šค ์ €์žฅ์†Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒํƒœ ๋…ผ๋ฆฌ๋ฅผ ๊ฑฐ๊ธฐ์— ๋„ฃ์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์€ ํ”Œ๋Ÿญ์Šค ์Šคํ† ์–ด๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ƒํƒœ ๊ด€๋ฆฌ์ž์ž…๋‹ˆ๋‹ค.

์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๊ฐ์†๊ธฐ๋Š” ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ "๋ฆฌ๋“€์„œ"๊ฐ€ ์‹ค์ œ๋กœ ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•œ ์ •ํ™•ํ•œ ์„ค๋ช…์ด๊ธฐ ๋•Œ๋ฌธ์— :)

์—…๋ฐ์ดํ„ฐ? ๊ฐ์†๊ธฐ๋ณด๋‹ค ์„ค๋ช…์  + ๋œ ์†๋ฌผ์  ์ธ ์†Œ๋ฆฌ.

๋‚˜๋„ reducer ์ข‹์•„ํ•ด

์™œ "๋ฆฌ๋“€์„œ"๊ฐ€ ์†๋ฌผ์ธ์ง€ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋œ ์„ค๋ช…์ ์ธ ์ƒˆ๋กœ์šด ์šฉ์–ด๋ฅผ ๋ฐœ๋ช…ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์‹ค์ œ ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚ซ์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ๋‘˜ ๋‹ค ์œ ํšจํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์ด ๊ทธ๊ฒƒ์„ ๋ณด๋Š” ๊ด€์ ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค: _reducer_ of action(into state) ๋˜๋Š” _updater_ of state.

"์—…๋ฐ์ดํ„ฐ"๋Š” ๋Œ์—ฐ๋ณ€์ด๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. "Reducer"๋Š” ์ด์ „ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ถ„๋ช…ํžˆ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ๋‚ด๊ฐ€ ์ƒ๊ฐํ•˜๊ธฐ์— ์ข‹์€ ์ ์ด๋ฉฐ, redux๊ฐ€ ๋Œ์—ฐ๋ณ€์ด์™€ ํ•จ๊ป˜ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ์— ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

FP์— ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ Redux๋ฅผ ์นœ์ˆ™ํ•˜๊ฒŒ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์— ๊ฐ์‚ฌํ•˜์ง€๋งŒ ๋” ๋‚˜์€ ๋ฌธ์„œ๋กœ ์ด๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ฌธ์„œ๊ฐ€ ๋งˆ์Œ์— ๋“ค์ง€๋งŒ ์–ธ๋œป ๋ณด๊ธฐ์—๋Š” ๋‹ค์†Œ ์••๋„์ ์ž…๋‹ˆ๋‹ค. ๊ณ ๊ธ‰ ํ•ญ๋ชฉ(๋ฏธ๋“ค์›จ์–ด, ํ•ซ ๋ฆฌ๋กœ๋”ฉ)๋ณด๋‹ค ์นœ์ˆ™ํ•œ ํ•ญ๋ชฉ(์•ก์…˜ ์ž‘์„ฑ์ž, ๋ฆฌ๋“€์„œ ๋กœ์ง)์„ ์ „๊ฒฝ์œผ๋กœ ํ•˜๋Š” ์ข‹์€ ๋ฌธ์„œ ์‚ฌ์ดํŠธ๊ฐ€ ๋งค์šฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋„ ์—ฌ๊ธฐ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋น ๋ฅด๊ฒŒ ์„ฑ์žฅํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํŒ๋‹จํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. :)

๋” ๋‚˜์€ ๋ฌธ์„œ์™€ ํ•จ๊ป˜ ์ด๋Ÿฌํ•œ ์ผ์ด ๋ฐœ์ƒํ•˜๋ฉด "Stores"๋ฅผ "Reducers"๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•„์ˆ˜ ์š”์†Œ๋Š” "Flux์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ๊ฑฑ์ •ํ•˜์ง€ ๋งˆ์„ธ์š”"๋ผ๋Š” ๋ถ„์œ„๊ธฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ด๊ฒƒ์ด Flux์™€ ๋น„์Šทํ•˜์ง€๋งŒ Flux์˜ ์ข‹์€ ์†์„ฑ ์ค‘ ์ผ๋ถ€๋ฅผ ๊นจ๋œจ๋ฆฌ๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋˜ํ•œ ๊ทธ๋“ค์ด FP๋ฅผ ๋ฐฐ์šธ ํ•„์š”๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๊ฒƒ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ, ๋‚˜๋Š” ์ด ๋ณ€ํ™”์— ๋Œ€ํ•ด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ํ™•์‹ ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ œ์•ˆ: Redux ํด๋ž˜์Šค์˜ ์ด๋ฆ„์„ Store๋กœ ๋ฐ”๊พธ๋ฉด(์ƒ๊ฐํ•ด ๋ณด์„ธ์š”. ๋‘ ๊ฐ€์ง€ ๋ชฉ์ ์€ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค) ์ตœ์ƒ์œ„ API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const store = createStore(reducers);

<Provider store={store} />

์ด๊ฒƒ์€ ์•„์ด๋””์–ด๋ฅผ ๊ฝค ์ž˜ ์ „๋‹ฌํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ๋Š” ์Šคํ† ์–ด ๋กœ์ง์ด ๊ฐ€๋Š” ๊ณณ์ด์ง€๋งŒ ์Šคํ† ์–ด ์ž์ฒด๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

store.dispatch ๊ฐ€ ์ž˜๋ชป๋œ ๋Š๋‚Œ์ด ๋“ค์ง€๋งŒ ๋‚˜๋Š” ์ด๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ๊ทธ๊ฒŒ ์ œ๊ฐ€ ์ •๋ง ์ข‹์•„ํ•˜์ง€ ์•Š๋Š” ํ•œ ๊ฐ€์ง€์ด์ง€๋งŒ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. store.getState() , store.setState() , store.subscribe()

์ง€๊ธˆ ์ƒ๊ฐํ•ด๋ณด๋ฉด ์šฐ๋ฆฌ๋Š” ์‹ค์ œ๋กœ "๋ฐฐํฌ"ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.
์•„, ๋„ค์ด๋ฐ์€ ํ† ๋ผ๊ตด์ž…๋‹ˆ๋‹ค.

์ข‹์•„, ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์€:

  • ์•ก์…˜(ํฌ๋ฆฌ์—์ดํ„ฐ)
  • (์ €์žฅ) ๊ฐ์†๊ธฐ
  • ๋ฏธ๋“ค์›จ์–ด ๊ธฐ๋Šฅ
  • ์ฝœ๋ฐฑ(๋ฆฌ์Šค๋„ˆ) ํ•จ์ˆ˜
  • ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ฒด์ธ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๊ฒƒ(๋””์ŠคํŒจ์ฒ˜๋ผ๊ณ  ํ•จ)
  • ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ(์„ธํ„ฐ ๋ฐ ๊ฒŒํ„ฐ ํฌํ•จ)

ํ•œ๋ฐœ ๋ฌผ๋Ÿฌ์„œ์„œ ์ด๋ฆ„์„ ๋‹ค์‹œ ์ƒ๊ฐํ•ด ๋ณผ๊นŒ์š”?

์–ด์ฉŒ๋ฉด store.dispatch ๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋งŽ์€ Store ๋Œ€์‹ ์— ํ•˜๋‚˜์˜ Store๊ฐ€ ์žˆ๊ณ  ๋‹น์‹ ์ด Reducers์—์„œ ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. No Stores = ๋ณ„๋„์˜ Dispatcher๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ dispatch ๋Š” Store์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@gaearon ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

@emmenko ์ข‹์€ ์š”์•ฝ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์šฉ์–ด ๋ถ„์„์€ _action creators_์™€ _actions_๋ฅผ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฏธ๋“ค์›จ์–ด + ๋ฆฌ๋“€์„œ๋ฅผ ํฌํ•จํ•˜๋Š” _dispatcher_ ๋˜๋Š” _dispatch ์ „๋žต_๊ณผ _dispatch ์ฃผ๊ธฐ_๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” _dispatch_ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌ๋ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•ด๋ณด์ž:

  • ์Šคํ† ์–ด ์ด๋ฆ„์„ ๋ฆฌ๋“€์„œ๋กœ ๋ณ€๊ฒฝ
  • https://github.com/gaearon/redux/issues/137#issuecomment -113252359์— ๋”ฐ๋ผ "Redux ์ธ์Šคํ„ด์Šค"์˜ ์ด๋ฆ„์„ Store๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.
  • ์ „ํ†ต์ ์ธ Flux Stores๋ฅผ ๊ณ๋ˆˆ์งˆํ•˜๋ฉด ๊ทธ ์•ˆ์— ๊ฐ‡ํžŒ Reducer๊ฐ€ ๋ณด์ผ ๊ฒƒ์ด๋ผ๊ณ  ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด ๋ฌธ์„œ ์ž‘์—…์„ ์ฃผ๋„ํ•˜๊ณ  ์‹ถ์€ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์šฉ์–ด์ง‘, README, ๊ฐ„๋‹จํ•œ "์‹คํ–‰ํ•˜๊ธฐ" ํŠœํ† ๋ฆฌ์–ผ, ๊ทธ๋ฆฌ๊ณ  ์ข€ ๋” ์‹ฌ์ธต์ ์ธ "์„ค๊ณ„ ๊ฒฐ์ •" ๊ฐ€์ด๋“œ์™€ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ๊ตฌ์กฐํ™” ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

@gaearon ์ž์›ํ•ด์„œ ์ด ์ผ์„ ์ด๋Œ๊ฒ ์Šต๋‹ˆ๋‹ค :) ์ด๋ฏธ ๊ฐœ์š”๋ฅผ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค:+1:

๋‚˜๋Š” ์ž์›ํ•ด์„œ ์ด ์ผ์„ ์ด๋Œ ๊ฒƒ์ด๋‹ค

๊ฐ์‚ฌ ํ•ด์š”! :+1: :+1: :+1:

๊ฐœ์ธ์ ์œผ๋กœ ์ตœ์ข… ๊ฒฐ๊ณผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž๋™ ์ƒ์„ฑ ์›น์‚ฌ์ดํŠธ๋ฅผ ๊ฐ–๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

  • ์‹œ์ž‘ํ•˜๊ธฐ
  • ํŠœํ† ๋ฆฌ์–ผ
  • ๋ผ์ด๋ธŒ ์˜ˆ์ œ

... ๊ทธ๋ฆฌ๊ณ  ์žˆ์œผ๋ฉด ์ข‹์€ ๊ธฐ๋Šฅ์œผ๋กœ:

  • ์ƒ์„ฑ๋œ ๋ฌธ์„œ a-la docco (์˜ˆ: jasmine ์ฒ˜๋Ÿผ) ์†Œ์Šค ์ฝ”๋“œ๊ฐ€ ๋ช…ํ™•ํ•˜๊ฒŒ ์„ค๋ช…๋˜๋„๋ก

ํ•˜์ง€๋งŒ ๋งˆํฌ๋‹ค์šด๊ณผ jsdoc๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ ๋ฌผ๋ก  ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค ;)

๋„ค, ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ๋ฌธ์„œ๋ฅผ Markdown ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ์ •๋ง ์ข‹์€ ๋ฌธ์„œ ์‚ฌ์ดํŠธ๋กœ ์ด์‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. :+1: JSDoc๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜ ๋ฐค https://github.com/gaearon/redux/pull/87 ์—์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ ํ•œ ๋ฒˆ ์ฐ”๋Ÿฌ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋ฒ ์ด์Šค์—์„œ ํ•จ์ˆ˜ ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š” ํ•œ ์ด ์‹œ์ ์—์„œ Flow ์ฃผ์„์ด ๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (๋˜๋Š” ๋ˆ„๊ตฐ๊ฐ€ Flow๊ฐ€ ๋ถˆํ‰ํ•˜์ง€ ์•Š๊ณ  ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž…๋ ฅํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฐ€๋ฅด์ณ์ฃผ์ง€ ์•Š๋Š” ํ•œ.)

ํ๋ฆ„์ด ์šฐ์„  ์ˆœ์œ„๊ฐ€ ์•„๋‹Œ ๊ฒƒ ๊ฐ™์•„์š”.

๊ฐ์†๊ธฐ๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์ƒ์ ์˜ ๊ฒฝ์šฐ +1.

์ €๋Š” ์ด๋Ÿฌํ•œ ์„ ์–ธ์ , stateless things store๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

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

-1์€ ๋ฆฌ๋“€์„œ(reducer)๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์ƒ์ ์˜ ๊ฒฝ์šฐ ์ด๋ฆ„์œผ๋กœ ์ƒˆ ์‚ฌ์šฉ์ž(์ ์–ด๋„ ๊ธฐ๋Šฅ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฐ๊ฒฝ์ด ์—†๋Š” ์‚ฌ์šฉ์ž)์—๊ฒŒ๋Š” ๋งค์šฐ ์ง๊ด€์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ Updater๋‚˜ Transformer๊ฐ€ ๋” ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Store Updater๊ฐ€ ๋” ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

"ํŠธ๋žœ์Šคํฌ๋จธ"๋Š” ๊ฝค ์—ฌ๋Ÿฌ ๋ฒˆ ์ œ์•ˆ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์—…๋ฐ์ดํ„ฐ์™€ ๊ฐ™์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ํŠน์„ฑ์„ ์ œ์•ˆํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋ฆฌ๋“€์„œ๋ณด๋‹ค ์ ‘๊ทผํ•˜๊ธฐ ์‰ฝ๊ณ  Store์˜ "์ €์žฅ" ์˜๋ฏธ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํŠธ๋žœ์Šคํฌ๋จธ๋Š” ์–ด๋– ์„ธ์š”?

๊ฐ์†๊ธฐ์˜ ๊ฒฝ์šฐ +1

Twitter์—์„œ @faassen์ด ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ "๋ฆฌ๋“€์„œ"์— ๋Œ€ํ•œ ์ข‹์€ ์ฃผ์žฅ์€ ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์„ ๋‹ค์‹œ ๋ถ€๋ฅด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” โ€œ์ด๊ฒƒ์€ Flux์™€ ๋น„์Šทํ•˜์ง€๋งŒ ํ•˜๋‚˜์˜ Store๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ฑ์„ React ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ Redux์—์„œ๋Š” ํ•ด๋‹น Store๋ฅผ Reducers๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. [].reduce() : (state, action) => state ์ „๋‹ฌ๋œ ์„œ๋ช… ์ผ์น˜ ํ•จ์ˆ˜ ๋•Œ๋ฌธ์— ๊ฐ์†๊ธฐ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋ธ”๋ผ๋ธ”๋ผ๋ธ”๋ผโ€

์‚ฐ๋ถˆ์ฒ˜๋Ÿผ ํผ์ง€๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ์ง€๋ น
  • ๊ฒฉ๋ฆฌ
  • ํฌํ•จํ•˜๋‹ค

ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๋ฌด์‹œํ•˜๊ณ  ๋ณ€ํ˜•ํ•˜๊ณ  ์ค„์ด๋Š” ๊ฒƒ์€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ •ํ™•ํ•œ ์ด๋ฆ„์„ ์„ ํƒํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ƒ์ ์ด๋ผ๊ณ  ๋ถ€๋ฅด์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

ํ•œ ํ˜•์‹์—์„œ ๋‹ค๋ฅธ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋งŽ์€ ๊ฐ’์—์„œ ํ•˜๋‚˜๋กœ ์ถ•์†Œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

๋ณ€์••๊ธฐ => ์ง€๋„
๊ฐ์†๊ธฐ => ๊ฐ์†Œ

๋‚˜์—๊ฒŒ ๊ฐ์†Œ์ฒ˜๋Ÿผ ๋“ค๋ฆฐ๋‹ค.

๋‚˜๋„ reducers ! :+1:

๋Š๋ฆ…๋‚˜๋ฌด์—์„œ ์˜๊ฐ์„ ์–ป์œผ์‹ญ์‹œ์˜ค. https://github.com/evancz/elm-architecture-tutorial#the -basic-pattern

๊ฐ€์žฅ ์ข‹์€ ๋‹จ์–ด๋Š” update ์ž…๋‹ˆ๋‹ค. ์ƒ์ ์€ ๋ง๋„ ์•ˆ๋˜๊ณ  ํ•ญ์ƒ "๋ชจ๋ธ"์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”ํ€ด๋ฅผ ์žฌ๋ฐœ๋ช…ํ•˜๊ฑฐ๋‚˜ ์‚ฌ๋žŒ๋“ค์„ ํ˜ผ๋ž€์Šค๋Ÿฝ๊ฒŒ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋“ค์„ ์—…๋ฐ์ดํ„ฐ๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๋‚˜์˜ ์‡ ๊ณ ๊ธฐ๋Š” ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๋“ค์ด ๋Œ์—ฐ๋ณ€์ด๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ช…๋ช…์ด ๋Œ์—ฐ๋ณ€์ด๊ฐ€ ์•„๋‹Œ ํŠน์„ฑ์„ ๋ช…ํ™•ํžˆ ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํฐ ๋ณด๋„ˆ์Šค๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•œ ํ˜•์‹์—์„œ ๋‹ค๋ฅธ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋งŽ์€ ๊ฐ’์—์„œ ํ•˜๋‚˜๋กœ ์ถ•์†Œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

์Œ“์ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. "ํ–‰๋™์ด ์ƒํƒœ๋ฅผ ๋‹ค์Œ ์ƒํƒœ๋กœ ๋ฐ”๊พธ๋Š” ๋ฐฉ๋ฒ•." ๊ฐœ๋…์ ์œผ๋กœ ์ดˆ๊ธฐ(์ •์˜๋˜์ง€ ์•Š์€) ์ƒํƒœ์—์„œ ๋งŽ์€ ์ž‘์—…์„ ์ค„์ด๊ณ  ๋ฉ”๋ชจ์ด์ œ์ด์…˜์€ ์ตœ์ ํ™”์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

์ƒํƒœ ๋ณ€์••๊ธฐ

๊ฐ€๋Šฅํ•œ ํ•œ ์žฌ๋ฐœ๋ช…/์žฌ๋ฐœ๊ฒฌ์„ ํ”ผํ•˜์‹ญ์‹œ์˜ค. ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๊ฒƒ์„ reduce , scan , fold ๋ฐ update ๋ผ๊ณ  ๋ถˆ๋ €์Šต๋‹ˆ๋‹ค.

reducer ์ž๋ฐ” ์Šคํฌ๋ฆฝํŠธ ๊ด€์ ์—์„œ ์ •ํ™•ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค ...
๊ทธ๊ฒƒ์ด ๋” ์ •ํ™•ํ•˜๋”๋ผ๋„ ๋‹ค๋ฅธ ์–ธ์–ด์˜ ๊ฐœ๋…์—์„œ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ๊ฐ’์„ ๋ณด์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ทธ๊ฒƒ์ด ๋ฌด์—‡์ด์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ํ™•๊ณ ํ•œ ์ž…์žฅ์€ ์—†์ง€๋งŒ IMO๋Š” ๊ณ„์‚ฐ ์œ ํ˜•์„ ๊ฐ€์žฅ ์ •ํ™•ํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ์ƒ์†Œํ•œ ๋‹จ์–ด๋ผ๋ฉด ๋ฌธ์„œ๋กœ ์ƒ์‡„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@vramana map ๊ฐ€ ์•„๋‹ˆ๋ผ reduce . ์ด์ „์— ๋ˆ„์ ๋œ state ์™€ ์ƒˆ action ๊ฐ€์ ธ์™€์„œ ์ƒˆ state .

์•ฑ์˜ ๋ชจ๋“  ์ž‘์—… ๋ฐฐ์—ด์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ข… ์•ฑ ์ƒํƒœ๋กœ ์ค„์ž…๋‹ˆ๋‹ค.

function reducer(state, action) {
  // switch (action.type) ...
  // return state;
}
const finalState = allAppActions.reduce(reducer, initialState);

์ด์ œ ์‹ค์ œ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์€ stream ์˜ actions ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐœ๋…์ ์œผ๋กœ ๋ฐฐ์—ด๊ณผ ๋™์ผํ•˜์ง€๋งŒ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด( stream ์˜ state ์ดˆ).

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ํˆฌ์˜(๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ ๋กœ๊ทธ)์œผ๋กœ ์ƒ๊ฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
DB ์‚ฌ๋žŒ๋“ค์€ ์ด๊ฒƒ์„ "๊ตฌ์ฒดํ™”๋œ ๋ทฐ"๋ผ๊ณ  ๋ถˆ๋ €์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ค„์ด๊ฑฐ๋‚˜ ์ ‘๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•˜๋ฉฐ ๋‹ค๋ฅธ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ž˜ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ฐ์†๊ธฐ๋ณด๋‹ค Transformers๋ฅผ ํ›จ์”ฌ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์˜์–ด ์‚ฌ์šฉ์—์„œ ์ด๊ฒƒ์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์†๊ธฐ.
๋จผ์ € ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ณ  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—๋Š” [].reduce(reducer, initialState) ์žˆ์Šต๋‹ˆ๋‹ค.
๋‘˜์งธ, Redu(cer)x๋Š” ์ด๋ฏธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด๋ฆ„์— ์žˆ์Šต๋‹ˆ๋‹ค.
์…‹์งธ, https://blog.javascripting.com/2015/06/19/flux-no-more-stores-meet-reducer/ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” '๋ฆฌ๋“€์„œ' ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์†๊ธฐ๋Š” ์ •ํ™•ํ•˜๊ณ  ๋ฐ”๋‹๋ผ JS์—์„œ ์„ ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ์†๊ธฐ๋Š” ๊ทธ๋Ÿด ๊ฒƒ์ž…๋‹ˆ๋‹ค.

(#140์˜ ์ง„ํ–‰ ์ƒํ™ฉ์„ ๋”ฐ๋ฅด์‹ญ์‹œ์˜ค)

๋•Œ๋•Œ๋กœ ๋‚˜๋Š” ๊ทธ๋“ค์„ "์ƒ์ "์ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ์˜ค๋ž˜๋œ ํ† ๋ก ์„ ๋ฐœ๊ฒฌํ•˜๊ณ  ๋’ค๋Šฆ๊ฒŒ ๊ทธ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์–ด๋ฆฌ์„๊ฒŒ ํ˜ผ๋ž€์Šค๋Ÿฌ์› ๋Š”์ง€์— ๊ฒฝํƒ„ํ•ฉ๋‹ˆ๋‹ค.

"์ƒํƒœ ์ปจํ…Œ์ด๋„ˆ"?

๋„ค, ์ข‹์€ ๋ณ€ํ™”์˜€์Šต๋‹ˆ๋‹ค :)

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰