๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Frontend Dev/๐Ÿฅ ์ฝ”๋“œ์Šคํ…Œ์ด์ธ  FE ๋ถ€ํŠธ์บ ํ”„

Section3 Unit4 [React] ์ƒํƒœ ๊ด€๋ฆฌ

๋ฐ˜์‘ํ˜•


Section3 Unit4 [React] ์ƒํƒœ ๊ด€๋ฆฌ

 

๐Ÿ“Œ Chapter1. ์ƒํƒœ ๊ด€๋ฆฌ

• ์ƒํƒœ๋ž€, UI์— ๋™์ ์œผ๋กœ ํ‘œํ˜„๋  ๋ฐ์ดํ„ฐ

๋กœ์ปฌ ์ƒํƒœ๋Š” ํŠน์ • ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ๋งŒ ๊ด€๋ฆฌ๋˜๋Š” ์ƒํƒœ๋กœ ๋ณดํ†ต ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ๋งŒ ์˜ํ–ฅ์„ ๋ผ์นœ๋‹ค. ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” ํผ(form) ๋ฐ์ดํ„ฐ๋Š” ๋Œ€๋ถ€๋ถ„ ๋กœ์ปฌ ์ƒํƒœ๋กœ input box, select box ๋“ฑ๊ณผ ๊ฐ™์ด ์ž…๋ ฅ๊ฐ’์„ ๋ฐ›๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ด์— ํ•ด๋‹นํ•œ๋‹ค.

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

 → ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ํˆด๋กœ๋Š” React Context, Redux ๋“ฑ์ด ์žˆ๋‹ค. 

 → ์ƒํƒœ ๊ด€๋ฆฌ ํˆด์€ ์ „์—ญ ์ƒํƒœ๋ฅผ ์œ„ํ•œ ์ €์žฅ์†Œ๋ฅผ ์ œ๊ณตํ•˜๊ณ , props drilling์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์ด์ ์ด ์žˆ๋‹ค.

 

๐Ÿ‘€ npm trends๋ฅผ ๋ณด๋ฉด, redux๊ฐ€ ์—ฌ์ „ํžˆ ์••๋„์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ“Œ Chapter2. Props Drilling

Props Drilling๊ณผ ์ƒํƒœ๊ด€๋ฆฌ์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๋”ฐ๋กœ ์ •๋ฆฌ๋ฅผ ํ•ด๋ณด์•˜๋‹ค. 

 

React์˜ Props Drilling๊ณผ ์ƒํƒœ๊ด€๋ฆฌ

๐Ÿ‘พ Props Drilling์ด๋ž€? Props Drilling์€ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์˜ state๋ฅผ props๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•˜๊ณ ์ž ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ๊ทธ ์‚ฌ์ด๋Š” props๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์šฉ๋„๋กœ๋งŒ ์“ฐ์ด๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฑฐ์น˜๋ฉด์„œ ๋ฐ์ดํ„ฐ๋ฅผ

fay-story.com

 

โญ๏ธ ๊ณผ์ œ. Cmarket Hooks

โœ”๏ธ Bare Minimum Requirement 

 โœ… react-router-dom์„ ์ด์šฉํ•ด Client Side Routingํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค. 

 โœ… useState๋ฅผ ์ด์šฉํ•ด ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

  • ์‡ผํ•‘๋ชฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฃผ์š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์„ธ์š”.

    โœ… [์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‹ด๊ธฐ] ๋ฒ„ํŠผ์„ ์ด์šฉํ•ด ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ํ•ด๋‹น ์ƒํ’ˆ์ด ์ถ”๊ฐ€๋˜๋„๋ก ๊ตฌํ˜„ํ•˜์„ธ์š”.

    โœ… ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‚ด [์‚ญ์ œ] ๋ฒ„ํŠผ์„ ์ด์šฉํ•ด ์žฅ๋ฐ”๊ตฌ๋‹ˆ์˜ ์ƒํ’ˆ์ด ์ œ๊ฑฐ๋˜๋„๋ก ๊ตฌํ˜„ํ•˜์„ธ์š”.

    โœ… ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‚ด์—์„œ ๊ฐ ์•„์ดํ…œ ๊ฐœ์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์„ธ์š”.

    โœ… ์žฅ๋ฐ”๊ตฌ๋‹ˆ์˜ ์ƒํ’ˆ ๊ฐœ์ˆ˜์˜ ๋ณ€๋™์ด ์ƒ๊ธธ ๋•Œ๋งˆ๋‹ค, ์ƒ๋‹จ ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋ฐ”์— ์ƒํ’ˆ ๊ฐœ์ˆ˜๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋„๋ก ๊ตฌํ˜„ํ•˜์„ธ์š”.

 

