π Next.jsλ‘ Todo μ± λ§λ€κΈ° - 첫 λ²μ§Έ μ΄μΌκΈ°
π νλ‘μ νΈ κ°μ
ADMIN νμ΄μ§μ LocalStorage κΈ°λ° Todo μ± κΈ°λ₯μ μΆκ°νμ΅λλ€. PRD.MD λ¬Έμλ₯Ό κΈ°λ°μΌλ‘ λͺ¨λ P1(μ΅μ°μ ) μμ μ μλ£νμ΅λλ€.
β μλ£λ μμ (μ΄ 7κ°)
- κΈ°λ³Έ μ€μ
- νλ‘μ νΈ ν΄λ ꡬ쑰 λ° νμ μ μ (lib/types.ts)
- LocalStorage μ νΈλ¦¬ν° ꡬν (lib/storage.ts)
- ν΅μ¬ κΈ°λ₯
- useTodos ν ꡬν - CRUD λ‘μ§, μλ μ μ₯
- UI μ»΄ν¬λνΈ
- TodoItem μ»΄ν¬λνΈ - 체ν¬λ°μ€, νΈμ§, μμ
- TodoList μ»΄ν¬λνΈ - 리μ€νΈ λ λλ§
- NewTodoInput μ»΄ν¬λνΈ - μ λ ₯ νΌ
- ν΅ν©
- TodoApp λ©μΈ μ»΄ν¬λνΈ μμ±
- ADMIN νμ΄μ§μ Todo μ± ν΅ν©
π ꡬνλ κΈ°λ₯
- Todo CRUD (μμ±, μ½κΈ°, μμ , μμ )
- νν°λ§ (All/Active/Completed)
- μ€μκ° κ²μ (λμλ¬Έμ 무μ)
- LocalStorage μλ μ μ₯ (250ms μ°λ‘νλ§)
- Clear Completed λ²νΌ
- λ€ν¬ λͺ¨λ μ§μ
- λ°μν λμμΈ
π μμ±λ νμΌ
- lib/types.ts
- lib/storage.ts
- hooks/useTodos.ts
- components/todo/TodoItem.tsx
- components/todo/TodoList.tsx
- components/todo/NewTodoInput.tsx
- components/todo/TodoApp.tsx
- app/admin/page.tsx (μμ )
μλ νμΈμ! μ€λμ μ λ§ λΏλ―ν ν루μμ΄μ. π
λΈλ‘κ·Έ κ΄λ¦¬μ νμ΄μ§μ Todo μ± κΈ°λ₯μ μΆκ°νλ νλ‘μ νΈλ₯Ό μμνλλ°μ, μκ°λ³΄λ€ μμ‘°λ‘κ² μ§νλμ΄μ μ€λ ν루 λ§μ ν΅μ¬ κΈ°λ₯λ€μ λͺ¨λ μμ±νλ΅λλ€! π―
π μ€λμ μ¬μ
μμΉ¨μ PRD λ¬Έμλ₯Ό κΌΌκΌΌν μ½μΌλ©΄μ μ΄λ€ κΈ°λ₯λ€μ΄ νμνμ§ νμ νμ΄μ. μ²μμ λ§μ°νλλ°, νλμ© μ 리νλ€ λ³΄λ λͺ νν λ‘λλ§΅μ΄ κ·Έλ €μ§λλΌκ³ μ.
κ°μ₯ λ¨Όμ ν μΌμ Notionμ 'νλ‘μ νΈ μμ κ΄λ¦¬' λ°μ΄ν°λ² μ΄μ€μ λͺ¨λ μμ λ€μ μ 리νλ κ²μ΄μμ΄μ. μ΄λ κ² νλκΉ μ 체 κ΅¬μ‘°κ° νλμ 보μ¬μ μ λ§ μ’μμ΄μ! π
π‘ ꡬννλ©΄μ λ°°μ΄ κ²λ€
- TypeScriptλ‘ νμ μ λ¨Όμ μ μνλ κ°λ°μ΄ ν¨μ¬ μμνμ΄μ
Todo μΈν°νμ΄μ€μ AppStateV1 νμ μ λ§λ€λ©΄μ, 'μ, μ΄λ κ² κ΅¬μ‘°λ₯Ό μ‘μΌλκΉ λμ€μ μ½λ μμ±ν λ μλμμ±μ΄ μ λκ² λ€!' νλ μκ°μ΄ λ€μμ£ .
- LocalStorage μ°λ‘νλ§μ μ€μμ±μ μ€κ°νμ΄μ
μ¬μ©μκ° λΉ λ₯΄κ² νμ΄νν λλ§λ€ μ μ₯νλ©΄ μ±λ₯μ΄ λ¨μ΄μ§ μ μμμμ? κ·Έλμ 250ms μ°λ‘νλ§μ μ μ©νλλ°, μ΄κ² μ λ§ ν¨κ³Όμ μ΄λλΌκ³ μ. μ¬μ©μ κ²½νλ μ’κ³ , λΈλΌμ°μ λΆλ΄λ μ€μΌ μ μμ΄μ μΌμμ΄μ‘°!
- React Hooksμ λ§€λ ₯μ λ€μ νλ² λκΌμ΄μ
useTodosλΌλ 컀μ€ν ν μ λ§λ€λ©΄μ, μν κ΄λ¦¬ λ‘μ§μ κΉλνκ² λΆλ¦¬ν μ μμμ΄μ. μ»΄ν¬λνΈλ UIλ§ μ κ²½ μ°κ³ , λΉμ¦λμ€ λ‘μ§μ ν μμ μ²λ¦¬νλκΉ μ½λκ° μ λ§ μ½κΈ° μ’μμ‘λ΅λλ€! π
π¨ UI μ»΄ν¬λνΈ λ§λ€κΈ°
μ»΄ν¬λνΈλ₯Ό λ§λλ κ³Όμ μ΄ μ λ§ μ¬λ―Έμμμ΄μ. νΉν TodoItem μ»΄ν¬λνΈμμ λλΈν΄λ¦μΌλ‘ νΈμ§ λͺ¨λλ‘ μ νλλ κΈ°λ₯μ ꡬνν λ, μ¬μ©μ μ μ₯μμ 'μ΄λ κ² νλ©΄ νΈνκ² λ€'λ μκ°μ κ³μ νλ©΄μ λ§λ€μμ΄μ.
Enterλ‘ μ μ₯νκ³ , Escλ‘ μ·¨μνκ³ , ν¬μ»€μ€λ₯Ό λ²μ΄λλ©΄ μλ μ μ₯λλ κ²λ ꡬννλλ°, μ΄λ° μμ λν μΌλ€μ΄ μ¬μ©μ κ²½νμ ν¬κ² ν₯μμν€λλΌκ³ μ! β¨
π λ€ν¬ λͺ¨λλ μμ§ μμμ΄μ
μμ¦ λ€ν¬ λͺ¨λλ₯Ό μ νΈνλ λΆλ€μ΄ λ§μμμ? λͺ¨λ μ»΄ν¬λνΈμ λ€ν¬ λͺ¨λ μ€νμΌμ μΆκ°ν΄μ, λΌμ΄νΈ λͺ¨λμ λ€ν¬ λͺ¨λ λͺ¨λμμ μμκ² λ³΄μ΄λλ‘ μ κ²½ μΌμ΄μ. π
νΉν μλ£λ νλͺ©μ μ·¨μμ κ³Ό ν¨κ» μμμ΄ μ μ΄μ§λλ°, λ€ν¬ λͺ¨λμμλ μμ°μ€λ½κ² 보μ΄λλ‘ μμμ μ‘°μ νλ΅λλ€!
π νν°λ§κ³Ό κ²μ κΈ°λ₯
ν μΌμ΄ λ§μμ§λ©΄ μ°ΎκΈ° μ΄λ ΅μμμ? κ·Έλμ μΈ κ°μ§ νν°λ₯Ό λ§λ€μμ΄μ:
- μ 체: λͺ¨λ ν μΌμ λ³Ό μ μμ΄μ
- μ§ν μ€: μμ§ μλ£νμ§ μμ ν μΌλ§ λͺ¨μλ³Ό μ μμ΄μ
- μλ£: λ€ λλΈ ν μΌλ€μ νμΈν μ μμ΄μ (λΏλ―ν¨ μΆ©μ μ©! π)
κ²μ κΈ°λ₯λ λ£μλλ°, λμλ¬Έμ κ΅¬λΆ μμ΄ λΆλΆ κ²μμ΄ κ°λ₯νλλ‘ νμ΄μ. 'νμ'λΌκ³ κ²μνλ©΄ 'ν νμ μ€λΉ', 'κ³ κ° νμ μλ£' κ°μ νλͺ©λ€μ΄ λͺ¨λ λμ€λ μμ΄μ£ !
πΎ λ°μ΄ν°λ μμ νκ²!
LocalStorageλ₯Ό νμ©ν΄μ λΈλΌμ°μ λ₯Ό λ«μλ λ°μ΄ν°κ° μ¬λΌμ§μ§ μλλ‘ λ§λ€μμ΄μ. μλ‘κ³ μΉ¨ν΄λ κ±±μ μμ΄μ! π
κ·Έλ¦¬κ³ νΉμλ μ©λμ΄ λΆμ‘±ν΄μ μ μ₯μ΄ μ λ μλ μμμμ? QuotaExceededError κ°μ μμΈ μν©λ λλΉν΄μ μλ¬ μ²λ¦¬λ₯Ό κΌΌκΌΌν ν΄λλ΅λλ€.
π μλ£ νλͺ© ν λ²μ μ 리!
μλ£λ ν μΌλ€μ΄ μμ΄λ©΄ 리μ€νΈκ° 볡μ‘ν΄μ§μμμ? κ·Έλμ 'Clear Completed' λ²νΌμ λ§λ€μμ΄μ. ν΄λ¦ ν λ²μΌλ‘ μλ£λ νλͺ©λ€μ κΉλνκ² μ 리ν μ μλ΅λλ€! π§Ή
π± λͺ¨λ°μΌμμλ νΈνκ²
λ°μν λμμΈμ μ μ©ν΄μ νΈλν°μΌλ‘ λ΄λ μμκ² λ³΄μ¬μ. μμ νλ©΄μμλ λ²νΌ ν μ€νΈλ₯Ό μ¨κΈ°κ³ μμ΄μ½λ§ 보μ¬μ£Όλ λ± μΈμ¬νκ² μ κ²½ μΌμ΄μ!
π€ μ‘°κΈ μ΄λ €μ λ μ
μ¬μ€ μ²μμ νΈμ§ λͺ¨λμμ ν¬μ»€μ€ μ²λ¦¬κ° μ’ κΉλ€λ‘μ μ΄μ. useRefμ useEffectλ₯Ό μ‘°ν©ν΄μ νΈμ§ λͺ¨λλ‘ μ νλ λ μλμΌλ‘ ν¬μ»€μ€κ° κ°κ³ , ν μ€νΈκ° μ 체 μ νλλλ‘ λ§λ€μλλ°, μ΄ λΆλΆμ΄ μκ°λ³΄λ€ μ κ²½ μΈ κ² λ§λλΌκ³ μ.
κ·Έλλ κ²°κ΅ μ ν΄κ²°νκ³ , μ΄μ λ μ λ§ λΆλλ½κ² λμν΄μ! πͺ
β¨ νΉλ³ν μ κ²½ μ΄ λΆλΆ
μ κ·Όμ±μ μ λ§ μ€μνκ² μκ°νμ΄μ. λͺ¨λ μΈν°λν°λΈ μμμ aria-labelμ μΆκ°ν΄μ μ€ν¬λ¦° 리λ μ¬μ©μλΆλ€λ νΈνκ² μΈ μ μλλ‘ νκ³ , ν€λ³΄λλ§μΌλ‘λ λͺ¨λ κΈ°λ₯μ μ¬μ©ν μ μκ² λ§λ€μμ΄μ. π
κ·Έλ¦¬κ³ μ¬μ©μκ° λΉ λ¬Έμμ΄μ μ λ ₯νλ €κ³ νλ©΄ μλμΌλ‘ λ°©μ§νκ³ , μλ£ λ²νΌλ λΉνμ±νλλ λ± μμ λν μΌλ€λ λμΉμ§ μμΌλ €κ³ λ Έλ ₯νλ΅λλ€.
π― λ€μ λ¨κ³λ?
μ€λμ P1(μ΅μ°μ ) μμ λ€μ λͺ¨λ μλ£νμ΄μ! μ΄μ κΈ°λ³Έμ μΈ Todo μ±μ΄ μμ±λμκ³ , μ€μ λ‘ μ¬μ©ν μ μλ μνκ° λμλ΅λλ€.
λ€μμλ P2 μμ λ€μ μ§νν μμ μΈλ°μ:
- κ²μμ λλ°μ΄μ€ μ μ©νκΈ° (150ms)
- λͺ¨λ°μΌ λ μ΄μμ λ μΈλ°νκ² μ΅μ ννκΈ°
- LocalStorage μ¬μ©μ΄ λΆκ°λ₯ν νκ²½μμ λ©λͺ¨λ¦¬ ν΄λ°± ꡬννκΈ°
- ν€λ³΄λ λ€λΉκ²μ΄μ λ κ°μ νκΈ°
π λ§λ¬΄λ¦¬νλ©°
μ€λ ν루 μ λ§ μμ°¨κ² κ°λ°νμ΄μ! PRDλ₯Ό 보면μ κ³νμ μΈμ°κ³ , NotionμΌλ‘ μμ μ κ΄λ¦¬νλ©΄μ νλμ© μλ£ν΄λκ°λκΉ μ±μ·¨κ°μ΄ λ°°κ° λλλΌκ³ μ.
무μλ³΄λ€ TypeScriptμ Reactμ κ°λ ₯ν¨μ λ€μ νλ² λλ μ μμκ³ , κΉλν μ½λ ꡬ쑰μ μ€μμ±λ μ€κ°νμ΄μ.
λ΄μΌλ νμ΄ν ! π
β¬οΈ If this helped, please click the ad below! It supports me a lot πββοΈ β¬οΈ
Related Posts
Chanel vs. Louis Vuitton for Momβs 60th Birthday: A Luxury Handbag Gift Guide
Trying to choose between Chanel and Louis Vuitton for your momβs 60th birthday? This guide breaks down prestige, practicality, weight, and style so you can pick the luxury bag sheβll actually love using.
The Ultimate Guide to Choosing the Right Ferragamo Loafers for You
Discover the differences between Ferragamo's iconic Gancini and sleek Rollo loafers, and learn how to choose the perfect pair for your style and budget.
The Ultimate Guide to Buying Pre-Owned Van Cleef & Arpels Necklaces: Prices, Models, and Pro Tips
Thinking about buying a pre-owned Van Cleef & Arpels necklace? Discover current resale prices for popular Alhambra models, essential authentication tips, and what to look for regarding chain lengths and gemstone conditions.