Skip to content

Conversation

@Dawon-Y
Copy link
Contributor

@Dawon-Y Dawon-Y commented Dec 18, 2025

๐Ÿ“ ๋ฏธ์…˜ ๋ฒˆํ˜ธ

10์ฃผ์ฐจ Misson 0, 1, 2

๐Ÿ“‹ ๊ตฌํ˜„ ์‚ฌํ•ญ

  • useCallback๊ณผ memo, useMemo ์ง„ํ–‰ํ•˜๊ธฐ
  • ์˜ํ™” ์‚ฌ์ดํŠธ ๋ Œ๋”๋ง ์ตœ์ ํ™”ํ•˜๊ธฐ
  • ์˜ํ™” ์‚ฌ์ดํŠธ Vercel๋กœ ๋ฐฐํฌํ•˜๊ธฐ

๐Ÿ“Ž ์Šคํฌ๋ฆฐ์ƒท

prac01

-.Clipchamp.mp4

prac02

-.Clipchamp.1.mp4

mission01

-.Clipchamp.2.mp4

mission02
image

https://umc-10th-mission-wendy.vercel.app/

โœ… ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • Merge ํ•˜๋ ค๋Š” ๋ธŒ๋žœ์น˜๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋˜์–ด ์žˆ๋‚˜์š”?
  • ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋‚˜์š”?
  • ๋ถˆํ•„์š”ํ•œ ์ฃผ์„์ด ์ œ๊ฑฐ๋˜์—ˆ๋‚˜์š”?
  • ์ฝ”๋“œ ์Šคํƒ€์ผ์ด ์ผ๊ด€์ ์ธ๊ฐ€์š”?

@Dawon-Y Dawon-Y requested a review from woojo230 December 18, 2025 06:20
@Dawon-Y Dawon-Y self-assigned this Dec 18, 2025
@github-actions
Copy link

๐Ÿค– Gemini ์ฝ”๋“œ๋ฆฌ๋ทฐ ๊ฒฐ๊ณผ

์•ˆ๋…•ํ•˜์„ธ์š”, ์‹œ๋‹ˆ์–ด ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค. ์ „๋‹ฌํ•ด์ฃผ์‹  Pull Request diff (์ด 12๊ฐœ ํŒŒํŠธ)๋ฅผ ์ข…ํ•ฉํ•˜์—ฌ ๋ฉด๋ฐ€ํžˆ ๊ฒ€ํ† ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ๋‹ค์–‘ํ•œ ์ธก๋ฉด์„ ์•„์šฐ๋ฅด๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ๋“ค์ด ๋งŽ์•„, ์ด๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์™„์„ฑ๋œ ๋ฆฌ๋ทฐ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

์ „๋ฐ˜์ ์ธ ์ธ์ƒ:
ํ”„๋กœ์ ํŠธ๋Š” React, TypeScript, Tailwind CSS๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์–‘ํ•œ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋…(์ƒํƒœ ๊ด€๋ฆฌ, React ํ›… ์ตœ์ ํ™”, ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ํŽ˜์นญ ๋“ฑ)์„ ํƒ๊ตฌํ•˜๊ณ  ์ ์šฉํ•˜๋ ค๋Š” ๋…ธ๋ ฅ์ด ๋‹๋ณด์ž…๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ๊น”๋”ํ•˜๊ฒŒ ๊ตฌ์กฐํ™”๋˜์–ด ์žˆ์œผ๋ฉฐ, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋„ ๋น„๊ต์  ์ž˜ ํ™œ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ React ํ›… (useState, useReducer, useCallback, useMemo) ๋ฐ React.memo๋ฅผ ํ™œ์šฉํ•œ ์ตœ์ ํ™” ์‹œ๋„๋Š” ๋งค์šฐ ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค.

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


1. ํ”„๋กœ์ ํŠธ ์ „๋ฐ˜ ๋ฐ ์„ค์ • ํŒŒ์ผ ๋ฆฌ๋ทฐ

