Redux: action-creators, reducers ๋ฐ selector์— ๊ด€ํ•œ ๋ชจ๋ฒ” ์‚ฌ๋ก€์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ

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

์šฐ๋ฆฌ ํŒ€์€ ์ง€๊ธˆ ๋ช‡ ๋‹ฌ ๋™์•ˆ Redux๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ ๋‚˜๋Š” ๋•Œ๋•Œ๋กœ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ณ  "์ด๊ฒƒ์ด ์•ก์…˜ ์ƒ์„ฑ๊ธฐ ๋˜๋Š” ๊ฐ์†๊ธฐ์— ์†ํ•ฉ๋‹ˆ๊นŒ?" ๋ฌธ์„œ๋Š” ์ด ์‚ฌ์‹ค์— ๋Œ€ํ•ด ์•ฝ๊ฐ„ ๋ชจํ˜ธํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. (์•„๋‹ˆ๋ฉด ์ œ๊ฐ€ ๋‹ค๋ฃฌ ๋ถ€๋ถ„์„ ๋†“์ณค์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์‚ฌ๊ณผ๋“œ๋ฆฝ๋‹ˆ๋‹ค.) ๊ทธ๋Ÿฌ๋‚˜ ๋” ๋งŽ์€ ์ฝ”๋“œ์™€ ๋” ๋งŽ์€ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ _ํ•ด์•ผ ํ•˜๋Š”_ ์œ„์น˜์— ๋Œ€ํ•ด ๋” ๊ฐ•ํ•œ ์˜๊ฒฌ์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ๊ณ  ๊ฐ€์น˜๊ฐ€ ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๊ณผ ๊ณต์œ ํ•˜๊ณ  ํ† ๋ก ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ ๋‚ด ์ƒ๊ฐ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ณณ์—์„œ ์„ ํƒ๊ธฐ ์‚ฌ์šฉ

์ด ์ฒซ ๋ฒˆ์งธ ๊ฒƒ์€ Redux์™€ ์—„๋ฐ€ํžˆ ๊ด€๋ จ์ด ์—†์ง€๋งŒ ์•„๋ž˜์—์„œ ๊ฐ„์ ‘์ ์œผ๋กœ ์–ธ๊ธ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด์จŒ๋“  ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ํŒ€์€ rackt/reselect ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒํƒœ ํŠธ๋ฆฌ์˜ ์ฃผ์–ด์ง„ ๋…ธ๋“œ(์˜ˆ: MyPageSelectors)์— ๋Œ€ํ•œ ์„ ํƒ๊ธฐ๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ํŒŒ์ผ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ "์Šค๋งˆํŠธ" ์ปจํ…Œ์ด๋„ˆ๋Š” ์ด๋Ÿฌํ•œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ "๋ฉ์ฒญํ•œ" ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ (์žฌ์„ ํƒ์˜ ๋งฅ๋ฝ์—์„œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ) ๋‹ค๋ฅธ ์œ„์น˜์—์„œ ์ด๋Ÿฌํ•œ ๋™์ผํ•œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ถ”๊ฐ€ ์ด์ ์ด ์žˆ์Œ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ž๋™ํ™”๋œ ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋˜ํ•œ action-creators์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ ์ฝํฌ ์—์„œ๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(์•„๋ž˜์—์„œ ์ž์„ธํžˆ).

๋”ฐ๋ผ์„œ ์ฒซ ๋ฒˆ์งธ ๊ถŒ์žฅ ์‚ฌํ•ญ์€ ๋™๊ธฐ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ์— ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ _๋ชจ๋“  ๊ณณ์—์„œ_ ๊ณต์œ  ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜ˆ: myValueSelector(state) ๋ณด๋‹ค state.myValue myValueSelector(state) ์„ ํ˜ธ). ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ์ •์˜๋˜์ง€ ์•Š์€ ๊ฐ’์œผ๋กœ ์ด์–ด์ง€๋Š” ์ž˜๋ชป๋œ ์œ ํ˜•์˜ ๋ณ€์ˆ˜ ๊ฐ€๋Šฅ์„ฑ์ด ์ค„์–ด๋“ค๊ณ  ์ƒ์  ๊ตฌ์กฐ ๋“ฑ์˜ ๋ณ€๊ฒฝ์ด ๊ฐ„์†Œํ™”๋ฉ๋‹ˆ๋‹ค.

action-creators์—์„œ๋Š” _more_, reducer์—์„œ๋Š” _less_ ์ˆ˜ํ–‰

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‹น์žฅ ๋ช…๋ฐฑํ•˜์ง€ ์•Š์„์ง€๋ผ๋„ ์ด๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ์— ์†ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์†๊ธฐ๋Š” ์–ด๋ฆฌ์„๊ณ  ๋‹จ์ˆœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๊ฐœ๋ณ„์ ์ธ ๊ฒฝ์šฐ์—๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์ง€๋งŒ ์ผ๊ด€์„ฑ์ด ์ข‹์œผ๋ฏ€๋กœ _์ผ๊ด€์ ์œผ๋กœ_ ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์•ก์…˜ ์ƒ์„ฑ์ž๋Š” redux-thunk ์™€ ๊ฐ™์€ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ์‹์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ข…์ข… ์Šคํ† ์–ด์— ๋Œ€ํ•œ ๋น„๋™๊ธฐ์‹ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•„์š”๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ถ€ "๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง"์€ ๊ฒฐ๊ตญ ๊ท€ํ•˜์˜ ์ž‘์—…์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  2. ์ž‘์—… ์ƒ์„ฑ์ž(๋ณด๋‹ค ์ •ํ™•ํ•˜๊ฒŒ๋Š” ์ฝํฌ ๋ฅผ ๋ฐ˜ํ™˜ํ•จ)๋Š” ์™„๋ฃŒ ์ƒํƒœ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ณต์œ  ์„ ํƒ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ๋Š” ์ž์‹ ์˜ ๋…ธ๋“œ์—๋งŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  3. redux-thunk ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹จ์ผ ์ž‘์—… ์ƒ์„ฑ์ž๊ฐ€ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ณต์žกํ•œ ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ  ๋” ๋‚˜์€ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์ƒํƒœ์— ํ•ญ๋ชฉ ๋ชฉ๋ก๊ณผ ๊ด€๋ จ๋œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์„ธ์š”. ํ•ญ๋ชฉ์ด ์ˆ˜์ •, ์ถ”๊ฐ€ ๋˜๋Š” ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ๋  ๋•Œ๋งˆ๋‹ค ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชฉ๋ก๊ณผ ํ•ด๋‹น ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋™๊ธฐํ™” ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•œ "๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง"์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์œ„์น˜์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๊ฐ์†๊ธฐ์—์„œ. ๊ฐ ๋ฆฌ๋“€์„œ(์ถ”๊ฐ€, ํŽธ์ง‘, ์ œ๊ฑฐ)๋Š” ๋ชฉ๋ก _๋ฐ_ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  2. ๋ณด๊ธฐ์—์„œ(์ปจํ…Œ์ด๋„ˆ/๊ตฌ์„ฑ์š”์†Œ). ์ž‘์—…(์ถ”๊ฐ€, ํŽธ์ง‘, ์ œ๊ฑฐ)์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฐ ๋ณด๊ธฐ๋Š” updateMetadata ์ž‘์—…๋„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ (๋ฐ”๋ผ๊ฑด๋Œ€) ๋ช…๋ฐฑํ•œ ์ด์œ ๋กœ ๋”์ฐํ•ฉ๋‹ˆ๋‹ค.
  3. ์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ์—์„œ. ๊ฐ ์ž‘์—… ์ƒ์„ฑ์ž(์ถ”๊ฐ€, ํŽธ์ง‘, ์ œ๊ฑฐ)๋Š” ๋ชฉ๋ก์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ž‘์—…์„ ์ „๋‹ฌํ•œ ๋‹ค์Œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๋Š”

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

Actions ๋ฐ Selectors์— ์ดˆ์ ์„ ๋งž์ถ˜ "ducks" ํ…Œ์ŠคํŠธ ์ž‘์„ฑ

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

๋” ์„ธ๋ถ„ํ™”ํ•˜๋ฉด ์•ก์…˜ ์ƒ์„ฑ์ž์— ์ดˆ์ ์„ ๋งž์ถ˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•œ ๋‹ค์Œ ์„ ํƒ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค. (๋ฆฌ๋“€์„œ๋ฅผ ์ง์ ‘ ํ…Œ์ŠคํŠธํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.) ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ฃผ์–ด์ง„ ์ž‘์—…์ด ์˜ˆ์ƒํ•œ ์ƒํƒœ๋กœ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (๊ณต์œ ) ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์€ ๋‹จ์ผ ํŒจ์Šค์—์„œ ์„ธ ๊ฐ€์ง€ ๋ชจ๋‘๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

discussion

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@dtinth @denis-sokolov ์ €๋„ ๊ทธ ์ ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. Btw ๋‚ด๊ฐ€ redux-saga ํ”„๋กœ์ ํŠธ๋ฅผ ์ฐธ์กฐํ•  ๋•Œ ๋‚˜๋Š” actionCreators๋ฅผ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ ์  ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์•„์ด๋””์–ด์— ๋ฐ˜๋Œ€ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ถ„๋ช…ํžˆ ํ•˜์ง€ ์•Š์•˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Redux-saga ํ”„๋กœ์ ํŠธ๋Š” @dtinth์—์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ์‹œ๋„ ๋ฏธ๋ฌ˜ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ก์…˜ ๋กœ๊ทธ์— ๋ฐœ์ƒํ•œ ๋ชจ๋“  ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์ด ์•ก์…˜ ๋กœ๊ทธ์˜ ๋ฆฌ๋“€์„œ์—์„œ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ์‰ฝ๊ฒŒ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋งํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ ˆ๋Œ€์ ์œผ๋กœ ์‚ฌ์‹ค์ด๋ฉฐ ์ž‘์—… ๋กœ๊ทธ๊ฐ€ ๋ช…์‹œ์ ์ด์ง€ ์•Š๊ณ  ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๊ฐ์†๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ๋ณต์žกํ•ด์ ธ์„œ ์•ฑ์„ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ค์›Œ์งˆ ๋•Œ๊นŒ์ง€ ํ•œ๋™์•ˆ ๊ทธ ๊ฒฝ๋กœ๋ฅผ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Redux ์‚ฌ๊ฐ€ ํ† ๋ก ์œผ๋กœ ์ด์–ด์ง€๋Š” ์›๋ž˜ ํ† ๋ก ์˜ ์ด ์ง€์ ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/paldepind/functional-frontend-architecture/issues/20#issuecomment -162822909

ํ•ด๊ฒฐํ•˜๋Š” ์œ ์Šค์ผ€์ด์Šค

๋ช…๋ฐฑํ•œ TodoCreated ์ด๋ฒคํŠธ๊ฐ€ ์žˆ๋Š” Todo ์•ฑ์ด ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์•ฑ ์˜จ๋ณด๋”ฉ์„ ์ฝ”๋”ฉํ•˜๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํ•  ์ผ์„ ์ƒ์„ฑํ•˜๋ฉด ํŒ์—…์œผ๋กœ ์ถ•ํ•˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

"๋ถˆ์ˆœํ•œ" ๋ฐฉ๋ฒ•:

์ด๊ฒƒ์€ @bvaughn ์ด ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function createTodo(todo) {
   return (dispatch, getState) => {
       dispatch({type: "TodoCreated",payload: todo});
       if ( getState().isOnboarding ) {
         dispatch({type: "ShowOnboardingTodoCreateCongratulation"});
       }
   }
}

๋‚˜๋Š” ์ด ์ ‘๊ทผ ๋ฐฉ์‹์ด ์•ฑ ๋ณด๊ธฐ์˜ ๋ ˆ์ด์•„์›ƒ๊ณผ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ์•ก์…˜ ์ƒ์„ฑ๊ธฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. actionCreator๊ฐ€ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ธฐ ์œ„ํ•ด UI ์ƒํƒœ ํŠธ๋ฆฌ์˜ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

"์›์‹œ ์ด๋ฒคํŠธ์—์„œ ๋ชจ๋“  ๊ฒƒ์„ ๊ณ„์‚ฐ" ๋ฐฉ์‹:

์ด๊ฒƒ์€ @denis-sokolov @dtinth ๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

function onboardingTodoCreateCongratulationReducer(state = defaultState, action) {
  var isOnboarding = isOnboardingReducer(state.isOnboarding,action);
  switch (action) {
    case "TodoCreated": 
        return {isOnboarding: isOnboarding, isCongratulationDisplayed: isOnboarding}
    default: 
        return {isOnboarding: isOnboarding, isCongratulationDisplayed: false}
  }
}

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

๋‹จ์ˆœํ™”๋œ ์‚ฌ๊ฐ€ ๋ฐฉ์‹.

redux-saga๋Š” ์ƒ์„ฑ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์•ฝ๊ฐ„ ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function createTodo(todo) {
   return (dispatch, getState) => {
       dispatch({type: "TodoCreated",payload: todo});
   }
}

function onboardingSaga(state, action, actionCreators) {
  switch (action) {
    case "OnboardingStarted": 
        return {onboarding: true, ...state};
    case "OnboardingStarted": 
        return {onboarding: false, ...state};
    case "TodoCreated": 
        if ( state.onboarding ) dispatch({type: "ShowOnboardingTodoCreateCongratulation"});
        return state;
    default: 
        return state;
  }
}

saga๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ํšจ๊ณผ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ ์ €์žฅ ์•กํ„ฐ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ด๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋ถˆ์ˆœํ•œ ๊ฐ์†๊ธฐ๋กœ ๊ตฌํ˜„๋˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” redux-saga ํ”„๋กœ์ ํŠธ์— ์—†์Šต๋‹ˆ๋‹ค.

์•ฝ๊ฐ„ ๋ณต์žกํ•œ ๊ทœ์น™:

์ดˆ๊ธฐ ๊ทœ์น™์„ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์— ๋Œ€ํ•ด ๋งค์šฐ ๋ช…์‹œ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์œ„์˜ ๊ตฌํ˜„์„ ๋ณด๋ฉด ์˜จ๋ณด๋”ฉ ์ค‘์— ํ•  ์ผ์„ ๋งŒ๋“ค ๋•Œ๋งˆ๋‹ค ์ถ•ํ•˜ ํŒ์—…์ด ์—ด๋ฆฌ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์˜จ๋ณด๋”ฉ ์ค‘์— ๋ฐœ์ƒํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ์ƒ์„ฑ๋œ ํ• ์ผ์— ๋Œ€ํ•ด์„œ๋งŒ ์—ด๋ฆฌ๊ธธ ์›ํ•˜๊ณ  ๋ชจ๋“  ํ• ์ผ์ด ์•„๋‹ˆ๋ผ ์—ด๋ฆฌ๊ธธ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒฐ๊ตญ ์ฒ˜์Œ๋ถ€ํ„ฐ ์˜จ๋ณด๋”ฉ์„ ๋‹ค์‹œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์˜จ๋ณด๋”ฉ์ด ์ ์  ๋” ๋ณต์žกํ•ด์ง์— ๋”ฐ๋ผ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ 3๊ฐ€์ง€ ๊ตฌํ˜„ ๋ชจ๋‘์—์„œ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ง€์ €๋ถ„ํ•ด์กŒ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

redux-saga ๋ฐฉ์‹

redux-saga์™€ ์œ„์˜ ์˜จ๋ณด๋”ฉ ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function* onboarding() {
  while ( true ) {
    take(ONBOARDING_STARTED)
    take(TODO_CREATED)
    put(SHOW_TODO_CREATION_CONGRATULATION)
    take(ONBOARDING_ENDED)
  }
}

์œ„์˜ ์†”๋ฃจ์…˜๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํ‹€๋ ธ๋‹ค๋ฉด ๋” ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„์„ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. :)

๋‹น์‹ ์€ ๋ถˆ์ˆœํ•œ ์ฝ”๋“œ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ–ˆ๊ณ  ์ด ๊ฒฝ์šฐ์—๋Š” ํ…Œ์ดํฌ/ํ’‹ ํšจ๊ณผ๊ฐ€ ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— Redux-saga ๊ตฌํ˜„์— ๋ถˆ์ˆœํ•จ์ด ์—†์Šต๋‹ˆ๋‹ค. take() ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ์‹คํ–‰ํ•  ํšจ๊ณผ์˜ ์„ค๋ช…์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์–ด๋Š ์‹œ์ ์—์„œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ ์‹œ์ž‘๋˜๋ฏ€๋กœ ๋ฌด์šฉ๋‹ด์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ์˜๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด Haskell์„ ํ•˜๋Š” ๊ธฐ๋Šฅ์ ์ธ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด Free / IO ๋ชจ๋‚˜๋“œ๋ฅผ ์ƒ๊ฐํ•˜์‹ญ์‹œ์˜ค.


์ด ๊ฒฝ์šฐ ๋‹ค์Œ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๋ณต์žกํ•œ actionCreator๋ฅผ ํ”ผํ•˜๊ณ  getState ์— ์˜์กดํ•˜๊ฒŒ ๋งŒ๋“œ์‹ญ์‹œ์˜ค.
  • ์•”์‹œ์ ์„ ๋” ๋ช…์‹œ์ ์œผ๋กœ ๋งŒ๋“ค๊ธฐ
  • ํšก๋‹จ ๋…ผ๋ฆฌ(์œ„์˜ ์˜จ๋ณด๋”ฉ๊ณผ ๊ฐ™์€)๋ฅผ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ(ํ•  ์ผ ์ƒ์„ฑ)์— ๊ฒฐํ•ฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๋˜ํ•œ ํ•ด์„ ๊ณ„์ธต์„ ์ œ๊ณตํ•˜์—ฌ ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‹ค ์˜๋ฏธ ์žˆ๊ณ  ๋†’์€ ์ˆ˜์ค€์˜ ์ด๋ฒคํŠธ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ELM์ด ์ด๋ฒคํŠธ๋ฅผ ๋ฒ„๋ธ”๋งํ•  ๋•Œ ๋ž˜ํ•‘ํ•˜๋Š” ๊ฒƒ๊ณผ ์•ฝ๊ฐ„ ์œ ์‚ฌ).

์˜ˆ:

  • "TIMELINE_SCROLLED_NEAR-BOTTOM"์ด(๊ฐ€) "NEXT_PAGE_LOADED"๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ค๋ฅ˜ ์ฝ”๋“œ๊ฐ€ 401์ธ ๊ฒฝ์šฐ "REQUEST_FAILED"๋กœ ์ธํ•ด "USER_DISCONNECTED"๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • "HASHTAG_FILTER_ADDED"๊ฐ€ "CONTENT_RELOADED"๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Œ

์˜ค๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“ˆ์‹ ์•ฑ ๋ ˆ์ด์•„์›ƒ์„ ๋‹ฌ์„ฑํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์˜ค๋ฆฌ๋ฅผ ํ•จ๊ป˜ ๊ฒฐํ•ฉํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ๊ฐ€๋Š” ์—ฐ๊ฒฐ์ ์ด ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋ฆฌ๋Š” ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ์•Œ์•„์•ผ ํ•˜๊ณ  ๋ฌด์šฉ๋‹ด์€ ์ด๋Ÿฌํ•œ ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ duck1 ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ์—์„œ ๋” ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ๋•Œ๋ฌธ์— duck1์ด duck2์˜ ์ง์ ‘ ์ž‘์—…์„ ๋””์ŠคํŒจ์น˜ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋‚ซ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฒฐํ•ฉ ์ง€์ ์ด actionCreators์—์„œ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ฃผ์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๊ฒƒ์ด ์˜ค๋Š˜๋‚  ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด ํ•˜๊ณ  ์žˆ๋Š” ์ผ์ž…๋‹ˆ๋‹ค.

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

Immutable.js ๋˜๋Š” ๊ธฐํƒ€๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. REDUX ๊ฒƒ๋“ค์˜ ์†Œ์ˆ˜์—์„œ ๋‚˜๋Š” ๋‚ด๊ฐ€ ๋ถˆ๋ณ€์„ ์‚ฌ์šฉํ•˜์ง€ ์ƒ์ƒํ•  ์ˆ˜ ์—†์—ˆ๋‹ค ๋‚ด์žฅํ–ˆ์ง€๋งŒ, ๋ถˆ๋ณ€๊ฐ€ ์ˆœ์ข…์„ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋‚˜๋Š” ๊ฝค ๋งŽ์ด ์ค‘์ฒฉ ๋œ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  _do_.

์šฐ์™€. ๊ทธ๊ฒƒ์„ ์–ธ๊ธ‰ํ•˜๋Š” ๊ฒƒ์€ _not_ ์ €์—๊ฒŒ ์žˆ์–ด ์–ผ๋งˆ๋‚˜ ๊ฐ„๊ณผ๋œ ์ผ์ž…๋‹ˆ๊นŒ? ์˜ˆ! ์šฐ๋ฆฌ๋Š” ๋ถˆ๋ณ€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค! ๋‹น์‹ ์ด ๋งํ–ˆ๋“ฏ์ด, ์ƒ๋‹นํ•œ ๊ฒƒ์„ ์œ„ํ•ด ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์ง€ _์•„๋‹Œ_ ์ƒ์ƒํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

@bvaughn ๋‚ด๊ฐ€ ๊ณ ์‹ฌํ–ˆ๋˜ ์˜์—ญ ์ค‘ ํ•˜๋‚˜๋Š” Immutable๊ณผ ๊ตฌ์„ฑ ์š”์†Œ ์‚ฌ์ด์— ์„ ์„ ๊ทธ๋ฆด ์œ„์น˜์ž…๋‹ˆ๋‹ค. ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ฐœ์ฒด๋ฅผ ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌํ•˜๋ฉด ์ˆœ์ˆ˜ ๋ Œ๋”๋ง ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ/๋ฏน์Šค์ธ์„ ๋งค์šฐ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ตฌ์„ฑ ์š”์†Œ์— IMmutable ์ฝ”๋“œ(๋‚ด๊ฐ€ ์ข‹์•„ํ•˜์ง€ ์•Š๋Š”)๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ๋‚˜๋Š” ๊ทธ๋ƒฅ ๊ตด๋ณตํ•˜๊ณ  ๊ทธ๊ฒƒ์„ ํ•ด๋ƒˆ์ง€๋งŒ Immutable.js์˜ ๋ฉ”์†Œ๋“œ์— ์ง์ ‘ ์•ก์„ธ์Šคํ•˜๋Š” ๋Œ€์‹  render() ๋ฉ”์†Œ๋“œ์—์„œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๊นŒ?

์†”์งํžˆ ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ์•„์ง ์—„๊ฒฉํ•œ ์ •์ฑ…์„ ์ •์˜ํ•˜์ง€ ์•Š์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ข…์ข… ์šฐ๋ฆฌ๋Š” "์Šค๋งˆํŠธ" ์ปจํ…Œ์ด๋„ˆ์—์„œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ฐœ์ฒด์˜ ๊ธฐ๋ณธ ๊ฐ’์„ ์ถ”๊ฐ€ํ•œ ๋‹ค์Œ ๊ธฐ๋ณธ ๊ฐ’์„ ๋ฌธ์ž์—ด, ๋ถ€์šธ ๋“ฑ์œผ๋กœ ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๋•Œ๋•Œ๋กœ ์šฐ๋ฆฌ๋Š” ๋ถˆ๋ณ€ ๊ฐœ์ฒด๋ฅผ ์ „๋‹ฌํ•˜์ง€๋งŒ ๊ทธ๋ ‡๊ฒŒ ํ•  ๋•Œ ๊ฑฐ์˜ ํ•ญ์ƒ Record ์œ ํ˜•์„ ์ „๋‹ฌํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ด๋ฅผ ๊ธฐ๋ณธ ๊ฐœ์ฒด(๊ฒŒํ„ฐ ํฌํ•จ)์ฒ˜๋Ÿผ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์œผ๋กœ ์›€์ง์—ฌ์„œ ์•ก์…˜ ์ œ์ž‘์ž๋ฅผ ๋” ํ•˜์ฐฎ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ €๋Š” ์ด์ œ ๋ง‰ redux๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ ‘๊ทผ ๋ฐฉ์‹์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์งˆ๋ฌธ:

1) ์•ก์…˜ ์ œ์ž‘์ž๋ฅผ ์–ด๋–ป๊ฒŒ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๊นŒ? ๋‚˜๋Š” ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ์™ธ๋ถ€ ์„œ๋น„์Šค์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์ˆœ์ˆ˜ ๋™๊ธฐ ํ•จ์ˆ˜๋กœ ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์€ ๋…ผ๋ฆฌ๋ฅผ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.
2) ํ•ซ ๋ฆฌ๋กœ๋”ฉ๊ณผ ํ•จ๊ป˜ ์‹œ๊ฐ„ ์—ฌํ–‰์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ? react redux devtools์˜ ๊น”๋”ํ•œ ์  ์ค‘ ํ•˜๋‚˜๋Š” ํ•ซ ๋ฆฌ๋กœ๋”ฉ์ด ์„ค์ •๋˜๋ฉด ์Šคํ† ์–ด๊ฐ€ ์ƒˆ ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•ด ๋ชจ๋“  ์ž‘์—…์„ ๋‹ค์‹œ ์‹คํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด ๋…ผ๋ฆฌ๋ฅผ ์•ก์…˜ ์ œ์ž‘์ž๋กœ ์˜ฎ๊ธฐ๋ฉด ์žƒ์–ด ๋ฒ„๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.
3) ์•ก์…˜ ์ƒ์„ฑ์ž๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋””์ŠคํŒจ์น˜ํ•˜์—ฌ ํšจ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค๋ฉด ์ƒํƒœ๊ฐ€ ์ž ์‹œ ๋™์•ˆ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํƒœ์— ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๊นŒ? (๋‚˜์ค‘์— ๋น„๋™๊ธฐ์‹์œผ๋กœ ๋””์ŠคํŒจ์น˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๋™๊ธฐ์‹ ๋””์ŠคํŒจ์น˜๋ฅผ โ€‹โ€‹์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.)

๋ชจ๋“  ๊ณณ์—์„œ ์„ ํƒ๊ธฐ ์‚ฌ์šฉ

์˜ˆ, ๊ฐ์†๊ธฐ๊ฐ€ ์ƒํƒœ์˜ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด๋ฉฐ ์ฟผ๋ฆฌ API๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ ์š”์†Œ์— ์ƒํƒœ๋ฅผ ๋…ธ์ถœํ•œ๋‹ค๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.
๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ถ„๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ  ์ƒํƒœ๋ฅผ ์‰ฝ๊ฒŒ ๋ฆฌํŒฉํ† ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ImmutableJS ์‚ฌ์šฉ

