Unit3 - [React] Custom Component - 2

๊ฐ•์„ฑ์ผยท2023๋…„ 6์›” 21์ผ
0
post-thumbnail

โœ… TIL


์–ด์ œ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ UI๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ์ด์œ ์™€ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— CSS๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๋ก ์ธ CSS-in-JS๋ฅผ ๋ฐฐ์› ๋‹ค.

UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ์ž‘ํ•˜๋Š” React Custom Component ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ์— ์•ž์„œ ๋‹ค์‹œ ๋ณต์Šตํ•ด๋ณด์ž.
์ถ”๊ฐ€๋กœ ์˜ค๋Š˜์€ ๋ฒ„๋ธ”๋ง ๊ฐœ๋… & stopPropagation() ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด์„œ ์ฒ˜์Œ ๋ฐฐ์›Œ์„œ ํ›„๋ฐ˜์— ๋‹ค๋ค„๋ณผ ์˜ˆ์ •์ด๋‹ค.



React Custom Component


UI ์ปดํฌ๋„ŒํŠธ์˜ ํ•„์š”์„ฑ


UI๋ฅผ ๊ฐœ๋ฐœํ•ด ๋ณธ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด UI ๊ฐœ๋ฐœ์€ ๋‹ค๋ฅธ ๋ถ„์•ผ์˜ ๊ฐœ๋ฐœ๋ณด๋‹ค ๋ณต์žกํ•˜๊ณ  ๊นŒ๋‹ค๋กญ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ ๊ฒƒ์ด๋‹ค.
UI ๊ฐœ๋ฐœ์€ ๋„๋Œ€์ฒด ์™œ ๊นŒ๋‹ค๋กœ์šด ๊ฑธ๊นŒ?

ํ”„๋กœ์ ํŠธ์˜ ์ƒํ™ฉ์—์„œ ์ ˆ๋Œ€์ ์œผ๋กœ ๋งŽ์€ ์ˆ˜์˜ ํ™”๋ฉด๊ณผ ๋ณต์žกํ•œ ํ™”๋ฉด์ด ๋ฌธ์ œ์ด๋‹ค.
๊ทธ๋ž˜์„œ ์›น์‚ฌ์ดํŠธ์˜ ๋ชจ๋“  ํ™”๋ฉด๋“ค์„ ๋ถ„์„ํ•ด ๋ณด์•˜๋‹ค.

ํ™”๋ฉด์„ ๋ถ„์„ํ•ด ๋ณด๋‹ˆ ๋ช‡ ๊ฐ€์ง€ ํŒจํ„ด๋“ค์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

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

๊ทธ๋ ‡๋‹ค๋ฉด ๊ฐœ๋ฐœ์ž๋“ค์€ ๋ฐ˜๋ณต๋˜๋Š” UI๋“ค์„ ์–ด๋–ป๊ฒŒ ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์„๊นŒ?

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

๊ฐœ๋ฐœํŒ€๋“ค์€ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„์ž…ํ•จ์œผ๋กœ์จ ์ ˆ๋Œ€์ ์ธ ์ฝ”๋“œ๋Ÿ‰์„ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
๋”๋ถˆ์–ด ํ™”๋ฉด์ด ์ ˆ๋Œ€์ ์œผ๋กœ ๋งŽ๊ณ  ๋ณต์žก๋„๊ฐ€ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๊ฐœ๋ฐœ ๊ธฐ๊ฐ„ ๋‹จ์ถ•์— ์ ˆ๋Œ€์ ์œผ๋กœ ๊ธฐ์—ฌํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.


๋””์ž์ธ ์‹œ์Šคํ…œ์ด๋ž€?


์ด๋Ÿฌํ•œ UI ์ปดํฌ๋„ŒํŠธ๋“ค์˜ ๋ชจ์Œ์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋””์ž์ธ ์‹œ์Šคํ…œ์ด๋ผ๋Š” ์šฉ์–ด๋„ ๋“ฑ์žฅํ•œ๋‹ค.

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

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

์ตœ๊ทผ์— ๋“ฑ์žฅํ•œ ์œ ์ € ์ธํ„ฐํŽ˜์ด์Šค(UI)๋“ค์€ ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด
์ˆ˜๋ฐฑ ๊ฐœ์˜ ๋ชจ๋“ˆ์‹ UI ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žฌ๋ฐฐ์—ด๋œ ๊ตฌ์กฐ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

๋นŒ๋“œ ์ปดํฌ๋„ŒํŠธ



๐Ÿ’ฌ Sprint Review


๐Ÿ”ฅ Bare minimum Requirement


[์˜ˆ์‹œ] ์ฝ”๋“œ์™€ ์‹คํ–‰ ๊ฒฐ๊ณผ


์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด React, Styled Components๋ฅผ ํ™œ์šฉํ•˜์—ฌ React-custom-component๋ฅผ ์™„์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • Modal, Toggle, Tab, Tag ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • npm run test ์Šคํฌ๋ฆฝํŠธ๋กœ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค.
    • /src/tests/index.test.js ์—์„œ ๊ตฌํ˜„ํ•  ์ปดํฌ๋„ŒํŠธ์˜ ํ…Œ์ŠคํŠธ ์ฃผ์„์„ ํ•˜๋‚˜์”ฉ ํ•ด์ œํ•˜๋ฉด์„œ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • npm run storybook ์Šคํฌ๋ฆฝํŠธ๋กœ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋ˆˆ์œผ๋กœ ํ™•์ธํ•˜๋ฉฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด, ํ•˜๋‹จ GIF ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๋ชจ์–‘์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•œ ๋’ค, npm run submit ์Šคํฌ๋ฆฝํŠธ๋กœ ๊ณผ์ œ๋ฅผ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค.

