π 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 πββοΈ β¬οΈ