์ƒˆ๋กœ์šด JS ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” IMO์—์„œ๋Š” ์ผ๋ฐ˜ JS๋กœ ๋ชฉ๋ก๊ณผ ๊ฐœ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ImmutableJS๋ฅผ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์†์„ฑ์ด ๋งŽ์€ ๋งค์šฐ ํฐ ๋ชฉ๋ก๊ณผ ๊ฐœ์ฒด๊ฐ€ ์žˆ๊ณ  ์„ฑ๋Šฅ์ƒ์˜ ์ด์œ ๋กœ ๊ตฌ์กฐ์  ๊ณต์œ ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋Š” ํ•œ ImmutableJS๋Š” ์—„๊ฒฉํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋” ๋งŽ์€ ์ผ์„ ํ•˜์„ธ์š”ํฌ๋ฆฌ์—์ดํ„ฐ

@bvaughn ๋‹น์‹ ์€ ์ •๋ง๋กœ ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: https://github.com/yelouafi/redux-saga
๋‚ด๊ฐ€ @yelouafi ์—๊ฒŒ

1) ์•ก์…˜ ์ œ์ž‘์ž๋ฅผ ์–ด๋–ป๊ฒŒ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๊นŒ? ๋‚˜๋Š” ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ์™ธ๋ถ€ ์„œ๋น„์Šค์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์ˆœ์ˆ˜ ๋™๊ธฐ ํ•จ์ˆ˜๋กœ ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์€ ๋…ผ๋ฆฌ๋ฅผ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.

์œ„์—์„œ ์ด๊ฒƒ์„ ์„ค๋ช…ํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ... "์˜ค๋ฆฌ"์™€ ๊ฐ™์€ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ์•ก์…˜ ์ œ์ž‘์ž๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด (์ง€๊ธˆ๊นŒ์ง€ ๋‚˜์—๊ฒŒ) ๊ฐ€์žฅ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. action-creator์˜ ๊ฒฐ๊ณผ๋ฅผ ๋””์ŠคํŒจ์น˜ํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•œ ๋‹ค์Œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹จ์ผ ํ…Œ์ŠคํŠธ๋กœ ์•ก์…˜ ์ƒ์„ฑ๊ธฐ, ํ•ด๋‹น ๊ฐ์†๊ธฐ ๋ฐ ๋ชจ๋“  ๊ด€๋ จ ์„ ํƒ๊ธฐ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2) ํ•ซ ๋ฆฌ๋กœ๋”ฉ๊ณผ ํ•จ๊ป˜ ์‹œ๊ฐ„ ์—ฌํ–‰์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ? react redux devtools์˜ ๊น”๋”ํ•œ ์  ์ค‘ ํ•˜๋‚˜๋Š” ํ•ซ ๋ฆฌ๋กœ๋”ฉ์ด ์„ค์ •๋˜๋ฉด ์Šคํ† ์–ด๊ฐ€ ์ƒˆ ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•ด ๋ชจ๋“  ์ž‘์—…์„ ๋‹ค์‹œ ์‹คํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด ๋…ผ๋ฆฌ๋ฅผ ์•ก์…˜ ์ œ์ž‘์ž๋กœ ์˜ฎ๊ธฐ๋ฉด ์žƒ์–ด ๋ฒ„๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

3) ์•ก์…˜ ์ƒ์„ฑ์ž๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋””์ŠคํŒจ์น˜ํ•˜์—ฌ ํšจ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค๋ฉด ์ƒํƒœ๊ฐ€ ์ž ์‹œ ๋™์•ˆ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํƒœ์— ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๊นŒ? (๋‚˜์ค‘์— ๋น„๋™๊ธฐ์‹์œผ๋กœ ๋””์ŠคํŒจ์น˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๋™๊ธฐ์‹ ๋””์ŠคํŒจ์น˜๋ฅผ โ€‹โ€‹์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.)

์ผ์‹œ์ ์ธ ๋ฌดํšจ ์ƒํƒœ๋Š” ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์‹ค์ œ๋กœ ํ”ผํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ตœ์ข… ์ผ๊ด€์„ฑ์ด ์žˆ๋Š” ํ•œ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด action-creators ๋˜๋Š” reducers์— ์žˆ๋Š”์ง€์— ๊ด€๊ณ„์—†์ด ์ƒํƒœ๊ฐ€ ์ผ์‹œ์ ์œผ๋กœ ์œ ํšจํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ถ€์ž‘์šฉ ๋ฐ ์ƒ์ ์˜ ํŠน์„ฑ๊ณผ ๋” ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด JS ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” IMO์—์„œ๋Š” ์ผ๋ฐ˜ JS๋กœ ๋ชฉ๋ก๊ณผ ๊ฐœ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ImmutableJS๋ฅผ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์†์„ฑ์ด ๋งŽ์€ ๋งค์šฐ ํฐ ๋ชฉ๋ก๊ณผ ๊ฐœ์ฒด๊ฐ€ ์žˆ๊ณ  ์„ฑ๋Šฅ์ƒ์˜ ์ด์œ ๋กœ ๊ตฌ์กฐ์  ๊ณต์œ ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋Š” ํ•œ ImmutableJS๋Š” ์—„๊ฒฉํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์ด ์•„๋‹™๋‹ˆ๋‹ค.

Immutable์„ ์‚ฌ์šฉํ•˜๋Š” ์ฃผ๋œ ์ด์œ ๋Š” ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ์„ฑ๋Šฅ์ด๋‚˜ ๊ตฌ๋ฌธ์ƒ์˜ ์„คํƒ•์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ฃผ๋œ ์ด์œ ๋Š” ์‚ฌ์šฉ์ž(๋˜๋Š” ๋‹ค๋ฅธ ์‚ฌ๋žŒ)๊ฐ€ ๊ฐ์†๊ธฐ ๋‚ด์—์„œ ๋“ค์–ด์˜ค๋Š” ์ƒํƒœ๋ฅผ _์šฐ์—ฐํ•˜๊ฒŒ_ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋ถˆํ–‰ํžˆ๋„ ์ผ๋ฐ˜ JS ๊ฐ์ฒด๋กœ ์‰ฝ๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@bvaughn ๋‹น์‹ ์€ ์ •๋ง๋กœ ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: https://github.com/yelouafi/redux-saga
๋‚ด๊ฐ€ @yelouafi ์—๊ฒŒ

๋‚˜๋Š” ์‹ค์ œ๋กœ ๊ทธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ „์— ์ฒดํฌ ์•„์›ƒํ–ˆ์Šต๋‹ˆ๋‹ค :) ๋น„๋ก ์•„์ง ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์ง€๋งŒ. ๊น”๋”ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

์œ„์—์„œ ์ด๊ฒƒ์„ ์„ค๋ช…ํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ... "์˜ค๋ฆฌ"์™€ ๊ฐ™์€ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ์•ก์…˜ ์ œ์ž‘์ž๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด (์ง€๊ธˆ๊นŒ์ง€ ๋‚˜์—๊ฒŒ) ๊ฐ€์žฅ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. action-creator์˜ ๊ฒฐ๊ณผ๋ฅผ ๋””์ŠคํŒจ์น˜ํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•œ ๋‹ค์Œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹จ์ผ ํ…Œ์ŠคํŠธ๋กœ ์•ก์…˜ ์ƒ์„ฑ๊ธฐ, ํ•ด๋‹น ๊ฐ์†๊ธฐ ๋ฐ ๋ชจ๋“  ๊ด€๋ จ ์„ ํƒ๊ธฐ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค, ๊ทธ ๋ถ€๋ถ„์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๊ถ๊ธˆํ•œ ๊ฒƒ์€ ๋น„๋™๊ธฐ์„ฑ๊ณผ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var store = createStore();
store.dispatch(actions.startRequest());
store.dispatch(actions.requestResponseReceived({...});
strictEqual(isLoaded(store.getState());

๊ทธ๋Ÿฌ๋‚˜ ๋‹น์‹ ์˜ ์‹œํ—˜์€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ์Šต๋‹ˆ๊นŒ? ์ด ๊ฐ™์€?

var mock = mockFetch();
store.dispatch(actions.request());
mock.expect("/api/foo.bar").andRespond("{status: OK}");
strictEqual(isLoaded(store.getState());

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

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

๊ฐ์†๊ธฐ ์‚ฌ์šฉ:

1) ๋‚ด ์•ฑ์—์„œ ์ž‘์—…์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
2) ๋‚ด ๋ฆฌ๋“€์„œ์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ์–ด์„œ ์ž˜๋ชป๋œ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
3) ๊ฐ์†๊ธฐ์˜ ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
4) ์‹œ๊ฐ„ ์—ฌํ–‰์€ ์ƒˆ๋กœ์šด ๊ฐ์†๊ธฐ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ๋‚ด๊ฐ€ ์žˆ์–ด์•ผ ํ–ˆ๋˜ ์ƒํƒœ๋กœ ๋‚˜๋ฅผ ๋‘ก๋‹ˆ๋‹ค.

์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ์™€ ํ•จ๊ป˜๋ผ๋ฉด

1) ๋‚ด ์•ฑ์—์„œ ์ž‘์—…์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
2) ์•ก์…˜ ์ƒ์„ฑ์ž์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ์–ด ์ž˜๋ชป๋œ ์•ก์…˜์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ
3) ์•ก์…˜ ์ƒ์„ฑ๊ธฐ์—์„œ ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
4) ๋‚˜๋Š” ์—ฌ์ „ํžˆ ์ž˜๋ชป๋œ ์ƒํƒœ์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ ์ž‘์—…์„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์•ผ ํ•˜๋ฉฐ, ์™„์ „ํžˆ ๋ง๊ฐ€์ง„ ์ƒํƒœ๊ฐ€ ๋˜๋ฉด ์ƒˆ๋กœ๊ณ ์นจํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ผ์‹œ์ ์ธ ๋ฌดํšจ ์ƒํƒœ๋Š” ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์‹ค์ œ๋กœ ํ”ผํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ตœ์ข… ์ผ๊ด€์„ฑ์ด ์žˆ๋Š” ํ•œ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด action-creators ๋˜๋Š” reducers์— ์žˆ๋Š”์ง€์— ๊ด€๊ณ„์—†์ด ์ƒํƒœ๊ฐ€ ์ผ์‹œ์ ์œผ๋กœ ์œ ํšจํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ถ€์ž‘์šฉ ๋ฐ ์ƒ์ ์˜ ํŠน์„ฑ๊ณผ ๋” ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

redux์— ๋Œ€ํ•œ ๋‚ด ์ƒ๊ฐ์€ ์ €์žฅ์†Œ๊ฐ€ ํ•ญ์ƒ ์œ ํšจํ•œ ์ƒํƒœ๋ผ๊ณ  ์ฃผ์žฅํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ฐ์†๊ธฐ๋Š” ํ•ญ์ƒ ์œ ํšจํ•œ ์ƒํƒœ๋ฅผ ์ทจํ•˜๊ณ  ์œ ํšจํ•œ ์ƒํƒœ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ๊ฒฝ์šฐ๊ฐ€ ์ผ๊ด€์„ฑ์ด ์—†๋Š” ์ƒํƒœ๋ฅผ ํ—ˆ์šฉํ•˜๋„๋ก ๊ฐ•์ œํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๊นŒ?

๋ฐฉํ•ดํ•ด์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํƒœ๋Š” ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?
์—ฌ๊ธฐ? ๋กœ๋“œ ์ค‘์ธ ๋ฐ์ดํ„ฐ ๋˜๋Š” ์‹คํ–‰ ์ค‘์ธ ์ž‘์—…์ด์ง€๋งŒ ์•„์ง ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ๋ชจ์–‘
๋‚˜์—๊ฒŒ ์œ ํšจํ•œ ์ผ์‹œ์ ์ธ ์ƒํƒœ์ฒ˜๋Ÿผ.

Redux @bvaughn ๋ฐ @sompylasar ์—์„œ ์ผ์‹œ์ ์ธ ์ƒํƒœ๋ž€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ? ๋””์ŠคํŒจ์น˜๊ฐ€ ์™„๋ฃŒ๋˜๊ฑฐ๋‚˜ ๋˜์ง‘๋‹ˆ๋‹ค. ๋˜์ง€๋ฉด ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฆฌ๋“€์„œ์— ์ฝ”๋“œ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ํ•œ Redux์—๋Š” ๋ฆฌ๋“€์„œ ๋…ผ๋ฆฌ์™€ ์ผ์น˜ํ•˜๋Š” ์ƒํƒœ๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ๋“  ์ „๋‹ฌ๋œ ๋ชจ๋“  ์ž‘์—…์€ ํŠธ๋žœ์žญ์…˜์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์ „์ฒด ํŠธ๋ฆฌ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๊ฑฐ๋‚˜ ์ƒํƒœ๊ฐ€ ์ „ํ˜€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ „์ฒด ํŠธ๋ฆฌ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์ง€๋งŒ ์ ์ ˆํ•œ ๋ฐฉ์‹์ด ์•„๋‹Œ ๊ฒฝ์šฐ(์˜ˆ: React๊ฐ€ ๋ Œ๋”๋งํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ), ์ž‘์—…์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. :)

Redux์—์„œ ํ˜„์žฌ ์ƒํƒœ๋Š” ๋‹จ์ผ ๋””์ŠคํŒจ์น˜๋ฅผ โ€‹โ€‹ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„๋กœ ๊ฐ„์ฃผํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋™์ผํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ 2๊ฐœ์˜ ์ž‘์—…์„ ๋™๊ธฐ์ ์œผ๋กœ ์ „๋‹ฌํ•˜๋ ค๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” @winstonewert ์˜ ์šฐ๋ ค๋ฅผ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ๋•Œ๋กœ๋Š” actionCreators๊ฐ€ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๊ณ  ๋ชจ๋“  ์ž‘์—…์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‹คํ–‰๋˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. 2๊ฐœ์˜ ์ž‘์—…์ด ์ „๋‹ฌ๋˜๊ณ  ๋‘ ๋ฒˆ์งธ ์ž‘์—…์ด ์‹คํŒจํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ ์ž‘์—…๋งŒ ์ ์šฉ๋˜์–ด "์ผ๊ด€๋˜์ง€ ์•Š์Œ"์œผ๋กœ ๊ฐ„์ฃผํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. @winstonewert ๋Š” ๋‘ ๋ฒˆ์งธ ์ž‘์—… ๋””์ŠคํŒจ์น˜๊ฐ€ ์‹คํŒจํ•˜๋ฉด ๋‘ ์ž‘์—…์„ ๋กค๋ฐฑํ•˜๊ธฐ๋ฅผ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@winstonewert ๋‚ด๋ถ€ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ด์™€ ๊ฐ™์€ ๊ฒƒ์„ ๊ตฌํ˜„ํ–ˆ์œผ๋ฉฐ ์ง€๊ธˆ๊นŒ์ง€๋Š” ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. https://github.com/stample/atom-react/blob/master/src/atom/atom.js
๋˜ํ•œ ๋ Œ๋”๋ง ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๋ Œ๋”๋งํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ UI ์ฐจ๋‹จ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์ƒํƒœ๊ฐ€ ๋กค๋ฐฑ๋˜๊ธฐ๋ฅผ ์›ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ๋‹ค์Œ ๋ฆด๋ฆฌ์Šค ๊นŒ์ง€ React๋Š” ๋ Œ๋” ๋ฉ”์†Œ๋“œ๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๋˜์งˆ ๋•Œ ๋งค์šฐ ๋‚˜์œ ์ผ์„ ํ•˜๋ฏ€๋กœ ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ๋ฏธ๋ž˜์—๋Š” ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งค์žฅ์—์„œ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ์—ฌ๋Ÿฌ ๋™๊ธฐํ™” ๋””์ŠคํŒจ์น˜๋ฅผ โ€‹โ€‹ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

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

@gaearon ์ด๋Ÿฐ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•  ๊ณ„ํš์ด ์žˆ๋Š”์ง€, ํ˜„์žฌ API๋กœ ๊ฐ€๋Šฅํ•œ์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

redux-batched-subscribe ๋Š” ์‹ค์ œ ํŠธ๋žœ์žญ์…˜์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ Œ๋”๋ง ์ˆ˜๋ฅผ ์ค„์ด๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋ณด๋Š” ๊ฒƒ์€ ๊ตฌ๋… ์ˆ˜์‹ ๊ธฐ๊ฐ€ ๋งˆ์ง€๋ง‰์— ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ์—๋„ ๊ฐ ๋””์ŠคํŒจ์น˜ ํ›„์— ์ €์žฅ์†Œ "์ปค๋ฐ‹"์ด ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์™„์ „ํ•œ ๊ฑฐ๋ž˜ ์ง€์›์ด ํ•„์š”ํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@gaearon ์•„์ง ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ @winstonewert ์‚ฌ์šฉ ์‚ฌ๋ก€ ์— ๋Œ€ํ•ด ๋” ์•Œ๊ฒŒ ๋˜์–ด

์•„์ด๋””์–ด๋Š” dispatch([a1,a2]) ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ  a2๊ฐ€ ์‹คํŒจํ•˜๋ฉด a1์ด ๋ฐœ์†ก๋˜๊ธฐ ์ „์˜ ์ƒํƒœ๋กœ ๋กค๋ฐฑํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ณผ๊ฑฐ์—๋Š” ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋™๊ธฐ์ ์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜๊ณ (์˜ˆ: ๋‹จ์ผ onClick ์ˆ˜์‹ ๊ธฐ์—์„œ ๋˜๋Š” actionCreator์—์„œ) ์ฃผ๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚  ๋•Œ๋งŒ ๋ Œ๋”๋ง์„ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํŠธ๋žœ์žญ์…˜์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. redux-batched-subscribe ํ”„๋กœ์ ํŠธ์— ์˜ํ•ด ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฌ๋‚˜ ๋ Œ๋”๋ง์ด ์‹คํŒจํ•˜๋ฉด ๋ Œ๋”๋งํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ์—์„œ ์ง„ํ–‰์„ ์‹œ๋„ํ•˜๋Š” ๋Œ€์‹  ๋ Œ๋”๋ง์ด ์‹คํŒจํ•˜์ง€ ์•Š์€ ๋งˆ์ง€๋ง‰ ์ƒํƒœ๋กœ ๋กค๋ฐฑ์„ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

๊ฐ„๋‹จํ•œ ๊ฐ์†๊ธฐ ์ธํ•ธ์„œ๊ฐ€ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ? ์˜ˆ

const enhanceReducerWithTheAbilityToConsumeMultipleActions = (reducer =>
  (state, actions) => (typeof actions.reduce === 'function'
    ? actions.reduce(reducer, state)
    : reducer(state, actions)
  )
)

์ด๋ฅผ ํ†ตํ•ด ์ €์žฅ์†Œ์— ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธํ•ธ์„œ๋Š” ๊ฐœ๋ณ„ ์ž‘์—…์˜ ์••์ถ•์„ ํ’€๊ณ  ์ด๋ฅผ ๊ฐ ๋ฆฌ๋“€์„œ์— ๊ณต๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ์กด์žฌํ•ฉ๋‹ˆ๋‹ค: https://github.com/tshelburne/redux-batched-actions

์˜ค @gaearon ๋ชฐ๋ž๋„ค์š” . ๋งค์šฐ ์œ ์‚ฌํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ•˜๋Š” 2๊ฐœ์˜ ๊ณ ์œ ํ•œ ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‘˜ ๋‹ค ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ํ”ผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ฒซ ๋ฒˆ์งธ๋Š” ๋ชจ๋“  ์ผ๊ด„ ์ฒ˜๋ฆฌ๋œ ์ž‘์—…์„ ๋กค๋ฐฑํ•˜๊ณ  ๋‘ ๋ฒˆ์งธ๋Š” ์‹คํŒจํ•œ ์ž‘์—…๋งŒ ์ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@gaearon ์•— ,


Action Creators๋Š” ๋ถˆ์ˆœํ•œ ์ฝ”๋“œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

๋‚˜๋Š” ์•„๋งˆ๋„ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค๋งŒํผ Redux์— ๋Œ€ํ•œ ์‹ค์ œ ๊ฒฝํ—˜์ด ๋งŽ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ฒซ๋ˆˆ์— ๋‚˜๋Š” "์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ์—์„œ๋Š” ๋” ๋งŽ์ด ํ•˜๊ณ  ๋ฆฌ๋“€์„œ์—์„œ๋Š” ๋œ ํ•˜๊ธฐ"์— ๋™์˜ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํšŒ์‚ฌ.

Flux ํŒจํ„ด์ด ๋„์ž…๋œ Hacker Way: Rethinking Web App Development at Facebook ์—์„œ Flux๋ฅผ ๋ฐœ๋ช…ํ•˜๊ฒŒ ๋œ ๋ฐ”๋กœ ๊ทธ ๋ฌธ์ œ๋Š” ๋ช…๋ นํ˜• ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ I/O๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” Action Creator๋Š” ๋ช…๋ นํ˜• ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ง์žฅ์—์„œ Redux๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ ๋‚ด๊ฐ€ ์ผํ•˜๋Š” ๊ณณ์—์„œ๋Š” ์„ธ๋ถ„ํ™”๋œ ์ž‘์—…(๋ฌผ๋ก  ๋ชจ๋‘ ์ž์ฒด์ ์œผ๋กœ ์˜๋ฏธ๊ฐ€ ์žˆ์Œ)์„ ์‚ฌ์šฉํ•˜๊ณ  ์ผ๊ด„์ ์œผ๋กœ ํŠธ๋ฆฌ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฉ”์‹œ์ง€๋ฅผ ํด๋ฆญํ•˜๋ฉด OPEN_MESSAGE_VIEW , FETCH_MESSAGE , MARK_NOTIFICATION_AS_READ ์„ธ ๊ฐ€์ง€ ์ž‘์—…์ด ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด๋Ÿฌํ•œ "๋‚ฎ์€ ์ˆ˜์ค€์˜" ์ž‘์—…์€ ์ƒ์  ๋‚ด๋ถ€์— ์–ด๋–ค ๊ฐ’์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ "๋ช…๋ น" ๋˜๋Š” "์„ค์ •์ž" ๋˜๋Š” "๋ฉ”์‹œ์ง€"์— ๋ถˆ๊ณผํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ฐํ˜€์กŒ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋Œ์•„๊ฐ€์„œ MVC๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ณ„์† ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋” ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ๋๋‚  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ์˜๋ฏธ์—์„œ Action Creators๋Š” ์ˆœ์ˆ˜ ์ฝ”๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ˜๋ฉด Reducers(๋ฐ Selector)๋Š” ์ˆœ์ˆ˜ ์ฝ”๋“œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค . Haskell ์‚ฌ๋žŒ๋“ค์€ ๋œ ๋ถˆ์ˆœํ•œ ์ฝ”๋“œ์™€ ๋” ์ˆœ์ˆ˜ํ•œ ์ฝ”๋“œ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ๋” ๋‚ซ๋‹ค ๋Š” ๊ฒƒ์„ ์•Œ์•„๋ƒˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‚ด ์‚ฌ์ด๋“œ โ€‹โ€‹ํ”„๋กœ์ ํŠธ(Redux ์‚ฌ์šฉ)์—์„œ ์›นํ‚ท์˜ ์Œ์„ฑ ์ธ์‹ API๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ง์„ ํ•˜๋ฉด onresult ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ์„ ํƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ด๋ฒคํŠธ๋Š” ์–ด๋””์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๊นŒ?

  • ์•ก์…˜ ์ƒ์„ฑ์ž๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๋จผ์ € ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ ์Šคํ† ์–ด๋กœ ๋ณด๋‚ด๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฒคํŠธ ๊ฐœ์ฒด๋ฅผ ์ €์žฅ์†Œ๋กœ ๋ณด๋‚ด๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‘ ๋ฒˆ์งธ๋กœ ๊ฐ”๋‹ค. ๊ทธ๋ƒฅ ์›์‹œ ์ด๋ฒคํŠธ ๊ฐ์ฒด๋ฅผ ์ €์žฅ์†Œ๋กœ ๋ณด๋‚ด๋ผ.

๊ทธ๋Ÿฌ๋‚˜ Redux dev-tools๋Š” ๋น„์ผ๋ฐ˜ ๊ฐœ์ฒด๊ฐ€ ์ €์žฅ์†Œ๋กœ ์ „์†ก๋˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €๋Š” ์ด๋Ÿฌํ•œ ์ด๋ฒคํŠธ ๊ฐœ์ฒด๋ฅผ ์ผ๋ฐ˜ ๊ฐœ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์•ก์…˜ ์ƒ์„ฑ์ž์— ๋ช‡ ๊ฐ€์ง€ ์ž‘์€ ๋กœ์ง์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. (์•ก์…˜ ์ƒ์„ฑ๊ธฐ์˜ ์ฝ”๋“œ๋Š” ๋„ˆ๋ฌด ๊ฐ„๋‹จํ•˜์—ฌ ์ž˜๋ชป๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.)

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ์†๊ธฐ๋Š” ์ด๋Ÿฌํ•œ ๋งค์šฐ ์›์‹œ์ ์ธ ์ด๋ฒคํŠธ๋ฅผ ๊ฒฐํ•ฉํ•˜๊ณ  ๋งํ•œ ๋‚ด์šฉ์˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋กœ์ง์€ ์ˆœ์ˆ˜ ์ฝ”๋“œ ์•ˆ์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์— (๋ฆฌ๋“€์„œ๋ฅผ ํ•ซ ๋ฆฌ๋กœ๋”ฉํ•˜์—ฌ) ๋ผ์ด๋ธŒ๋กœ ์•„์ฃผ ์‰ฝ๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@dtinth๋ฅผ ์ง€์›ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ํ–‰๋™์€ ์šฐ๋ฆฌ๊ฐ€ ์ด๋Ÿฌํ•œ ์‚ฌ๊ฑด์— ์–ด๋–ป๊ฒŒ ๋ฐ˜์‘ํ•˜๊ณ  ์‹ถ์€์ง€๊ฐ€ ์•„๋‹ˆ๋ผ ํ˜„์‹ค ์„ธ๊ณ„์—์„œ ์ผ์–ด๋‚œ ์‚ฌ๊ฑด์„ ๋‚˜ํƒ€๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ CQRS๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ์šฐ๋ฆฌ๋Š” ์‹ค์ œ ์‚ฌ๊ฑด์— ๋Œ€ํ•œ ๋งŽ์€ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๊ธฐ๋กํ•˜๊ณ  ์‹ถ๊ณ , ์•ž์œผ๋กœ ๊ฐ์†๊ธฐ๊ฐ€ ๊ฐœ์„ ๋˜๊ณ  ์ƒˆ๋กœ์šด ๋…ผ๋ฆฌ๋กœ ์˜ค๋ž˜๋œ ์‚ฌ๊ฑด์„ ์ฒ˜๋ฆฌํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.