Modal Component ์™„์„ฑ ์˜ˆ์‹œ

Modal UI ์ปดํฌ๋„ŒํŠธ๋Š” ๊ธฐ์กด์˜ ๋ธŒ๋ผ์šฐ์ € ํŽ˜์ด์ง€ ์œ„์— ์ƒˆ๋กœ์šด ์œˆ๋„์šฐ ์ฐฝ์ด ์•„๋‹Œ, ๋ ˆ์ด์–ด๋ฅผ ๊นŒ๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.
(ํŒ์—…์ฐฝ๊ณผ๋Š” ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ์ง์ ‘ ๊ตฌ๊ธ€๋ง์„ ํ†ตํ•ด ์ฐพ์•„๋ณด์„ธ์š”!)
ํ˜„์žฌ ์ œ๊ณต๋˜๊ณ  ์žˆ๋Š” Modal.js๋Š” Modal ๋ฒ„ํŠผ๋งŒ ์žˆ๊ณ  ์•„๋ฌด ๊ธฐ๋Šฅ์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋”ฐ๋ผ Modal ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด ์œ„์˜ GIF ํŒŒ์ผ๊ณผ ๊ฐ™์ด Modal ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด Modal ์ฐฝ์ด ์ผœ์ง€๊ณ  ๊บผ์งˆ ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„ํ•˜์„ธ์š”.

์‹œ์ž‘ํ•˜๊ธฐ

Modal ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„์— ํ•„์š”ํ•œ ์ •๋ณด๊ฐ€ ์ž์„ธํžˆ ์ ํ˜€์žˆ์Šต๋‹ˆ๋‹ค. ํ™•์ธ ํ›„ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜์„ธ์š”.

  • Modal ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๋Š” ์ฃผ์„ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์–ด์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์ง„ํ–‰ํ•ด ์ฃผ์„ธ์š”.
  • Modal ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ state๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ์„œ state๋ฅผ ๋” ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
    • isOpen state๋Š” ๋ชจ๋‹ฌ ์ฐฝ์˜ ์—ด๊ณ  ๋‹ซํž˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ModalBtn ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋‹ฌ ์ฐฝ ์ œ์–ด๋ฅผ ์œ„ํ•ด ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ openModalHandler๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • openModalHandler ํ•จ์ˆ˜๋Š”
      • ModalBtn ํด๋ฆญ ์‹œ ๋ฐœ์ƒ๋˜๋Š” change ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค.
      • ํด๋ฆญํ•  ๋•Œ๋งˆ๋‹ค ์ƒํƒœ๊ฐ€ Boolean ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.
  • ModalView ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  isOpen ์ƒํƒœ๊ฐ€ true ์ผ ๊ฒฝ์šฐ์—๋งŒ ๋ Œ๋”๋ง ํ•ฉ๋‹ˆ๋‹ค.
  • ModalBackdrop ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  isOpen ์ƒํƒœ๊ฐ€ true ์ผ ๊ฒฝ์šฐ์—๋งŒ ๋ Œ๋”๋ง ํ•ฉ๋‹ˆ๋‹ค.

์š”๊ตฌ์‚ฌํ•ญ

  • Styled Components ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ด ModalContainer ModalBackdrop ModalBtn ModalView ์ปดํฌ๋„ŒํŠธ์˜ CSS๋ฅผ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    • ModalContainer : Modal์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ฃผ๋Š” ์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • ModalBackdrop : Modal์ด ๋–ด์„ ๋•Œ์˜ ๋ฐฐ๊ฒฝ์„ ๊น”์•„์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • ModalBtn : Modal ์ฐฝ์„ ์ผœ๊ณ  ๋Œ ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ์ž…๋‹ˆ๋‹ค.
    • ModalView : Modal ์ฐฝ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
  • ๊ตฌํ˜„ํ•œ Styled Components๋“ค์„ Modal ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.

Modal ๋ฒ„ํŠผ ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ

  • ModalBtn์„ ํด๋ฆญํ•˜๋ฉด Modal์ด ์—ด๋ฆฐ ์ƒํƒœ(isOpen)๋ฅผ boolean ํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ํ™œ์šฉํ•ด์„œ Modal์ด ์—ด๋ฆฐ ์ƒํƒœ(isOpen์ด true์ธ ์ƒํƒœ)์ผ ๋•Œ๋งŒ ๋ชจ๋‹ฌ์ฐฝ๊ณผ ๋ฐฐ๊ฒฝ์ด ๋œฐ ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ํ™œ์šฉํ•ด์„œ Modal์ด ์—ด๋ฆฐ ์ƒํƒœ(isOpen์ด true์ธ ์ƒํƒœ)์ผ ๋•Œ๋Š” ModalBtn์˜ ๋‚ด๋ถ€ ํ…์ŠคํŠธ๊ฐ€ 'Opened!'๋กœ Modal์ด ๋‹ซํžŒ ์ƒํƒœ(isOpen์ด false์ธ ์ƒํƒœ)์ผ ๋•Œ๋Š” ModalBtn์˜ ๋‚ด๋ถ€ ํ…์ŠคํŠธ๊ฐ€ 'Open Modal'์ด ๋˜๋„๋ก ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


Toggle Component ์™„์„ฑ ์˜ˆ์‹œ

