TIL 42: [React] ์ƒํƒœ ๊ด€๋ฆฌ

 ์˜ค๋Š˜์€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜์ธ Redux๋ฅผ ์‚ฌ์šฉํ•ด์„œ Sprint๋ฅผ ๊ณต๋ถ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์•ž์„œ ๋งํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ „์—ญ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ์–ด props drilling์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ฃผ๋Š”๋ฐ์š”! ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌํ•˜๊ณ  ๊ทธ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค!

 

 

Flux

์•„๋ž˜ ์˜์ƒ๊ณผ ๊ณต์‹๋ฌธ์„œ๋ฅผ ํ†ตํ•ด Flux์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

https://facebook.github.io/flux/docs/in-depth-overview/

 

In-Depth Overview | Flux

Flux is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can

facebook.github.io

 

 

 

 

Flux๋Š” ํŽ˜์ด์Šค๋ถ์—์„œ MVC์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœํ•œ ์•„ํ‚คํ…์ฒ˜์ž…๋‹ˆ๋‹ค.

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

Flux์˜ ์žฅ์ ์œผ๋กœ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Improved data consistency
  • Easier to pintpoint root of a bug
  • More meaningful unit tests

 

 

 

 

 

 

Flux์˜ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์€ ์•„๋ž˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. Action์€ Dispatcher๋ฅผ ํ†ตํ•ด Store๋กœ, Store์—์„œ View๋กœ, View๋Š” Action์„ ํ†ตํ•ด ๋‹ค์‹œ Dispatcher๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ํ๋ฅด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์€ ๋ฐ์ดํ„ฐ ๋ณ€ํ™”๋ฅผ ํ›จ์”ฌ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ์•ž์„œ ๋งํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. 

 

 

 

Dispatcher

Flux์—์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. Action์„ ์ „๋‹ฌํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค. Action์—์„œ ์ƒˆ๋กœ์šด action์„ ๋ณด๋‚ด๋ฉด Store๋Š” dispatcher๋ฅผ ํ†ตํ•ด action์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณต์žกํ•ด์งˆ์ˆ˜๋ก Dispatcher์˜ ์ค‘์š”์„ฑ์€ ์ปค์ง‘๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋“ค ๊ฐ„์˜ ์˜์กด์„ฑ์„ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ MVC๋ณด๋‹ค ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Redux์—์„œ๋Š” Reducer๋ฅผ ํ˜ธ์ถœํ•ด state ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

const state = useSelector(state => state.itemReducer);
// useSelector๋Š” ์ปดํฌ๋„ŒํŠธ์™€ state๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. 
// ์ปดํฌ๋„ŒํŠธ์—์„œ useSelector ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด store์˜ state์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const { items, cartItems } = state;
const dispatch = useDispatch();
// useDispatch()๋Š” Action ๊ฐ์ฒด๋ฅผ Reducer๋กœ ์ „๋‹ฌํ•ด์ฃผ๋Š” ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค. 
// Action์ด ์ผ์–ด๋‚ ๋งŒํ•œ ๊ณณ์€ ํด๋ฆญ ๋“ฑ์˜ ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.

 

Store

Dispatcher์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•˜๋ฉด Dispatcher๋กœ๋ถ€ํ„ฐ ๋ฉ”์„ธ์ง€๋ฅผ ์ˆ˜์‹ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Store๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ณ€๊ฒฝ๋œ ์‚ฌ์‹ค์„ View์— ์•Œ๋ฆฌ๊ณ , View๋Š” ์ƒˆ ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

View

View๋Š” ํ™”๋ฉด์— ์ƒˆ ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธํ•ด์„œ ๋‚˜ํƒ€๋‚ด๊ณ , View Controller์˜ ์—ญํ• ๋„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. Conroller-View๋Š” ์ž์‹ View๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

 

Action

์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š” ๊ฐ์ฒด๊ฐ€ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ์ „๋‹ฌ๋˜๋Š” ๊ฐ์ฒด๋ฅผ Action์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

์ฆ‰, ์–ด๋–ค ์•ก์…˜์„ ์ทจํ•  ๊ฒƒ์ธ์ง€ ์ •์˜ํ•ด๋†“์€ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ด๋ฆ„์ด ์ ํžŒ type๊ณผ ์š”์ฒญ ๊ธฐ๋Šฅ์ธ payload๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

export const addToCart = (itemId) => {
  return {
    type: ADD_TO_CART,
    payload: {
      quantity: 1,
      itemId
    }
  }
}