์ผ๋ถ€ PR ํŒŒํŠธ(1, 3, 5, 7, 9)์—์„œ๋Š” src ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด๋ถ€์˜ .ts ๋˜๋Š” .tsx ํŒŒ์ผ์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์—†์–ด ์ฝ”๋“œ ๋ฆฌ๋ทฐ๊ฐ€ ์ œํ•œ์ ์ด์—ˆ์ง€๋งŒ, package-lock.json, .gitignore, README.md, eslint.config.js, tsconfig.json ๋“ฑ ํ”„๋กœ์ ํŠธ ์ „๋ฐ˜์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ํŒŒ์ผ๋“ค์˜ ๋ณ€๊ฒฝ์‚ฌํ•ญ๋„ ํ•จ๊ป˜ ๊ณ ๋ คํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์ด ํ†ตํ•ฉ ์˜๊ฒฌ์„ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์„ฑ๋Šฅ ๋ฌธ์ œ (์ „๋ฐ˜)

  • ํ˜„์žฌ ์ฝ”๋“œ ๊ทœ๋ชจ์—์„œ๋Š” ๋นŒ๋“œ/๋Ÿฐํƒ€์ž„์— ์‹ฌ๊ฐํ•œ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์œ ๋ฐœํ•˜๋Š” ๋ถ€๋ถ„์€ ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๋‹ค๋งŒ, useFetch์—์„œ ๊ฐ์ฒด ๋น„๊ต๋ฅผ ์œ„ํ•ด JSON.stringify๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋ณต์žกํ•œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋”ฅ ์ดํ€„๋ฆฌํ‹ฐ ๋น„๊ต ์‹œ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (ํ˜„์žฌ params ์ •๋„๋Š” ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.)

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ• / ํƒ€์ž… ๊ฐœ์„ ์  (์ „๋ฐ˜)

  • ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํƒ€์ž… ์„ ์–ธ ๋ถ€์žฌ: import.meta.env.VITE_TMDB_TOKEN์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋‚˜, vite-env.d.ts์— ํ•ด๋‹น ํ™˜๊ฒฝ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์ด ๋ช…์‹œ๋˜์–ด ์žˆ์ง€ ์•Š์•„ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์กด์žฌ ์—ฌ๋ถ€๋‚˜ ํƒ€์ž…์„ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • tsconfig.app.json์˜ noImplicitOverride ๊ณ ๋ ค: tsconfig.app.json์— noImplicitOverride: true ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ, ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œ ์‹œ override ํ‚ค์›Œ๋“œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์ œํ•˜์—ฌ ์ฝ”๋“œ์˜ ๋ช…ํ™•์„ฑ๊ณผ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํŒจํ‚ค์ง€ ๋ฒ„์ „ ๋ถˆ์ผ์น˜ ํ™•์ธ: package.json์˜ react, react-dom, @types/react, @types/react-dom, vite, eslint ๋“ฑ์˜ ๋ฒ„์ „๊ณผ package-lock.json์— ๊ธฐ๋ก๋œ ์‹ค์ œ ์„ค์น˜ ๋ฒ„์ „ ๊ฐ„์˜ ๋ถˆ์ผ์น˜๊ฐ€ ๋ฐœ๊ฒฌ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํƒ€์ž… ๊ฒ€์‚ฌ ๋ฐ ๋Ÿฐํƒ€์ž„ ๋™์ž‘์— ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณ€์ˆ˜๋ช…, ํ•จ์ˆ˜๋ช…, ์ฃผ์„ ํ’ˆ์งˆ (์ „๋ฐ˜)

  • ์ „๋ฐ˜์ ์œผ๋กœ ๋ณ€์ˆ˜๋ช…, ํ•จ์ˆ˜๋ช…์€ ๋ช…ํ™•ํ•˜๊ณ  ์ฝ”๋“œ์˜ ์˜๋„๋ฅผ ์ž˜ ๋ฐ˜์˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ฃผ์„์€ ํ•„์š”ํ•œ ๊ณณ์— ์ ์ ˆํžˆ ์กด์žฌํ•˜๋ฉฐ, ํŠนํžˆ ํ•™์Šต ๋ชฉ์ ์˜ ์ฝ”๋“œ์— ๋ถ™์€ ์„ค๋ช…์€ ์ดํ•ด๋„๋ฅผ ๋†’์ด๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ๋„ฃ์€ console.log๋Š” ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ ์‹œ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ค‘๋ณต ์ฝ”๋“œ ๋ฐ ๋ฆฌํŒฉํ† ๋ง ํฌ์ธํŠธ (์ „๋ฐ˜)

  • Tailwind CSS ํ†ตํ•ฉ ๋ฐ ์„ค์ •: src/App.css์— ์ผ๋ฐ˜ CSS ์Šคํƒ€์ผ์ด ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Tailwind CSS์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ-ํผ์ŠคํŠธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์™„์ „ํžˆ ํ™œ์šฉํ•˜๊ณ  ์Šคํƒ€์ผ๋ง ์ผ๊ด€์„ฑ์„ ์œ„ํ•ด, ์ด ๊ทœ์น™๋“ค์„ Tailwind ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ @apply ์ง€์‹œ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, tailwind.config.js ํŒŒ์ผ์ด ๋ณด์ด์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ด๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๋ฐ ์ตœ์ ํ™”๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์˜์กด์„ฑ ํ™•์ธ: package.json์— react-hook-form๊ณผ zod๊ฐ€ ์ถ”๊ฐ€๋˜์–ด ์žˆ์ง€๋งŒ, ํ˜„์žฌ PR์˜ src ์ฝ”๋“œ์—์„œ๋Š” ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์‚ฌ์šฉ๋œ ํ”์ ์ด ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ณ„ํš์ด ์—†๋‹ค๋ฉด ์ œ๊ฑฐ๋ฅผ ๊ณ ๋ คํ•˜๊ณ , ๊ณ„ํš์ด ์žˆ๋‹ค๋ฉด PR ์„ค๋ช…์— ๋ช…์‹œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • ๊ฒฝ๋กœ ๋ณ„์นญ(Path Aliases) ์‚ฌ์šฉ ๊ณ ๋ ค: ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด ../../../์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ์ƒ๋Œ€ ๊ฒฝ๋กœ ๋Œ€์‹  tsconfig.json์— ๊ฒฝ๋กœ ๋ณ„์นญ์„ ์„ค์ •ํ•˜์—ฌ import CountButton from '@components/CountButton';์™€ ๊ฐ™์ด ๊น”๋”ํ•˜๊ฒŒ import ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ํ•ต์‹ฌ ์•„ํ‚คํ…์ฒ˜ ๋ถˆ์ผ์น˜: ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒํƒœ ๊ด€๋ฆฌ

๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ฆฌํŒฉํ† ๋ง ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.

src/components/CartContainer.tsx ๋ฐ ๊ด€๋ จ ํŒŒ์ผ๋“ค์€ Zustand๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ๋ฐ˜๋ฉด, src/components/CartList.tsx ํŒŒ์ผ์€ Redux Toolkit ๊ด€๋ จ ํ›… (useAppSelector, useAppDispatch)์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Š” ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ˜ผ์žฌ๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•ฉ๋‹ˆ๋‹ค:

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

๊ฐœ์„  ์ œ์•ˆ:
์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ•˜๋‚˜๋กœ ํ†ต์ผํ•˜๋Š” ๊ฒƒ์„ ๊ฐ•๋ ฅํžˆ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ Zustand๋ฅผ ๋ฉ”์ธ ์ƒํƒœ ๊ด€๋ฆฌ ์†”๋ฃจ์…˜์œผ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค๋ฉด, src/components/CartList.tsx ํŒŒ์ผ์€ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜, ๊ทธ ๊ธฐ๋Šฅ์ด ํ•„์ˆ˜์ ์ด๋ผ๋ฉด CartContainer.tsx์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ Zustand๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์™„์ „ํžˆ ๋ฆฌํŒฉํ† ๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


3. ํŒŒ์ผ ๋ฐ ๊ธฐ๋Šฅ๋ณ„ ์ƒ์„ธ ๋ฆฌ๋ทฐ ๋ฐ ๊ฐœ์„  ์ œ์•ˆ