Toggle UI ์ปดํฌ๋„ŒํŠธ๋Š” ๋‘ ๊ฐ€์ง€ ์ƒํƒœ๋งŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์Šค์œ„์น˜์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•œ๋ฒˆ ๋ˆ„๋ฅด๋ฉด ๋ถˆ์ด ๋“ค์–ด์˜ค๊ณ  ํ•œ๋ฒˆ ๋ˆ„๋ฅด๋ฉด ๋ถˆ์ด ๋‚˜๊ฐ€๋Š” ์Šค์œ„์น˜๋ฅผ Toggle Switch๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Toggle.js๋Š” CSS๋Š” ๊ฑฐ์˜ ์™„์„ฑ๋˜์–ด ์žˆ์ง€๋งŒ ๊ธฐ๋Šฅ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋”ฐ๋ผ Toggle ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด ์œ„์˜ GIF ํŒŒ์ผ๊ณผ ๊ฐ™์ด ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋„๋ก ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ

Toggle ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„์— ํ•„์š”ํ•œ ์ •๋ณด๊ฐ€ ์ž์„ธํžˆ ์ ํ˜€์žˆ์Šต๋‹ˆ๋‹ค. ํ™•์ธ ํ›„ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜์„ธ์š”.

  • ์šฐ์„  Toggle ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ์˜ ์ฃผ์„์„ ํ•ด์ œํ•˜๊ณ  ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • Toggle ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ state๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ์„œ state๋ฅผ ๋” ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
    • isOn state๋Š” ํ† ๊ธ€ ๋ฒ„ํŠผ์˜ on/off ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ToggleContainer ์ปดํฌ๋„ŒํŠธ๋Š” ํ† ๊ธ€ ๋ฒ„ํŠผ ์ œ์–ด๋ฅผ ์œ„ํ•ด ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ toggleHandler๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • toggleHandler ํ•จ์ˆ˜๋Š”
      • ToggleContainer ํด๋ฆญ ์‹œ ๋ฐœ์ƒ๋˜๋Š” change ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค.
      • ํด๋ฆญํ•  ๋•Œ๋งˆ๋‹ค ์ƒํƒœ๊ฐ€ Boolean ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.

์š”๊ตฌ์‚ฌํ•ญ

  • Styled Components ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ด ToggleContainer Desc ์ปดํฌ๋„ŒํŠธ์˜ CSS๋ฅผ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    • ToggleContainer : Toggle์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ฃผ๋Š” ์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • Desc : Toggle Switch์˜ ์ƒํƒœ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ํ…์ŠคํŠธ๋ฅผ ๋‹ด๋Š” ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
  • ToggleContainer ๋‚ด๋ถ€์— .toggle-container .toggle-circle ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง„ div ์š”์†Œ๋ฅผ ๊ฐ๊ฐ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒ์„ฑํ•œ ์š”์†Œ์— ์กฐ๊ฑด๋ถ€ ์Šคํƒ€์ผ๋ง์„ ํ™œ์šฉํ•ด Toggle Switch๊ฐ€ ON์ธ ์ƒํƒœ์ผ ๊ฒฝ์šฐ์—๋งŒ toggle--checked ํด๋ž˜์Šค๋ฅผ ๋‘ ์š”์†Œ ๋ชจ๋‘์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ธฐ๋ณธ CSS์—์„œ๋Š” ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด๊ณผ ์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋ฅผ ํ™œ์šฉํ•ด ์กฐ๊ฑด๋ถ€ ์Šคํƒ€์ผ๋ง์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • <div className={`toggle-container ${isOn ? "toggle--checked" : ""}`} />
  • ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ํ™œ์šฉํ•ด Toggle Switch๊ฐ€ ON์ธ ์ƒํƒœ์ผ ๊ฒฝ์šฐ์— Desc ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ํ…์ŠคํŠธ๋ฅผ 'Toggle Switch ON'์œผ๋กœ Toggle Switch๊ฐ€ OFF์ธ ์ƒํƒœ์ผ ๊ฒฝ์šฐ์—๋Š” 'Toggle Switch OFF'๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
  • ํ† ๊ธ€์Šค์œ„์น˜๊ฐ€ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์˜ฎ๊ฒจ์ง€๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋Š” CSS์˜ transition ์†์„ฑ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ† ๊ธ€์„ ๊ธฐ๋Šฅ์„ ๋‹ค ๊ตฌํ˜„ํ–ˆ๋‹ค๋ฉด ์‹œ๋„ํ•ด ๋ณด์„ธ์š”!


Tab Component ์™„์„ฑ ์˜ˆ์‹œ

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

์‹œ์ž‘ํ•˜๊ธฐ

Tab ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„์— ํ•„์š”ํ•œ ์ •๋ณด๊ฐ€ ์ž์„ธํžˆ ์ ํ˜€์žˆ์Šต๋‹ˆ๋‹ค. ํ™•์ธ ํ›„ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜์„ธ์š”.

  • ์šฐ์„  Tab ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ์˜ ์ฃผ์„์„ ํ•ด์ œํ•˜๊ณ  ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • Tab ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ state๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ์„œ state๋ฅผ ๋” ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
    • currentTab state๋Š” ํ˜„์žฌ tab์˜ index๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • TabMenu ์ปดํฌ๋„ŒํŠธ๋Š” ํ† ๊ธ€ ๋ฒ„ํŠผ ์ œ์–ด๋ฅผ ์œ„ํ•ด ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ selectMenuHandler๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
    • selectMenuHandler ํ•จ์ˆ˜๋Š”
      • TabMenu ํด๋ฆญ ์‹œ ๋ฐœ์ƒ๋˜๋Š” change ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค.
      • ํด๋ฆญํ•  ๋•Œ๋งˆ๋‹ค ์ƒํƒœ๊ฐ€ index ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.
  • li ์š”์†Œ๋ฅผ ์ด์šฉํ•ด ๋ฉ”๋‰ด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฐ ๋ฉ”๋‰ด๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ ๋ทฐ๊ฐ€ ์ „ํ™˜๋˜๋„๋ก handler(selectMenuHandler) ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์กฐ๊ฑด๋ถ€ ์Šคํƒ€์ผ๋ง๊ณผ currentTab ์ƒํƒœ๋ฅผ ์ด์šฉํ•˜์—ฌ ํด๋ฆญํ•œ Tab ๋ฉ”๋‰ด๋งŒ className(submenu focused)๊ณผ CSS ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋„๋ก ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์กฐ๊ฑด๋ถ€ ์Šคํƒ€์ผ๋ง์€ ์•ž์„œ ํ† ๊ธ€์—์„œ ๊ตฌํ˜„ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด๊ณผ ์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”๊ตฌ์‚ฌํ•ญ