@dtinth @denis-sokolov ์ €๋„ ๊ทธ ์ ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. Btw ๋‚ด๊ฐ€ redux-saga ํ”„๋กœ์ ํŠธ๋ฅผ ์ฐธ์กฐํ•  ๋•Œ ๋‚˜๋Š” actionCreators๋ฅผ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ ์  ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์•„์ด๋””์–ด์— ๋ฐ˜๋Œ€ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ถ„๋ช…ํžˆ ํ•˜์ง€ ์•Š์•˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Redux-saga ํ”„๋กœ์ ํŠธ๋Š” @dtinth์—์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ์‹œ๋„ ๋ฏธ๋ฌ˜ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ก์…˜ ๋กœ๊ทธ์— ๋ฐœ์ƒํ•œ ๋ชจ๋“  ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์ด ์•ก์…˜ ๋กœ๊ทธ์˜ ๋ฆฌ๋“€์„œ์—์„œ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ์‰ฝ๊ฒŒ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋งํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ ˆ๋Œ€์ ์œผ๋กœ ์‚ฌ์‹ค์ด๋ฉฐ ์ž‘์—… ๋กœ๊ทธ๊ฐ€ ๋ช…์‹œ์ ์ด์ง€ ์•Š๊ณ  ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๊ฐ์†๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ๋ณต์žกํ•ด์ ธ์„œ ์•ฑ์„ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ค์›Œ์งˆ ๋•Œ๊นŒ์ง€ ํ•œ๋™์•ˆ ๊ทธ ๊ฒฝ๋กœ๋ฅผ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Redux ์‚ฌ๊ฐ€ ํ† ๋ก ์œผ๋กœ ์ด์–ด์ง€๋Š” ์›๋ž˜ ํ† ๋ก ์˜ ์ด ์ง€์ ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/paldepind/functional-frontend-architecture/issues/20#issuecomment -162822909

ํ•ด๊ฒฐํ•˜๋Š” ์œ ์Šค์ผ€์ด์Šค

๋ช…๋ฐฑํ•œ TodoCreated ์ด๋ฒคํŠธ๊ฐ€ ์žˆ๋Š” Todo ์•ฑ์ด ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์•ฑ ์˜จ๋ณด๋”ฉ์„ ์ฝ”๋”ฉํ•˜๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํ•  ์ผ์„ ์ƒ์„ฑํ•˜๋ฉด ํŒ์—…์œผ๋กœ ์ถ•ํ•˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

"๋ถˆ์ˆœํ•œ" ๋ฐฉ๋ฒ•:

์ด๊ฒƒ์€ @bvaughn ์ด ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function createTodo(todo) {
   return (dispatch, getState) => {
       dispatch({type: "TodoCreated",payload: todo});
       if ( getState().isOnboarding ) {
         dispatch({type: "ShowOnboardingTodoCreateCongratulation"});
       }
   }
}

๋‚˜๋Š” ์ด ์ ‘๊ทผ ๋ฐฉ์‹์ด ์•ฑ ๋ณด๊ธฐ์˜ ๋ ˆ์ด์•„์›ƒ๊ณผ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ์•ก์…˜ ์ƒ์„ฑ๊ธฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. actionCreator๊ฐ€ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ธฐ ์œ„ํ•ด UI ์ƒํƒœ ํŠธ๋ฆฌ์˜ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

"์›์‹œ ์ด๋ฒคํŠธ์—์„œ ๋ชจ๋“  ๊ฒƒ์„ ๊ณ„์‚ฐ" ๋ฐฉ์‹:

์ด๊ฒƒ์€ @denis-sokolov @dtinth ๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

function onboardingTodoCreateCongratulationReducer(state = defaultState, action) {
  var isOnboarding = isOnboardingReducer(state.isOnboarding,action);
  switch (action) {
    case "TodoCreated": 
        return {isOnboarding: isOnboarding, isCongratulationDisplayed: isOnboarding}
    default: 
        return {isOnboarding: isOnboarding, isCongratulationDisplayed: false}
  }
}

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

๋‹จ์ˆœํ™”๋œ ์‚ฌ๊ฐ€ ๋ฐฉ์‹.

redux-saga๋Š” ์ƒ์„ฑ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์•ฝ๊ฐ„ ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function createTodo(todo) {
   return (dispatch, getState) => {
       dispatch({type: "TodoCreated",payload: todo});
   }
}

function onboardingSaga(state, action, actionCreators) {
  switch (action) {
    case "OnboardingStarted": 
        return {onboarding: true, ...state};
    case "OnboardingStarted": 
        return {onboarding: false, ...state};
    case "TodoCreated": 
        if ( state.onboarding ) dispatch({type: "ShowOnboardingTodoCreateCongratulation"});
        return state;
    default: 
        return state;
  }
}

saga๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ํšจ๊ณผ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ ์ €์žฅ ์•กํ„ฐ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ด๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋ถˆ์ˆœํ•œ ๊ฐ์†๊ธฐ๋กœ ๊ตฌํ˜„๋˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” redux-saga ํ”„๋กœ์ ํŠธ์— ์—†์Šต๋‹ˆ๋‹ค.

์•ฝ๊ฐ„ ๋ณต์žกํ•œ ๊ทœ์น™:

์ดˆ๊ธฐ ๊ทœ์น™์„ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์— ๋Œ€ํ•ด ๋งค์šฐ ๋ช…์‹œ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์œ„์˜ ๊ตฌํ˜„์„ ๋ณด๋ฉด ์˜จ๋ณด๋”ฉ ์ค‘์— ํ•  ์ผ์„ ๋งŒ๋“ค ๋•Œ๋งˆ๋‹ค ์ถ•ํ•˜ ํŒ์—…์ด ์—ด๋ฆฌ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์˜จ๋ณด๋”ฉ ์ค‘์— ๋ฐœ์ƒํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ์ƒ์„ฑ๋œ ํ• ์ผ์— ๋Œ€ํ•ด์„œ๋งŒ ์—ด๋ฆฌ๊ธธ ์›ํ•˜๊ณ  ๋ชจ๋“  ํ• ์ผ์ด ์•„๋‹ˆ๋ผ ์—ด๋ฆฌ๊ธธ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒฐ๊ตญ ์ฒ˜์Œ๋ถ€ํ„ฐ ์˜จ๋ณด๋”ฉ์„ ๋‹ค์‹œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์˜จ๋ณด๋”ฉ์ด ์ ์  ๋” ๋ณต์žกํ•ด์ง์— ๋”ฐ๋ผ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ 3๊ฐ€์ง€ ๊ตฌํ˜„ ๋ชจ๋‘์—์„œ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ง€์ €๋ถ„ํ•ด์กŒ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

redux-saga ๋ฐฉ์‹

redux-saga์™€ ์œ„์˜ ์˜จ๋ณด๋”ฉ ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function* onboarding() {
  while ( true ) {
    take(ONBOARDING_STARTED)
    take(TODO_CREATED)
    put(SHOW_TODO_CREATION_CONGRATULATION)
    take(ONBOARDING_ENDED)
  }
}

์œ„์˜ ์†”๋ฃจ์…˜๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํ‹€๋ ธ๋‹ค๋ฉด ๋” ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„์„ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. :)

๋‹น์‹ ์€ ๋ถˆ์ˆœํ•œ ์ฝ”๋“œ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ–ˆ๊ณ  ์ด ๊ฒฝ์šฐ์—๋Š” ํ…Œ์ดํฌ/ํ’‹ ํšจ๊ณผ๊ฐ€ ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— Redux-saga ๊ตฌํ˜„์— ๋ถˆ์ˆœํ•จ์ด ์—†์Šต๋‹ˆ๋‹ค. take() ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ์‹คํ–‰ํ•  ํšจ๊ณผ์˜ ์„ค๋ช…์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์–ด๋Š ์‹œ์ ์—์„œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ ์‹œ์ž‘๋˜๋ฏ€๋กœ ๋ฌด์šฉ๋‹ด์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ์˜๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด Haskell์„ ํ•˜๋Š” ๊ธฐ๋Šฅ์ ์ธ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด Free / IO ๋ชจ๋‚˜๋“œ๋ฅผ ์ƒ๊ฐํ•˜์‹ญ์‹œ์˜ค.


์ด ๊ฒฝ์šฐ ๋‹ค์Œ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๋ณต์žกํ•œ actionCreator๋ฅผ ํ”ผํ•˜๊ณ  getState ์— ์˜์กดํ•˜๊ฒŒ ๋งŒ๋“œ์‹ญ์‹œ์˜ค.
  • ์•”์‹œ์ ์„ ๋” ๋ช…์‹œ์ ์œผ๋กœ ๋งŒ๋“ค๊ธฐ
  • ํšก๋‹จ ๋…ผ๋ฆฌ(์œ„์˜ ์˜จ๋ณด๋”ฉ๊ณผ ๊ฐ™์€)๋ฅผ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ(ํ•  ์ผ ์ƒ์„ฑ)์— ๊ฒฐํ•ฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๋˜ํ•œ ํ•ด์„ ๊ณ„์ธต์„ ์ œ๊ณตํ•˜์—ฌ ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‹ค ์˜๋ฏธ ์žˆ๊ณ  ๋†’์€ ์ˆ˜์ค€์˜ ์ด๋ฒคํŠธ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ELM์ด ์ด๋ฒคํŠธ๋ฅผ ๋ฒ„๋ธ”๋งํ•  ๋•Œ ๋ž˜ํ•‘ํ•˜๋Š” ๊ฒƒ๊ณผ ์•ฝ๊ฐ„ ์œ ์‚ฌ).

์˜ˆ:

  • "TIMELINE_SCROLLED_NEAR-BOTTOM"์ด(๊ฐ€) "NEXT_PAGE_LOADED"๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ค๋ฅ˜ ์ฝ”๋“œ๊ฐ€ 401์ธ ๊ฒฝ์šฐ "REQUEST_FAILED"๋กœ ์ธํ•ด "USER_DISCONNECTED"๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • "HASHTAG_FILTER_ADDED"๊ฐ€ "CONTENT_RELOADED"๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Œ

์˜ค๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“ˆ์‹ ์•ฑ ๋ ˆ์ด์•„์›ƒ์„ ๋‹ฌ์„ฑํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์˜ค๋ฆฌ๋ฅผ ํ•จ๊ป˜ ๊ฒฐํ•ฉํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ๊ฐ€๋Š” ์—ฐ๊ฒฐ์ ์ด ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋ฆฌ๋Š” ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ์•Œ์•„์•ผ ํ•˜๊ณ  ๋ฌด์šฉ๋‹ด์€ ์ด๋Ÿฌํ•œ ์›์‹œ ์ด๋ฒคํŠธ๋ฅผ ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ duck1 ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ์—์„œ ๋” ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ๋•Œ๋ฌธ์— duck1์ด duck2์˜ ์ง์ ‘ ์ž‘์—…์„ ๋””์ŠคํŒจ์น˜ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋‚ซ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฒฐํ•ฉ ์ง€์ ์ด actionCreators์—์„œ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ฃผ์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๊ฒƒ์ด ์˜ค๋Š˜๋‚  ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด ํ•˜๊ณ  ์žˆ๋Š” ์ผ์ž…๋‹ˆ๋‹ค.

@slorber ์ด๊ฒƒ์€ ํ›Œ๋ฅญํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค! ์‹œ๊ฐ„์„ ๋‚ด์–ด ๊ฐ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์žฅ์ ๊ณผ ๋‹จ์ ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. (๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๋ฌธ์„œ์— ์žˆ์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.)

๋‚˜๋Š” ๋น„์Šทํ•œ ์•„์ด๋””์–ด๋ฅผ ํƒ๊ตฌํ•˜๊ณค ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๊ฒƒ์€ ์•„๋ฌด ๊ฒƒ๋„ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์ง€๋งŒ( render: () => null ) ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ (์˜ˆ: ์ƒ์ ์—์„œ) ๋‹ค๋ฅธ ๋ถ€์ž‘์šฉ์„ ์œ ๋ฐœํ•˜๋Š” React ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ•ด๋‹น ์ž‘์—…์ž ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๋ฃจํŠธ ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด๋ถ€์— ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๋ถ€์ž‘์šฉ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฏธ์นœ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. :stuck_out_tongue:

๋‚ด๊ฐ€ ์ž๋Š” ๋™์•ˆ ์—ฌ๊ธฐ์—์„œ ๋งŽ์€ ํ† ๋ก ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

@winstonewert , ๋‹น์‹ ์€ ์‹œ๊ฐ„ ์—ฌํ–‰๊ณผ ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š” ์ฝ”๋“œ ์žฌ์ƒ์— ๋Œ€ํ•ด ์ข‹์€ ์ง€์ ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํŠน์ • ์œ ํ˜•์˜ ๋ฒ„๊ทธ/๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์–ด๋Š ์ชฝ์ด๋“  ์‹œ๊ฐ„ ์—ฌํ–‰์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์ „๋ฐ˜์ ์œผ๋กœ ๋‹น์‹ ์ด ์˜ณ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@dtinth , ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค๋งŒ, ๊ท€ํ•˜์˜ ์˜๊ฒฌ ๋Œ€๋ถ€๋ถ„์„ ๋”ฐ๋ฅด๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. action-creator/reducer "ducks" ์ฝ”๋“œ์˜ ์ผ๋ถ€๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค๋Š” ์ ์—์„œ ๋ถˆ์ˆœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ด์ƒ์œผ๋กœ ๋‹น์‹ ์€ ๋‚˜๋ฅผ ์žƒ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์ดˆ๊ธฐ ๊ฒŒ์‹œ๋ฌผ์˜ ์ฃผ์š” ๋ชฉ์  ์ค‘ ํ•˜๋‚˜๋Š” ์‹ค์šฉ์ฃผ์˜ ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค.


@winstonewert ๋Š” "redux์— ๋Œ€ํ•œ ๋‚ด ์ƒ๊ฐ์€ ์ €์žฅ์†Œ๊ฐ€ ํ•ญ์ƒ ์œ ํšจํ•œ ์ƒํƒœ๋ผ๊ณ  ์ฃผ์žฅํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค."๋ผ๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค.
@slorber ๋Š” "Redux @bvaughn ๋ฐ @sompylasar ์—์„œ ์ผ์‹œ์ ์ธ ์ƒํƒœ๋ž€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ? ๋””์ŠคํŒจ์น˜๊ฐ€ ์™„๋ฃŒ๋˜๊ฑฐ๋‚˜ ๋˜์ง‘๋‹ˆ๋‹ค. ๋˜์ง€๋ฉด ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."

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

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์ €์žฅ์†Œ์— [{id: 1, name: "Alex"}, {id: 2, name: "Brian"}, {id: 3, name: "Charles"}] ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•œ ๊ฐœ์ฒด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์‹ญ์‹œ์˜ค. ์‚ฌ์šฉ์ž๊ฐ€ ํ•„ํ„ฐ ํ…์ŠคํŠธ "e"๋ฅผ ์ž…๋ ฅํ–ˆ์œผ๋ฏ€๋กœ ๊ฒ€์ƒ‰ ๋ฏธ๋“ค์›จ์–ด์—๋Š” ID 1๊ณผ 3์˜ ๋ฐฐ์—ด์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ์‚ฌ์šฉ์ž 1(Alex)์ด ๋กœ์ปฌ์—์„œ ์‚ฌ์šฉ์ž ์ž‘์—…์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ์‚ญ์ œ๋˜๊ฑฐ๋‚˜ ๋” ์ด์ƒ ํ•ด๋‹น ์‚ฌ์šฉ์ž ๋ ˆ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ๊ฐ€ ์‚ฌ์šฉ์ž ์ปฌ๋ ‰์…˜์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์‹œ์ ์—์„œ redux-search๊ฐ€ ์ปฌ๋ ‰์…˜์— ๋” ์ด์ƒ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ID๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ† ์–ด๊ฐ€ ์ผ์‹œ์ ์œผ๋กœ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋ฉด ์ž˜๋ชป๋œ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ์ผ์€ ํŠธ๋ฆฌ์˜ ํ•œ ๋…ธ๋“œ๊ฐ€ ๋‹ค๋ฅธ ๋…ธ๋“œ์™€ ๊ด€๋ จ๋˜์–ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


@slorber ๋Š” "์•ก์…˜ ์ž‘์„ฑ์ž๊ฐ€ ์•ฑ ๋ณด๊ธฐ์˜ ๋ ˆ์ด์•„์›ƒ๊ณผ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ ‘๊ทผ ๋ฐฉ์‹์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Š” actionCreator๊ฐ€ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ธฐ ์œ„ํ•ด UI ์ƒํƒœ ํŠธ๋ฆฌ์˜ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค."๋ผ๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค.

์•ก์…˜ ์ƒ์„ฑ์ž๋ฅผ "์•ฑ ๋ณด๊ธฐ์˜ ๋ ˆ์ด์•„์›ƒ์—" ๊ฒฐํ•ฉํ•˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋ฅผ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ํŠธ๋ฆฌ๋Š” UI์— _drives_(๋˜๋Š” ์•Œ๋ ค์ค๋‹ˆ๋‹ค). ์ด๊ฒƒ์ด Flux์˜ ์ฃผ์š” ๋ชฉ์  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์•ก์…˜ ์ƒ์„ฑ์ž์™€ ๋ฆฌ๋“€์„œ๋Š” ์ •์˜์— ๋”ฐ๋ผ ํ•ด๋‹น ์ƒํƒœ์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค(UI์™€๋Š” ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์Œ).

๋‚ด๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ž‘์„ฑํ•œ ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๋‚ด๊ฐ€ ์—ผ๋‘์— ๋‘” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ์–ด์ฉŒ๋ฉด ๋‚ด๊ฐ€ ๋‚˜ ์ž์‹ ์„ ์ž˜ ์„ค๋ช…ํ•˜์ง€ ๋ชปํ–ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๋…ผ์˜์˜ ์–ด๋ ค์›€์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹จ์ˆœํ•˜๊ฑฐ๋‚˜ ์ผ๋ฐ˜์ ์ธ ์˜ˆ์—์„œ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์˜ˆ๋ฅผ ๋“ค์–ด ํ‘œ์ค€ TODO MVC ์•ฑ์€ ์ด์™€ ๊ฐ™์€ ๋ฏธ๋ฌ˜ํ•œ ๋…ผ์˜๋ฅผ ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํžˆ ๋ณต์žกํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

๋งˆ์ง€๋ง‰ ์š”์ ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ํŽธ์ง‘ ํ–ˆ์Šต๋‹ˆ๋‹ค.

Btw @slorber ๋Š” ๋‚ด๊ฐ€ ์—ผ๋‘์— ๋‘์—ˆ๋˜ ๊ฒƒ์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ์ธ์œ„์ ์ž…๋‹ˆ๋‹ค.

์ƒํƒœ์— ๋งŽ์€ ๋…ธ๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋…ธ๋“œ ์ค‘ ํ•˜๋‚˜๋Š” ๊ณต์œ  ๋ฆฌ์†Œ์Šค๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ("๊ณต์œ "๋ž€ ๋กœ์ปฌ๋กœ ์บ์‹œ๋˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์˜ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€์—์„œ ์•ก์„ธ์Šคํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.) ์ด๋Ÿฌํ•œ ๊ณต์œ  ๋ฆฌ์†Œ์Šค์—๋Š” ๊ณ ์œ ํ•œ ์ž‘์—… ์ƒ์„ฑ์ž์™€ ๊ฐ์†๊ธฐ("๋•")๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋…ธ๋“œ๋Š” ํŠน์ • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ํŽ˜์ด์ง€์—๋Š” ์ž์ฒด ์˜ค๋ฆฌ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ท€ํ•˜์˜ ํŽ˜์ด์ง€๊ฐ€ ์ตœ์‹ ์˜ ๊ฐ€์žฅ ๋›ฐ์–ด๋‚œ ๊ฒƒ์„ ๋กœ๋“œํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์•ก์…˜ ์ƒ์„ฑ์ž ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค.

import { fetchThing, thingSelector } from 'resources/thing/duck'
import { showError } from 'messages/duck'

export function fetchAndProcessThing ({ params }): Object {
  const { id } = params
  return async ({ dispatch, getState }) => {
    try {
      await dispatch(fetchThing({ id }))

      const thing = thingSelector(getState())

      dispatch({ type: 'PROCESS_THING', thing })
    } catch (err) {
      dispatch(showError(`Invalid thing id="${id}".`))
    }
  }
}

@winstonewert ๋Š” ๋‘ ๋ฒˆ์งธ ์ž‘์—… ๋””์ŠคํŒจ์น˜๊ฐ€ ์‹คํŒจํ•˜๋ฉด ๋‘ ์ž‘์—…์„ ๋กค๋ฐฑํ•˜๊ธฐ๋ฅผ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„๋‹ˆ์š”. ๋‘ ๊ฐ€์ง€ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๋Š” ์ž‘์—… ์ž‘์„ฑ์ž๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋‹จ์ผ ์ž‘์—…์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. OP๋Š” ๋‚ด๊ฐ€ ์‹ซ์–ดํ•˜๋Š” ์ผ์‹œ์ ์ธ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํƒœ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋” ์ž‘์€ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๋Š” ์ž‘์—… ์ž‘์„ฑ์ž๋ฅผ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ฆฌ๋“€์„œ๊ฐ€ ์‚ฌ์šฉ์ž ์ปฌ๋ ‰์…˜์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์‹œ์ ์—์„œ redux-search๊ฐ€ ์ปฌ๋ ‰์…˜์— ๋” ์ด์ƒ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ID๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ† ์–ด๊ฐ€ ์ผ์‹œ์ ์œผ๋กœ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋ฉด ์ž˜๋ชป๋œ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ์ผ์€ ํŠธ๋ฆฌ์˜ ํ•œ ๋…ธ๋“œ๊ฐ€ ๋‹ค๋ฅธ ๋…ธ๋“œ์™€ ๊ด€๋ จ๋˜์–ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ๋‚˜๋ฅผ ๊ดด๋กญํžˆ๋Š” ์ข…๋ฅ˜์˜ ์ผ€์ด์Šค์ž…๋‹ˆ๋‹ค. ๋‚ด ์ƒ๊ฐ์— ์ธ๋ฑ์Šค๋Š” ์ด์ƒ์ ์œผ๋กœ๋Š” ๊ฐ์†๊ธฐ ๋˜๋Š” ์„ ํƒ๊ธฐ์— ์˜ํ•ด ์™„์ „ํžˆ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฒ€์ƒ‰์„ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ์ž‘์—…์„ ๋ณด๋‚ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ๋œ ์ˆœ์ˆ˜ํ•œ redux ์‚ฌ์šฉ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

OP๋Š” ๋‚ด๊ฐ€ ์‹ซ์–ดํ•˜๋Š” ์ผ์‹œ์ ์ธ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํƒœ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋” ์ž‘์€ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๋Š” ์ž‘์—… ์ž‘์„ฑ์ž๋ฅผ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ •ํ™•ํžˆ. ์ƒํƒœ ํŠธ๋ฆฌ์˜ ์ž‘์—… ์ƒ์„ฑ์ž์˜ ๋…ธ๋“œ์™€ ๊ด€๋ จํ•˜์—ฌ ๋‹จ์ผ ์ž‘์—…์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์ผ ๊ฐœ๋…์  ์‚ฌ์šฉ์ž "์ž‘์—…"์ด ์ƒํƒœ ํŠธ๋ฆฌ์˜ ์—ฌ๋Ÿฌ ๋…ธ๋“œ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ž‘์—…์„ ๊ฐœ๋ณ„์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜(_bad_๋ผ๊ณ  ์ƒ๊ฐํ•จ) ๋‹จ์ผ ์ž‘์—… ์ƒ์„ฑ์ž๊ฐ€ ์ž‘์—…์„ ๋ฐœ์†กํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ณด๊ธฐ ๋ ˆ์ด์–ด์—์„œ ํ•ด๋‹น ์ •๋ณด๋ฅผ ์ˆจ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— _better_๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” redux-thunk ๋ฐฉ์‹).

์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ๋‚˜๋ฅผ ๊ดด๋กญํžˆ๋Š” ์ข…๋ฅ˜์˜ ์ผ€์ด์Šค์ž…๋‹ˆ๋‹ค. ๋‚ด ์ƒ๊ฐ์— ์ธ๋ฑ์Šค๋Š” ์ด์ƒ์ ์œผ๋กœ๋Š” ๊ฐ์†๊ธฐ ๋˜๋Š” ์„ ํƒ๊ธฐ์— ์˜ํ•ด ์™„์ „ํžˆ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฒ€์ƒ‰์„ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ์ž‘์—…์„ ๋ณด๋‚ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ๋œ ์ˆœ์ˆ˜ํ•œ redux ์‚ฌ์šฉ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์ž‘์—…์„ ๋ฐœ์†กํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฒ€์ƒ‰์€ ๋ฏธ๋“ค์›จ์–ด์ž…๋‹ˆ๋‹ค. ์ž๋™์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํŠธ๋ฆฌ์˜ ๋‘ ๋…ธ๋“œ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๋•Œ ์ผ์‹œ์ ์ธ ์ƒํƒœ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

@bvaughn ์•„, ์ˆœ์ˆ˜์ฃผ์˜์ž

์Œ, ์ˆœ์ˆ˜ ์ฝ”๋“œ๋Š” ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ๋ฐ ๊ธฐํƒ€ ๋ถ€์ž‘์šฉ/IO์™€ ๊ด€๋ จ์ด ์žˆ๋Š” ๋ฐ˜๋ฉด ์ˆœ์ˆ˜ ์ฝ”๋“œ๋Š” ๋ถ€์ž‘์šฉ์„ ์œ ๋ฐœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ˆœ์ˆ˜ ์ฝ”๋“œ์™€ ์ˆœ์ˆ˜ ์ฝ”๋“œ๋ฅผ ๋น„๊ตํ•˜๋ ค๋ฉด ์ด ํ‘œ ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Flux ๋ชจ๋ฒ” ์‚ฌ๋ก€์— ๋”ฐ๋ฅด๋ฉด ์ž‘์—…์€ "์‚ฌ์šฉ์ž์˜ ์ž‘์—…์„ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋ฉฐ ์„ค์ •์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค." Flux ๋ฌธ์„œ ๋Š” ๋˜ํ•œ ์ด๋Ÿฌํ•œ ์ž‘์—…์ด ์–ด๋””์—์„œ ์™”๋Š”์ง€ ์ถ”๊ฐ€๋กœ ์•”์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

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

๊ธฐ๋ณธ์ ์œผ๋กœ ์กฐ์น˜๋Š” "๋ฐœ์ƒํ•ด์•ผ ํ•  ์ผ"์ด ์•„๋‹ˆ๋ผ "์ผ์–ด๋‚œ ์ผ"์„ ์„ค๋ช…ํ•˜๋Š” ์‚ฌ์‹ค/๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค. ์ƒ์ ์€ ๋‹ค๋ฅธ ๋ถ€์ž‘์šฉ ์—†์ด ๋™๊ธฐ์ ์ด๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ด๋Ÿฌํ•œ ์กฐ์น˜์—๋งŒ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“  ๋ถ€์ž‘์šฉ์€ ์•ก์…˜ ์ œ์ž‘์ž(๋˜๋Š” sagas :wink:)์—์„œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