โœ๏ธ ๊ณผ์ œ ๊ตฌํ˜„ ์ฝ”๋“œ

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

 ์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋‚ด๊ฐ€ ํ—ท๊ฐˆ๋ ธ๋˜ ๋ถ€๋ถ„๋งŒ ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค. ๊ฐ€์žฅ ์–ด๋ ค์› ๋˜ ๋ถ€๋ถ„์€ handleQuantityChange ์˜€๋Š”๋ฐ, quantity๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐ”๊พธ์–ด์•ผ ํ•˜๋Š”์ง€ ๊ณ„์† ๊ณ ๋ฏผ์„ ํ–ˆ์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

 Redux์— ๋“ค์–ด๊ฐ€๊ธฐ ์ „์— Props๋กœ ์ƒํƒœ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ถˆํŽธํ•จ์„ ๋Š๊ปด๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ณผ์ œ์˜€๋‹ค. ๐Ÿ™‚

 

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป handleClick

const handleClick = (e, id) => { 

  const addItem = items.filter((item) => item.id === id)
  console.log("addItem", addItem);

  // 1. ์ฒซ๋ฒˆ์งธ ๋ฐฉ๋ฒ•
  // some: ํ•ด๋‹น ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์š”์†Œ์— ๋Œ€ํ•˜์—ฌ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ช…์‹œ๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ ํ›„, ๊ทธ ๊ฒฐ๊ด๊ฐ’์ด ํ•˜๋‚˜๋ผ๋„ true์ด๋ฉด true๋ฅผ ๋ฐ˜ํ™˜
  /*
  if ( !cartItems.some((item) => item.itemId === addItem[0].id) ) {
    setCartItems((prev) => [...prev, {
      itemId: id,
      quantity: 1
    }])
    setCount((prev) => prev + 1)
  }
  */
  

  // 2. ๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•
  // findIndex: ์ „๋‹ฌ๋ฐ›์€ ํ•จ์ˆ˜๋ฅผ ๋งŒ์กฑํ•˜๋Š” ๋ฐฐ์—ด ์š”์†Œ์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ์˜ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜ํ™˜. ๋งŒ์กฑํ•˜๋Š” ๊ฐ’์ด ์—†์œผ๋ฉด -1์„ ๋ฐ˜ํ™˜.
  const idx = cartItems.findIndex((item) => item.itemId === id)
  
  // ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์•„์ดํ…œ์ด ์—†๋Š” ๊ฒฝ์šฐ(idx === -1) ์•„์ดํ…œ ์ถ”๊ฐ€
  // ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์•„์ดํ…œ์ด ์ด๋ฏธ ๋“ค์–ด์žˆ๋Š” ๊ฒฝ์šฐ(idx !== -1) quantity ์ถ”๊ฐ€
  if (idx === -1) {
    setCartItems((prev) => [...prev, {
      itemId: addItem[0].id,
      quantity: 1
    }])
    setCount((prev) => prev + 1)
  } else {
    setCartItems([...cartItems]);
    cartItems[idx].quantity += 1
  }

  // 3. ๋‹จ, ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ X
  // ๋ฆฌ์•กํŠธ์—์„œ ์ƒํƒœ(state)๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๋Š” ์ƒํƒœ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค.
  // push๋ฅผ ์‚ฌ์šฉํ•ด ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ํ•ด๋‹น ๋ฐฐ์—ด์˜ ์ƒํƒœ๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋ฏ€๋กœ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Œ
  /*
  if ( !cartItems.some((item) => item.itemId === addItem[0].id) ) {
    cartItems.push( {'itemId': id, 'quantity' : 1} );
    setCartItems(cartItems);
    setCount((prev) => prev + 1);
  }
  */
}

 

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป handleQuantityChange, handleDelete