Component

  • Styled Components ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ด TabMenu Desc ์ปดํฌ๋„ŒํŠธ์˜ CSS๋ฅผ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    • TabMenu : Tab์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ฃผ๋Š” ์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • Desc : Toggle Switch์˜ ์ƒํƒœ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ํ…์ŠคํŠธ๋ฅผ ๋‹ด๋Š” ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.

TabMenu

  • TabMenu ๋‚ด๋ถ€์— .submenu ํด๋ž˜์Šค๋ช…์„ ๊ฐ€์ง„ li ์š”์†Œ๋“ค์„ map์„ ์ด์šฉํ•œ ๋ฐ˜๋ณต์„ ํ†ตํ•ด ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • TabMenu ๋‚ด๋ถ€์— .submenu ํด๋ž˜์Šค๋ช…์„ ๊ฐ€์ง„ li ์š”์†Œ์˜ textContent๋Š” ๊ฐ ์š”์†Œ์˜ name์ž…๋‹ˆ๋‹ค.

currentTab

  • ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ํ™œ์šฉํ•ด์„œ Tab ๋ฉ”๋‰ด๊ฐ€ ์„ ํƒ๋œ ์ƒํƒœ์ผ ๋•Œ, ์„ ํƒ๋œ Tab ๋ฉ”๋‰ด li ์š”์†Œ์˜ ํด๋ž˜์Šค๋ช…๋งŒ submenu focused ๊ฐ€ ๋˜์–ด์•ผ ํ•˜๊ณ , ์„ ํƒ๋˜์ง€ ์•Š์€ ๋‚˜๋จธ์ง€๋Š” submenu ๊ฐ€ ๋˜๋„๋ก ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • TabMenu๋ฅผ ํด๋ฆญํ•˜๋ฉด ํ˜„์žฌ ์„ ํƒ๋œ ํƒญ์˜ ์ธ๋ฑ์Šค ๊ฐ’์„ ์ „๋‹ฌ๋ฐ›์•„ currentTab ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” selectMenuHandler ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • TabMenu๋ฅผ ํด๋ฆญํ•˜๋ฉด ํ˜„์žฌ ์„ ํƒ๋œ ํƒญ ๋ฉ”๋‰ด๋งŒ .focused CSS๊ฐ€ ์ ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • TabMenu๋ฅผ ํด๋ฆญํ•˜๋ฉด Desc ์ปดํฌ๋„ŒํŠธ์˜ content์˜ ๋‚ด์šฉ์ด ํ•ด๋‹น ํƒญ์˜ content๋กœ ๋ฐ”๋€Œ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


Tag Component ์™„์„ฑ ์˜ˆ์‹œ

Tag UI ์ปดํฌ๋„ŒํŠธ๋Š” ๋ ˆ์ด๋ธ” ์ง€์ •์„ ํ†ตํ•ด ๊ตฌ์„ฑ์ด๋‚˜ ๋ถ„๋ฅ˜์— ๋„์›€์ด ๋˜๋Š” ํ‚ค์›Œ๋“œ ์ง‘ํ•ฉ์„ ๋งŒ๋“ค ๋•Œ ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. Tag.js ๋Š” CSS๋Š” ๊ฑฐ์˜ ์™„์„ฑ๋˜์–ด ์žˆ์ง€๋งŒ ๊ธฐ๋Šฅ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋”ฐ๋ผ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜์—ฌ Tag ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋„๋ก ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค. ๋˜ํ•œ ํ•™์Šตํ•œ Styled Components ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ๋ถ„๋งŒ์˜ ๋ฉ‹์ง„ Tag ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์„ธ์š”.

์‹œ์ž‘ํ•˜๊ธฐ

Tag ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„์— ํ•„์š”ํ•œ ์ •๋ณด๊ฐ€ ์ž์„ธํžˆ ์ ํ˜€์žˆ์Šต๋‹ˆ๋‹ค. ํ™•์ธ ํ›„ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜์„ธ์š”.

  • ์šฐ์„  Tag ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ์˜ ์ฃผ์„์„ ํ•ด์ œํ•˜๊ณ  ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • Tag ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ state๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ์„œ state๋ฅผ ๋” ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
    • tags state๋Š” ๋ฐฐ์—ด์˜ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.
    • ์ดˆ๊นƒ๊ฐ’์œผ๋กœ initialTags๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • TagsInput ์ปดํฌ๋„ŒํŠธ๋Š” ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ addTags๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
    • addTags ํ•จ์ˆ˜๋Š”
      • input ์ฐฝ์— Enter ํ‚ค๋ฅผ ๋ˆ„๋ฅผ ๋•Œ ๋ฐœ์ƒ๋˜๋Š” change ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค.
      • Enter๋ฅผ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค ์ž…๋ ฅํ•œ ๊ฐ’์ด state์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.
  • span.tag-close-icon ์—๋Š” ์•„์ง ์‹ค์ œ ์ž‘๋™ํ•˜๋Š” ์‚ญ์ œ ์•„์ด์ฝ˜(x)์ด ์—†์Šต๋‹ˆ๋‹ค. ์‚ญ์ œ ์•„์ด์ฝ˜์„ ๋งŒ๋“ค๊ณ , ์ด ๋ฒ„ํŠผ์ด ๋™์ž‘ํ•˜๋„๋ก handler (removeTags) ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • hint : 'HTML Entities'๋ผ๋Š” ํ‚ค์›Œ๋“œ๋กœ ๊ตฌ๊ธ€๋ง ํ•ด์„œ ์ฐธ๊ณ ํ•ด ๋ณด์„ธ์š”.