๋‚˜๋Š” ์ด๊ฒƒ์ด ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์ด๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์–ด๋–ค ๋ฐฉ๋ฒ•๋ณด๋‹ค ๋” ๋‚ซ๋‹ค๊ฑฐ๋‚˜ ์‹ฌ์ง€์–ด ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ํ˜„์žฌ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž๊ฐ€ ์›๊ฒฉ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•ด์•ผ ํ•˜๋Š” ์Šค์ฝ”์–ด๋ณด๋“œ๋ฅผ ๋ณด๊ณ  ์‹ถ์–ดํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๋ฐœ์ƒํ•ด์•ผ ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž๊ฐ€ ์Šค์ฝ”์–ด๋ณด๋“œ ๋ณด๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
  • ์Šค์ฝ”์–ด๋ณด๋“œ ๋ณด๊ธฐ๋Š” ๋กœ๋”ฉ ํ‘œ์‹œ๊ธฐ์™€ ํ•จ๊ป˜ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • ์Šค์ฝ”์–ด๋ณด๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„์— ์š”์ฒญ์ด ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
  • ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ์‹ญ์‹œ์˜ค.
  • ์„ฑ๊ณตํ•˜๋ฉด ์Šค์ฝ”์–ด๋ณด๋“œ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • ์‹คํŒจํ•˜๋ฉด ์Šค์ฝ”์–ด๋ณด๋“œ๊ฐ€ ๋‹ซํžˆ๊ณ  ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€์™€ ํ•จ๊ป˜ ๋ฉ”์‹œ์ง€ ์ƒ์ž๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž๋Š” ์Šค์ฝ”์–ด๋ณด๋“œ๋ฅผ ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ก์…˜์ด ์‚ฌ์šฉ์ž์˜ ์•ก์…˜์ด๋‚˜ ์„œ๋ฒ„ ์‘๋‹ต์˜ ๊ฒฐ๊ณผ๋กœ๋งŒ ์Šคํ† ์–ด์— ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด 5๊ฐœ์˜ ์•ก์…˜์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • SCOREBOARD_VIEW (์‚ฌ์šฉ์ž๊ฐ€ ์Šค์ฝ”์–ด๋ณด๋“œ ๋ณด๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ ๊ฒฐ๊ณผ)
  • SCOREBOARD_FETCH_SUCCESS (์„œ๋ฒ„์˜ ์„ฑ๊ณต์ ์ธ ์‘๋‹ต ๊ฒฐ๊ณผ)
  • SCOREBOARD_FETCH_FAILURE (์„œ๋ฒ„์˜ ์˜ค๋ฅ˜ ์‘๋‹ต ๊ฒฐ๊ณผ)
  • SCOREBOARD_CLOSE (์‚ฌ์šฉ์ž๊ฐ€ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ ๊ฒฐ๊ณผ)
  • MESSAGE_BOX_CLOSE (์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”์‹œ์ง€ ์ƒ์ž์˜ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ ๊ฒฐ๊ณผ)

์ด 5๊ฐ€์ง€ ์ž‘์—…์€ ์œ„์˜ ๋ชจ๋“  ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ 4๊ฐœ์˜ ์ž‘์—…์€ "์˜ค๋ฆฌ"์™€ ์•„๋ฌด ๊ด€๋ จ์ด ์—†์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์ž‘์—… ์€ ์™ธ๋ถ€ ์„ธ๊ณ„์—์„œ ๋ฐœ์ƒํ•œ ์ผ๋งŒ ์„ค๋ช… MESSAGE_BOX_OPEN ์•ก์…˜์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ทธ๊ฒƒ์€ "์ผ์–ด๋‚œ ์ผ"์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(๋น„๋ก ๊ทธ๊ฒƒ์ด ์ผ์–ด๋‚˜์•ผ ํ•˜์ง€๋งŒ).

์ƒํƒœ ํŠธ๋ฆฌ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ๋ฐœ์ƒํ•œ ์ผ์„ ์„ค๋ช…ํ•˜๋Š” ๊ฐ์ฒด์ธ ์ž‘์—…์„ ๋‚ด๋ณด๋‚ด๋Š” Redux์˜ README

๊ทธ๋“ค์€ ๋‹ค์Œ ์•ก์…˜ ์ œ์ž‘์ž์™€ ํ•จ๊ป˜ ๋ถ™์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

function viewScoreboard () {
  return async function (dispatch) {
    dispatch({ type: 'SCOREBOARD_VIEW' })
    try {
      const result = fetchScoreboardFromServer()
      dispatch({ type: 'SCOREBOARD_FETCH_SUCCESS', result })
    } catch (e) {
      dispatch({ type: 'SCOREBOARD_FETCH_FAILURE', error: String(e) })
    }
  }
}
function closeScoreboard () {
  return { type: 'SCOREBOARD_CLOSE' }
}

๊ทธ๋Ÿฌ๋ฉด ์ €์žฅ์†Œ์˜ ๊ฐ ๋ถ€๋ถ„(๋ฆฌ๋“€์„œ๋กœ ๊ด€๋ฆฌ)์ด ๋‹ค์Œ ์ž‘์—…์— ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

| ์ €์žฅ/๊ฐ์†๊ธฐ์˜ ์ผ๋ถ€ | ํ–‰๋™ |
| --- | --- |
| ์Šค์ฝ”์–ด๋ณด๋“œ๋ณด๊ธฐ | SCOREBOARD_VIEW ์— ๋Œ€ํ•œ ๊ฐ€์‹œ์„ฑ ์—…๋ฐ์ดํŠธ, SCOREBOARD_CLOSE ๋ฐ SCOREBOARD_FETCH_FAILURE ์— ๋Œ€ํ•œ false |
| ์Šค์ฝ”์–ด๋ณด๋“œ ๋กœ๋”ฉ ํ‘œ์‹œ๊ธฐ | SCOREBOARD_VIEW ์— ๋Œ€ํ•œ ๊ฐ€์‹œ์„ฑ ์—…๋ฐ์ดํŠธ, SCOREBOARD_FETCH_* ์— ๋Œ€ํ•œ false |
| ์Šค์ฝ”์–ด๋ณด๋“œ๋ฐ์ดํ„ฐ | SCOREBOARD_FETCH_SUCCESS ์— ๋งค์žฅ ๋‚ด ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ |
| ๋ฉ”์‹œ์ง€ ์ƒ์ž | ์‚ฌ์‹ค ๋ฐ ์ €์žฅ์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ ๊ฐ€์‹œ์„ฑ SCOREBOARD_FETCH_FAILURE , ๊ทธ๋ฆฌ๊ณ  ๊ฑฐ์ง“์œผ๋กœ ์—…๋ฐ์ดํŠธ ๊ฐ€์‹œ์„ฑ MESSAGE_BOX_CLOSE |

๋ณด์‹œ๋‹ค์‹œํ”ผ, ๋‹จ์ผ ์ž‘์—…์€ ์ƒ์ ์˜ ๋งŽ์€ ๋ถ€๋ถ„์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ์ ์—๋Š” ๋ช…๋ น(๋ฌด์—‡์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?)๋ณด๋‹ค๋Š” ์ž‘์—…(๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ฌ์Šต๋‹ˆ๊นŒ?)์— ๋Œ€ํ•œ ๋†’์€ ์ˆ˜์ค€์˜ ์„ค๋ช…๋งŒ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ:

  1. ์˜ค๋ฅ˜๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ์ด ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค.

์•„๋ฌด ๊ฒƒ๋„ ๋ฉ”์‹œ์ง€ ์ƒ์ž์˜ ์ƒํƒœ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์ด์œ ๋กœ๋“  ์—ด๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒ์€ ์•„๋ฌด๋„ ์—†์Šต๋‹ˆ๋‹ค. ๊ตฌ๋…ํ•œ ํ•ญ๋ชฉ(์‚ฌ์šฉ์ž ์ž‘์—… ๋ฐ ์„œ๋ฒ„ ์‘๋‹ต)์—๋งŒ ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค.

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

์ˆ˜์ •์€ ์‚ฌ์†Œํ•˜๊ณ  ํ•ซ ๋ฆฌ๋กœ๋“œ๋˜๊ณ  ์‹œ๊ฐ„ ์—ฌํ–‰์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์•ก์…˜ ์ƒ์„ฑ์ž์™€ ๋ฆฌ๋“€์„œ๋Š” ๋ณ„๋„๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋ฆฌ๋“€์„œ๋Š” ์™ธ๋ถ€ ์„ธ๊ณ„์˜ ๋™์ž‘์— ์ ์ ˆํ•˜๊ฒŒ ๋ฐ˜์‘ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฐ„๋‹จํžˆ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋Š” ์—ฌ์ „ํžˆ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.)

๊ฑฑ์ • ๋งˆ. :) ์ถ”๊ฐ€ ์„ค๋ช…์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์šฐ๋ฆฌ๊ฐ€ ์—ฌ๊ธฐ์— ๋™์˜ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ์˜ˆ์ œ action-creator viewScoreboard ๋ฅผ ๋ณด๋ฉด ๋ฐ”๋กœ ์œ„์˜ ์˜ˆ์ œ action-creator fetchAndProcessThing ์™€ ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์•ก์…˜ ์ƒ์„ฑ์ž์™€ ๋ฆฌ๋“€์„œ๋Š” ๋ณ„๋„๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์ผ ๊ฐœ๋…์  ์‚ฌ์šฉ์ž "์ž‘์—…"์ด ์ƒํƒœ ํŠธ๋ฆฌ์˜ ์—ฌ๋Ÿฌ ๋…ธ๋“œ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ๋ฐ”๋กœ ๋‹น์‹ ์ดํ•˜๋Š” ์ผ์ด redux์— ๋Œ€ํ•œ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋กœ ๊ฐ„์ฃผ๋˜๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅด๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ํ‘œ์ค€ ๋ฐฉ๋ฒ•์€ ์ƒํƒœ ํŠธ๋ฆฌ์˜ ์—ฌ๋Ÿฌ ๋…ธ๋“œ๊ฐ€ ์‘๋‹ตํ•˜๋Š” ํ•˜๋‚˜์˜ ์ž‘์—…์„ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„, ํฅ๋ฏธ๋กœ์šด ๊ด€์ฐฐ @winstonewert. ์šฐ๋ฆฌ๋Š” ๊ฐ "ducks" ๋ฒˆ๋“ค์— ๋Œ€ํ•ด ๊ณ ์œ ํ•œ ์œ ํ˜• ์ƒ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด์„ ๋”ฐ๋ฅด๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํ™•์žฅ์ž๋Š” ํ˜•์ œ ์ž‘์—… ์ƒ์„ฑ์ž๊ฐ€ ์ „๋‹ฌํ•œ ์ž‘์—…์—๋งŒ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ์•ก์…˜์— ๋ฐ˜์‘ํ•˜๋Š” ์ž„์˜์˜ ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ๋Š๋ผ๋Š”์ง€ ์†”์งํžˆ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ๋‚˜์œ ์บก์Šํ™” ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ญ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๊ฐ "ducks" ๋ฒˆ๋“ค์— ๋Œ€ํ•ด ๊ณ ์œ ํ•œ ์œ ํ˜• ์ƒ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด์„ ๋”ฐ๋ž์Šต๋‹ˆ๋‹ค.

๋ฌธ์„œ์˜ ์–ด๋Š ๊ณณ์—์„œ๋„ ์ด๋ฅผ ๋ณด์ฆํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์‹ญ์‹œ์˜ค. ;-) ๊ทธ๊ฒƒ์ด ๋‚˜์˜๋‹ค๊ณ  ๋งํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ Redux์— ๋Œ€ํ•ด ๋•Œ๋•Œ๋กœ ์ž˜๋ชป๋œ ์•„์ด๋””์–ด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ™•์žฅ์ž๋Š” ํ˜•์ œ ์ž‘์—… ์ƒ์„ฑ์ž๊ฐ€ ์ „๋‹ฌํ•œ ์ž‘์—…์—๋งŒ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

Redux์—๋Š” ๊ฐ์†๊ธฐ/์•ก์…˜ ์ƒ์„ฑ๊ธฐ ํŽ˜์–ด๋ง๊ณผ ๊ฐ™์€ ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ˆœ์ „ํžˆ ์˜ค๋ฆฌ์˜ ์ผ์ž…๋‹ˆ๋‹ค. ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๊ฒƒ์„ ์ข‹์•„ํ•˜์ง€๋งŒ Redux/Flux ๋ชจ๋ธ์˜ ๊ทผ๋ณธ์ ์ธ ๊ฐ•์ ์„ ํ๋ฆฌ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ๋Œ์—ฐ๋ณ€์ด๋Š” ์„œ๋กœ ๋ถ„๋ฆฌ๋˜๊ณ  ์ด๋ฅผ ์ผ์œผํ‚ค๋Š” ์ฝ”๋“œ์—์„œ ๋ถ„๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” ์•ก์…˜์— ๋ฐ˜์‘ํ•˜๋Š” ์ž„์˜์˜ ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ๋Š๋ผ๋Š”์ง€ ์†”์งํžˆ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ๋‚˜์œ ์บก์Šํ™” ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ญ๋‹ˆ๋‹ค.

์บก์Šํ™” ๊ฒฝ๊ณ„๋ฅผ ๊ณ ๋ คํ•˜๋Š” ํ•ญ๋ชฉ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์•ก์…˜์€ ์•ฑ์—์„œ ์ „์—ญ์ด๊ณ  ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์•„์š”. ๋ณต์žกํ•œ ์ œํ’ˆ ์š”๊ตฌ ์‚ฌํ•ญ ๋•Œ๋ฌธ์— ์•ฑ์˜ ํ•œ ๋ถ€๋ถ„์ด ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ์ž‘์—…์— ๋ฐ˜์‘ํ•˜๊ธฐ๋ฅผ ์›ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์ด ๊ดœ์ฐฎ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ปคํ”Œ๋ง์€ ์ตœ์†Œํ™”๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์˜์กดํ•˜๋Š” ๊ฒƒ์€ ๋ฌธ์ž์—ด๊ณผ ์ž‘์—… ๊ฐœ์ฒด ๋ชจ์–‘๋ฟ์ž…๋‹ˆ๋‹ค. ์ด์ ์€ ์•ก์…˜ ์ œ์ž‘์ž์™€ ๋งŽ์€ ์—ฐ๊ฒฐ์„ ๋งŒ๋“ค์ง€ ์•Š๊ณ ๋„ ์•ฑ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์—์„œ ์•ก์…˜์˜ ์ƒˆ๋กœ์šด ํŒŒ์ƒ๋ฌผ์„ ์‰ฝ๊ฒŒ ๋„์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋Š” ์•ก์…˜์ด โ€‹โ€‹๋””์ŠคํŒจ์น˜๋  ๋•Œ ์ •ํ™•ํžˆ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ฆฌ๋“€์„œ ์ชฝ์—์„œ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

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

์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ƒํƒœ์—์„œ ์ฝ๋Š” ์œ ์ง€ ๊ธฐ๋Šฅ("์„ ํƒ๊ธฐ")์„ ๊ฐ์†๊ธฐ์™€ ํ•จ๊ป˜ ๋‚ด๋ณด๋‚ด๊ณ  ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ƒํƒœ ๊ตฌ์กฐ๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉํ•˜๋Š” ๋Œ€์‹  ํ•ญ์ƒ mapStateToProps ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‚ด๋ถ€ ์ƒํƒœ ๋ชจ์–‘์„ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ฑ๋Šฅ์„ ์œ„ํ•ด reselect ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ(๊ผญ ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ) shopping-cart ์˜ˆ์ œ์™€ ๊ฐ™์ด ์ˆœ์ง„ํ•˜๊ฒŒ ์„ ํƒ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

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

  • ๋ช…๋ นํ˜• ์Šคํƒ€์ผ์—์„œ ์ƒ์ ์€ SHOW_MESSAGE_BOX ๋˜๋Š” SHOW_ERROR ์™€ ๊ฐ™์ด "ํ•  ์ผ"์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
  • ๋ฐ˜์‘ํ˜• ์Šคํƒ€์ผ์—์„œ ์ƒ์ ์—๋Š” "๋ฐœ์ƒํ•œ ์‚ฌ์‹ค"์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค(์˜ˆ: DATA_FETCHING_FAILED ๋˜๋Š” USER_ENTERED_INVALID_THING_ID . ๊ทธ์— ๋”ฐ๋ผ ๋งค์žฅ์ด ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค.

์ด์ „ ์˜ˆ์—์„œ๋Š” ์‚ฌ์‹ค์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— SHOW_MESSAGE_BOX action ๋˜๋Š” showError('Invalid thing id="'+id+'"') action creator๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ช…๋ น์ž…๋‹ˆ๋‹ค.

๊ทธ ์‚ฌ์‹ค์ด ์ €์žฅ์†Œ์— ๋“ค์–ด์˜ค๋ฉด ๊ทธ ์‚ฌ์‹ค์„ ์ˆœ์ˆ˜ ๋ฆฌ๋“€์„œ ๋‚ด์—์„œ ๋ช…๋ น์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด

// type Command = State โ†’ State
// :: Action โ†’ Command
function interpretAction (action) {
  switch (action.type) {
  case 'DATA_FETCHING_FAILED':
    return showErrorMessage('Data fetching failed')
    break
  case 'USER_ENTERED_INVALID_THING_ID':
    return showErrorMessage('User entered invalid thing ID')
    break
  case 'CLOSE_ERROR_MESSAGE':
    return hideErrorMessage()
    break
  default:
    return doNothing()
  }
}

// :: (State, Action) โ†’ State
function errorMessageReducer (state, action) {
  return interpretAction(action)(state)
}

const showErrorMessage = message => state => ({ visible: true, message })
const hideErrorMessage = () => state => ({ visible: false })
const doNothing = () => state => state

ํ–‰๋™์ด "๋ช…๋ น"์ด ์•„๋‹Œ "์‚ฌ์‹ค"๋กœ ์ƒ์ ์— ๋“ค์–ด๊ฐˆ ๋•Œ ์ž˜๋ชป๋  ๊ฐ€๋Šฅ์„ฑ์ด ์ ์Šต๋‹ˆ๋‹ค. ๊ธ€์Ž„์š”, ์‚ฌ์‹ค์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด์ œ ๊ฐ์†๊ธฐ๊ฐ€ ๊ทธ ์‚ฌ์‹ค์„ ์ž˜๋ชป ํ•ด์„ํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ˆ˜์ • ์‚ฌํ•ญ์€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์•ก์…˜ ์ œ์ž‘์ž๊ฐ€ ๊ทธ ์‚ฌ์‹ค์„ ์ž˜๋ชป ํ•ด์„ํ•˜๋ฉด ์•ก์…˜ ์ œ์ž‘์ž๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

USER_ENTERED_INVALID_THING_ID ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์‚ฌ๋ฌผ ID ํ…์ŠคํŠธ ํ•„๋“œ๊ฐ€ ์žฌ์„ค์ •๋˜๋„๋ก ๊ฐ์†๊ธฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋ณ€ํ™”๋Š” ๋˜ํ•œ ์‹œ๊ฐ„์„ ํ†ตํ•ด ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜์ง€ ์•Š๊ณ ๋„ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ํ˜„์ง€ํ™”ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ”ผ๋“œ๋ฐฑ ๋ฃจํ”„๋ฅผ ๊ฐ•ํ™”ํ•˜๊ณ  ๋””๋ฒ„๊น… ๋ฐ ์กฐ์ •์„ ํ›จ์”ฌ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

(์—ฌ๊ธฐ์„œ ๋‚˜๋Š” ๋‹จ์ง€ ์žฅ์ ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋‹จ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์ƒ์ ์ด ์ด๋Ÿฌํ•œ ์‚ฌ์‹ค์— ๋™๊ธฐ์ ์œผ๋กœ ๊ทธ๋ฆฌ๊ณ  ๋ถ€์ž‘์šฉ ์—†์ด ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ๊ทธ ์‚ฌ์‹ค์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋” ๋งŽ์ด ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์— ๋Œ€ํ•œ ํ† ๋ก ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ์ด ์งˆ๋ฌธ์„ StackOverflow์— ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค . ์•„์ง ๊ทธ ๋ถ€๋ถ„์„ ํŒŒ์•…ํ•˜์ง€ ๋ชปํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.)


์ฒ˜์Œ์—๋Š” ์•ก์…˜์— ๋ฐ˜์‘ํ•˜๋Š” ์ž„์˜์˜ ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ๋Š๋ผ๋Š”์ง€ ์†”์งํžˆ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ๋‚˜์œ ์บก์Šํ™” ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ญ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋™์ผํ•œ ์ €์žฅ์†Œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๋„ ๋งค์šฐ ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹จ์ผ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ €์žฅ์†Œ์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ์— ์˜์กดํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ๋‚˜์œ ์บก์Šํ™”์ฒ˜๋Ÿผ ๋“ค๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ์ง„์ •ํ•œ ๋ชจ๋“ˆํ™”๊ฐ€ ๋˜๋ ค๋ฉด React ์ปดํฌ๋„ŒํŠธ๋„ "duck" ๋ฒˆ๋“ค ์•ˆ์— ์žˆ์–ด์•ผ ํ•˜์ง€ ์•Š์„๊นŒ์š”? ( Elm ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค .)

React๋Š” ์Šคํ† ์–ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์‹ค๋กœ ์ฒ˜๋ฆฌ

๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ Redux/Flux๋Š” ์•ก์…˜์„ ์‚ฌ์‹ค๋กœ ์ทจ๊ธ‰

@dtinth, ์‹œ๊ฐ„์„ ๋‚ด์–ด ๊ธ€์„ ์ž‘์„ฑํ•˜๊ณ  ์ƒ๊ฐ์„ ๊ณต์œ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด ํ† ๋ก ์— ์ฐธ์—ฌํ•ด ์ฃผ์‹ 

์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋™์ผํ•œ ์ €์žฅ์†Œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๋„ ๋งค์šฐ ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹จ์ผ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ €์žฅ์†Œ์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ์— ์˜์กดํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ๋‚˜์œ ์บก์Šํ™”์ฒ˜๋Ÿผ ๋“ค๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

์Œ... ์ฃผ๊ด€์ ์ธ ๋ถ€๋ถ„๋„ ์žˆ์ง€๋งŒ ์•„๋‹™๋‹ˆ๋‹ค. ๋‚ด๋ณด๋‚ธ action-creators์™€ selectors๋ฅผ ๋ชจ๋“ˆ์˜ API๋กœ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ์ข‹์€ ํ† ๋ก ์ด์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด์ „ ๋‹ต๋ณ€์—์„œ ์–ธ๊ธ‰ํ•œ Thai์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์šฐ๋ฆฌ๊ฐ€ ๋…ผ์˜ํ•˜๊ณ  ์žˆ๋Š” ์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์—๋Š” ์žฅ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์— ๋Œ€ํ•œ ํ†ต์ฐฐ๋ ฅ์„ ์–ป๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. :)

๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ  ๋ฉ”์‹œ์ง€ ์ƒ์ž๋Š” ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด ๋ณ„๋„์˜ ์ž‘์—… ์ž‘์„ฑ์ž๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜๋Š” ์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ ์ƒ์„ฑ๋œ ์‹œ๊ฐ„์„ ์ „๋‹ฌํ•˜์—ฌ ์ž๋™์œผ๋กœ ํ•ด์ œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์—(๊ทธ๋ฆฌ๊ณ  ์•ก์…˜ ์ƒ์„ฑ๊ธฐ๋Š” impure Date.now() ํ˜ธ์ถœํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค), ์ด๋ฅผ ํ•ด์ œํ•˜๋Š” ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•˜๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ํƒ€์ด๋จธ ๋“ฑ์„ ๋””๋ฐ”์šด์Šคํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฉ”์‹œ์ง€ ์ƒ์ž์˜ "์ž‘์—… ํ๋ฆ„"์ด ๊ฐœ์ธ์ ์ธ ์ž‘์—…์„ ๋ณด์ฆํ•  ๋งŒํผ ์ถฉ๋ถ„ํžˆ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์€ https://github.com/yelouafi/redux-saga์—์„œ ๋” ์šฐ์•„ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

์ฒ˜์Œ์— Discord Reactiflux ์ฑ„ํŒ…์— ์ด๊ฒƒ์„ ์ผ์ง€๋งŒ ์—ฌ๊ธฐ์— ๋ถ™์—ฌ๋„ฃ์œผ๋ผ๋Š” ์š”์ฒญ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

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

  1. ์ž‘์—… ์ƒ์„ฑ์ž์—๊ฒŒ ์—…๋ฐ์ดํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ์ •๋ณด๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ˜„์žฌ ์ƒํƒœ์—์„œ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๊ทธ ์•ˆ์— ์žˆ์œผ๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
  2. ์ƒํƒœ๋Š” ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ •๋ณด์— ๋Œ€ํ•ด ์ฟผ๋ฆฌ๋ฉ๋‹ˆ๋‹ค(์˜ˆ: id X๋กœ Todo๋ฅผ ๋ณต์‚ฌํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ๋„๋ก id X๋กœ Todo์˜ ์†์„ฑ์„ ๊ฐ€์ ธ์˜ด). ์ด๊ฒƒ์€ ์ž‘์—… ์ƒ์„ฑ์ž์—์„œ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ•ด๋‹น ์ •๋ณด๋Š” ์ž‘์—… ๊ฐœ์ฒด์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋šฑ๋šฑํ•œ ์ž‘์—… ๊ฐœ์ฒด๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ๊ฐ์†๊ธฐ - ์–‡์€ ์ž‘์—… ๊ฐœ์ฒด์—์„œ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ํ•ด๋‹น ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ˆœ์ˆ˜ ๋ฆฌ๋“€์„œ ๋กœ์ง์ด ์ ์šฉ๋˜์–ด ๋‹ค์Œ ์ƒํƒœ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

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

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

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋‹ต์ด ๋ฌด์—‡์ธ์ง€ ๋ชจ๋ฅด๋ฉฐ ์•„์ง ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ƒ๊ฐ์„ ๊ณต์œ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค @tommikaikkonen. ๋‚˜๋Š” ์—ฌ๊ธฐ์— "๋Œ€๋‹ต"์ด ๋ฌด์—‡์ธ์ง€ ์•„์ง ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹น์‹ ์˜ ์š”์•ฝ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. "๋ชจ๋“  ๋…ผ๋ฆฌ๋ฅผ ์ž‘์—… ์ƒ์„ฑ์ž์— ๋„ฃ๊ธฐ..." ์„น์…˜์— ์ž‘์€ ๋ฉ”๋ชจ ํ•˜๋‚˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์„น์…˜์—์„œ๋Š” ์ผ๋ถ€ ๊ฒฝ์šฐ์— ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ธฐ ์œ„ํ•ด (๊ณต์œ ) ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ํฅ๋ฏธ๋กœ์šด ์Šค๋ ˆ๋“œ์ž…๋‹ˆ๋‹ค! redux ์•ฑ์—์„œ ์ฝ”๋“œ๋ฅผ ๋ฐฐ์น˜ํ•  ์œ„์น˜๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๊ฒƒ์€ ์šฐ๋ฆฌ ๋ชจ๋‘๊ฐ€ ์ง๋ฉดํ•œ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ผ์–ด๋‚œ ์ผ์„ ๊ธฐ๋กํ•˜๋Š” CQRS ์•„์ด๋””์–ด๋ฅผ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ CQRS์—์„œ ์•„์ด๋””์–ด์˜ ๋ถˆ์ผ์น˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. AFAIK ๋ชจ๋ฒ” ์‚ฌ๋ก€๋Š” ๋ณด๊ธฐ์—์„œ ์ง์ ‘ ์†Œ๋น„ํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…/์ด๋ฒคํŠธ์—์„œ ๋น„์ •๊ทœํ™”๋œ ์ƒํƒœ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ redux์—์„œ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ์™„์ „ํžˆ ์ •๊ทœํ™”๋œ ์ƒํƒœ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์„ ํƒ๊ธฐ๋ฅผ ํ†ตํ•ด ๋ทฐ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋ทฐ์—์„œ ์ง์ ‘ ์†Œ๋น„ํ•  ์ˆ˜ ์žˆ๋Š” ๋น„์ •๊ทœํ™” ์ƒํƒœ๋ฅผ ๋นŒ๋“œํ•˜๋ฉด ๋ฆฌ๋“€์„œ๊ฐ€ ๋‹ค๋ฅธ ๋ฆฌ๋“€์„œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋ ค๋Š” ๋ฌธ์ œ๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค(๊ฐ ๋ฆฌ๋“€์„œ๊ฐ€ ์ •๊ทœํ™”์— ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๋˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ). ๊ทธ๋Ÿฌ๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ํ† ๋ก ์˜ ํ•ต์‹ฌ์ด ์•„๋‹๊นŒ์š”?