const handleQuantityChange = (quantity, itemId) => {
  // console.log(quantity, itemId)

  // ๋‚ด๊ฐ€ ์“ด ์ฝ”๋“œ
  /*
  const updatedItems = [...cartItems];
  const idx = cartItems.findIndex((item) => item.itemId === itemId);
  updatedItems[idx].quantity = quantity;
  setCartItems(updatedItems)
  */

  // ๋ผ์ด๋ธŒ์„ธ์…˜ ์ฝ”๋“œ
  setCartItems((oldItem) => 
    oldItem.map((item) => (item.itemId === itemId ? { ...item, quantity } : item))
  )
}

const handleDelete = (itemId) => {
  // ๋‚ด๊ฐ€ ์“ด ์ฝ”๋“œ
  setCartItems( cartItems.filter((item) => item.itemId !== itemId) )

  // ๋ผ์ด๋ธŒ์„ธ์…˜ ์ฝ”๋“œ
  // reduce๋ฅผ ์‚ฌ์šฉํ•ด์„œ delete ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜๋„ ์žˆ๋‹ค!
  /*
  setCartItems((oldItem) => (
    oldItem.reduce((acc, item) => {
      // console.log("acc", acc, "item", item)
      return item.itemId === itemId ? acc : acc.concat([item])
    }, [])
  ))
  */

  setCheckedItems(checkedItems.filter((el) => el !== itemId))
  setCount((prev) => prev - 1)
}

 


๐ŸŒ™  ์˜ค๋Š˜์˜ ํšŒ๊ณ 

 ์‹œ๊ฐ„์ด ์™œ์ด๋ ‡๊ฒŒ ๋น ๋ฅธ์ง€ ๋ฒŒ์จ Redux๋ฅผ ํ•™์Šตํ•˜๋Š” ์œ ๋‹›๊นŒ์ง€ ์™”๋‹ค. ๋ณธ๊ฒฉ์ ์œผ๋กœ ๋ฆฌ๋•์Šค๋ฅผ ํ•™์Šตํ•˜๊ธฐ ์ „์— ๋ฆฌ๋•์Šค๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€, Props Drilling์ด ์–ผ๋งˆ๋‚˜ ๋ถˆํŽธํ•œ์ง€์— ๋Œ€ํ•ด ์‹ค์Šตํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์กŒ๋‹ค. ๋ฆฌ๋•์Šค ๋ฌธ๋ฒ•์ด ์ต์ˆ™ํ•˜์ง€ ์•Š๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ์ด๋ฒˆ์— Cmarket ๊ณผ์ œ๋ฅผ ํ•˜๋ฉฐ state์™€ ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด props๋กœ ์—ฌ๋Ÿฌ๋ฒˆ ์ „๋‹ฌ์„ ํ•˜๋Š”๋ฐ์„œ ๋ถˆํŽธํ•จ์„ ๋งŽ์ด ๋Š๊ผˆ๊ธฐ ๋•Œ๋ฌธ์— (์ด์ „์—๋„ ๋ฆฌ์•กํŠธ๋ฅผ ๊ณต๋ถ€ํ•˜๋ฉฐ props๋ฅผ ์—ฌ๋Ÿฌ ์ฐจ๋ก€ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ถˆํŽธํ•จ์„ ๋Š๋ผ๊ณค ํ–ˆ๋‹ค.) ๋ฆฌ๋•์Šค๊ฐ€ ์ด ๋ถˆํŽธํ•จ์„ ํ•ด์†Œ์‹œ์ผœ์ค„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” ์ค‘์ด๋‹ค..!

 ๋ฆฌ๋•์Šค๋Š” ์–ด๋–จ๊นŒ?! ๊ถ๊ธˆํ•˜๋‹ˆ๊นŒ ์–ผ๋ฅธ ๊ณต๋ถ€๋ฅผ ํ•˜๋Ÿฌ ๊ฐ€๋ด์•ผ๊ฒ ๋‹ค! ๐Ÿ“š

๋ฐ˜์‘ํ˜•