์š”๊ตฌ์‚ฌํ•ญ

input ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ

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

์‚ญ์ œ ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ

  • ๊ธฐ๋ณธ์ ์œผ๋กœ tags ๋ฐฐ์—ด ์•ˆ์˜ ๋ชจ๋“  ํƒœ๊ทธ๋“ค์ด ํ™”๋ฉด์— ๋ณด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ํƒœ๊ทธ ์ด๋ฆ„ ์˜†์— ์‚ญ์ œ ์•„์ด์ฝ˜(x)์ด ํ‘œ์‹œ๋˜๋„๋ก ํ•˜๊ณ , ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ํƒœ๊ทธ๋ฅผ ์‚ญ์ œํ•˜๋Š” removeTags ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • removeTags ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ญ์ œ ์•„์ด์ฝ˜(x)์ด ๋ˆŒ๋ฆฐ ํƒœ๊ทธ๋ฅผ ์‚ญ์ œํ•˜๋„๋ก removeTags ๋ฉ”์„œ๋“œ๋ฅผ ์™„์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ’ฌ Review


Modal Component


[์ฝ”๋“œ] ๋ชจ๋‹ฌ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • Modal: ๋ชจ๋‹ฌ ์ฐฝ์˜ ์ „๋ฐ˜์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•œ๋‹ค.

  • openModalHandler: ์ƒํƒœ ๊ด€๋ฆฌ ์ค‘์ธ isOpen์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.

    • ๋…ผ๋ฆฌ ๋ถ€์ • ์—ฐ์‚ฐ์ž์ธ ! ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ isOpen์˜ boolean ๊ฐ’์„ ์—ญ์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
  • closeModalHandler: modalRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋‹ฌ ์ฐฝ ์™ธ๋ถ€๋ฅผ ํด๋ฆญํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋ชจ๋‹ฌ์„ ๋‹ซ๋„๋ก ์„ค์ •ํ•œ๋‹ค.
    ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋Š” useEffect๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋  ๋•Œ์—๋งŒ ๋“ฑ๋ก๋˜๋ฉฐ, ์–ธ๋งˆ์šดํŠธ ์‹œ์—๋Š” ์ •๋ฆฌ๋œ๋‹ค.

  • ModalBtn: onClick ์œผ๋กœ openModalHandler ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ isOpen๋ฅผ true๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
    ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง(์‚ผํ•ญ ์—ฐ์‚ฐ์ž)์„ ํ™œ์šฉํ•ด์„œ Modal์ด ์—ด๋ฆฌ๊ณ  ๋‹ซํ˜”์„ ๋•Œ, ๋ฒ„ํŠผ ๋ฌธ๊ตฌ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ…์ŠคํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

  • ModalView: ref ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•ด๋‹น ์š”์†Œ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.

  • CloseBtn: onClick ์œผ๋กœ openModalHandler ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ isOpen๋ฅผ false๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

ํŠน์ดํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด, useRef๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  closeModalHandler ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ, ๋ชจ๋‹ฌ ์ฐฝ ์™ธ๋ถ€๋ฅผ ํด๋ฆญํ•  ๋•Œ ๋ชจ๋‹ฌ์ด ๋‹ซํžˆ๊ฒŒ ํ–ˆ๋‹ค.
์ด๋ฅผ ์œ„ํ•ด useRef, useEffect, mousedown ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

const closeModalHandler = (e) => {
    // ๋ชจ๋‹ฌ ์ฐธ์กฐ(modalRef)๊ฐ€ ์กด์žฌํ•˜๊ณ , ํด๋ฆญํ•œ ์š”์†Œ(e.target)๊ฐ€ ๋ชจ๋‹ฌ ์ฐฝ ๋‚ด๋ถ€์— ํฌํ•จ๋˜์ง€ ์•Š์„ ๋•Œ ๋ชจ๋‹ฌ์„ ๋‹ซ๋Š”๋‹ค.
    if (modalRef.current && !modalRef.current.contains(e.target)) {
      setIsOpen(false);
    }
  };

  useEffect(() => {
    // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋  ๋•Œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ถ”๊ฐ€
    document.addEventListener("mousedown", closeModalHandler);
    return () => {
      // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ œ๊ฑฐ
      document.removeEventListener("mousedown", closeModalHandler);
    };
  }, []);


๋„ˆ๋ฌด ๋ณต์žกํ•˜๋‹ค.

๋ฌผ๋ก , useRef์™€ useEffect๋ฅผ ์“ฐ์ง€ ์•Š๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.

isOpen? (
          <ModalBackdrop onClick={openModalHandler}>
            <ModalView onClick={event => event.stopPropagation()}>
              <h2>Modal</h2>
              <p>์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.</p>
              <CloseBtn onClick={openModalHandler}>Close</CloseBtn>
            </ModalView>
          </ModalBackdrop>
        ) : null}


