[Mini Project] Note-App
๐ฉ๐ป๐ป Github Repository https://github.com/sw2377/note-app
์์ ๊ธฐ๊ฐ : 2024. 01. 09 ~ 2024. 01. 16
ํ๋ก ํธ์๋ ์ฑ์ฉ ๊ณผ์ ๋ก ์ํํ Note-App ๊ตฌํ ๊ณผ์ (๊ตฌํ ์ค ์๋ฌ์ฌํญ & ๊ณ ๋ฏผํ ๋ถ๋ถ)์ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
๐ ์๋ฆฌ์ฆ ์ด์ด๋ณด๊ธฐ
ํ์ฌ๊ธ : Note-App ๊ตฌํ ๊ณผ์ ์ ๋ฆฌ (1)
Note-App ๊ตฌํ ๊ณผ์ ์ ๋ฆฌ (2)
Note-App ๊ตฌํ ๊ณผ์ ์ ๋ฆฌ (3)
๐ ๋ชฉ์ฐจ
1. ๊ธฐ์ ์คํ์ ์ ํ (TypeScript, Styled-components๋ฅผ ์ฌ์ฉํ ์ด์ )
2. ๋ ์ด์์ ๊ณ ๋ฏผํ๊ธฐ
3. Vite๋ก React + TypeScript ์กฐํฉ์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์์ฑ ํ,main.tsx ํ์ผ์ document.getElementById('root') ๋ถ๋ถ์ ์๋ฌ
4. ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด์ ๋ ์ด์์์ ์์ ํ ๋จผ์ ์์
5. zustand๋ก notebooks ์ํ๊ด๋ฆฌ ๋์
6. LocalStorage์ ์ด๋ ํ ํ์์ผ๋ก notebooks๋ฅผ ์ ์ฅํ ๊น?
๐ค FE ๊ธฐ์ ์คํ
- React + Typscript (Vite)
- Styled Components
- Zustand
- Lexical Editor
1. ๊ธฐ์ ์คํ์ ์ ํ
์ ํด์ง ๊ธฐ์ ์คํ์ React ์์ผ๋ฉฐ, React๋ฅผ ์ฌ์ฉํ์ฌ ์นํ์ด์ง๋ฅผ ๊ตฌํํ๋ผ๋ ๊ฒ์ด ์๊ตฌ์ฌํญ์ด์๋ค. TypeScript์ ๋์ ๊ณผ ์คํ์ผ๋ง์ ์ด๋ป๊ฒ ํ ์ง ์ ํด์ผ ํ๋๋ฐ, ์ด ๋ถ๋ถ์ ๋น ๋ฅด๊ฒ ๊ฒฐ์ ํ ์ ์์๋ค.
๐ TypeScript๋ฅผ ์ฌ์ฉํ ์ด์ ๋?
ํ์ ์คํฌ๋ฆฝํธ๋ ์ ์ ํ์ ๊ฒ์ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ์ด๋ ์ปดํ์ผ ๋จ๊ณ์์ ์ค๋ฅ๋ฅผ ์ก์๋ผ ์ ์์ผ๋ฉฐ ๋ฐํ์ ์๋ฌ๋ฅผ ๋ฐฉ์งํ ์ ์๋ค. ๋ํ ํ์ ์ ๋ช ์ํจ์ผ๋ก์จ ์ฝ๋์ ์๋ ๋ํ ๋ช ํํด์ง๊ธฐ ๋๋ฌธ์ ํ์ ์ ์ฝ๋์ ๊ฐ๋ ์ฑ๋ ๋์ฌ์ค๋ค. ๋ํ ๊ฐ๋ฐํ๊ฒฝ์์ ์๋์์ฑ ๋ฑ์ ๊ธฐ๋ฅ์ ํตํด ๊ฐ๋ฐ์ ํจ์จ์ฑ๋ ๋์ฌ์ฃผ๋ฉฐ, Interface, Generic๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋ณด๋ค ์ฝ๊ฒ ํ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ค.
ํนํ ์ด๋ฒ์ ์์๋ก ๊ธฐ๋ฅ ๊ตฌํ ๋น ๋ฅด๊ฒ ํด๋ณด๊ธฐ ์ํด JavaScript๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ์์ฑํ์๋๋ฐ, ํ์ ์ ๋ช ์๊ฐ ๋์ด์์ง ์์ ํด๋น ๋ณ์์ ํ์ ์ ์ฐพ์๋ณด๋ ์ผ๋ ๋ช ๋ฒ ์์๊ณ , ์๋์์ฑ ๊ธฐ๋ฅ ๋ํ ์ฌ์ฉํ ์ ์์๊ธฐ ๋๋ฌธ์ ๋ถํธํจ์ ์กฐ๊ธ ๋๋ผ๊ธฐ๋ ํ์๋ค.
์์ง์ ํ์ ์คํฌ๋ฆฝํธ๊ฐ ๋ฅ์ํ๊ฒ ์ฌ์ฉํ์ง๋ ๋ชปํด ์ ์ฉํ๋๋ฐ ์๊ฐ์ด ์ข ๋ ๊ฑธ๋ฆฌ๊ณ , ํ์ต๊ณผ ํ์ฉ์ด ๋ ํ์ํ์ง๋ง ์ต์ํด์ง๋ค๋ฉด ๋ถ๋ช ๋๋ฒ๊น ๋ ์ฌ์์ง๊ณ , ๊ฐ๋ฐ์ ๊ฒฝํ์ ํฅ์๋ ๋๋ ์ ์์ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๊ณ ์์ผ๋ก๋ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ ๊ทน์ ์ผ๋ก ์ฌ์ฉํด์ผ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
๐ Styled-components๋ฅผ ์ฌ์ฉํ ์ด์ ๋?
Styled components๋ ํน์ ์คํ์ผ์ด ์ฒจ๋ถ๋ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ถํ ์ ์๋๋ก ๋์์ฃผ๋ ํจํค์ง๋ก JavaScript ํ์ผ์ CSS ์คํ์ผ์ ์์ฑํ๋ CSS-in-JS์ ์คํ์ผ ์ ์ ๋ฐฉ์์ด๋ค. ์ด๋ ํด๋น ์คํ์ผ์ด ์ฌ์ฉ๋๋ ์ปดํฌ๋ํธ์๋ง ์ํฅ์ ๋ฏธ์น๊ณ , ๋ค๋ฅธ ์ปดํฌ๋ํธ์๋ ์ ํ ์ํฅ์ ๋ฏธ์น์ง ์๋๋ค๋ ์ฅ์ ์ด ์๋ค. ๋ํ Styled components๋ JavaScript์ ํ๊ฒฝ์ ํ์ฉํ ์ ์์ผ๋ฉฐ, props๋ฅผ ํ์ฉํ ์กฐ๊ฑด๋ถ ์คํ์ผ๋ง ๋ฑ์ด ๊ฐ๋ฅํ๋ฉฐ, ์คํ์ผ์ ๋ํ ๊ณ ์ ํ className์ด ์์ฑ๋๊ธฐ ๋๋ฌธ์ className ์ค๋ณต์ ๋ํ ๊ฑฑ์ ์ ํ ํ์๊ฐ ์๋ค.
์ค์ ๋ก Styled components๋ฅผ ์ฌ์ฉํ style ์์ฑ์ className์ ์ค๋ณต์ ๊ฑฑ์ ํ ํ์๊ฐ ์์ผ๋ฉฐ, ํ๋์ ํ์ผ ์์์ ํด๋น ์ปดํฌ๋ํธ์ ์คํ์ผ์ ์ง์ ํ์ฌ ์คํ์ผ ์์ ์ ์ด๋ค ํ์ผ์ ํด๋น ์คํ์ผ์ด ์ ์ฉ๋์ด ์๋์ง ์ฐพ์ง ์์๋ ๋๋ ์ฅ์ ์ด ์์๋ค. ์ฆ, ์ ์ง๋ณด์๊ฐ ํธ๋ฆฌํ ๊ฒ์ด๋ค.
์ง์ํ ํ์ฌ์ ๊ธฐ์ ์คํ์ Styled-components์ Tailwind๊ฐ ์์๊ธฐ ๋๋ฌธ์ ๋ ์ค ํ๋๋ฅผ ์ฌ์ฉํด์ผ๊ฒ ๋ค๋ ์๊ฐ๋ ์์๋ค. ํ๋ก์ ํธ๊ฐ ํฌ์ง ์๊ณ , ๋น๊ต์ ๊ฐ๋ฒผ์ด ๊ธฐ๋ฅ์ ๊ตฌํํ ๊ฒ์ด๋ผ CSS-in-JS์ ๋ฐฉ์๋ ์ ํฉํ ๊ฒ์ด๋ผ ํ๋จ๋์๊ณ , ์ด์ ์ Styled-components๋ฅผ ์ฌ์ฉํ ์ ์ด ์์๊ธฐ ๋๋ฌธ์ ์ต์ํ๋ค๋ ์ด์ ๋ ์์๋ค. ์ฌ์ค ์ด๋ฒ ํ๋ก์ ํธ์๋ ๊ฐ๋จํ ์คํ์ผ๋ง ์ ๋๋ง ๊ตฌํํ๋ฉด ๋์๊ธฐ ๋๋ฌธ์ Styled-components๋ฅผ ๊ธฐ๋ฅ์ ์ต๋ํ์ผ๋ก ํ์ฉํ์ง๋ ๋ชปํ๊ฒ ๊ฐ์ด ์กฐ๊ธ ์์ฝ๊ธฐ๋ ํ์ง๋ง.
2. ๋ ์ด์์ ๊ณ ๋ฏผํ๊ธฐ
์ฒ์ ๊ณผ์ ๋ฅผ ๋ฐ์์ ๋ ๋ ๋์ค์ ๊ฑธ์ณ์ ธ ์๋ ๋ ์ด์์์ ์ด๋ค์์ผ๋ก ์ง์ผํ ์ง ๊ณ ๋ฏผ์ ๋ง์ด ํ์๋ค.
๊ณ ๋ฏผ๋ง ํ๊ณ ์์ผ๋ ์ง๋๊ฐ ์๋๊ฐ์ ๋ ธํธ์ ๋ ์ด์์ ๊ตฌ์ฑ์ ์ ๋ฆฌํด๋ณด๊ณ , ์ฐ์ ์ ์๋ง์ผ๋ก๋ผ๋(?) ํ์ ์ก์๋ณด๊ธฐ๋ก ํ๋ค.
3. Vite๋ก React + TypeScript ์กฐํฉ์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์์ฑ ํ,
main.tsx ํ์ผ์ document.getElementById('root') ๋ถ๋ถ์ ์๋ฌ
// Before
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
// โฌ๏ธ ๋ณ๊ฒฝ //
// After
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
4. ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด์ ๋ ์ด์์์ ์์ ํ ๋จผ์ ์์
๋ ์ด์์๊ณผ ๋ผ์ฐํ ์ด ์ํ๋ ๋ฐฉํฅ์ผ๋ก ์ ๋์ง๊ฐ ์์์ ๊ธฐ์กด์ ์์ ํ๋ ํ๋ก์ ํธ๋ฅผ ์ ๊น ๋๊ณ , ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด ์ต์ํ React + JS, Pure CSS ์กฐํฉ์ผ๋ก ๋น ๋ฅด๊ฒ ๋ ์ด์์์ ๋จผ์ ๋ง๋ค์ด๋ณด์๋ค.
5. zustand๋ก notebooks ์ํ๊ด๋ฆฌ ๋์
์ฑ ๋ด์์ Notebook ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ Props Drilling์ด ๋ง์ด ์ผ์ด๋์ ์ปดํฌ๋ํธ๊ฐ ๋ณต์กํด ๋ณด์๊ธฐ ๋๋ฌธ์ ์ํ๊ด๋ฆฌ ํด์ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค.
๐ Zustand๋ฅผ ์ ์ญ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ฌ์ฉํ ์ด์
Zustand๋ ๋ ์ผ์ด๋ก “์ํ”๋ผ๋ ๋ป์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ๊ฐ๊ฒฐํ Flux ์์น์ ๋ฐํ์ผ๋ก ์๊ณ ๋น ๋ฅด๊ฒ ํ์ฅ ๊ฐ๋ฅํ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
๋ด๊ฐ ์ ์ผํ๊ฒ ์ฌ์ฉํด๋ดค๋ Redux๋ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ, ์ฆ ์ด๋ค ์ผ์ ํ๊ธฐ ์ํด ๊ผญ ์์ฑํด์ผ ํ๋ ์ฝ๋๊ฐ ๋ง์ด ์๊ตฌ๋๋ค. Redux Toolkit์ ํตํด ์ค์ ์ด ์กฐ๊ธ ๋ ๊ฐํธํด์ง๊ธฐ๋ ํ์ง๋ง, ๋ค๋ฅธ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋น ์ฌ์ ํ ์ค์ ์ด ๋ณต์กํ๋ฉฐ ๋ฌ๋ ์ปค๋ธ๊ฐ ๊ธด ํธ์ด๋ค.
๋ฐ๋ฉด Zustand๋ Redux์ฒ๋ผ ๋ง์ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ๊ฐ ํ์ํ์ง ์๋ค. Zustand๋ ์ํ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ์ก์ ์ ์ ์ํ๊ณ , ๋ฆฌํด ๋ฐ์ hook์ ์ด๋ ์ปดํฌ๋ํธ์์๋ import ํ์ฌ ์ํ๋ ๋๋ก ์ฌ์ฉํ ์ ์๋ค. Zustand๋ ์ฌ์ฉ๋ฒ์ด ๊ฐ๋จํ์ฌ ๋ฌ๋ ์ปค๋ธ๊ฐ ๋น๊ต์ ๋ฎ์ ํธ์ด๋ค.
๋ํ ์ด๋ฒ note-app์ API ์์ด ํ๋ก ํธ ๋จ์์๋ง ๊ตฌํํ๋ผ๋ ์๊ตฌ์ฌํญ์ด ์์๊ธฐ ๋๋ฌธ์ localStorage๋ฅผ ์ฌ์ฉํด์ผ ํ๋๋ฐ, Zustand๊ฐ ์ ๊ณตํ๋ ๋ฏธ๋ค์จ์ด ์ค storage๋ฅผ ๊ด๋ฆฌํ ์ ์๋ ๋ฏธ๋ค์จ์ด๊ฐ ์์๋ค.
์ง์ํ ํ์ฌ์ ๊ธฐ์ ์คํ์ ํฌํจ๋์ด ์๋ Recoil๊ณผ Zustand ์ค ๋ฌด์์ ์ฌ์ฉํ ์ง ๊ณ ๋ฏผ์ ์ ๊น ํ์๋๋ฐ, ๋น ๋ฅด๊ฒ ๊ฒฐ๊ณผ๋ฌผ์ ๋ด์ผ ํ๋ ์ํฉ์ด์๊ธฐ ๋๋ฌธ์ ๋ณด๋ค ์ฌ์ฉํ๊ธฐ ๊ฐํธํ๊ณ ํธ๋ฆฌํ ๋ฏธ๋ค์จ์ด๋ฅผ ์ ๊ณตํ๋ Zustand๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค.
Zustand๋ ์ฒ์ ์ฌ์ฉํด๋ดค์ง๋ง ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ์ด ๊ณต์๋ฌธ์์์๋ ํ ํ์ด์ง ๋ฐ์ ๋์ง ์๊ณ , ๊ต์ฅํ ๊ฐ๋จํ๊ธฐ ๋๋ฌธ์ ์ด๋ ต์ง ์๊ฒ ๊ธ๋ฐฉ ์ตํ์ ์ฌ์ฉํ ์ ์์๋ค. ๊ฒ๋ค๊ฐ Zustand์ ๋ฏธ๋ค์จ์ด์ธ persist๋ฅผ ํตํด localStorage์ ์ ์ญ์ํ๋ฅผ ํธ๋ฆฌํ๊ฒ ์๋์ผ๋ก ์ ์ฅํ๊ณ ๊ด๋ฆฌํ ์ ์์๋ค.
์ ๊น, Flux ํจํด์ด๋?
Flux๋ ์ฌ์ฉ์ ์ ๋ ฅ์ ๊ธฐ๋ฐ์ผ๋ก Action์ ๋ง๋ค๊ณ Action์ Dispatcher์ ์ ๋ฌํ์ฌ Store(Model)์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ ๋ค View์ ๋ฐ์ํ๋ ๋จ๋ฐฉํฅ์ ํ๋ฆ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋๋ ์ํคํ ์ฒ์ด๋ค.
5-1) Zustand ๊ฐ๋จํ ํ์ต
๊ณต์๋ฌธ์์ ์ ํ๋ธ ์ผ๋ถ ์๋ฃ๋ฅผ ํตํด Zustand๋ฅผ ๊ฐ๋จํ ํ์ตํ๋ค.
์ฌ์ฉํ๊ธฐ ๋๋ฌด ๊ฐ๋จํ๊ณ ์ฌ์์ ๋๋ผ์ ๋ Zustand. ์ Redux ๋์ Zustand์ ๊ฐ์ ์ํ๊ด๋ฆฌ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋์ง ์ ๊ฒ ๊ฐ์๋ค.
5-2) Zustnad๋ฅผ ์ ์ฉํ์ฌ Props Drilling ์ผ๋ก ๋ณต์กํด์ง ์ปดํฌ๋ํธ ๋จ์ํํ๊ธฐ
// Before
// notebooks๊ฐ ์ด๋์์๋ ์ฌ์ฉ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ปดํฌ๋ํธ๋ง๋ค notebooks๋ฅผ props๋ก ๋ด๋ ค์ค์ผ๋ง ํ๋ค.
const notebooks = [...]
const Root = () => {
return (
<div className="app">
<Sidebar notebooks={notebooks} />
{ notebooks.length > 0 && (
<NoteContainer notebooks={notebooks} />
) }
</div>
)
}
// โฌ๏ธ ๋ณ๊ฒฝ //
// After
// notebooks๋ฅผ store์์ ๋ถ๋ฌ์ ํ์ํ ์ปดํฌ๋ํธ์์ ์ง์ ์ฌ์ฉํ ์ ์๊ฒ ๋์๋ค.
import { useStore } from "../store/notebooks";
const Root = () => {
const { notebooks } = useStore();
return (
<div className="app">
<Sidebar/>
{ notebooks.length > 0 && (
<NoteContainer />
) }
</div>
)
}
5-3) Zustand์ middleware persist๋ฅผ ์ฌ์ฉํ์ฌ storage์ ์ํ ์ ์ฅํ๊ธฐ
๐ ๊ณต์๋ฌธ์: https://docs.pmnd.rs/zustand/integrations/persisting-store-data
import { create } from "zustand";
import { persist } from 'zustand/middleware'
export const useStore = create(
persist(
(set) => ({
notebooks: [],
createNotebook: (name) => set((prev) => ({
notebooks: [
...prev.notebooks,
{
id: new Date().getMilliseconds(),
name,
notelist: []
}
]
})),
{ name: "note-storage" }
)
);
→ ์์ ๊ฐ์ด persist๋ก ๊ฐ์ธ์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ค. persist๋ก ๊ฐ์ธ์ง ์ํ์ ๋ณํ๊ฐ ์๊ธฐ๋ฉด localStorage์๋ ์๋์ผ๋ก ์ ๋ฐ์ดํธ๊ฐ ๋๋ค. ์ฆ, notebook๋๋ note๋ฅผ ์ถ๊ฐํ์ ๋ localStorage๋ ์๋์ผ๋ก ์ ๋ฐ์ดํธ๊ฐ ๋ notebooks๋ฅผ ๋ฐ์ํ๋ค.
์ฐธ๊ณ ๋ก, ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์์ฑํ์ฌ ํ์ ์ ๋ฃ์ด์ค ์ ์์๋ค.
import { create } from "zustand";
import { persist } from "zustand/middleware";
import { NoteType, NotebookType } from "../type/notebookTypes";
interface StoreType {
notebooks: NotebookType[];
createNotebook: (name: string) => void;
}
export const useStore = create<StoreType>()(
persist(
set => ({
notebooks: [],
createNotebook: name =>
set(prev => ({
notebooks: [
{
id: Date.now(),
name,
notelist: [],
},
...prev.notebooks,
],
})),
}),
{
name: "NOTE_APP_STORAGE",
},
),
);
6. LocalStorage์ ์ด๋ ํ ํ์์ผ๋ก notebooks๋ฅผ ์ ์ฅํ ๊น?
์ฒ์์๋ ์์ ์ ํธ์๋ฅผ ์ํด ์๋์ ๊ฐ์ด notebook๊ณผ ํด๋น notebook์ notelist๋ฅผ ๋ฐ๋ก ์ ์ฅํ ๋๋ฏธ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ํ ์คํธ๋ฅผ ํ์๋ค.
const notebooks = [
{ id: 1, name: "notebook1" },
{ id: 2, name: "notebook2" },
]
const noteList = {
"notebook1" : [
{ id: 1, title: "new note1", content: "this is a new note", date: new Date() },
],
"notebook2" : [
{ id: 2, title: "new note2", content: "this is a new note", date: new Date() },
{ id: 3, title: "new note3", content: "this is a new note", date: new Date() },
]
}
๊ทธ๋ฐ๋ฐ ์๊ฐํด๋ณด๋ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ ํ๊ณ , ๋ฐ์ดํฐ๊ฐ “notebooks”๋ผ๋ ํ ๊ณณ์ ์ ์ฅ์ด ๋์ด ์์ด์ผ ์์ฑ๊ณผ ์์ ๋ฑ์ ์์ ์ด ํธํ ๊ฒ ๊ฐ์ notebooks ๋ฐฐ์ด์ notebook์ ๋ฃ๊ณ , notebook์ notelist์ ๋ฐฐ์ด์ ๋ฃ๋ ํ์์ผ๋ก ์์ ํ์๋ค.
const notebooks = [
{
id: 1,
name: "notebook1",
notelist: [
{ id: 11, title: "new note1", content: "this is a new note", date: new Date() },
]
},
{
id: 2,
name: "notebook2",
notelist: [
{ id: 21, title: "new note2", content: "this is a new note", date: new Date() },
{ id: 31, title: "new note3", content: "this is a new note", date: new Date() },
]
},
]
โญ๏ธ
โฌ๏ธ ๊ธ์ด ๊ธธ์ด์ ธ์ ๋๋์ด ์์ฑํ์์ต๋๋ค. ๋ค์ ๊ธ ์ ๋๋ค. โฌ๏ธ