3.1. ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ธฐ๋Šฅ (CartContainer, CartItem, Modal, Navbar, useStore, cartItems.ts)

  • ์„ฑ๋Šฅ: Zustand์˜ ์„ ํƒ์  ๊ตฌ๋… ๋ฐฉ์‹์€ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ตœ์†Œํ™”ํ•˜๋ฉฐ, useEffect์˜ ์ข…์†์„ฑ ๋ฐฐ์—ด ์‚ฌ์šฉ, key prop ์‚ฌ์šฉ ๋“ฑ์€ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. calculateTotals๋Š” ๋ฐฐ์—ด ์ˆœํšŒํ•˜์ง€๋งŒ, ์ผ๋ฐ˜์ ์ธ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ทœ๋ชจ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • ํƒ€์ž… ๊ฐœ์„ : CartItemType์˜ price ํ•„๋“œ (src/features/cart/cartSlice.ts, src/store/useStore.ts)๊ฐ€ string์œผ๋กœ ์„ ์–ธ๋˜์–ด ์žˆ์œผ๋‚˜, ์‹ค์ œ ์ฝ”๋“œ์—์„œ๋Š” Number()๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. price๋ฅผ number ํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  src/constants/cartItems.ts์˜ ๊ฐ’๋“ค๋„ ์ˆซ์ž๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ „์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฆฌํŒฉํ† ๋ง:
    • ๊ฐ€๊ฒฉ ํฌ๋งทํŒ… ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ ๋ถ„๋ฆฌ: toLocaleString()์„ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”๋ฐ, src/utils ํด๋” ๋“ฑ์— formatCurrency์™€ ๊ฐ™์€ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์ผ๊ด€๋œ ํฌ๋งทํŒ…์„ ๋ณด์žฅํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • Modal ์ปดํฌ๋„ŒํŠธ์˜ ์ ‘๊ทผ์„ฑ(Accessibility) ๊ฐ•ํ™”: role="dialog", aria-modal="true", aria-labelledby ์†์„ฑ ์ถ”๊ฐ€, ํฌ์ปค์Šค ํŠธ๋žฉ ๊ตฌํ˜„, Escape ํ‚ค ๋‹ซ๊ธฐ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€ ๋“ฑ ๋ชจ๋‹ฌ์˜ ์ ‘๊ทผ์„ฑ์„ ๊ฐœ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ์œ„ํ•œ data-testid ์†์„ฑ ์ถ”๊ฐ€: ํ•ต์‹ฌ UI ์š”์†Œ์— data-testid ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ž๋™ํ™”๋œ UI ํ…Œ์ŠคํŠธ๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
    • Navbar์˜ SVG ์•„์ด์ฝ˜ react-icons๋กœ ๋Œ€์ฒด: package.json์— react-icons ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋Š”๋ฐ๋„ SVG ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‚ฝ์ž…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. react-icons์—์„œ ์ œ๊ณตํ•˜๋Š” ์•„์ด์ฝ˜์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ๋„๋ฅผ ๋†’์ด๊ณ  ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์„ ๊ฐœ์„ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
    • src/constants/cartItems.ts ํŒŒ์ผ๋ช… ๋ณ€๊ฒฝ: ํŒŒ์ผ๋ช…์„ src/constants/initialCartData.ts ๋˜๋Š” src/constants/defaultCartItems.ts ๋“ฑ์œผ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ํŒŒ์ผ์˜ ๋ชฉ์ ์„ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
    • calculateTotals ๋กœ์ง ๊ฐœ์„  (์„ ํƒ ์‚ฌํ•ญ): increase, decrease ์•ก์…˜ ๋ฐœ์ƒ ์‹œ amount์™€ total์„ ํ•ด๋‹น ์•„์ดํ…œ์˜ price๋งŒํผ ์ฆ๊ฐ์‹œํ‚ค๋Š” ๋ฐฉ์‹์œผ๋กœ ์ตœ์ ํ™”ํ•˜์—ฌ calculateTotals ํ˜ธ์ถœ ๋นˆ๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3.2. useState / useReducer ํ•™์Šต ์˜ˆ์ œ (src/pages/UseReducerCompany.tsx, src/pages/UseReducerPage.tsx)

  • ์„ฑ๋Šฅ: useState์™€ useReducer์˜ ์‚ฌ์šฉ์ด ํšจ์œจ์ ์ด๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์€ ์—†์Šต๋‹ˆ๋‹ค.
  • ํƒ€์ž… ๊ฐœ์„ : IState, IAction, TActionType๊ณผ ๊ฐ™์€ ์ ‘๋‘์‚ฌ(I, T)๋Š” ์ตœ์‹  TypeScript ์ปจ๋ฒค์…˜์—์„œ ์ƒ๋žตํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์œผ๋ฏ€๋กœ State, Action ๋“ฑ์œผ๋กœ ๋ณ€๊ฒฝ์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฆฌํŒฉํ† ๋ง:
    • 'use client'; ์ง€์‹œ์ž ์ œ๊ฑฐ ๊ณ ๋ ค: ํ˜„์žฌ Vite + React ํ™˜๊ฒฝ์—์„œ๋Š” ์ด ์ง€์‹œ์ž๊ฐ€ ๊ธฐ๋Šฅ์  ์—ญํ• ์„ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, Next.js ๋“ฑ ํŠน์ • ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉ ๊ณ„ํš์ด ์—†๋‹ค๋ฉด ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
    • ์•ก์…˜ ํƒ€์ž…์„ ์ƒ์ˆ˜๋กœ ์ •์˜ํ•˜์—ฌ ์ค‘๋ณต ์ œ๊ฑฐ: ์•ก์…˜ ํƒ€์ž… ๋ฌธ์ž์—ด("CHANGE_DEPARTMENT", "INCREASE")์„ enum ๋˜๋Š” const ๊ฐ์ฒด๋กœ ์ •์˜ํ•˜์—ฌ ํƒ€์ž… ์ •์˜์™€ dispatch ํ˜ธ์ถœ ์‹œ ๋ชจ๋‘ ํ™œ์šฉํ•˜๋ฉด ์˜คํƒ€๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ดˆ๊ธฐ ์ƒํƒœ ๋ฐ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋ฌธ์ž์—ด ์ƒ์ˆ˜ ๋ถ„๋ฆฌ: useReducer์˜ ์ดˆ๊ธฐ ์ƒํƒœ ๋ฐ RESET ์•ก์…˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ณธ๊ฐ’, ๊ทธ๋ฆฌ๊ณ  ์ง๋ฌด๋ช…์ด๋‚˜ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋“ฑ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋ฌธ์ž์—ด๋“ค์„ ์ƒ์ˆ˜๋กœ ์ •์˜ํ•˜์—ฌ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ ํ™•์žฅ์ด ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.
    • ์•ก์…˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ณด๋‹ค ๊ฒฌ๊ณ ํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ (Discriminated Union): IAction์—์„œ payload๊ฐ€ ํŠน์ • ์•ก์…˜ ํƒ€์ž…์—์„œ๋งŒ ํ•„์š”ํ•˜๋‹ค๋ฉด, Discriminated Union ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3.3. TMDB ์˜ํ™” ์•ฑ (src/hooks/useFetch.ts, src/pages/HomePage.tsx, src/components/MovieFilter.tsx, src/pages/MovieDetailPage.tsx ๋“ฑ)

  • ์„ฑ๋Šฅ: MovieFilter.tsx ๋‚ด console.log๋Š” ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ์—์„œ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ํƒ€์ž… ๊ฐœ์„ :
    • ์ค‘๋ณต๋œ Movie ๋ฐ MovieFilters ์ธํ„ฐํŽ˜์ด์Šค: src/types/movie.ts์— ์ •์˜๋œ ํƒ€์ž…๋“ค์ด ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋กœ์ปฌ๋กœ ๋‹ค์‹œ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. src/types/movie.ts๋ฅผ ๋‹จ์ผ ์†Œ์Šค(Single Source of Truth)๋กœ ๋งŒ๋“ค์–ด ๋ชจ๋“  ๊ด€๋ จ ํƒ€์ž…์„ ํฌํ•จํ•˜๊ณ , ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์ด๋ฅผ importํ•˜์—ฌ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌํŒฉํ† ๋ง:
    • useFetch ํ›…์— ์—๋Ÿฌ ์ƒํƒœ ์ถ”๊ฐ€: useFetch๋Š” ํ˜„์žฌ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์ฝ˜์†” ๋กœ๊ทธ๋งŒ ๋‚จ๊ธฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. error ์ƒํƒœ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ UI์—์„œ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • MovieFilter ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ ์žฌ์‚ฌ์šฉ: src/components/common์— ์ด๋ฏธ ์ •์˜๋œ Input, CheckBox, LanguageSelector ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์žฌํ™œ์šฉํ•˜์—ฌ ์ฝ”๋“œ ์ผ๊ด€์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.
    • MovieDetailPage์— ์‹ค์ œ ์˜ํ™” ์ƒ์„ธ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋กœ์ง ์ถ”๊ฐ€: movieId ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ TMDB API์—์„œ ์˜ํ™” ์ƒ์„ธ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์™€ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ URL ํ—ฌํผ ํ•จ์ˆ˜ ๋„์ž…: ์ด๋ฏธ์ง€ URL ์ƒ์„ฑ์„ ์ค‘์•™ ์ง‘์ค‘ํ™”ํ•˜๊ณ  ์œ ์—ฐ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด getImageUrl(path, size)์™€ ๊ฐ™์€ ํ—ฌํผ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • React Query ๋„์ž… ๊ณ ๋ ค: package.json์— @tanstack/react-query๊ฐ€ ์ด๋ฏธ ์ถ”๊ฐ€๋˜์–ด ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์•„, useFetch ํ›…์„ useQuery๋กœ ๋Œ€์ฒดํ•˜์—ฌ ์บ์‹ฑ, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋ฆฌํŒจ์นญ ๋“ฑ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๋ฅผ ๋”์šฑ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3.4. useCallback / memo ํ•™์Šต ์˜ˆ์ œ (src/pages/UseCallbackPage.tsx, src/components/CountButton.tsx, src/components/TextInput.tsx)

  • ์„ฑ๋Šฅ: React.memo์™€ useCallback์„ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ๋ฅผ ํ†ตํ•ด useCallback ์˜์กด์„ฑ ๋ฐฐ์—ด์—์„œ count ๊ฐ’์„ ์ œ์™ธํ•œ ๊ฒƒ์€ ๋ชจ๋ฒ”์ ์ธ ํ™œ์šฉ์ž…๋‹ˆ๋‹ค.
  • ํƒ€์ž… ๊ฐœ์„ : ํƒ€์ž… ์ •์˜๋Š” ๊น”๋”ํ•˜๊ณ  ์ •ํ™•ํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฆฌํŒฉํ† ๋ง:
    • React ๋ชจ๋“ˆ import ๊ฐ„๊ฒฐํ™”: React 17+์˜ ์ƒˆ๋กœ์šด JSX transform ๋•๋ถ„์— JSX๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŒŒ์ผ์—์„œ import React๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. import { memo } from 'react';๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
    • h2 ํƒœ๊ทธ ์Šคํƒ€์ผ๋ง ์ผ๊ด€์„ฑ ์œ ์ง€: CountButton๊ณผ UseCallbackPage์˜ h2 ํƒœ๊ทธ ์Šคํƒ€์ผ๋ง์„ ์ผ๊ด€๋˜๊ฒŒ ์ ์šฉํ•˜์—ฌ ์‹œ๊ฐ์  ํ†ต์ผ์„ฑ์„ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ปดํฌ๋„ŒํŠธ ์„ ์–ธ ์Šคํƒ€์ผ ์ผ๊ด€์„ฑ: ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ์„ ์–ธ(const ComponentName = ... vs function ComponentName()) ๋ฐฉ์‹์„ ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