์ „์ฒด๋ฅผ ๋ชจ๋‹ฌ์ฐฝ ๋ฐ–์„ ์˜๋ฏธํ•˜๋Š” Backdrop์œผ๋กœ ๊ฐ์‹ธ์ฃผ๊ณ ,
onClick ์œผ๋กœ openModalHandler ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ์ฃผ๋ฉด ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์ด์™€ ๊ฐ™์ด ์„ค์ • ์‹œ, '๋ฒ„๋ธ”๋ง' ์ด๋ผ๋Š” ํ˜„์ƒ์ด ์ƒ๊ธฐ๊ฒŒ ๋œ๋‹ค.
๋”ฐ๋ผ์„œ ๋ชจ๋‹ฌ์ฐฝ์ธ ModalView์—๋„ stopPropagation() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ํ˜„์ƒ์„ ๋ง‰์•„์ค˜์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ ์œ„ ๊ณผ์ •์ด ์ƒ๋žต๋œ๋‹ค๋ฉด, ๋ชจ๋‹ฌ์ฐฝ ์•ˆ ์ชฝ ์•„๋ฌด ๊ณณ์ด๋‚˜ ํด๋ฆญํ•ด๋„ ๋ฒ„๋ธ”๋ง ํ˜„์ƒ์œผ๋กœ ์ธํ•ด ๋ชจ๋‹ฌ์ฐฝ์ด ๋‹ซํžˆ๊ฒŒ ๋œ๋‹ค.

๋ฒ„๋ธ”๋ง๊ณผ stopPropagation() ๋ฉ”์„œ๋“œ ๊ฐœ๋…์€ Error Note.์—์„œ ๋‹ค๋ฃจ๊ฒ ๋‹ค.



Toggle Component


[์ฝ”๋“œ] ํ† ๊ธ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • Toggle: ํ† ๊ธ€์˜ ์ „๋ฐ˜์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•œ๋‹ค.

  • toggleHandler: ์ƒํƒœ ๊ด€๋ฆฌ ์ค‘์ธ isOn์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.

    • ๋…ผ๋ฆฌ ๋ถ€์ • ์—ฐ์‚ฐ์ž์ธ ! ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ isOn์˜ boolean ๊ฐ’์„ ์—ญ์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
  • ToggleContainer: onClick ์œผ๋กœ toggleHandler ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ isOn๋ฅผ true๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
    ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง(์‚ผํ•ญ ์—ฐ์‚ฐ์ž)์„ ํ™œ์šฉํ•ด์„œ ํ† ๊ธ€ ํด๋ฆญ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.
    ์ถ”๊ฐ€๋กœ props๋ฅผ ๋ฐ›๋Š” ์—ฌ๋ถ€์— ๋”ฐ๋ผ ํ† ๊ธ€์˜ ์ƒ‰์ƒ๊ณผ ์› ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.

  • Desc: ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง(์‚ผํ•ญ ์—ฐ์‚ฐ์ž)์„ ํ™œ์šฉํ•ด์„œ ํ† ๊ธ€ ํด๋ฆญ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ํ…์ŠคํŠธ๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.

ํŠน์ดํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด, ToggleContainer๊ฐ€ checked ๋ผ๋Š” props๋ฅผ ์ „๋‹ฌ๋ฐ›๋Š” ๊ฒƒ์ด๋‹ค.

์ •ํ™•ํžˆ๋Š” checked={isOn} ๋ถ€๋ถ„์—์„œ isOn ๊ฐ’์„ checked props๋กœ ์ „๋‹ฌํ•˜๊ณ  ์žˆ์œผ๋ฉฐ,
์ด๋ ‡๊ฒŒ ์ „๋‹ฌ๋œ checked props๋Š” ToggleContainer ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ props.checked๋กœ ์ฐธ์กฐ๋˜์–ด ์‚ฌ์šฉ๋œ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด Toggle ์Šค์œ„์น˜์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ํ•ด๋‹น ์Šคํƒ€์ผ์ด ์ ์šฉ๋˜๋„๋ก ๊ตฌํ˜„๋˜์—ˆ๋‹ค.

๋ฌผ๋ก , props๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
ToggleContainer ์Šคํƒ€์ผ ์‹œํŠธ ์•ˆ ์ชฝ์— ๋‹ค์Œ ์ฝ”๋“œ๋งŒ ์ถ”๊ฐ€์‹œํ‚ค๋ฉด ๋œ๋‹ค.

   &.toggle--checked {
     background-color: var(--coz-purple-600);
   }


Tab Component


[์ฝ”๋“œ] ํƒญ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • Tab: ํƒญ์˜ ์ „๋ฐ˜์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•œ๋‹ค.

    • ์ „ ๊ธฐ๋Šฅ ๊ตฌํ˜„๋“ค๊ณผ ๋‹ค๋ฅธ ์ ์ด ์žˆ๋‹ค๋ฉด, boolean ๊ฐ’์ด ์•„๋‹Œ number ํ˜•ํƒœ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.
    • ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋Š” menuArr ๋ผ๋Š” ๋ฐฐ์—ด ์•ˆ์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค.
  • menuArr: ์„ ํƒ๋œ ํƒญ ์ •๋ณด๋ฅผ ๊ฐ์ฒด ๋ชจ์Œ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด์ด๋‹ค.

  • selectMenuHandler: parameter๋กœ ํ˜„์žฌ ์„ ํƒํ•œ index ๊ฐ’์„ ์ „๋‹ฌํ•œ๋‹ค.

  • TabMenu: ์•ˆ ์ชฝ์— ๋ฐฐ์—ด์ธ menuArr์˜ ๊ฐ์ฒด ์ •๋ณด๋ฅผ map์œผ๋กœ ๋ฟŒ๋ ค์ค€๋‹ค.

    • map ํ•จ์ˆ˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋ฐ›์œผ๋ฉฐ, ์ฒซ ๋ฒˆ์งธ ์ธ์ž์ธ ๋งค๊ฐœ๋ณ€์ˆ˜ el์€ ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ์˜๋ฏธํ•˜๊ณ ,
      ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜ index๋Š” ํ•ด๋‹น ์š”์†Œ์˜ ์ธ๋ฑ์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
    • map์œผ๋กœ ๊ฐ์ž ๋ฟŒ๋ ค์ง„ ์ •๋ณด๋“ค์€ <li> ์š”์†Œ๋กœ ๋ Œ๋”๋ง๋˜๋ฉฐ, onClick ์œผ๋กœ ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ํด๋ฆญ ์‹œ,
      selectMenuHandler ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ index ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.
    • ๋™์‹œ์— ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง(์‚ผํ•ญ ์—ฐ์‚ฐ์ž)์„ ํ™œ์šฉํ•ด์„œ ํƒญ ํด๋ฆญ ์‹œ,
      ํด๋ฆญ ํ•ด๋‹น ํƒญ index์™€ ํ˜„์žฌ ํด๋ฆญํ•œ ํƒญ์ด ๋งž๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.
    • ์ถ”๊ฐ€๋กœ ๊ฐ ํƒญ์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•œ๋‹ค.
  • Desc: ์„ ํƒ๋œ ํƒญ์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ์ฒด์˜ content ์†์„ฑ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

    • menuArr ๋ฐฐ์—ด์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ ์ค‘์ธ currentTab ๋ณ€์ˆ˜์— ํ•ด๋‹นํ•˜๋Š” ์ธ๋ฑ์Šค์— ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์„ ํƒํ•œ๋‹ค.
    • ๊ทธ๋ฆฌ๊ณ  ํด๋ฆญํ•œ ํ˜„์žฌ ํƒญ์˜ ๋‚ด๋ถ€ ์ •๋ณด(content)๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.


Tag Component


[์ฝ”๋“œ] ํƒœ๊ทธ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • Tag: ํƒœ๊ทธ์˜ ์ „๋ฐ˜์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•œ๋‹ค.

    • ์ „ ๊ธฐ๋Šฅ ๊ตฌํ˜„๋“ค๊ณผ ๋‹ค๋ฅธ ์ ์ด ์žˆ๋‹ค๋ฉด, boolean ๊ฐ’์ด ์•„๋‹Œ initialTags ๋ฐฐ์—ด ๋ฐ์ดํ„ฐ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.
  • removeTags: ํƒœ๊ทธ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

    • indexToRemove ๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์œผ๋ฉฐ, ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์‚ญ์ œํ•  ํƒœ๊ทธ์˜ ์ธ๋ฑ์Šค๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
    • setTags ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ tags ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
    • tags.filter() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•œ๋‹ค.
      filter ๋ฉ”์„œ๋“œ๋Š” ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๋“ค๋กœ ๊ตฌ์„ฑ๋œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • ์ฝœ๋ฐฑ ํ•จ์ˆ˜ (el, index) => indexToRemove !== index ๋Š” tags ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ์— ๋Œ€ํ•ด ์‹คํ–‰๋œ๋‹ค.
      ์ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ํ˜„์žฌ ์š”์†Œ์˜ ์ธ๋ฑ์Šค๊ฐ€ indexToRemove ์™€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋งŒ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ํ•ด๋‹น ์š”์†Œ๋ฅผ ์œ ์ง€ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ indexToRemove์™€ ์ผ์น˜ํ•˜๋Š” ์ธ๋ฑ์Šค๋ฅผ ๊ฐ€์ง„ ์š”์†Œ๋Š” ํ•„ํ„ฐ๋ง๋˜์–ด ์ œ์™ธ๋œ๋‹ค.
  • addTags: event๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ๋œ ๊ฐ’์„ ํƒœ๊ทธ ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•œ๋‹ค.

    • ์กฐ๊ฑด๋ฌธ !tags.includes(event.target.value) ์„ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฏธ ์žˆ๋Š” ํƒœ๊ทธ๋ผ๋ฉด ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • ์กฐ๊ฑด๋ฌธ event.target.value !== "" ์„ ์‚ฌ์šฉํ•ด์„œ ์ž…๋ ฅ๋œ ๊ฐ’์ด ๋น„์–ด์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
    • event.target.value = "" ๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ ์ฐฝ์˜ ๊ฐ’์„ ๋นˆ ๋ฌธ์ž์—ด๋กœ ์„ค์ •ํ•˜์—ฌ ๋น„์šด๋‹ค.
  • TagsInput: ์‚ฌ์šฉ์ž๊ฐ€ ํƒœ๊ทธ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก UI๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

    • <ul> ํƒœ๊ทธ ๋‚ด์— ์žˆ๋Š” <li> ํƒœ๊ทธ๋“ค์€ tags ๋ฐฐ์—ด์˜ ๊ฐ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ๋ Œ๋”๋ง๋œ๋‹ค.
      tags.map ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ํƒœ๊ทธ๋ฅผ ์ˆœํšŒํ•˜๊ณ , ๊ฐ ํƒœ๊ทธ์— ๋Œ€ํ•œ <li> ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    • <li> ํƒœ๊ทธ์˜ ๋‚ด๋ถ€์—๋Š” tag ๊ฐ’์„ ํ‘œ์‹œํ•˜๋Š” <span> ์š”์†Œ์™€ ์‚ญ์ œ ์•„์ด์ฝ˜์„ ๋‚˜ํƒ€๋‚ด๋Š” <span> ์š”์†Œ๊ฐ€ ์žˆ๋‹ค.
      removeTags ํ•จ์ˆ˜๋Š” ์‚ญ์ œ ์•„์ด์ฝ˜์ด ํด๋ฆญ๋˜๋ฉด ์‹คํ–‰๋˜๋„๋ก ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค.
    • <input> ์š”์†Œ๋Š” ํƒœ๊ทธ๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
      ์ž…๋ ฅ์ฐฝ์— ํƒœ๊ทธ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  Enter ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด addTags ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
      • onKeyUp ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‚ค๋ณด๋“œ์˜ Enter ํ‚ค๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ์ด ๊ฒฝ์šฐ์— addTags ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
      • ์ž…๋ ฅ ์ฐฝ์—๋Š” "Press enter to add tags"๋ผ๋Š” placeholder๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค.


๐Ÿ’ก Error Note.


๐Ÿ’ก ๋ฒ„๋ธ”๋ง

  • HTML ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๊ฐ€ ๋ถ€๋ชจ ์š”์†Œ๋กœ ์ „ํŒŒ๋˜๋Š” ๋™์ž‘์„ ๋งํ•œ๋‹ค.
    ์ฆ‰, ํ•˜์œ„ ์š”์†Œ์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์œ„ ์š”์†Œ๋กœ ์—ฐ์‡„์ ์œผ๋กœ ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

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

  • <div id="outer">
      <div id="inner">
        <button id="button">Click me!</button>
      </div>
    </div>
    
  • button ์š”์†Œ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” click ์ด๋ฒคํŠธ๋Š” ๋ฒ„๋ธ”๋ง์„ ํ†ตํ•ด ์ƒ์œ„ ์š”์†Œ๋กœ ์ „ํŒŒ๋œ๋‹ค.
    ๋”ฐ๋ผ์„œ, button ์š”์†Œ์— ์—ฐ๊ฒฐ๋œ click ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋จผ์ € ์‹คํ–‰๋œ ํ›„, inner ์š”์†Œ์˜ click ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋˜๊ณ , ๋งˆ์ง€๋ง‰์œผ๋กœ outer ์š”์†Œ์˜ click ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

  • ์ด๋Ÿฌํ•œ ๋ฒ„๋ธ”๋ง ๋™์ž‘์€ ์ด๋ฒคํŠธ์˜ ์ „ํŒŒ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ์ƒ์œ„ ์š”์†Œ์—์„œ ํ•˜์œ„ ์š”์†Œ๋กœ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ƒ์œ„ ์š”์†Œ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ event.stopPropagation() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ฒ„๋ธ”๋ง์„ ์ค‘์ง€์‹œํ‚ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

๐Ÿ’ก event.stopPropagation() ๋ฉ”์†Œ๋“œ

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

  • ์ด ๋ฉ”์†Œ๋“œ๋Š” ์ฃผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.

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

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

  • ์ฃผ์˜ํ•  ์ ์€ event.stopPropagation()์€ ์ด๋ฒคํŠธ ์ „ํŒŒ๋ฅผ ํ˜„์žฌ ์š”์†Œ์—์„œ๋งŒ ์ค‘์ง€์‹œํ‚ค๊ณ , ๋‹ค๋ฅธ ์š”์†Œ์— ์—ฐ๊ฒฐ๋œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ๊ณ„์† ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ, ๋™์ผํ•œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ์š”์†Œ์—์„œ๋„ ์ค‘์ง€์‹œํ‚ค๊ณ ์ž ํ•œ๋‹ค๋ฉด ๊ฐ ์š”์†Œ์— ๋Œ€ํ•ด ๊ฐœ๋ณ„์ ์œผ๋กœ event.stopPropagation()์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿ’ก .toggle-container.toggle--checked ์™€ .toggle-container .toggle--checked

  • ๋‘˜์€ ์„œ๋กœ ๋‹ค๋ฅธ ์„ ํƒ์ž์ด๋‹ค.
  • .toggle-container.toggle--checked: .toggle-container์™€ .toggle--checked ํด๋ž˜์Šค๊ฐ€ ๋™์‹œ์— ์ ์šฉ๋œ ์š”์†Œ๋ฅผ ์„ ํƒํ•œ๋‹ค. ์ฆ‰, ๊ฐ™์€ ์š”์†Œ์— ๋‘ ๊ฐœ์˜ ํด๋ž˜์Šค๊ฐ€ ํ•จ๊ป˜ ์ ์šฉ๋œ ๊ฒฝ์šฐ๋ฅผ ์„ ํƒํ•œ๋‹ค.
  • .toggle-container .toggle--checked: .toggle-container ์š”์†Œ์˜ ํ•˜์œ„์— ์žˆ๋Š” .toggle--checked ํด๋ž˜์Šค๊ฐ€ ์ ์šฉ๋œ ์š”์†Œ๋ฅผ ์„ ํƒํ•œ๋‹ค. ์ฆ‰, .toggle-container ์š”์†Œ์˜ ์ž์‹ ์š”์†Œ ์ค‘์— .toggle--checked ํด๋ž˜์Šค๊ฐ€ ์ ์šฉ๋œ ์š”์†Œ๋ฅผ ์„ ํƒํ•œ๋‹ค.
  • ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด์—ˆ๋˜ &.toggle--checked ์œผ๋กœ๋„ ํ•ด๊ฒฐ ๊ฐ€๋Šฅํ•˜๋‹ค !
profile
์•„์ด๋””์–ด๊ฐ€ ๋„˜์น˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฟˆ๊ฟ‰๋‹ˆ๋‹ค ๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€