์ˆ˜๋…„๊ฐ„์˜ ๊ฐ์ฒด ์ง€ํ–ฅ ๊ฐœ๋ฐœ์—์„œ ๋น„๋กฏ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Redux๋Š” ํฌ๊ฒŒ ํ›„ํ‡ดํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๋ฒคํŠธ(์•ก์…˜ ์ƒ์„ฑ์ž)์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์บก์Šํ™”ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋‹ฌ๋ผ๊ณ  ์• ์›ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์—ฌ์ „ํžˆ ์˜๋ฏธ ์žˆ๋Š” ํƒ€ํ˜‘์„ ์ฐพ์œผ๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์ง€๋งŒ ์•„์ง ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋„ ๊ฐ™์€ ๊ธฐ๋ถ„์ด ๋“ค๊นŒ์š”?

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

@jayesbe ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฐ๊ฒฝ์—์„œ https://www.leaseweb.com/labs/2015/08/object-oriented-programming-is-exceptionally-bad/.

๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์—์„œ ์ž‘์—…์„ ๋ถ„๋ฆฌํ•˜๋ฉด ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์˜ ์ ์šฉ ํ…Œ์ŠคํŠธ๊ฐ€ ๋” ๊ฐ„๋‹จํ•ด์ง‘๋‹ˆ๋‹ค. ๋ณ€ํ™˜์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ์— ๋œ ์˜์กดํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๊ณ  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ์ฒด๋‚˜ ํด๋ž˜์Šค๋ฅผ ํฌ๊ธฐํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด React ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๊ฐ์ฒด๋กœ ๊ตฌํ˜„๋˜๊ณ  ์ด์ œ๋Š” ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ React ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋‹จ์ˆœํžˆ ์ œ๊ณต๋œ ๋ฐ์ดํ„ฐ์˜ ํˆฌ์˜์„ ์ƒ์„ฑํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๋Š” ์ˆœ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด Redux๊ฐ€ ๋“ฑ์žฅํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์ž‘์—…๊ณผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ์˜ ํ•ด๋‹น ๋ณ€ํ™˜์„ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

@johnsoftek ๋งํฌ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ง€๋‚œ 10๋…„ ๋™์•ˆ์˜ ๋‚ด ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด. ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ๋™์˜ํ•˜์ง€ ์•Š์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ OO์™€ non-OO ์‚ฌ์ด์˜ ๋…ผ์Ÿ์— ๋“ค์–ด๊ฐˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๊ฐ€์ง„ ๋ฌธ์ œ๋Š” ์ฝ”๋“œ์™€ ์ถ”์ƒํ™”๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด ๋ชฉํ‘œ๋Š” ๊ตฌ์„ฑ ๊ฐ’๋งŒ ์‚ฌ์šฉํ•˜์—ฌ 100๊ฐœ์˜ ์•ฑ์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ์ผ ์•ฑ/๋‹จ์ผ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๋งŽ์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ํ™”์ดํŠธ ๋ ˆ์ด๋ธ” ์†Œํ”„ํŠธ์›จ์–ด ์†”๋ฃจ์…˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ๊ฐ์€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ž์ฒด์ ์œผ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

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

๋‚ด ์„œ๋ฒ„ ์ธก ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ๊ณผ ์ธํ„ฐํŽ˜์ด์Šคํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ, API ๋ž˜ํผ ๋“ฑ์ด ํฌํ•จ๋œ ๋‹จ์ผ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ํด๋ž˜์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ..

export default Application {
    constructor(config) {
        this.config = config;
    } 

    config() {
        return this.config;
    }

    login(data, cb) {
        const url = [
            this.config.url,
            '?client=' + this.config.client,
            '&username=' + data.username,
            ....
        ].join('');

        fetch(url).then((responseText) => {
            cb(responseText);
        })
    }

    ... more business logic 
}

์ด ๊ฐ์ฒด์˜ ๋‹จ์ผ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์ปจํ…์ŠคํŠธ์— ๋ฐฐ์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค. Redux ๊ณต๊ธ‰์ž๋ฅผ ํ™•์žฅํ•˜์—ฌ

import { Provider } from 'react-redux';

export default class MyProvider extends Provider {
    getChildContext() {
        return Object.assign({}, Provider.prototype.getChildContext.call(this), {
            app: this.props.app
        });
    }

    render() {
        return this.props.children;
    }
}
MyProvider.childContextTypes = {
    store: React.PropTypes.object,
    app: React.PropTypes.object
}

๊ทธ๋Ÿฐ ๋‹ค์Œ์ด ๊ณต๊ธ‰์ž๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

import Application from './application';
import config from './config';

class MyApp extends Component {
  render() {
    return (
      <MyProvider store={store} app={new Application(config)}>
        <Router />
      </MyProvider>
    );
  }
}

AppRegistry.registerComponent('MyApp', () => MyApp);

๋งˆ์นจ๋‚ด ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ๋‚ด ์•ฑ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

class Login extends React.Component {
    render() {
        const { app } = this.context;
        const { state, actions } = this.props;
        return (
              <View style={style.transparentContainer}>
                <Form ref="form" type={User} options={options} />
                <Button 
                  onPress={() => {
                    value = this.refs.form.getValue();
                    if (value) {
                      app.login(value, actions.login);
                    }
                  }}
                >
                  Login
                </Button>
              </View>
        );
    }
};
Login.contextTypes = {
  app: React.PropTypes.object,
};

function mapStateToProps(state) {
  return {
      state: state.default.auth
  };
};

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(authActions, dispatch),
    dispatch
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Login);

๋”ฐ๋ผ์„œ Action Creator๋Š” ๋‚ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋Œ€ํ•œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

                      app.login(value, actions.login);

์ด ์†”๋ฃจ์…˜์€ ์ธ์ฆ์œผ๋กœ๋งŒ ์‹œ์ž‘ํ–ˆ์ง€๋งŒ ํ˜„์žฌ ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์Šคํ† ์–ด๋ฅผ ๋‚ด Application ์ธ์Šคํ„ด์Šค์— ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์Šคํ† ์–ด๊ฐ€ ์šฐ์—ฐํ•œ ๋Œ์—ฐ๋ณ€์ด๋ฅผ ๊ฒช๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒ์ ์— ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•˜๋ฉด ๋” ์ƒ๊ฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ํฅ๋ฏธ๋กœ์šด ์ ˆ์ถฉ์•ˆ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์„ ์ƒ๊ฐํ•ด ๋ƒˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ถฉ๋ถ„ํžˆ ์ž˜ ์ฒ˜๋ฆฌํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ตฐ์ค‘ ํ‘œ์ค€์„ ์ถฉ์กฑํ•˜์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ "๊ธฐ๋Šฅ์ ์ธ ๊ตฐ์ค‘"์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค :wink: . Redux์—์„œ ๊ธฐ๋Šฅ์  ์†”๋ฃจ์…˜์„ ์„ ํƒํ•˜๋Š” ์ด์œ ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋…๋‹จ์ ์ด๊ธฐ ๋•Œ๋ฌธ์ด ์•„๋‹ˆ๋ผ ์‚ฌ๋žŒ๋“ค์ด ์ˆ˜์—… ๋•Œ๋ฌธ์— ์ข…์ข… ๋งŒ๋“œ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌ๋“€์„œ๋ฅผ ์•ก์…˜ ์ƒ์„ฑ์ž์™€ ๋ถ„๋ฆฌํ•˜๋ฉด ๋ฒ„๊ทธ๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ์žฌ์ƒํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ๊ฐœ์ฒด์ธ ์ž‘์—…์€ ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ก ๋ฐ ์žฌ์ƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒํƒœ๊ฐ€ MyAppState ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹Œ ์ผ๋ฐ˜ ๊ฐ์ฒด์ด๋ฏ€๋กœ ์„œ๋ฒ„์—์„œ ์ง๋ ฌํ™”ํ•˜๊ณ  ์„œ๋ฒ„ ๋ Œ๋”๋ง์„ ์œ„ํ•ด ํด๋ผ์ด์–ธํŠธ์—์„œ ์—ญ์ง๋ ฌํ™”ํ•˜๊ฑฐ๋‚˜ localStorage ์— ์ผ๋ถ€๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ๋ฅผ ํ•จ์ˆ˜๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์‹œ๊ฐ„ ์—ฌํ–‰๊ณผ ํ•ซ ๋ฆฌ๋กœ๋”ฉ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ณ , ์…€๋ ‰ํ„ฐ๋ฅผ ํ•จ์ˆ˜๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ชจ๋“  ์ด์ ์€ ์šฐ๋ฆฌ๊ฐ€ "๊ธฐ๋Šฅ์  ๊ตฐ์ค‘"์ด ๋˜๋Š” ๊ฒƒ๊ณผ ์•„๋ฌด ๊ด€๋ จ์ด ์—†์œผ๋ฉฐ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ƒ์„ฑ๋œ ํŠน์ • ์ž‘์—…์„ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฐ์ฒด์˜ ๋‹จ์ผ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์ปจํ…์ŠคํŠธ์— ๋ฐฐ์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค. Redux ๊ณต๊ธ‰์ž๋ฅผ ํ™•์žฅํ•˜์—ฌ

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

๊ทธ๋Ÿฌ๋‚˜ Provider ๋ฅผ ํ™•์žฅํ•˜๋Š” ๊ฒƒ์€ ๊นจ์ง€๊ธฐ ์‰ฌ์šฐ๋ฏ€๋กœ ํ”ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. React๋Š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๋ณ‘ํ•ฉํ•˜๋ฏ€๋กœ ๋Œ€์‹  ๊ฐ์‹ธ๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

import { Component } from 'react';
import { Provider } from 'react-redux';

export default class MyProvider extends Component {
    getChildContext() {
        return {
            app: this.props.app
        };
    }

    render() {
        return (
            <Provider store={this.props.store}>
                {this.props.children}
            </Provider>
        );
    }
}
MyProvider.childContextTypes = {
    app: React.PropTypes.object
}
MyProvider.propTypes = {
    app: React.PropTypes.object,
    store: React.PropTypes.object
}

์‹ค์ œ๋กœ ๋‚ด ๋ณด๊ธฐ์—๋Š” ๋” ์ฝ๊ธฐ ์‰ฝ๊ณ  ๋œ ๊นจ์ง€๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ „๋ฐ˜์ ์œผ๋กœ ๊ท€ํ•˜์˜ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์™„์ „ํžˆ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ createActions(config) ์™€ ๊ฐ™์€ ๊ฒƒ๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์•ก์…˜ ์ƒ์„ฑ์ž๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๊ถŒ์žฅํ•˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์ „ํ˜€ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

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

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๊ตฌ์„ฑ์ด ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ(๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ž˜์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์•„๋งˆ๋„ ๊ธฐ๋Šฅ์ ์ธ ์ฟจ ์—์ด๋“œ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ๋งˆ์‹  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค) ๋‹ค์Œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const appSelector = createSelector(
   (state) => state.config,
   (config) => new Application(config)
)

๊ทธ๋Ÿฐ ๋‹ค์Œ mapStateToProps์—์„œ:

function mapStateToProps(state) {
  return {
      app: appSelector(state)
  };
};

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ฑ„ํƒํ•œ ๊ณต๊ธ‰์ž ๊ธฐ์ˆ ์ด ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ƒํƒœ์—์„œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๊ฐœ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. reselect ๋•๋ถ„์— Application ๊ฐœ์ฒด๋Š” ๊ตฌ์„ฑ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ๊ตฌ์„ฑ๋˜๋ฉฐ, ์ด๋Š” ์•„๋งˆ๋„ ํ•œ ๋ฒˆ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ ๋ฐฉ์‹์ด ์žฅ์ ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ๊ฐœ์ฒด๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๊ณ  ํ•ด๋‹น ๊ฐœ์ฒด๊ฐ€ ์ƒํƒœ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์— ์ข…์†๋˜๋„๋ก ํ•˜๋Š” ์•„์ด๋””์–ด๋ฅผ ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ตฌ์„ฑ๊ณผ ์ƒํƒœ์˜ ์ผ๋ถ€์— ๋ชจ๋‘ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ๊ทธ์ธ/๋กœ๊ทธ์•„์›ƒ/etc ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” UserControl ํด๋ž˜์Šค๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ „๋ฐ˜์ ์œผ๋กœ ๊ท€ํ•˜์˜ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์™„์ „ํžˆ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

:+1: ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. MyProvider์˜ ๊ฐœ์„  ์‚ฌํ•ญ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ฅด๋„๋ก ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Redux๋ฅผ ์ฒ˜์Œ ๋ฐฐ์šธ ๋•Œ ๊ฒช์—ˆ๋˜ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋Š” "Action Creators"์˜ ์˜๋ฏธ๋ก ์  ๊ฐœ๋…์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ์™€ ๋™์ผ์‹œํ•  ๋•Œ๊นŒ์ง€๋Š” ์˜๋ฏธ๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์—๊ฒŒ ๊ทธ๊ฒƒ์€ .. ์ด๊ฒƒ๋“ค์ด ํŒŒ๊ฒฌ๋˜๋Š” ์ด๋ฒคํŠธ์™€ ๊ฐ™์€ ์ผ์ข…์˜ ๊นจ๋‹ฌ์Œ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

@winstonewert ๋Š” react-native์—์„œ createSelector๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๋ฏฟ์ง€ ์•Š๋Š”๋‹ค. ๋™์‹œ์— ์ผ๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ์˜ mapStateToProps์— ์—ฐ๊ฒฐํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๋‚ด ๋ชฉํ‘œ๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ๋ชจ๋“  ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜๊ณ  ํ•ด๋‹น ๊ฐœ์ฒด๊ฐ€ ์ „์—ญ์ ์œผ๋กœ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋‹จ์ผ ๊ฐœ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ œ์•ˆ์ด ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€ ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์•„์ด๋””์–ด๊ฐ€ ์ข‹์ง€๋งŒ.. ๊ธฐ์ˆ ์ ์œผ๋กœ Application ์ธ์Šคํ„ด์Šค๋ฅผ ํ†ตํ•ด ํ•„์š”์— ๋”ฐ๋ผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Redux๋ฅผ ์ฒ˜์Œ ๋ฐฐ์šธ ๋•Œ ๊ฒช์—ˆ๋˜ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋Š” "Action Creators"์˜ ์˜๋ฏธ๋ก ์  ๊ฐœ๋…์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ์™€ ๋™์ผ์‹œํ•  ๋•Œ๊นŒ์ง€๋Š” ์˜๋ฏธ๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์—๊ฒŒ ๊ทธ๊ฒƒ์€ .. ์ด๊ฒƒ๋“ค์ด ํŒŒ๊ฒฌ๋˜๋Š” ์ด๋ฒคํŠธ์™€ ๊ฐ™์€ ์ผ์ข…์˜ ๊นจ๋‹ฌ์Œ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