3.5. useMemo ํ•™์Šต ์˜ˆ์ œ (src/pages/UseMemoPage.tsx, src/components/TextInput.tsx, src/utils/math.ts)

  • ์„ฑ๋Šฅ: findPrimes ํ•จ์ˆ˜์™€ useMemo๋ฅผ ํ†ตํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์‹œ๋„๋Š” ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ, TextInput ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌ๋˜๋Š” handleText ํ•จ์ˆ˜๊ฐ€ useCallback์œผ๋กœ ๋ฉ”๋ชจ์ด์ œ์ด์…˜๋˜์ง€ ์•Š์•„ TextInput์ด ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ฆฌ๋ Œ๋”๋ง๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. findPrimes์˜ map().filter() ๋Œ€์‹  ์ง์ ‘ ๋ฐฐ์—ด์— pushํ•˜๋Š” ๋ฐฉ์‹์ด ๋ฏธ์„ธํ•˜๊ฒŒ ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํƒ€์ž… ๊ฐœ์„ : ํƒ€์ž… ์ •์˜๋Š” ๋ช…ํ™•ํ•˜๊ณ  ์ ์ ˆํ•˜๋ฉฐ, findPrimes์˜ as number[] ์–ด์„ค์…˜๋„ ์ ์ ˆํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌํŒฉํ† ๋ง:
    • UseMemoPage.tsx์˜ handleText ํ•จ์ˆ˜ useCallback์œผ๋กœ ๋ž˜ํ•‘: handleText ํ•จ์ˆ˜๋ฅผ useCallback์œผ๋กœ ๊ฐ์‹ธ TextInput์˜ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • UseMemoPage.tsx์˜ ์ˆซ์ž ์ž…๋ ฅ(limit)์— min ์†์„ฑ ์ถ”๊ฐ€: <input type="number"> ์š”์†Œ์— min="0" ๋˜๋Š” min="2" ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์œ ํšจํ•œ ์ž…๋ ฅ ๋ฒ”์œ„๋ฅผ ์•ˆ๋‚ดํ•˜๊ณ  ๊ฒฌ๊ณ ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.
    • UseMemoPage.tsx์˜ ์†Œ์ˆ˜ ๋ฆฌ์ŠคํŠธ ์„น์…˜์— ์•ˆ๋‚ด ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€: limit ๊ฐ’์ด ์—†๊ฑฐ๋‚˜ ์†Œ์ˆ˜๊ฐ€ ๊ณ„์‚ฐ๋˜์ง€ ์•Š์•˜์„ ๋•Œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์•ˆ๋‚ด ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜์—ฌ UX๋ฅผ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • utils/math.ts์˜ findPrimes ์ตœ์ข… ์†Œ์ˆ˜ ์ˆ˜์ง‘ ๋ฐฉ์‹ ์ตœ์ ํ™”: map().filter() ๋Œ€์‹  for ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†Œ์ˆ˜๋“ค์„ ์ง์ ‘ ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์ด ๋” ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • utils/math.ts์˜ findPrimes์— ์Œ์ˆ˜ max ๊ฐ’ ๋ฐฉ์–ด ๋กœ์ง ์ถ”๊ฐ€: max ๊ฐ’์ด ์Œ์ˆ˜์ผ ๋•Œ ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์–ด ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ๋”์šฑ ๊ฒฌ๊ณ ํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
    • App.tsx์— React.StrictMode ์ ์šฉ ๊ถŒ์žฅ: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ์„œ StrictMode๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์ž ์žฌ์ ์ธ ๋ฌธ์ œ๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
    • App ์ปดํฌ๋„ŒํŠธ์˜ ์—ญํ•  ์ฃผ์„ ์ถ”๊ฐ€ ๋ฐ ๋ผ์šฐํŒ… ๊ตฌ์กฐ ๊ณ ๋ ค: package.json์— react-router-dom์ด ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์•„, App ์ปดํฌ๋„ŒํŠธ์— ๋ผ์šฐํŒ… ๊ตฌ์กฐ(์˜ˆ: BrowserRouter, Routes)๋ฅผ ๋ฏธ๋ฆฌ ๊ณ ๋ คํ•˜๊ณ  ๊ด€๋ จ ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
    • ์• ์…‹ ๊ฐ€์ ธ์˜ค๊ธฐ ๋ฐฉ์‹ ๋ฐ ์ปจ๋ฒค์…˜: public ํด๋”์™€ src/assets ํด๋”์˜ SVG ํŒŒ์ผ ์‚ฌ์šฉ ๋ฐฉ์‹์„ ๋ช…ํ™•ํžˆ ํ•˜๊ณ , ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ์ผ๊ด€๋œ ์• ์…‹ ๊ด€๋ฆฌ ์ปจ๋ฒค์…˜์„ ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ตœ์ข… ์ •๋ฆฌ ๋ฐ ๊ถŒ์žฅ ์‚ฌํ•ญ

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