Redux์—๋Š” Action Creators์˜ ์˜๋ฏธ๋ก ์  ๊ฐœ๋…์ด ์ „ํ˜€ ์—†๋‹ค๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. Actions์˜ ์˜๋ฏธ๋ก ์  ๊ฐœ๋…์ด ์žˆ์Šต๋‹ˆ๋‹ค(์ผ์–ด๋‚œ ์ผ์„ ์„ค๋ช…ํ•˜๊ณ  ์ด๋ฒคํŠธ์™€ ๋Œ€๋žต ๋™์ผํ•˜์ง€๋งŒ ์™„์ „ํžˆ ๊ฐ™์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด #351์˜ ํ† ๋ก  ์ฐธ์กฐ). ์•ก์…˜ ์ƒ์„ฑ์ž๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํŒจํ„ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ฐ™์€ ์œ ํ˜•์˜ ์ž‘์—…์ด ์ผ๊ด€๋œ ๊ตฌ์กฐ๋ฅผ ๊ฐ–๊ณ  ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ๋™์ผํ•œ ๋ถ€์ž‘์šฉ์ด ์žˆ๋Š”์ง€ ๋“ฑ์„ ํ™•์ธํ•˜๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์—…์„ ์œ„ํ•œ ํŒฉํ† ๋ฆฌ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Redux์˜ ๊ด€์ ์—์„œ ๋ณผ ๋•Œ ์ž‘์—… ์ƒ์„ฑ์ž๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Redux ํ–‰๋™๋งŒ ๋ณด์ž…๋‹ˆ๋‹ค.

react-native์—์„œ createSelector๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ข…์†์„ฑ์ด ์—†๋Š” ์ผ๋ฐ˜ JavaScript์ด๋ฉฐ ์›น, ๊ธฐ๋ณธ, ์„œ๋ฒ„ ๋“ฑ์—์„œ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋Š” Reselect ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„. ์•Œ์•˜์–ด. ์ƒํ™ฉ์ด ํ›จ์”ฌ ๋” ๋ช…ํ™•ํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ฑด๋ฐฐ.

mapStateToProps ๋ฐ mapDispatchToProps์— ๊ฐœ์ฒด๋ฅผ ์ค‘์ฒฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

์ตœ๊ทผ Redux๊ฐ€ mapStateToProps์™€ mapDispatchToProps๋ฅผ ๋ณ‘ํ•ฉํ•  ๋•Œ ์ค‘์ฒฉ๋œ ๊ฐ์ฒด๊ฐ€ ์†์‹ค๋˜๋Š” ๋ฌธ์ œ์— ๋ถ€๋”ช์ณค์Šต๋‹ˆ๋‹ค(reactjs/react-redux#324 ์ฐธ์กฐ). @gaearon ์€ ์ค‘์ฒฉ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•˜์ง€๋งŒ

์ด์™€ ๊ฐ™์ด ๊ฐ์ฒด๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ํ• ๋‹น์ด ๋ฐœ์ƒํ•˜๊ณ  ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ๋” ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ props๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋” ์ด์ƒ ๊ฒฐ๊ณผ props์˜ ์–•์€ ๋™๋“ฑ์„ฑ์— ์˜์กดํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฌธ์„œ์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ์—†๋Š” ๋‹จ์ˆœํ•œ ์ ‘๊ทผ ๋ฐฉ์‹๋ณด๋‹ค ๋” ๋งŽ์€ ๋ Œ๋”๋ง์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@bvaughn์ด ๋งํ–ˆ๋‹ค

๊ฐ์†๊ธฐ๋Š” ์–ด๋ฆฌ ์„๊ณ  ๋‹จ์ˆœํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

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

ํ•œ๋™์•ˆ ์ €๋ฅผ ํ˜ผ๋ž€์Šค๋Ÿฝ๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค...

์™œ ์—ฌ์ „ํžˆ ๊ฐ์†๊ธฐ ํŒŒ์ผ๊ณผ ๊ธฐ๋Šฅ์„ ์ˆ˜๋™์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

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

์ด๊ฒƒ์€ ๋ฆฌ๋“€์„œ์— ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋กœ์ง์˜ ๋Œ€๋ถ€๋ถ„์„ ์œ ์ง€ํ•˜๋Š” ์ด์ ์ž…๋‹ˆ๋‹ค.

@dtinth "์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋…ผ๋ฆฌ"๋ผ๊ณ  ๋งํ•˜๋ฉด "๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ"๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

๋‚˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋…ผ๋ฆฌ๋ฅผ ์•ก์…˜ ์ƒ์„ฑ์ž์—๊ฒŒ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ธ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ฆฌ๋“€์„œ๊ฐ€ ADD_X ์™€ ๊ฐ™์€ ์ž‘์—…์„ ํ—ˆ์šฉํ•˜๋Š” ์‚ฌ์†Œํ•œ ๊ธฐ๋Šฅ์ด๋ผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ข‹์Šต๋‹ˆ๋‹ค! ๊ทธ๋Ÿฌ๋‚˜ ๋ชจ๋“  ์˜ค๋ฅ˜๊ฐ€ ์ž‘์—… ์ž‘์„ฑ์ž์—๊ฒŒ ํ‘ธ์‹œ๋˜๊ณ  @dtinth๊ฐ€ ์•”์‹œํ•˜๋Š” ํ›Œ๋ฅญํ•œ ๋””๋ฒ„๊น… ๊ฒฝํ—˜์„

๊ทธ๋Ÿฌ๋‚˜ @tommikaikkonen์ด ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ๋ณต์žกํ•œ ๋ฆฌ๋“€์„œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๋ฆฌ ๊ฐ„๋‹จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚ด ์ง๊ฐ์— ๋”ฐ๋ฅด๋ฉด Redux์˜ ์ด์ ์„ ์–ป๊ณ  ์‹ถ๋‹ค๋ฉด ํ‘ธ์‹œํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ถ€์ž‘์šฉ์„ ๊ฐ€์žฅ์ž๋ฆฌ๋กœ ๋ฐ€์–ด ๋„ฃ๋Š” ๋Œ€์‹  ๊ฐ€์žฅ ์‚ฌ์†Œํ•œ ์ž‘์—…๋งŒ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์ˆœ์ˆ˜ํ•œ ๊ธฐ๋Šฅ์„ ๋ฐ€์–ด๋ถ™์ด๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ๊ตญ๊ฐ€๊ฐ€ ๋ชฐ๊ณ  ์žˆ๋Š” ์ง€์˜ฅ์—์„œ ์•ฑ์˜ :)

@sompylasar "๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง"๊ณผ "์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋กœ์ง"์€ ๊ฐ™์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚ด ์ž์‹ ์˜ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์œผ๋กœ ์ฐจ์ž„ํ•˜๊ธฐ ์œ„ํ•ด .. ๋‚ด ์ž‘์—…์€ ์ฃผ๋กœ ์ž‘์—…์— ๋Œ€ํ•œ ์ž…๋ ฅ์— ๋Œ€ํ•œ ์กฐํšŒ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋ชจ๋“  "๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ"๋ฅผ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์ปจํ…์ŠคํŠธ๋กœ ์ด๋™ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ์ž‘์—…์€ ์ˆœ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด .. ์ด๊ฒƒ์€ ๋‚ด ์ผ๋ฐ˜์ ์ธ ๊ฐ์†๊ธฐ

export default function reducer(state = initialState, action = {}) {
  switch (action.type) {
    case 'FOO_REQUEST':
    case 'FOO_RESPONSE':
    case 'FOO_ERROR':
    case 'FOO_RESET':
      return {
        ...state,
        ...action.data
      }; 
    default:
      return state;
  }
}

๋‚˜์˜ ์ „ํ˜•์ ์ธ ํ–‰๋™:

export function fooRequest( res ) {
  return {
    type: 'FOO_REQUEST',
    data: {
        isFooing: true,
        toFoo: res.saidToFoo
    }
  };
}

export function fooResponse( res ) {
  return {
    type: 'FOO_RESPONSE',
    data: {
        isFooing: false,
        isFooed: true,
        fooData: res.data
    }
  };
}

export function fooError( res ) {
  return {
    type: 'FOO_ERROR',
    data: {
        isFooing: false,
        fooData: null,
        isFooed: false,
        fooError: res.error
    }
  };
}

export function fooReset( res ) {
  return {
    type: 'FOO_RESET',
    data: {
        isFooing: false,
        fooData: null,
        isFooed: false,
        fooError: null,
        toFoo: true
    }
  };
}

๋‚ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋œ ๊ฐœ์ฒด์— ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

export default class FooBar
{
    constructor(store)
    {
        this.actions = bindActionCreators({
            ...fooActions
        }, store.dispatch);
    }

    async getFooData()
    {
        this.actions.fooRequest({
            saidToFoo: true
        });

        fetch(url)
        .then((response) => {
            this.actions.fooResponse(response);
        })
    }
}

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

๋‚˜๋Š” ๋” ์ด์ƒ ์–ด๋””์—์„œ๋‚˜ mapDispatchToProps()๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Redux์˜ ๊ฒฝ์šฐ ์ด์ œ ์—ฐ๊ฒฐ๋œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ mapStateToProps๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ .. ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด ๋‚ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๊ฐœ์ฒด๋ฅผ ํ†ตํ•ด ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class SomeComponent extends React.Component {
    componentWillReceiveProps(nextProps) {
        if (nextProps.someFoo != this.props.someFoo) {
            const { app } = this.context;
            app.actions.getFooData();
        }
    }
}
SomeComponent.contextTypes = {
    app: React.PropTypes.object
};

์œ„์˜ ๊ตฌ์„ฑ ์š”์†Œ๋Š” redux ์—ฐ๊ฒฐ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ์ž‘์—…์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด์—์„œ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์ƒํƒœ ๋ณ€๊ฒฝ์ด ์ „ํŒŒ๋˜๋„๋ก ์—ฐ๊ฒฐ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ํ•ต์‹ฌ "๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง"์„ ๊ตฌ์„ฑํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋‚ด ์ƒํƒœ๊ฐ€ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„์—์„œ ์‹ค์ œ๋กœ ์œ ์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์— .. ์ด๊ฒƒ์€ ๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€์— ์ •๋ง ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

"๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ"๋ฅผ ์ €์žฅํ•˜๋Š” ์œ„์น˜๋Š” ์‹ค์ œ๋กœ ๊ท€ํ•˜์™€ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋งž๋Š” ๋ฐฉ๋ฒ•์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค.

@jayesbe ๋‹ค์Œ ๋ถ€๋ถ„์€ ๋ฆฌ๋“€์„œ์— "๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง"์ด ์—†๊ณ , ๊ฒŒ๋‹ค๊ฐ€ ์ƒํƒœ ๊ตฌ์กฐ๊ฐ€ ๋ฆฌ๋“€์„œ๋ฅผ ํ†ตํ•ด ์Šคํ† ์–ด๋กœ ์ „์†ก๋˜๋Š” ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์•ก์…˜

    case 'FOO_REQUEST':
    case 'FOO_RESPONSE':
    case 'FOO_ERROR':
    case 'FOO_RESET':
      return {
        ...state,
        ...action.data
      }; 
export function fooRequest( res ) {
  return {
    type: 'FOO_REQUEST',
    data: {
        isFooing: true,
        toFoo: res.saidToFoo
    }
  };
}

@jayesbe ๋‚ด ์ž‘์—…๊ณผ ๊ฐ์†๊ธฐ๋Š” ๊ท€ํ•˜์™€ ๋งค์šฐ ์œ ์‚ฌํ•˜๋ฉฐ ์ผ๋ถ€ ์ž‘์—…์€ ์ผ๋ฐ˜ ๋„คํŠธ์›Œํฌ ์‘๋‹ต ๊ฐœ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ์ˆ˜์‹ ํ•˜๋ฉฐ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์—…์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ๋งค์šฐ ๊ฐ„๋‹จํ•œ ๊ฐœ์ฒด๋ฅผ ๋ฐ˜ํ™˜๋œ ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ ๋‹ค์Œ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋…ผ๋ฆฌ๋ฅผ ์บก์Šํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜ธ์ถœ dispatch()๋ฅผ ํ†ตํ•œ ๊ฐ์†๊ธฐ. ๋‹น์‹ ์ด ํ•œ ์ผ์ฒ˜๋Ÿผ. ๋ฌธ์ œ๋Š” ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑ๋œ ์•ก์…˜์ด ๊ฑฐ์˜ ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์œผ๋ฉฐ ๋ฆฌ๋“€์„œ์˜ ์ฑ…์ž„์ด ๋งค์šฐ ๊ฐ€๋ณ๋‹ค๋ฉด ๋ฆฌ๋“€์„œ๊ฐ€ ๋‹จ์ˆœํžˆ ์•ก์…˜ ๊ฐ์ฒด๋ฅผ ํ™•์‚ฐํ•˜๋Š” ๊ฒฝ์šฐ ์ˆ˜๋™์œผ๋กœ ์ €์žฅํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? Redux๊ฐ€ ์šฐ๋ฆฌ๋ฅผ ์œ„ํ•ด ์ž๋™์œผ๋กœ ํˆฌ์—ฌํ•˜๋Š” ๊ฒƒ์€ ์ „ํ˜€ ์–ด๋ ค์šด ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค.

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

๊ทน๋‹จ์ ์ธ ๊ฒฝ์šฐ ๋‹ค์Œ์„ ํ™•์ธํ•˜์„ธ์š”.
"๋™๊ธฐ์‹ RTS ์—”์ง„๊ณผ ๋น„๋™๊ธฐ์‹ ์ด์•ผ๊ธฐ" @ForrestTheWoods
https://blog.forrestthewoods.com/synchronous-rts-engines-and-a-tale-of-desyncs-9d8c3e48b2be

2016๋…„ 4์›” 5์ผ ์˜คํ›„ 5์‹œ 54๋ถ„์— "John Babak" [email protected]์ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋…ผ๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๋Š” ์ด์ ์ž…๋‹ˆ๋‹ค.
๊ฐ์†๊ธฐ.

@dtinth https://github.com/dtinth ๋ช…ํ™•ํžˆ ํ•˜์ž๋ฉด
"์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋…ผ๋ฆฌ"๋Š” "๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ"๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/reactjs/redux/issues/1171#issuecomment -205754910

@LumiaSaki ์ž‘์„ฑ์ž์—๊ฒŒ ๋ณต์žกํ•œ ๋กœ์ง์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ฆฌ๋“€์„œ๋ฅผ ๋‹จ์ˆœํ•˜๊ฒŒ ์œ ์ง€

๊ทธ ๋•Œ๋ฌธ์— Redux๋Š” ์ž‘์—…์—์„œ ์ €์žฅ์†Œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ „์†กํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Redux๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๋ฐฉ์‹์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. Redux๋Š” ์˜๋„ํ•œ ๊ฒƒ๊ณผ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฌผ๋ก , ๋‹น์‹ ์€ ๋‹น์‹ ์—๊ฒŒ ๋งž๋Š” ์ผ์„ ํ•˜๋Š” ๊ฒƒ์ด ์ ˆ๋Œ€์ ์œผ๋กœ ์ž์œ ๋กญ์ง€๋งŒ Redux๊ฐ€ ๊ทธ๊ฒƒ์„ ์œ„ํ•ด ๋ฐ”๋€” ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ทธ ๊ฐ€์น˜๋ฅผ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์†๊ธฐ๋ฅผ ์ƒ์‚ฐํ•ฉ๋‹ˆ๋‹ค.

let {reducer, actions} = defineActions({
   fooRequest: (state, res) => ({...state, isFooing: true, toFoo: res.saidToFoo}),
   fooResponse: (state, res) => ({...state, isFooing: false, isFooed: true, fooData: res.data}),
   fooError: (state, res) => ({...state, isFooing: false, fooData: null, isFooed: false, fooError: res.error})
   fooReset: (state, res) => ({...state, isFooing: false, fooData: null, isFooed: false, fooError: null, toFoo: false})
})

defineActions๋Š” ๋ฆฌ๋“€์„œ์™€ ์•ก์…˜ ์ƒ์„ฑ์ž๋ฅผ ๋ชจ๋‘ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์†Œํ•œ ์ž‘์—… ์ƒ์„ฑ๊ธฐ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ๋งŽ์€ ์‹œ๊ฐ„์„ ํ• ์• ํ•˜์ง€ ์•Š๊ณ ๋„ ์—…๋ฐ์ดํŠธ ๋…ผ๋ฆฌ๋ฅผ ๊ฐ์†๊ธฐ ๋‚ด๋ถ€์— ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์‰ฝ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ก์…˜ ์ƒ์„ฑ์ž์—๊ฒŒ ๋…ผ๋ฆฌ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ฃผ์žฅํ•œ๋‹ค๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์ž๋™ํ™”ํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์†๊ธฐ๋Š” ๊ธฐ๋Šฅ์ด๋ฉฐ ์›ํ•˜๋Š” ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ์†๊ธฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function reducer(state, action) {
    if (action.data) {
        return {...state, ...action.data}
   } else {
        return state;
   }
}

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

  • ๊ฒฐ์ •์ ์ด์ง€ ์•Š์€ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์™ธ๋ถ€ ์„œ๋น„์Šค, ๋น„๋™๊ธฐ ์ฝ”๋“œ, ์‹œ์Šคํ…œ ์‹œ๊ฐ„ ๋˜๋Š” ๋‚œ์ˆ˜ ์ƒ์„ฑ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์ƒ๊ฐ์— ์ด ๋ถ€๋ถ„์€ I/O ๊ธฐ๋Šฅ(๋˜๋Š” ์ž‘์—… ์ƒ์„ฑ์ž)์ด ๊ฐ€์žฅ ์ž˜ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” ๊ทธ๋“ค์„ ๋น„์ฆˆ๋‹ˆ์Šค ํ”„๋กœ์„ธ์Šค๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์‹คํ–‰ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ์ˆ˜ ์žˆ๊ณ  ์•ฑ์„ ์ปดํŒŒ์ผํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” IDE์™€ ์œ ์‚ฌํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค. (์—ฌ๊ธฐ์„œ๋Š” ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋Œ€์‹  redux-thunk ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

js export async function runApp (store) { try { store.dispatch({ type: 'startCompiling' }) const compiledApp = await compile(store) store.dispatch({ type: 'startRunning', app: compiledApp }) } catch (e) { store.dispatch({ type: 'errorCompiling', error: e }) } }

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

``` js
'updeep'์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ

๋‚ด๋ณด๋‚ด๊ธฐ const ๊ฐ์†๊ธฐ = createReducer({
// [์•ก์…˜ ์ด๋ฆ„]: ์•ก์…˜ => currentState => nextState
์‹œ์ž‘ ์ปดํŒŒ์ผ: () => u({ ์ปดํŒŒ์ผ: ์ฐธ }),
errorCompiling: ({ ์˜ค๋ฅ˜ }) => u({ ์ปดํŒŒ์ผ: false, compileError: ์˜ค๋ฅ˜ }),
์‹œ์ž‘ ์‹คํ–‰: ({ ์•ฑ }) => u({
์‹คํ–‰ ์ค‘: () => ์•ฑ,
์ปดํŒŒ์ผ: ๊ฑฐ์ง“
}),
stopRunning: () => u({ ์‹คํ–‰ ์ค‘: false }),
ํ๊ธฐCompileError: () => u({ compileError: null }),
// ...
})
```

๋‚˜๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์ด ๊ฒฐ์ •์ ์ธ ์˜์—ญ์— ๋„ฃ์œผ๋ ค๊ณ  ๋…ธ๋ ฅํ•˜์ง€๋งŒ, ๋ฆฌ๋“€์„œ์˜ ์œ ์ผํ•œ ์ฑ…์ž„์€ ๋“ค์–ด์˜ค๋Š” ์ž‘์—…์ด ์ฃผ์–ด์ง€๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด๋ผ๋Š” ์ ์„ ์—ผ๋‘์— ๋‘ก๋‹ˆ๋‹ค. ๋” ์ด์ƒ ์•„๋ฌด๊ฒƒ๋„ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ ์™ธ์—๋Š” Redux๊ฐ€ ์ƒํƒœ ์ปจํ…Œ์ด๋„ˆ์ผ ๋ฟ์ด๋ฏ€๋กœ Redux ์™ธ๋ถ€์—์„œ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

@dtinth ์šฐ์ˆ˜ํ•จ,์—์„œ ์•ž์˜ ์˜ˆ ๋•Œ๋ฌธ์— https://github.com/reactjs/redux/issues/1171#issuecomment -205782740์€ ๋‹น์‹ ์ด ์“ด ๊ฒƒ๊ณผ ์™„์ „ํžˆ ๋‹ค๋ฅธ ๋ชจ์Šต https://github.com/reactjs/redux/ Issues/1171#issuecomment -205888533 -- ์•ก์…˜ ์ƒ์„ฑ์ž์—์„œ ์ƒํƒœ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๋ฆฌ๋“€์„œ์— ์ „๋‹ฌํ•˜์—ฌ ์—…๋ฐ์ดํŠธ๋ฅผ ํผ๋œจ๋ฆด ์ˆ˜ ์žˆ๋„๋ก ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. https://github.com/reactjs/redux/issues/1171#issuecomment-205865840 ).

@winstonewert

Redux์—์„œ ๊ถŒ์žฅํ•˜๋Š” ํŒจํ„ด์€ ๋ฐ˜๋Œ€์ž…๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ์—์„œ ๋ณต์žกํ•œ ๋…ผ๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์ž‘์—… ์ž‘์„ฑ์ž๋ฅผ ๋‹จ์ˆœํ•˜๊ฒŒ ์œ ์ง€ํ•˜์„ธ์š”.

์–ด๋–ป๊ฒŒ ruducers์— ๋ณต์žกํ•œ ๋…ผ๋ฆฌ๋ฅผ ๋„ฃ๊ณ  ์—ฌ์ „ํžˆ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์˜ˆ๋ฅผ ๋“ค์–ด fetch()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ฒฝ์šฐ.. ์–ด๋–ค ์‹์œผ๋กœ๋“  ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์•„์ง "๋ณต์žกํ•œ ๋…ผ๋ฆฌ"๋ฅผ ๊ฐ€์ง„ ๊ฐ์†๊ธฐ์˜ ์˜ˆ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

@jayesbe : ์–ด... "๋ณต์žกํ•œ"๊ณผ "์ˆœ์ˆ˜ํ•œ"์€ ์ง๊ตํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์†๊ธฐ ๋‚ด๋ถ€์— _์ •๋ง__ ๋ณต์žกํ•œ ์กฐ๊ฑด๋ถ€ ๋…ผ๋ฆฌ๋‚˜ ์กฐ์ž‘์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž…๋ ฅ์˜ ๊ธฐ๋Šฅ์ผ ๋ฟ์ด๊ณ  ๋ถ€์ž‘์šฉ์ด ์—†๋Š” ํ•œ ์—ฌ์ „ํžˆ ์ˆœ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค.

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

@markerikson ok ๋…ผ๋ฆฌ ๋ฌธ์€ ํ•œ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํŠน์ • ์ž‘์—…์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด ํ•œ ๊ฒฝ์šฐ์—๋Š” ์„ธ ๊ฐ€์ง€ ๋‹ค๋ฅธ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋Š” ๋‘ ๊ฐœ์˜ ๋ณ„๊ฐœ์˜ ๋ณ„๋„ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ํ•˜๋‚˜์˜ ์ž‘์—…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋…ผ๋ฆฌ + ์ž‘์—… ์‹คํ–‰์€ ๊ฐ์†๊ธฐ์— ๋“ค์–ด๊ฐ€์•ผ ํ•  ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

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

@jayesbe : ๋‹ค๋ฅธ ํ–‰๋™์˜ ํŠธ๋ฆฌ๊ฑฐ๋ง์ด ๊ฐ์†๊ธฐ์— ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค๊ณ  ๋งํ•œ ์‚ฌ๋žŒ์€ ์•„๋ฌด๋„ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์‹ค, ๊ทธ๋Ÿฌ๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๊ฐ์†๊ธฐ์˜ ์ž‘์—…์€ ๋‹จ์ˆœํžˆ (currentState + action) -> newState ์ž…๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ์ž‘์—…์„ ํ•จ๊ป˜ ๋ฌถ์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์ฝํฌ ๋˜๋Š” ์‚ฌ๊ฐ€์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์ˆ˜์‹ ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์„ ๊ฐ€๋กœ์ฑ„๊ณ  ์ถ”๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์†”์งํžˆ ๋งํ•ด์„œ ์ด ์‹œ์ ์—์„œ ๋…ผ์˜๊ฐ€ ๋ฌด์—‡์ธ์ง€ ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

@markerikson ์ฃผ์ œ๋Š” "๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง"๊ณผ ๊ทธ๊ฒƒ์ด ์–ด๋””๋กœ

๋‹น์‹ ์ด ๋งํ–ˆ๋“ฏ์ด ์ •๋ง๋กœ ์ค‘์š”ํ•œ ๊ฒƒ์€ ๋‹น์‹ ์—๊ฒŒ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์— ๊ท€ํ•˜๊ฐ€ ์งˆ๋ฌธํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด fetch()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ฒฝ์šฐ.. ์–ด๋–ค ์‹์œผ๋กœ๋“  ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์•„์ง "๋ณต์žกํ•œ ๋…ผ๋ฆฌ"๋ฅผ ๊ฐ€์ง„ ๊ฐ์†๊ธฐ์˜ ์˜ˆ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ๊ฐ์†๊ธฐ๋Š” ๋‚ด ์„œ๋ฒ„์—์„œ ์›์‹œ ์‘๋‹ต์„ ๋ฐ›์•„ ๋‚ด ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒํ•˜๋ฉด ๊ท€ํ•˜๊ฐ€ ๋งํ•˜๋Š” ์ฒ˜๋ฆฌ ์‘๋‹ต์ด ๋‚ด ๊ฐ์†๊ธฐ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์š”์ฒญ์€ ๋ฆฌ๋“€์„œ๊ฐ€ ๋กœ์ปฌ ๋ ˆ์ฝ”๋“œ ์บ์‹œ์— ์ €์žฅํ•˜๋Š” ๋‚ด ์„œ๋ฒ„์— ๋Œ€ํ•œ JSON ๋ ˆ์ฝ”๋“œ ๊ฐ€์ ธ์˜ค๊ธฐ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

k ๋…ผ๋ฆฌ ๋ฌธ์€ ํ•œ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํŠน์ • ์ž‘์—…์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด ํ•œ ๊ฒฝ์šฐ์—๋Š” ์„ธ ๊ฐ€์ง€ ๋‹ค๋ฅธ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋Š” ๋‘ ๊ฐœ์˜ ๋ณ„๊ฐœ์˜ ๋ณ„๋„ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ํ•˜๋‚˜์˜ ์ž‘์—…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋…ผ๋ฆฌ + ์ž‘์—… ์‹คํ–‰์€ ๊ฐ์†๊ธฐ์— ๋“ค์–ด๊ฐ€์•ผ ํ•  ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ๋‹น์‹ ์ดํ•˜๋Š” ์ผ์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ„๋ช…ํžˆ ์„œ๋ฒ„ ๊ฐ€์ ธ์˜ค๊ธฐ์˜ ๊ฒฝ์šฐ ํ•œ ์ž‘์—…์ด ๋‹ค๋ฅธ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ถŒ์žฅ๋˜๋Š” Redux ์ ˆ์ฐจ ๋‚ด์— ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

function createFoobar(dispatch, state, updateRegistry) {
   dispatch(createFoobarRecord());
   if (updateRegistry) {
      dispatch(updateFoobarRegistry());
   } else {
       dispatch(makeFoobarUnregistered());
   }
   if (hasFoobarTemps(state)) {
      dispatch(dismissFoobarTemps());
   }
}

์ด๊ฒƒ์€ Redux๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค. Redux์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด๋Ÿฌํ•œ ๋ชจ๋“  ์›ํ•˜๋Š” ๋ณ€๊ฒฝ์„ ์ผ์œผํ‚ค๋Š” ๋‹จ์ผ CREATE_FOOBAR ์ž‘์—…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@winstonewert :

์ด๊ฒƒ์€ Redux๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค. Redux์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด๋Ÿฌํ•œ ๋ชจ๋“  ์›ํ•˜๋Š” ๋ณ€๊ฒฝ์„ ์ผ์œผํ‚ค๋Š” ๋‹จ์ผ CREATE_FOOBAR ์ž‘์—…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ง€์ •๋œ ์–ด๋”˜๊ฐ€์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚ด๊ฐ€ FAQ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์กฐ์‚ฌ๋ฅผ ํ•  ๋•Œ ๋‚ด๊ฐ€ ์ƒ๊ฐํ•ด๋‚ธ ๊ฒƒ์€ Dan์ด ์ง์ ‘ ์ œ์•ˆํ•œ "๊ทธ๊ฒƒ์€ ์˜์กด์ "์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. http://redux.js.org/docs/FAQ.html#actions -multiple-actions ๋ฐ Dan์˜ SO on this ๋‹ต๋ณ€์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

"๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ"๋Š” ์‹ค์ œ๋กœ ๊ฝค ๊ด‘๋ฒ”์œ„ํ•œ ์šฉ์–ด์ž…๋‹ˆ๋‹ค. "์ผ์–ด๋‚œ ์ผ์ด ์žˆ์—ˆ๋‚˜์š”?", "์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ–ˆ์œผ๋‹ˆ ์ด์ œ ์–ด๋–ป๊ฒŒ ํ•ฉ๋‹ˆ๊นŒ?", "์ด๊ฒƒ์ด ์œ ํšจํ•œ๊ฐ€์š”?" ๋“ฑ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Redux์˜ ์„ค๊ณ„๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์—ฌ ์ด๋Ÿฌํ•œ ์งˆ๋ฌธ์€ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ์œ„์น˜์—์„œ ๋‹ต๋ณ€ํ•  ์ˆ˜ _์ˆ˜_ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น„๋ก "์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๊นŒ?"๋Š” ์•ก์…˜ ์ƒ์„ฑ์ž์˜ ๋” ๋งŽ์€ ์ฑ…์ž„์œผ๋กœ ๋ณด๊ณ  "์ง€๊ธˆ์€"์€ ๊ฑฐ์˜ ํ™•์‹คํžˆ ๊ฐ์†๊ธฐ ์ฑ…์ž„์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ „๋ฐ˜์ ์œผ๋กœ, "๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ"์— ๋Œ€ํ•œ ์ด _ ์ „์ฒด ์งˆ๋ฌธ _"๊ทธ๊ฒƒ์€ _์—

๋‚ด๊ฐ€ ๋™์˜ํ•˜๋Š” ๋‹จํ˜ธํ•˜๊ณ  ํ™•์‹คํ•œ ๊ทœ์น™์€ "์•ก์…˜ ์ƒ์„ฑ์ž์˜ ๋น„๊ฒฐ์ •๋ก , ๋ฆฌ๋“€์„œ์˜ ์ˆœ์ˆ˜ํ•œ ๊ฒฐ์ •๋ก "์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ฃผ์–ด์ง„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ ์ด์™ธ์˜? ๋‹น์‹ ์—๊ฒŒ ๋งž๋Š” ๊ฒƒ์„ ์ฐพ์œผ์‹ญ์‹œ์˜ค. ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜์‹ญ์‹œ์˜ค. ํŠน์ • ๋ฐฉ์‹์œผ๋กœ ํ•˜๋Š” ์ด์œ ๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•จ๊ป˜ ๊ฐ€์„ธ์š”.

"๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๊นŒ?"๊ฐ€ ๋” ๋งŽ์€ ์ž‘์—… ์ž‘์„ฑ์ž ์ฑ…์ž„์œผ๋กœ ๊ฐ„์ฃผ๋˜์ง€๋งŒ "์ง€๊ธˆ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ"๋Š” ๊ฑฐ์˜ ํ™•์‹คํžˆ ๊ฐ์†๊ธฐ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๋ฐ”๋กœ ๋ถ€์ž‘์šฉ, ์ฆ‰ "what now"์˜ ์ˆœ์ˆ˜ํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„์„ reducer: #1528์— ๋„ฃ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋ณ‘๋ ฌ ํ† ๋ก ์ด ์žˆ๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ ํŒจํ„ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ํ•ด์•ผ ํ•  ์ผ : ์•ก์…˜/์•ก์…˜ ์ƒ์„ฑ๊ธฐ
  • ๋ฐฉ๋ฒ• : ๋ฏธ๋“ค์›จ์–ด(์˜ˆ: '๋น„๋™๊ธฐ' ์ž‘์—…์„ ์ˆ˜์‹ ํ•˜๊ณ  ๋‚ด API ๊ฐœ์ฒด๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด)
  • ๊ฒฐ๊ณผ๋กœ ์ˆ˜ํ–‰ํ•  ์ž‘์—… : ๊ฐ์†๊ธฐ

์ด ์Šค๋ ˆ๋“œ์˜ ์•ž๋ถ€๋ถ„์—์„œ Dan์˜ ์ง„์ˆ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฐ ์ ์—์„œ ๊ถŒ์žฅ๋˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ด๋ฒคํŠธ๋‹น ํ•˜๋‚˜์˜ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์šฉ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ์ผ์„ ํ•˜์‹ญ์‹œ์˜ค.

@winstonewert : Dan์€ "๋ฆฌ๋“€์„œ ๊ตฌ์„ฑ" ํŒจํ„ด์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, "ํ•˜๋‚˜์˜ ๋ฆฌ๋“€์„œ๋งŒ ๋“ฃ๋Š” ์ž‘์—…" ๋Œ€ "๋งŽ์€ ๋ฆฌ๋“€์„œ๊ฐ€ ๋™์ผํ•œ ์ž‘์—…์— ์‘๋‹ตํ•  ์ˆ˜ ์žˆ์Œ"์ž…๋‹ˆ๋‹ค. Dan์€ ๋‹จ์ผ ์ž‘์—…์— ์‘๋‹ตํ•˜๋Š” ์ž„์˜์˜ ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•ด ๋งค์šฐ ๊ด€์‹ฌ์ด ๋งŽ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์€ ๋ฆฌ๋“€์„œ์™€ ์•ก์…˜์ด ๋งค์šฐ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๋ฌถ์ด๊ณ  ์˜ค์ง ํ•˜๋‚˜์˜ ๋ฆฌ๋“€์„œ๋งŒ์ด ์ฃผ์–ด์ง„ ์•ก์…˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” "์˜ค๋ฆฌ" ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ์˜ˆ๋Š” "์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆœ์„œ๋Œ€๋กœ ์ „๋‹ฌ"ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ "๋‚ด ๊ฐ์†๊ธฐ ๊ตฌ์กฐ์˜ ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ๋ถ€๋ถ„์ด ์ด์— ์‘๋‹ตํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜๋Š”์ง€"์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‹ค์šฉ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ์ผ์„ ํ•˜์‹ญ์‹œ์˜ค.

:+1:

@sompylasar ๋‚ด ์ž‘์—…์— ์ƒํƒœ ๊ตฌ์กฐ๊ฐ€ ์žˆ์œผ๋ฉด ๋‚ด ๋ฐฉ์‹์˜ ์˜ค๋ฅ˜๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ๊ตฌ์กฐ๋ฅผ ๋‚ด ๋ฆฌ๋“€์„œ๋กœ ์‰ฝ๊ฒŒ ์ „ํ™˜ํ•˜๊ณ  ๋‚ด ์ž‘์—…์„ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฑด๋ฐฐ.

์ œ๊ฐ€ ๋ณด๊ธฐ์—๋Š” ๊ฐ™์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์ผ์œผํ‚ค๋Š” ์—ฌ๋Ÿฌ ๊ฐ์†๊ธฐ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๋‹จ์ผ ์ž‘์—…์ด ์žˆ๊ฑฐ๋‚˜ ๋‹จ์ผ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์œ ๋ฐœํ•˜๋Š” ๋‹จ์ผ ๊ฐ์†๊ธฐ๋ฅผ ๊ฐ๊ฐ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ์—ฌ๋Ÿฌ ์ž‘์—…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋ฆฌ๋“€์„œ๊ฐ€ ์ž‘์—…์— ์‘๋‹ตํ•˜๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์€ ๋™์ผํ•œ ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋Œ€์•ˆ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

์–ธ๊ธ‰ํ•œ StackOverflow ์งˆ๋ฌธ์—์„œ ๊ทธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•œ ํ•œ ์‚ฌ์šฉ์ž ์ƒํ˜ธ ์ž‘์šฉ์˜ ๊ธฐ๋ก์— ๊ฐ€๊นŒ์šด ์ž‘์—… ๋กœ๊ทธ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ์†๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ ์ผ๋ถ€ ์ž‘์—…์„ ์—ฌ๋Ÿฌ ๊ฐœ๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ณ  UI ์—…๋ฐ์ดํŠธ๊ฐ€ ์šฐ์—ฐํžˆ ํ•จ๊ป˜ ๋ฐœ์ƒํ•˜๋Š” ๋‘ ๊ฐœ์˜ ๊ฐœ๋ณ„ ์ž‘์—…์œผ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด.

๋‚ด๊ฐ€ ๋ณด๊ธฐ์— Dan์€ ์ด์ƒ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉ์ž ์ƒํ˜ธ ์ž‘์šฉ๋‹น ํ•˜๋‚˜์˜ ์ž‘์—…์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์„ ์ง€์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๋Š” ์‹ค์šฉ์ ์ž…๋‹ˆ๋‹ค. ๊ฐ์†๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค ๋•Œ ๊ทธ๋Š” ์ž‘์—… ๋ถ„ํ• ์„ ์ง€์ง€ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋‹ค์†Œ ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์‹œ๊ฐํ™”ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

1) ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ์ฃผ์˜ ์—ฌ๋Ÿฌ ์˜์—ญ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ combineReducers ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ํ•˜์œ„ ๋„๋ฉ”์ธ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ณ„๋„์˜ ๊ฐ์†๊ธฐ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์— ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์€:

  • ๊ฐ์†๊ธฐ A์™€ ๊ฐ์†๊ธฐ B๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•œ ์ž‘์—…์— ์‘๋‹ตํ•˜๊ณ  ์ƒํƒœ ๋น„ํŠธ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ๋ฆฌ๋“€์„œ๊ฐ€ ์ž์ฒด ์ฒญํฌ ์™ธ๋ถ€์˜ ๋‹ค๋ฅธ ์ƒํƒœ ๋น„ํŠธ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝํฌ์— ๋ชจ๋“  ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์—…์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
  • Reducer A์˜ ์ƒํƒœ ๋น„ํŠธ๋ฅผ ์žก๊ณ  ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์— Reducer B์— ์ „๋‹ฌํ•˜๋Š” ๋‹ค๋ฅธ ์ตœ์ƒ์œ„ ๊ฐ์†๊ธฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
  • ํ•„์š”ํ•œ ์ƒํƒœ ๋น„ํŠธ์™€ ํ•จ๊ป˜ Reducer A๋ฅผ ์œ„ํ•œ ์ž‘์—…์„ ์ „๋‹ฌํ•˜๊ณ  ํ•„์š”ํ•œ ์ƒํƒœ๋กœ Reducer B๋ฅผ ์œ„ํ•œ ๋‘ ๋ฒˆ์งธ ์ž‘์—…์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๊นŒ?

2) ํŠน์ • ์ˆœ์„œ๋กœ ๋ฐœ์ƒํ•˜๋Š” ์ผ๋ จ์˜ ๋‹จ๊ณ„๊ฐ€ ์žˆ์œผ๋ฉฐ ๊ฐ ๋‹จ๊ณ„์—๋Š” ์ผ๋ถ€ ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋˜๋Š” ๋ฏธ๋“ค์›จ์–ด ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์€:

  • ๊ฐ ๊ฐœ๋ณ„ ๋‹จ๊ณ„๋ฅผ ๊ฐœ๋ณ„ ์ž‘์—…์œผ๋กœ ์ „๋‹ฌํ•˜์—ฌ ์ง„ํ–‰ ์ƒํ™ฉ์„ ๋‚˜ํƒ€๋‚ด๊ณ  ๊ฐœ๋ณ„ ๊ฐ์†๊ธฐ๊ฐ€ ํŠน์ • ์ž‘์—…์— ์‘๋‹ตํ•˜๋„๋ก ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
  • ํ•˜๋‚˜์˜ ํฐ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ๋ฆฌ๋“€์„œ๊ฐ€ ์ด๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•œ๋‹ค๊ณ  ๋ฏฟ์Šต๋‹ˆ๊นŒ?

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

@markerikson ๊ทธ๋ž˜์„œ ๋‹น์‹ ์˜ ์กฐ์–ธ์€ '์–ด๋–ค ์ƒํ™ฉ์„ ๋งŒ๋‚ฌ๋Š๋ƒ์— ๋‹ฌ๋ ค์žˆ๋‹ค'๊ณ , ์•ก์…˜์ด๋‚˜ ๋ฆฌ๋“€์„œ์—์„œ '๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง'์˜ ๊ท ํ˜•์„ ๋งž์ถ”๋Š” ๋ฐฉ๋ฒ•์€ ๋‹น์‹ ์˜ ๊ณ ๋ ค์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋„ ๊ฐ€๋Šฅํ•œ ํ•œ ์ˆœ์ˆ˜ ๊ธฐ๋Šฅ์˜ ์ด์ ์„ ์ทจํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ?

์‘. ๊ฐ์†๊ธฐ๋Š” Redux ์š”๊ตฌ ์‚ฌํ•ญ์œผ๋กœ ์ˆœ์ˆ˜ํ•ด์•ผ _๊ฐ€์ง€๊ณ _ ์žˆ์Šต๋‹ˆ๋‹ค(ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์˜ 0.00001% ์ œ์™ธ). ์•ก์…˜ ์ œ์ž‘์ž๋Š” ์ ˆ๋Œ€์ ์œผ๋กœ _ ํ•˜์ง€ ์•Š์•„๋„ _ ์ˆœ์ˆ˜ํ•ด์•ผ ํ•˜๋ฉฐ ์‹ค์ œ๋กœ ๋Œ€๋ถ€๋ถ„์˜ "๋ถˆ์ˆœ๋ฌผ"์ด ์‚ด ๊ณณ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋ณด๋‹ค ์ดํ•ดํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ๋ถ„๋ช…ํžˆ ๋” ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— _if_ ์ผ๋ถ€ ์ž‘์—… ์ƒ์„ฑ ๋…ผ๋ฆฌ๋ฅผ ์ˆœ์ˆ˜ํ•˜๊ณ  ํ›Œ๋ฅญํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋„ค, ์ œ ๊ด€์ ์—์„œ ๋ณผ ๋•Œ ์•ฑ์˜ ๋…ผ๋ฆฌ์™€ ์œ„์น˜์— ์ ์ ˆํ•œ ๊ท ํ˜•์ด ๋ฌด์—‡์ธ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์€ ๊ฐœ๋ฐœ์ž์˜ ๋ชซ์ž…๋‹ˆ๋‹ค. ์•ก์…˜ ์ƒ์„ฑ์ž/๋ฆฌ๋“€์„œ ๋ถ„ํ• ์˜ ์–ด๋Š ์ชฝ์ด ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋‹จ์ผํ•˜๊ณ  ํ™•์‹คํ•œ ๊ทœ์น™์€ ์—†์Šต๋‹ˆ๋‹ค. (์Œ, ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ "๊ฒฐ์ •๋ก /๋น„๊ฒฐ์ •๋ก "์„ ์ œ์™ธํ•˜๊ณ . ์ด ์ฃผ์„์—์„œ ๋ถ„๋ช…ํžˆ ์–ธ๊ธ‰ํ•˜๋ ค๊ณ  ํ–ˆ๋˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ถ„๋ช…ํžˆ.)

@cpsubrian

๊ฒฐ๊ณผ๋กœ ์ˆ˜ํ–‰ํ•  ์ž‘์—…: ๊ฐ์†๊ธฐ

์‹ค์ œ๋กœ ์ด๊ฒƒ์ด saga๊ฐ€ "์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด, ๊ทธ๊ฒƒ๋„ ๋ฐœ์ƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค"์™€ ๊ฐ™์€ ํšจ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.


@markerikson @LumiaSaki

์•ก์…˜ ์ œ์ž‘์ž๋Š” ์ ˆ๋Œ€์ ์œผ๋กœ ์ˆœ์ˆ˜ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ ์‹ค์ œ๋กœ ๋Œ€๋ถ€๋ถ„์˜ "๋ถˆ์ˆœ๋ฌผ"์ด ์‚ด ๊ณณ์ž…๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ๋Š” ๋ถˆ์ˆœํ•˜๊ฑฐ๋‚˜ ์กด์žฌํ•  ํ•„์š”์กฐ์ฐจ ์—†์Šต๋‹ˆ๋‹ค.
http://stackoverflow.com/a/34623840/82609 ์ฐธ์กฐ

๊ทธ๋ฆฌ๊ณ  ๋„ค, ์ œ ๊ด€์ ์—์„œ ๋ณผ ๋•Œ ์•ฑ์˜ ๋…ผ๋ฆฌ์™€ ์œ„์น˜์— ์ ์ ˆํ•œ ๊ท ํ˜•์ด ๋ฌด์—‡์ธ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์€ ๊ฐœ๋ฐœ์ž์˜ ๋ชซ์ž…๋‹ˆ๋‹ค. ์•ก์…˜ ์ƒ์„ฑ์ž/๋ฆฌ๋“€์„œ ๋ถ„ํ• ์˜ ์–ด๋Š ์ชฝ์ด ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋‹จ์ผํ•˜๊ณ  ํ™•์‹คํ•œ ๊ทœ์น™์€ ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ, ํ•˜์ง€๋งŒ ๊ฒฝํ—˜ ์—†์ด ๊ฐ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ๋‹จ์ ์„ ์•Œ์•„์ฐจ๋ฆฌ๋Š” ๊ฒƒ์€ ๊ทธ๋ฆฌ ๋ถ„๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ๋‚ด ์˜๊ฒฌ๋„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. https://github.com/reactjs/redux/issues/1171#issuecomment -167585575

์—„๊ฒฉํ•œ ๊ทœ์น™์€ ๋Œ€๋ถ€๋ถ„์˜ ๊ฐ„๋‹จํ•œ ์•ฑ์— ์ ํ•ฉํ•˜์ง€ ์•Š์ง€๋งŒ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋นŒ๋“œํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ž์ฒด ๋ฒ”์œ„ ๋ฐ–์˜ ๊ฒƒ์„ ์ธ์‹ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ „์ฒด ์•ฑ์— ๋Œ€ํ•œ ์ „์—ญ ์ž‘์—… ๋ชฉ๋ก์„ ์ •์˜ํ•˜๋Š” ๋Œ€์‹  ์•ฑ์„ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ์—๋Š” ์ž์ฒด ์ž‘์—… ๋ชฉ๋ก์ด ์žˆ์œผ๋ฉฐ ์ด๋Ÿฌํ•œ ์ž‘์—…๋งŒ ์ „๋‹ฌ/์ถ•์†Œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” "๋‚ ์งœ ์„ ํƒ๊ธฐ์—์„œ ๋‚ ์งœ๊ฐ€ ์„ ํƒ๋˜๋ฉด ํ•ด๋‹น ํ•  ์ผ ํ•ญ๋ชฉ์— ๋ฏธ๋ฆฌ ์•Œ๋ฆผ์„ ์ €์žฅํ•˜๊ณ  ํ”ผ๋“œ๋ฐฑ ์•Œ๋ฆผ์„ ํ‘œ์‹œํ•œ ๋‹ค์Œ ๋ฏธ๋ฆฌ ์•Œ๋ฆผ์ด ์žˆ๋Š” ํ• ์ผ ๋ชฉ๋ก์œผ๋กœ ์•ฑ์„ ํƒ์ƒ‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค"๋ฅผ ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ•ฉ๋‹ˆ๊นŒ? saga๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค: ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜

https://github.com/slorber/scalable-frontend-with-elm-or-redux ๋„

๊ทธ๋ฆฌ๊ณ  ๋„ค, ์ œ ๊ด€์ ์—์„œ ๋ณผ ๋•Œ ์•ฑ์˜ ๋…ผ๋ฆฌ์™€ ์œ„์น˜์— ์ ์ ˆํ•œ ๊ท ํ˜•์ด ๋ฌด์—‡์ธ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์€ ๊ฐœ๋ฐœ์ž์˜ ๋ชซ์ž…๋‹ˆ๋‹ค. ์•ก์…˜ ์ƒ์„ฑ์ž/๋ฆฌ๋“€์„œ ๋ถ„ํ• ์˜ ์–ด๋Š ์ชฝ์ด ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋‹จ์ผํ•˜๊ณ  ํ™•์‹คํ•œ ๊ทœ์น™์€ ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ, ๋ฆฌ๋“€์„œ์— ๋กœ์ง์„ ๋„ฃ๋“  ์•ก์…˜ ์ƒ์„ฑ์ž์— ๋กœ์ง์„ ๋„ฃ๋“  Redux์˜ ์š”๊ตฌ ์‚ฌํ•ญ์€ ์—†์Šต๋‹ˆ๋‹ค. Redux๋Š” ์–ด๋Š ์ชฝ์ด๋“  ์ค‘๋‹จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์‹์œผ๋กœ๋“  ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์—„๊ฒฉํ•˜๊ณ  ๋น ๋ฅธ ๊ทœ์น™์€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Dan์˜ ๊ถŒ์žฅ ์‚ฌํ•ญ์€ "๊ฐ€๋Šฅํ•œ ํ•œ ์‚ฌ์šฉ์ž ์ƒํ˜ธ ์ž‘์šฉ์˜ ๊ธฐ๋ก์— ๊ฐ€๊นŒ์šด ์ž‘์—… ๋กœ๊ทธ๋ฅผ ์œ ์ง€"ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ๋‹น ๋‹จ์ผ ์ž‘์—…์„ ์ „๋‹ฌํ•  ํ•„์š”๋Š” ์—†์ง€๋งŒ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

์ œ ๊ฒฝ์šฐ์—๋Š” 1๊ฐœ์˜ ์ž‘์—…์— ๊ด€์‹ฌ์ด ์žˆ๋Š” 2๊ฐœ์˜ ๊ฐ์†๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์›์‹œ action.data๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ณ€ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 2๊ฐœ์˜ ๊ฐ์†๊ธฐ์—์„œ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ฝํฌ๋กœ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์˜ฎ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์‹์œผ๋กœ ๋‚ด ๋ฆฌ๋“€์„œ๋Š” ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด ์งง์€ 1๊ฐœ์›” redux ๊ฒฝํ—˜์—์„œ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๊ณ ์ž…๋‹ˆ๋‹ค.

์ƒ์  ๊ตฌ์กฐ์—์„œ ๊ตฌ์„ฑ ์š”์†Œ/๋ณด๊ธฐ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ? ๋‚ด ๋ชฉํ‘œ๋Š” ์ €์žฅ์†Œ ๊ตฌ์กฐ์˜ ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋ฆฌ๋“€์„œ์—์„œ ๊ด€๋ฆฌ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์„ ํƒ๊ธฐ๋ฅผ ๋ฆฌ๋“€์„œ์™€ ํ•จ๊ป˜ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•˜๋ฏ€๋กœ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ €์žฅ์†Œ์˜ ํŠน์ • ๋…ธ๋“œ๋ฅผ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ด๋Š” ๊ตฌ์„ฑ ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ž‘์—…์„ ์ „๋‹ฌํ•  ๋•Œ ๋ฐ˜๋Œ€์˜ ๊ฒฝ์šฐ๋Š” ์–ด๋–ป์Šต๋‹ˆ๊นŒ?

์˜ˆ๋ฅผ ๋“ค์–ด Todo ์•ฑ์—์„œ Todo ํ•ญ๋ชฉ์˜ ์ด๋ฆ„์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋Š” ํ•ญ๋ชฉ์˜ ์ผ๋ถ€๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ž‘์—…์„ ์ „๋‹ฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

dispatch(updateItem({name: <text variable>}));

, ์ž‘์—… ์ •์˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const updateItem = (updatedData) => {type: "UPDATE_ITEM", updatedData}

์ด๊ฒƒ์€ ๊ฐ„๋‹จํžˆ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์†๊ธฐ์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

Object.assign({}, item, action.updatedData)

ํ•ญ๋ชฉ์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋™์ผํ•œ ์ž‘์—…๊ณผ ๊ฐ์†๊ธฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ Todo ํ•ญ๋ชฉ์˜ ๋ชจ๋“  ์†Œํ’ˆ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ:

updateItem({description: <text variable>})

๋Œ€์‹  ์„ค๋ช…์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ.

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์„œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ƒ์ ์—์„œ Todo ํ•ญ๋ชฉ์ด ์–ด๋–ป๊ฒŒ ์ •์˜๋˜๋Š”์ง€ ์•Œ์•„์•ผ ํ•˜๊ณ  ํ•ด๋‹น ์ •์˜๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๊ทธ๊ฒƒ์— ์˜์กดํ•˜๋Š” ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ถ„๋ช…ํžˆ ๋‚˜์œ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•œ ์ œ์•ˆ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@dcoellarb

์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์ƒํ™ฉ์—์„œ ๋‚ด ์†”๋ฃจ์…˜์€ ์ƒ์šฉ๊ตฌ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด Javascript์˜ ์œ ์—ฐ์„ฑ์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‚˜๋Š” ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค :

const {reducer, actions, selector} = makeRecord({
    name: TextField,
    description: TextField,
    completed: BooleanField
})

์—ฌ๊ธฐ์„œ makeRecord๋Š” ๋‚ด ์„ค๋ช…์—์„œ ์ž๋™์œผ๋กœ ๊ฐ์†๊ธฐ, ์•ก์…˜ ์ƒ์„ฑ๊ธฐ ๋ฐ ์„ ํƒ๊ธฐ๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒ์šฉ๊ตฌ๊ฐ€ ์ œ๊ฑฐ๋˜์ง€๋งŒ ๋‚˜์ค‘์— ์ด ๊น”๋”ํ•œ ํŒจํ„ด์— ๋งž์ง€ ์•Š๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ makeRecord์˜ ๊ฒฐ๊ณผ์— ์‚ฌ์šฉ์ž ์ง€์ • ๊ฐ์†๊ธฐ/๋™์ž‘/์„ ํƒ๊ธฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

tks @winstonewert ๋‚˜๋Š” ์ƒ์šฉ๊ตฌ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๋ชจ๋ธ์ด ์žˆ๋Š” ์•ฑ์—์„œ ๋งŽ์€ ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ €์žฅ์†Œ ๊ตฌ์กฐ์—์„œ ๋ถ„๋ฆฌํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ž‘์—…์ด ์ƒ์„ฑ๋˜๋”๋ผ๋„ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์—…๋ฐ์ดํŠธ๋œ ํ•„๋“œ๋ฅผ ์—ฌ์ „ํžˆ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์—ฌ์ „ํžˆ ๋‹ค์Œ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€๊ฒŒ ๋งž์ง€?

@winstonewert @dcoellarb ์ œ ์ƒ๊ฐ์—๋Š” ์•ก์…˜ ํŽ˜์ด๋กœ๋“œ ๊ตฌ์กฐ๋Š” ๋ฆฌ๋“€์„œ๊ฐ€ ์•„๋‹Œ ์•ก์…˜์— ์†ํ•ด์•ผ ํ•˜๋ฉฐ ๋ฆฌ๋“€์„œ์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์ƒํƒœ ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ตฌ์กฐ๊ฐ€ ์ดˆ๊ธฐ ๋‹จ์ˆœ์„ฑ์„ ์œ„ํ•ด ์„œ๋กœ ๋ฏธ๋Ÿฌ๋ง๋œ๋‹ค๋Š” ๊ฒƒ์€ ์šด์ด ์ข‹์€ ์šฐ์—ฐ์˜ ์ผ์น˜์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋‘ ๊ตฌ์กฐ๋Š” ๋™์ผํ•œ ๊ฐœ์ฒด๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ ์„œ๋กœ๋ฅผ ๋ฏธ๋Ÿฌ๋งํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

@sompylasar ๋งž์•„์š”, ๊ทธ๋ ‡๊ฒŒ ํ•ด์š”. api/rest ๋ฐ์ดํ„ฐ๋ฅผ ๋‚ด ์ €์žฅ์†Œ ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์ €์žฅ์†Œ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š” ์œ ์ผํ•œ ๊ฒƒ์€ ๊ฐ์†๊ธฐ์™€ ์„ ํƒ๊ธฐ๋ฟ์ธ๊ฐ€์š”? ๋‚ด๊ฐ€ ๊ทธ๋“ค์„ ๊ฐ™์€ ์œ„์น˜์— ๋ฐฐ์น˜ํ•˜๋Š” ์ด์œ , ๋‚ด ๋ฌธ์ œ๋Š” ๊ตฌ์„ฑ ์š”์†Œ/๋ณด๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ๋ณ€๊ฒฝํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•  ๊ฒฝ์šฐ์— ๋Œ€๋น„ํ•˜์—ฌ ์ƒ์  ๊ตฌ์กฐ๋ฅผ ์•Œ ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜์ง€๋งŒ ๋‚ด ์˜ˆ์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—…๋ฐ์ดํŠธํ•  ์˜ฌ๋ฐ”๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด์‹ญ์‹œ์˜ค. ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

@dcoellarb ๋ณด๊ธฐ๋ฅผ ํŠน์ • ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ์œผ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ฌธ์ž์—ด ๋˜๋Š” ์ˆซ์ž์™€ ๊ฐ™์ง€๋งŒ ํ•„๋“œ๊ฐ€ ์žˆ๋Š” ๊ตฌ์กฐํ™”๋œ ๊ฐœ์ฒด). ์ด ๋ฐ์ดํ„ฐ ๊ฐœ์ฒด๋Š” ๋ฐ˜๋“œ์‹œ ์ €์žฅ์†Œ ๊ตฌ์กฐ๋ฅผ ๋ฏธ๋Ÿฌ๋งํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋ฐ์ดํ„ฐ ๊ฐœ์ฒด๋ฅผ ์ž‘์—…์— ๋„ฃ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ƒ์  ๊ตฌ์กฐ์™€ ๊ฒฐํ•ฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์Šคํ† ์–ด์™€ ๋ทฐ๋Š” ๋ชจ๋‘ ์•ก์…˜ ํŽ˜์ด๋กœ๋“œ ๊ตฌ์กฐ์™€ ๊ฒฐํ•ฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@sompylasar ๋Š” ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹œ๋„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!!!

redux-saga ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ก์…˜์„ ๋” ์ˆœ์ˆ˜ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ง๋ถ™์ด์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ redux-saga๋Š” ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์„ ๊ฒช์œผ๋ฏ€๋กœ redux-saga ๋Œ€์‹  RxJS(๋˜๋Š” ๋ชจ๋“  FRP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ์•„์ด๋””์–ด๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋” ๋ฐœ์ „์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ KefirJS๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค. https://github.com/awesome-editor/awesome-editor/blob/saga-demo/src/stores/app/AppSagaHandlers.js

์•ˆ๋…•ํ•˜์„ธ์š” @frankandrobot ์ž…๋‹ˆ๋‹ค .

redux-saga๋Š” ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ๊ตฐ๋ถ„ํˆฌํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒŒ ๋ฌด์Šจ ๋ง์ด์—์š”? redux-saga ๋Š” ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ์™€ ๋ถ€์ž‘์šฉ์„ ์šฐ์•„ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š์•˜์Šต๋‹ˆ๊นŒ? https://github.com/reactjs/redux/issues/1171#issuecomment -167715393์„ ์‚ดํŽด๋ณด์„ธ์š”.

์•„๋‹ˆ @IceOnFire . ์ง€๋‚œ๋ฒˆ์— redux-saga ๋ฌธ์„œ๋ฅผ ์ฝ์—ˆ์„ ๋•Œ ๋ณต์žกํ•œ ๋น„๋™๊ธฐ ์›Œํฌํ”Œ๋กœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ฐธ์กฐ: http://yelouafi.github.io/redux-saga/docs/advanced/NonBlockingCalls.html
๊ทธ๊ฒƒ์€ (์—ฌ์ „ํžˆ ๋งํ•ฉ๋‹ˆ๊นŒ?) ํšจ๊ณผ์— ๋Œ€ํ•ด ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ณต์žกํ•ด์ง€๊ธฐ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜๋จธ์ง€ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ๋…์ž์—๊ฒŒ ๋งก๊ธฐ๊ฒ ์Šต๋‹ˆ๋‹ค.

FRP ๋ฐฉ์‹๊ณผ ๋น„๊ต: https://github.com/frankandrobot/rflux/blob/master/doc/06-sideeffects.md#a -more-complex-workflow
์ „์ฒด ์›Œํฌํ”Œ๋กœ๊ฐ€ ์™„์ „ํžˆ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. (๋ช‡ ์ค„๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.) ๊ฒŒ๋‹ค๊ฐ€ redux-saga ์˜ ์žฅ์ ๋„ ๋Œ€๋ถ€๋ถ„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ชจ๋“  ๊ฒƒ์ด ์ˆœ์ˆ˜ ํ•จ์ˆ˜์ด๋ฉฐ ๋Œ€๋ถ€๋ถ„ ์‰ฌ์šด ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์ž„).

๋งˆ์ง€๋ง‰์œผ๋กœ ์ด๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ–ˆ์„ ๋•Œ ๋ฌธ์ œ๋Š” redux-saga๊ฐ€ ๋ชจ๋“  ๊ฒƒ์„ ๋™๊ธฐ์‹์œผ๋กœ ๋ณด์ด๊ฒŒ ํ•œ๋‹ค๋Š” ๊ฒฐ๋ก ์— ๋„๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์›Œํฌํ”Œ๋กœ์—๋Š” ํ›Œ๋ฅญํ•˜์ง€๋งŒ ๋ณต์žกํ•œ ๋น„๋™๊ธฐ ์›Œํฌํ”Œ๋กœ์˜ ๊ฒฝ์šฐ ๋น„๋™๊ธฐ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด FRP๊ฐ€ ํƒ์›”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @frankandrobot ์ž…๋‹ˆ๋‹ค .

์„ค๋ช…ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹น์‹ ์ด ์–ธ๊ธ‰ํ•œ ์ธ์šฉ๋ฌธ์„ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ง„ํ™”ํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด, ์ง€๊ธˆ์€ ์ „์— ๋ณธ ์ ์ด ์—†๋Š” cancel ํšจ๊ณผ๋ฅผ ๋ด…๋‹ˆ๋‹ค).

๋‘ ์˜ˆ์ œ(saga ๋ฐ FRP)๊ฐ€ ์ •ํ™•ํžˆ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ํฐ ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” try/catch ๋ธ”๋ก ๋‚ด๋ถ€์˜ ๋ช…๋ น ์‹œํ€€์Šค์ด๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์ŠคํŠธ๋ฆผ์˜ ๋ฉ”์„œ๋“œ ์ฒด์ธ์ž…๋‹ˆ๋‹ค. ์ŠคํŠธ๋ฆผ์— ๋Œ€ํ•œ ๊ฒฝํ—˜์ด ๋ถ€์กฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— yield ํ•˜๋‚˜ํ•˜๋‚˜๋ฅผ ํ•˜๋‚˜์”ฉ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‚ฌ๊ฐ€ ์˜ˆ์ œ๋ฅผ ๋” ์ฝ๊ธฐ ์‰ฝ๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ๊ธฐ์ˆ ๋ณด๋‹ค ๋‚ด ๋งˆ์Œ๊ฐ€์ง ๋•Œ๋ฌธ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ์ด์— ๋Œ€ํ•œ @yelouafi ์˜ ์˜๊ฒฌ์„ ์•Œ๊ณ 

@bvaughn ์—ฌ๊ธฐ์— ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ…Œ์ŠคํŠธ์—์„œ ์ž‘์—…, ๊ฐ์†๊ธฐ, ์„ ํƒ๊ธฐ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ์ ์ ˆํ•œ ์˜ˆ๋ฅผ

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

์•ˆ๋…•ํ•˜์„ธ์š” @morgs32 ๐Ÿ˜„

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

๊ธฐ๋ณธ์ ์œผ๋กœ ์ €๋Š” ์•ก์…˜๊ณผ ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ๋”ฐ๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•จ๊ป˜ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ง€์ ํ–ˆ์Šต๋‹ˆ๋‹ค.

import configureMockStore from 'redux-mock-store'
import { actions, selectors, reducer } from 'your-redux-module';

it('should support adding new todo items', () => {
  const mockStore = configureMockStore()
  const store = mockStore({
    todos: []
  })

  // Start with a known state
  expect(selectors.todos(store.getState())).toEqual([])

  // Dispatch an action to modify the state
  store.dispatch(actions.addTodo('foo'))

  // Verify the action & reducer worked successfully using your selector
  // This has the added benefit of testing the selector also
  expect(selectors.todos(store.getState())).toEqual(['foo'])
})

์ด๊ฒƒ์€ ํ”„๋กœ์ ํŠธ์—์„œ ๋ช‡ ๋‹ฌ ๋™์•ˆ Redux๋ฅผ ์‚ฌ์šฉํ•œ ํ›„ ๊ด€์ฐฐํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ณต์‹์ ์ธ ๊ถŒ์žฅ ์‚ฌํ•ญ์ด ์•„๋‹™๋‹ˆ๋‹ค. YMMV. ๐Ÿ‘

"์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ์—์„œ ๋” ๋งŽ์€ ์ผ์„ ํ•˜๊ณ  ๋ฆฌ๋“€์„œ์—์„œ ๋” ์ ๊ฒŒ ์ˆ˜ํ–‰"

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์„œ๋ฒ„&ํด๋ผ์ด์–ธํŠธ์ด๊ณ  ์„œ๋ฒ„์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ป๊ฒŒ ๋ฉ๋‹ˆ๊นŒ?
๊ทธ๋ž˜์„œ ๋‚˜๋Š” ์•ก์…˜์„ ๊ทธ๋Œ€๋กœ ๋ณด๋‚ด๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ์ž‘์—…์€ ์„œ๋ฒ„ ์ธก์—์„œ ๊ฐ์†๊ธฐ์— ์˜ํ•ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค ...

๋จผ์ €, ๋‚ด ์˜์–ด์— ๋Œ€ํ•ด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ €๋Š” ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ์˜๊ฒฌ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ œ ์„ ํƒ์€ fat ๋ฆฌ๋“€์„œ, thin ์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ์ž…๋‹ˆ๋‹ค.

๋‚ด ์ž‘์—… ์ƒ์„ฑ์ž๋Š” ์ผ๋ถ€ __promise ๋ฏธ๋“ค์›จ์–ด__๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” __dispatch__ ์ž‘์—…(๋น„๋™๊ธฐ, ๋™๊ธฐํ™”, ์ง๋ ฌ ๋น„๋™๊ธฐ, ๋ณ‘๋ ฌ ๋น„๋™๊ธฐ, for ๋ฃจํ”„์˜ ๋ณ‘๋ ฌ ๋น„๋™๊ธฐ)์ž…๋‹ˆ๋‹ค.

๋‚ด ๋ฆฌ๋“€์„œ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์€ ์ž‘์€ ์ƒํƒœ ์Šฌ๋ผ์ด์Šค๋กœ ๋ถ„ํ• ๋ฉ๋‹ˆ๋‹ค. combineReduers ํ•˜์—ฌ ๊ฒฐํ•ฉํ•˜์‹ญ์‹œ์˜ค. reducer ๋Š” __์ˆœ์ˆ˜ ํ•จ์ˆ˜__์ด๋ฏ€๋กœ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์–ธ์  ๊ฐ€ AngularJS๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๋™์ผํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์œ„ํ•ด ๋‚ด ์„œ๋น„์Šค์—์„œ reducer ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. reducer ์— ๋ผ์ธ ์ฝ”๋“œ๊ฐ€ ๋งŽ์œผ๋ฉด ๋” ์ž‘์€ ๋ฆฌ๋“€์„œ๋กœ ๋ถ„ํ• ํ•˜๊ฑฐ๋‚˜ ์ผ๋ถ€ ๊ธฐ๋Šฅ์„ ์ถ”์ƒํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ, A ๊ฐ€ B, C ์— ์˜์กดํ•˜๊ณ  B, C ๊ฐ€ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ์ž„์„ ์˜๋ฏธํ•˜๋Š” ๊ต์ฐจ ์ƒํƒœ ์‚ฌ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. A๋ฅผ ์ฑ„์šฐ๊ฑฐ๋‚˜ ์ดˆ๊ธฐํ™”ํ•˜๋ ค๋ฉด B,C ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ crossSliceReducer ํ•ฉ๋‹ˆ๋‹ค.

__์•ก์…˜ ํฌ๋ฆฌ์—์ดํ„ฐ์—์„œ ๋” ๋งŽ์€ ์ผ์„ ํ•˜๊ณ  ๋ฆฌ๋“€์„œ์—์„œ ๋” ์ ์€ ์ผ์„ ํ•˜์‹ญ์‹œ์˜ค__.

  1. redux-thunk ๋“ฑ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. getState() ์•ก์…˜ ์ƒ์„ฑ์ž ๋‚ด์—์„œ ์ „์ฒด ์ƒํƒœ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์„ ํƒ์ž…๋‹ˆ๋‹ค. ๋˜๋Š” ์ผ๋ถ€ __crossSliceReducer__๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ „์ฒด ์ƒํƒœ์—๋„ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๊ณ  ์ผ๋ถ€ ์ƒํƒœ ์Šฌ๋ผ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ์ƒํƒœ๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

__๋‹จ์œ„ ํ…Œ์ŠคํŠธ__ ์ •๋ณด

reducer ๋Š” __์ˆœ์ˆ˜ ํ•จ์ˆ˜__์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ๋‹ค๋ฅธ ๋ถ€๋ถ„๋ณด๋‹ค ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์†๊ธฐ๋ฅผ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.

action creators ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด? ๋‚˜๋Š” ๊ทธ๋“ค์ด "๋šฑ๋šฑํ•œ"๊ฒƒ์ด๋ผ๋ฉด ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ์‰ฝ์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ __async ์•ก์…˜ ์ƒ์„ฑ์ž__.

@mrdulin์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์ €๋„ ๊ทธ๋ ‡๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

@mrdulin ๋„ค. ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋ถˆ์ˆœํ•œ ๋…ผ๋ฆฌ๋ฅผ ๋ฐฐ์น˜ํ•˜๊ธฐ์— ์ ํ•ฉํ•œ ์žฅ์†Œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ ๊ฐ์†๊ธฐ๋Š” ์˜ฌ๋ฐ”๋ฅธ ์žฅ์†Œ์ฒ˜๋Ÿผ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ์— ํ•„์š”ํ•œ ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์—ฌ๋Ÿฌ "์ข…ํ•ฉ์ ์ธ" ์ž‘์—…์œผ๋กœ ๋๋‚ฉ๋‹ˆ๋‹ค.

ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•œ ์„ ํƒ์€ ๋ฏธ๋“ค์›จ์–ด์—์„œ ์ผ๋ถ€ ์ˆœ์ˆ˜ ํ•จ์ˆ˜/ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

middleware = (...) => {
  // if(action.type == 'HIGH_LEVEL') 
  handlers[action.name]({ dispatch, params: action.payload })
}
const handlers = {
  async highLevelAction({ dispatch, params }) {
    dispatch({ loading: true });
    const data = await api.getData(params.someId);
    const processed = myPureLogic(data);
    dispatch({ loading: false, data: processed });
  }
}

@bvaughn

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

๋ฉ”๋ชจ์ด์ œ์ด์…˜์ด๋‚˜ ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ์‚ฌ์†Œํ•œ ์ƒํƒœ์˜ ๊ฒฝ์šฐ์—๋„ ๋ชจ๋“  ๊ณณ์—์„œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋ฐ˜๋Œ€ํ•˜๋Š” ์ œ ๊ฒฝ์šฐ:

  • ๋ฆฌ๋“€์„œ์— ๋Œ€ํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ์ด๋ฏธ ์ž˜๋ชป ์ž…๋ ฅ๋œ ์ƒํƒœ ์†์„ฑ์„ ์žก์•„์•ผ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?
  • ๋งค์žฅ ๊ตฌ์กฐ์˜ ๋ณ€๊ฒฝ ์€ ์ œ ๊ฒฝํ—˜์ƒ state.stuff.item1 ๋ฅผ state.stuff.item2 ๋ณ€๊ฒฝํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ๋ชจ๋“  ๊ณณ์—์„œ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์น˜ ๋‹ค๋ฅธ ์ด๋ฆ„์„ ์‹ค์ œ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํŠนํžˆ IDE๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” ์ผ๋ฐ˜์ ์ธ ์ž‘์—…์ด๋ฉฐ ์ƒ๊ฐํ•  ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ๊ณณ์—์„œ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ผ์ข…์˜ ๊ณตํ—ˆํ•œ ์ถ”์ƒํ™”์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์ƒํƒœ ๋ถ€๋ถ„์— ์ง์ ‘ ์•ก์„ธ์Šคํ•˜๋Š” ์ด ๋ฌธ์ œ๋ฅผ ๊ฒฐ์ฝ” ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด API๋ฅผ ํ†ตํ•ด ์ƒํƒœ์— ์•ก์„ธ์Šคํ•˜๋ฉด ์ผ๊ด€์„ฑ์„ ์–ป์„ ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹จ์ˆœ์„ฑ์„ ํฌ๊ธฐํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๋ช…ํžˆ ์„ ํƒ์ž๋Š” ํ•„์š”ํ•˜์ง€๋งŒ ํ•„์ˆ˜ API๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ๋‹ค๋ฅธ ์ฃผ์žฅ์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์‹ค์šฉ์ ์ธ ๊ด€์ ์—์„œ ๋‚ด ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ์ข‹์€ ์ด์œ  ์ค‘ ํ•˜๋‚˜๋Š” reselect ๋˜๋Š” redux-saga์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์„ ํƒ๊ธฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ƒํƒœ ์กฐ๊ฐ์— ์•ก์„ธ์Šคํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ์„ ํƒ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

์ฒ ํ•™์ ์œผ๋กœ ๋งํ•ด์„œ, ๋‚˜๋Š” ํ•ญ์ƒ ์„ ํƒ์ž๋ฅผ ๊ธฐ๋Šฅ์  ์„ธ๊ณ„์˜ "๊ฒŒํ„ฐ ๋ฉ”์†Œ๋“œ"๋กœ ๋ด…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚ด๊ฐ€ Java ๊ฐ์ฒด์˜ public ์†์„ฑ์— ์ ˆ๋Œ€ ์ ‘๊ทผํ•˜์ง€ ์•Š๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ Redux ์•ฑ์—์„œ ์ง์ ‘ ํ•˜์œ„ ์ƒํƒœ์— ์ ‘๊ทผํ•˜์ง€๋„ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@IceOnFire ๊ณ„์‚ฐ์ด ๋น„์‹ธ์ง€ ์•Š๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํ™œ์šฉํ•  ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค.

Getter ๋ฉ”์„œ๋“œ๋Š” Java์—์„œ ์ผ๋ฐ˜์ ์ธ ๊ด€ํ–‰์ผ ์ˆ˜ ์žˆ์ง€๋งŒ JS์—์„œ ์ง์ ‘ POJO์— ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

@timotgl

์Šคํ† ์–ด์™€ ๋‹ค๋ฅธ redux ์ฝ”๋“œ ์‚ฌ์ด์— API๊ฐ€ ์žˆ๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

์„ ํƒ์ž๋Š” ๋ฆฌ๋“€์„œ์˜ ์ฟผ๋ฆฌ(์ฝ๊ธฐ) ๊ณต๊ฐœ API์ด๊ณ , ์•ก์…˜์€ ๋ฆฌ๋“€์„œ์˜ ๋ช…๋ น(์“ฐ๊ธฐ) ๊ณต๊ฐœ API์ž…๋‹ˆ๋‹ค. Reducer์˜ ๊ตฌ์กฐ๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

์„ ํƒ๊ธฐ์™€ ์•ก์…˜์€ ๋ฆฌ๋“€์„œ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ UI ๋ ˆ์ด์–ด์™€ ์‚ฌ๊ฐ€ ๋ ˆ์ด์–ด(redux-saga๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ)์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

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

์„ ํƒ๊ธฐ๋ฅผ ๊ฐ์†๊ธฐ์˜ "์ฝ๊ธฐ" API๋กœ ์ƒ๊ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ œ ์งˆ๋ฌธ์€ ์„ ํƒ๊ธฐ๋ฅผ ์ฒ˜์Œ์— ํ•„์ˆ˜ API๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์ •๋‹นํ™”ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค(๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹Œ ํ”„๋กœ์ ํŠธ์—์„œ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋กœ ์‹œํ–‰ํ•  ๋•Œ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. ์„ค๊ณ„).

@timotgl ์˜ˆ, ์„ ํƒ์ž๋Š” ํ•„์ˆ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์•ฑ ์ฝ”๋“œ์˜ ํ–ฅํ›„ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์— ๋Œ€๋น„ํ•˜์—ฌ ๊ฐœ๋ณ„์ ์œผ๋กœ ๋ฆฌํŒฉํ† ๋งํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

  • ํŠน์ • ์ƒํƒœ๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌ์กฐํ™”๋˜๊ณ  ์ž‘์„ฑ๋˜๋Š”์ง€ (๋ฆฌ๋“€์„œ ๋ฌธ์ œ, ํ•œ ๊ณณ)
  • ํ•ด๋‹น ์ƒํƒœ ๋ถ€๋ถ„์ด ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ์‹(UI ๋ฐ ๋ถ€์ž‘์šฉ ๋ฌธ์ œ, ๋™์ผํ•œ ์ƒํƒœ ๋ถ€๋ถ„์ด ์ฟผ๋ฆฌ๋˜๋Š” ์—ฌ๋Ÿฌ ์œ„์น˜)

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

@sompylasar ์ž…๋ ฅ

์ด๊ฒƒ์€ ์ž ์žฌ์ ์œผ๋กœ ์‚ฌ์†Œํ•œ ์ผ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

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

@timotgl ๊ณต๊ฐœ์ ์œผ๋กœ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ:

export const PROMISE_REDUCER_STATE_IDLE = 'idle';
export const PROMISE_REDUCER_STATE_PENDING = 'pending';
export const PROMISE_REDUCER_STATE_SUCCESS = 'success';
export const PROMISE_REDUCER_STATE_ERROR = 'error';

export const PROMISE_REDUCER_STATES = [
  PROMISE_REDUCER_STATE_IDLE,
  PROMISE_REDUCER_STATE_PENDING,
  PROMISE_REDUCER_STATE_SUCCESS,
  PROMISE_REDUCER_STATE_ERROR,
];

export const PROMISE_REDUCER_ACTION_START = 'start';
export const PROMISE_REDUCER_ACTION_RESOLVE = 'resolve';
export const PROMISE_REDUCER_ACTION_REJECT = 'reject';
export const PROMISE_REDUCER_ACTION_RESET = 'reset';

const promiseInitialState = { state: PROMISE_REDUCER_STATE_IDLE, valueOrError: null };
export function promiseReducer(state = promiseInitialState, actionType, valueOrError) {
  switch (actionType) {
    case PROMISE_REDUCER_ACTION_START:
      return { state: PROMISE_REDUCER_STATE_PENDING, valueOrError: null };
    case PROMISE_REDUCER_ACTION_RESOLVE:
      return { state: PROMISE_REDUCER_STATE_SUCCESS, valueOrError: valueOrError };
    case PROMISE_REDUCER_ACTION_REJECT:
      return { state: PROMISE_REDUCER_STATE_ERROR, valueOrError: valueOrError };
    case PROMISE_REDUCER_ACTION_RESET:
      return { ...promiseInitialState };
    default:
      return state;
  }
}

export function extractPromiseStateEnum(promiseState = promiseInitialState) {
  return promiseState.state;
}
export function extractPromiseStarted(promiseState = promiseInitialState) {
  return (promiseState.state === PROMISE_REDUCER_STATE_PENDING);
}
export function extractPromiseSuccess(promiseState = promiseInitialState) {
  return (promiseState.state === PROMISE_REDUCER_STATE_SUCCESS);
}
export function extractPromiseSuccessValue(promiseState = promiseInitialState) {
  return (promiseState.state === PROMISE_REDUCER_STATE_SUCCESS ? promiseState.valueOrError || null : null);
}
export function extractPromiseError(promiseState = promiseInitialState) {
  return (promiseState.state === PROMISE_REDUCER_STATE_ERROR ? promiseState.valueOrError || true : null);
}

์ €์žฅ๋˜๋Š” ๊ฒƒ์ด state, valueOrError ์ธ์ง€ ์•„๋‹ˆ๋ฉด ๋‹ค๋ฅธ ๊ฒƒ์ธ์ง€๋Š” ์ด ๊ฐ์†๊ธฐ ์‚ฌ์šฉ์ž์˜ ๊ด€์‹ฌ์‚ฌ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์ƒํƒœ ๋ฌธ์ž์—ด(์—ด๊ฑฐํ˜•), ํ•ด๋‹น ์ƒํƒœ์— ๋Œ€ํ•ด ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ฒ€์‚ฌ, ๊ฐ’ ๋ฐ ์˜ค๋ฅ˜๊ฐ€ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” "์„ ํƒ์ž ์ŠคํŒŒ๊ฒŒํ‹ฐ"๋ฅผ ์ ‘ํ–ˆ๋Š”๋ฐ, ์ƒํƒœ์˜ ๋ชจ๋“  ์‚ฌ์†Œํ•œ ํ•˜์œ„ ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์ค‘์ฒฉ ์„ ํƒ์ž๊ฐ€ ์ƒ๋‹นํ•œ ํ˜ผ๋ž€์„ ์•ผ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ค‘์ฒฉ์ด ๋ฆฌ๋“€์„œ ์ค‘์ฒฉ(๊ตฌ์„ฑ)์„ ๋ฏธ๋Ÿฌ๋งํ•˜์—ฌ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ํ•ด๋‹น ๊ฐ์†๊ธฐ์˜ ๊ตฌํ˜„ ์„ธ๋ถ€์ •๋ณด์ž…๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ์˜ ์ผ๋ถ€์— ๋Œ€ํ•ด promiseReducer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์†๊ธฐ๋Š” ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์— ๋”ฐ๋ผ ๋ช…๋ช…๋œ ์ž์ฒด ์„ ํƒ๊ธฐ๋ฅผ ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค. ๋˜ํ•œ ์„ ํƒ๊ธฐ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๋‚ด๋ณด๋‚ด๊ณ  ๊ฐ์†๊ธฐ API์˜ ์ผ๋ถ€๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

function extractTransactionLogPromiseById(globalState, transactionId) {
  return extractState(globalState).transactionLogPromisesById[transactionId] || undefined;
}

export function extractTransactionLogPromiseStateEnumByTransactionId(globalState, transactionId) {
  return extractPromiseStateEnum(extractTransactionLogPromiseById(globalState, transactionId));
}

export function extractTransactionLogPromiseErrorTransactionId(globalState, transactionId) {
  return extractPromiseError(extractTransactionLogPromiseById(globalState, transactionId));
}

export function extractTransactionLogByTransactionId(globalState, transactionId) {
  return extractPromiseSuccessValue(extractTransactionLogPromiseById(globalState, transactionId));
}

์•„, ๋‚ด๊ฐ€ ๊ฑฐ์˜ ์žŠ์–ด ๋ฒ„๋ฆฐ ๋˜ ํ•˜๋‚˜. ํ•จ์ˆ˜ ์ด๋ฆ„๊ณผ ๋‚ด๋ณด๋‚ด๊ธฐ/๊ฐ€์ ธ์˜ค๊ธฐ๋Š” ์ž˜๋˜๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ์ถ•์†Œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ค‘์ฒฉ๋œ ๊ฐœ์ฒด ํ‚ค โ€” ๊ทธ๋‹ค์ง€ ๋งŽ์ง€๋Š” ์•Š์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ๋ง์น˜์ง€ ์•Š์œผ๋ ค๋ฉด ์ถ•์†Œ๊ธฐ์— ์ ์ ˆํ•œ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์ถ”์ ๊ธฐ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

@timotgl : Redux์— ๋Œ€ํ•ด ๊ถŒ์žฅ๋˜๋Š” ๋งŽ์€ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋Š” Redux ๊ด€๋ จ ๋…ผ๋ฆฌ ๋ฐ ๋™์ž‘์„ ์บก์Šํ™”ํ•˜๋ ค๋Š” ์‹œ๋„์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด this.props.dispatch({type : "INCREMENT"}) ๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ ์—ฐ๊ฒฐ๋œ ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์ง์ ‘ ์ž‘์—…์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ Redux์™€ ํ†ต์‹ ํ•˜๊ณ  ์žˆ์Œ์„ "์•Œ๊ฒŒ" ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋” React ๊ด€์šฉ์ ์ธ ๋ฐฉ๋ฒ•์€ ๋ฐ”์ธ๋”ฉ๋œ ์ž‘์—… ์ƒ์„ฑ์ž๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ this.props.increment() ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ Redux ์ž‘์—… ์ƒ์„ฑ์ž์ธ์ง€ ์—ฌ๋ถ€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ ์ „๋‹ฌ ๋ถ€๋ชจ์— ์˜ํ•ด ๋‹ค์šด๋˜๊ฑฐ๋‚˜ ํ…Œ์ŠคํŠธ์˜ ๋ชจ์˜ ํ•จ์ˆ˜.

๋ชจ๋“  ๊ณณ์—์„œ ์ž‘์—… ์œ ํ˜•์„ ์ง์ ‘ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ƒ์ˆ˜ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜์—ฌ ๊ฐ€์ ธ์˜ค๊ณ  ์ถ”์ ํ•˜๊ณ  ์˜คํƒ€ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ mapState ํ•จ์ˆ˜ ๋˜๋Š” ์ฝํฌ์—์„œ state.some.deeply.nested.field ์— ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉํ•ดํ•˜๋Š” ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์Šค๋ ˆ๋“œ์—์„œ ์ด๋ฏธ ์„ค๋ช…ํ–ˆ๋“ฏ์ด ์ด๋Š” ์˜คํƒ€์˜ ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์ด๊ณ  ํŠน์ • ์ƒํƒœ๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ์œ„์น˜๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค๊ณ  ๋ฆฌํŒฉํ† ๋ง์„ ๋” ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค๊ณ  ๊ฐ’๋น„์‹ผ ๋ณ€ํ™˜ ๋…ผ๋ฆฌ๊ฐ€ - ํ•„์š”ํ•˜์ง€ ์•Š๋”๋ผ๋„ ๋งค๋ฒˆ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์„ ํƒ์ž๋ฅผ ์‚ฌ์šฉํ•  _๊ฐ€์ง€๊ณ  ์žˆ์ง€_๋Š” ์•Š์ง€๋งŒ ์ข‹์€ ์•„ํ‚คํ…์ฒ˜ ๊ด€ํ–‰์ž…๋‹ˆ๋‹ค.

๋‚ด ๊ฒŒ์‹œ๋ฌผ Idiomatic Redux: Using Reselect Selectors for Encapsulation and Performance ๋ฅผ ์ฝ๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@markerikson ๋‚˜๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์„ ํƒ๊ธฐ๋‚˜ ๊ฐ’๋น„์‹ผ ๊ณ„์‚ฐ์„ ์œ„ํ•œ ์„ ํƒ๊ธฐ์— ๋Œ€ํ•ด ๋…ผ์Ÿํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” ๋””์ŠคํŒจ์น˜ ์ž์ฒด๋ฅผ ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌํ•  ์˜๋„๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. :)

๋‚ด ์š”์ ์€ ๋‚ด๊ฐ€ ์ด ๋ฏฟ์Œ์— ๋™์˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ƒ์ ์œผ๋กœ๋Š” ๊ฐ์†๊ธฐ ๊ธฐ๋Šฅ๊ณผ ์„ ํƒ๊ธฐ๋งŒ ์ •ํ™•ํ•œ ์ƒํƒœ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•˜๋ฏ€๋กœ ์ผ๋ถ€ ์ƒํƒœ๊ฐ€ ์žˆ๋Š” ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ ์ด ๋‘ ๊ฐ€์ง€ ๋…ผ๋ฆฌ๋งŒ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

state.some.deeply.nested.field ๋Œ€ํ•œ ๊ท€ํ•˜์˜ ์˜ˆ์— ๋Œ€ํ•ด, ๋‚˜๋Š” ์ด๊ฒƒ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด ์„ ํƒ๊ธฐ๋ฅผ ๊ฐ–๋Š” ๊ฐ€์น˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. selectSomeDeeplyNestedField() ๋Š” ํ•˜๋‚˜์˜ ํ•จ์ˆ˜ ์ด๋ฆ„๊ณผ ๋‚ด๊ฐ€ ์ž˜๋ชป ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” 5๊ฐœ์˜ ์†์„ฑ์ž…๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์—, ์ด ๊ฐ€์ด๋“œ๋ผ์ธ์„ ํŽธ์ง€์— ๋”ฐ๋ฅธ๋‹ค๋ฉด const selectSomeField = state => state.some.field; ๋˜๋Š” const selectSomething = state => state.something; ๋˜๋ฉฐ ์–ด๋Š ์‹œ์ ์—์„œ ์ด๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ(๊ฐ€์ ธ์˜ค๊ธฐ, ๋‚ด๋ณด๋‚ด๊ธฐ, ํ…Œ์ŠคํŠธ)๋ฅผ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋‚ด ์˜๊ฒฌ์œผ๋กœ๋Š” ๋” ์ด์ƒ (๋…ผ์Ÿ์˜ ์—ฌ์ง€๊ฐ€ ์žˆ๋Š”) ์•ˆ์ „๊ณผ ์ˆœ๊ฒฐ์„ ์ •๋‹นํ™”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ข‹์€ ์ทจ์ง€์ง€๋งŒ ๊ฐ€์ด๋“œ๋ผ์ธ์˜ ๋…๋‹จ์ ์ธ ์ •์‹ ์„ ๋–จ์น  ์ˆ˜ ์—†๋‹ค. ๋‚˜๋Š” ๋‚ด ํ”„๋กœ์ ํŠธ์˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ์„ ํƒ๊ธฐ๋ฅผ ํ˜„๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ง€๊ธˆ๊นŒ์ง€ ๋‚ด ๊ฒฝํ—˜์ด ๊ทธ๋ ‡๊ฒŒ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํŠน์ • ์กฐ๊ฑด์—์„œ ๋‚˜๋Š” ๋‹น์‹ ์ด ์™œ ์•ˆ์ „๊ณผ ๊ด€์Šต์˜ ์ธก๋ฉด์—์„œ ์‹ค์ˆ˜๋ฅผ ํ•˜๊ณ  ์‹ถ์–ดํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์‹œ๊ฐ„๊ณผ ์ฐธ์—ฌ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. redux๊ฐ€ ์žˆ์–ด์„œ ์ „๋ฐ˜์ ์œผ๋กœ ๋งค์šฐ ๊ธฐ์ฉ๋‹ˆ๋‹ค.

ํ™•์‹ ํ•˜๋Š”. FWIW์—๋Š” ๋‹ค๋ฅธ ์„ ํƒ๊ธฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ Reselect ์ฃผ๋ณ€์˜ ๋ž˜ํผ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด https://github.com/planttheidea/selectorator๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์  ํ‘œ๊ธฐ๋ฒ• ํ‚ค ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‚ด๋ถ€์ ์œผ๋กœ ์ค‘๊ฐ„ ์„ ํƒ๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

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