๊ฐ€์žฅ ์šฐ์„ ์ ์œผ๋กœ ํ•ด๊ฒฐํ•ด์•ผ ํ•  ๊ณผ์ œ๋Š” "์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ธฐ๋Šฅ์˜ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ผ๊ด€์„ฑ ํ™•๋ณด"์ž…๋‹ˆ๋‹ค. Zustand์™€ Redux Toolkit ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜์—ฌ ๋‚˜๋จธ์ง€ ๊ตฌํ˜„์„ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ํ†ต์ผํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•ด ์ฃผ์„ธ์š”.

์ด ๋ฆฌ๋ทฐ๊ฐ€ ์ฝ”๋“œ ๊ฐœ์„ ์— ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ์œผ์‹œ๋ฉด ์–ธ์ œ๋“ ์ง€ ์งˆ๋ฌธํ•ด์ฃผ์„ธ์š”. ์ˆ˜๊ณ ํ•˜์…จ์Šต๋‹ˆ๋‹ค!

// options์˜ ๊นŠ์€ ๋น„๊ต๋ฅผ ์œ„ํ•œ ref
const optionsRef = useRef<string>('');

useEffect(() => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค

Copy link
Collaborator

@woojo230 woojo230 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsx ๋ฌธ๋ฒ•์ด ๊ธธ์–ด์ง€๋Š” ๋ถ€๋ถ„์€ ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ ํ•ด์ฃผ๋ฉด ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์งˆ ๊ฒƒ ๊ฐ™์•„์š”

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants