์ง๊ธ๊ป html์ ์ง์ Web ํ๋ฉด์ ๊ตฌ์ฑํ๋ค๋ฉด ์ด์ ๊ทธ๋ง~~
DOM ์ ์ง์ ๊ตฌํํ๋ ๋ฐฉ์์ ํ๊ณ
- DOM์ ์ ๊ทผํ๊ณ ์ ๋ฐ์ดํธํ๋ ์์ ์ ๋ช ํํ ๊ธฐ์ค์ ์ด ์๊ธฐ ๋๋ฌธ์ UI ๊ฐ ๋ง์์ง์๋ก DOM ์ ๋ฐ์ดํธ ๊ตฌ๊ฐ ์ถ์ ์ด ์ด๋ ค์์ง๋ค.
- DOM ์ ๋ฟ๋ ค์ค data๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ผ์ผํ ์ฐพ์์ ์กฐ์ํด์ผ ํ๋ค.
- ์ค๋ณต ์ฝ๋๊ฐ ๋ง์์ง๊ณ DOM ์ ๊ทผ์ด ๋ง์์ง๋ค.
๋ฐ๋ผ์ Data๋ฅผ ๊ด๋ฆฌํ๋ component์ Data๋ฅผ ๋ฟ๋ ค์ค component๋ฅผ ๋ถ๋ฆฌ์ํฌ ํ์๊ฐ ์๋ค.
๊ทธ๋ ๋ค๋ฉด ๊ธฐ์กด DOM์ ์ง์ ์ ๊ทผํ๋ ๋ฐฉ์์ ์ฝ๋๋ฅผ ๋ณด๋ค ์ปดํฌ๋ํธ ํํ๋ก ์ถ์ํํด๋ณด์!
๐ ์ปดํฌ๋ํธ ํํ๋ก ๋ณ๊ฒฝ
๊ธฐ์กด ์ฝ๋
<html lang="kr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Tami - TODOS</title>
<link rel="stylesheet" href="./src/css/style.css" />
<script src="./index.js" type="module"></script>
</head>
<body>
<div class="todoapp">
<h1>TODOS</h1>
<input
id="new-todo-title"
class="new-todo"
placeholder="ํ ์ผ์ ์ถ๊ฐํด์ฃผ์ธ์"
autofocus
/>
<main class="App">
<input class="toggle-all" type="checkbox" />
<ul id="todo-list" class="todo-list"></ul>
<div class="count-container">
<span class="todo-count">์ด <strong>0</strong> ๊ฐ</span>
<ul class="filters">
<li>
<a class="all selected" href="#">์ ์ฒด๋ณด๊ธฐ</a>
</li>
<li>
<a class="active" href="#active">ํด์ผํ ์ผ</a>
</li>
<li>
<a class="completed" href="#completed">์๋ฃํ ์ผ</a>
</li>
</ul>
</div>
</main>
</div>
</body>
</html>
์์ ๊ฐ์ธ index.html ์ index.js ์คํฌ๋ฆฝํธ๋ง ์ ๊ฑธ์ด๋๊ณ ๊น๋ํ๊ฒ ์ฌ๋ผ์ก๋ค!
index.js์์๋ App์ ๋ถ๋ฅด๊ณ
App์์๋ ๋ค์ํ component๋ฅผ ๋ถ๋ฅด๋ฉฐ data๋ฅผ ๊ด๋ฆฌํ๋ ์ญํ ์ ํ ๊ฒ์ด๋ค
TodoList component์ ๊ฐ์ ๊ฒ๋ค์ด data๋ฅผ ๋ฟ๋ ค์ฃผ๋ ์ญํ ๋ง ํ ์์
index.html
<head>
//์ค๋ต
<script src="./index.js" type="module"></script>
</head>
<body>
<div class="todoapp">
<h1>TODOS</h1>
</div>
</body>
</html>
index.js
import TodoApp from './src/js/TodoApp.js';
new TodoApp(document.querySelector('.todoapp'));
TodoApp
import TodoList from './TodoList.js';
//๊ธฐ๋ณธ์ ์ธ ์ด๊ธฐ ์ํ (state)๋ฅผ ๊ฐ์ง๊ณ ์์
export default function TodoApp($app) {
this.state = {
todoes: ['hi', 'hello'],
};
//์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ณ๊ฒฝ๋ state๋ฅผ nextState๋ก ๋๊ฒจ์ค
this.setState = (nextState) => {
this.state = nextState;
todoList.setState(this.state.todoes);
};
//TodoList ์คํ
const todoList = new TodoList({
$app,
initialState: this.state.todoes,
});
//์ด๊ธฐ ์คํ
const init = () => {
this.setState({
...this.state,
});
};
init();
}
TodoList
export default function TodoList({ $app, initialState }) {
//$app ์ ๋ฐ์ ์ํ(inisialState)๋ก ๋ ๋๋ง ํ ์์
this.state = initialState;
//๋ ๋๋งํ DOM ์์ฑ
this.$target = document.createElement('ul');
this.$target.className = 'todo-list';
$app.appendChild(this.$target);
//state๋ฅผ ๋ฐ์์ ํ์ฌ component์ state๋ฅผ ๋ณ๊ฒฝํ๊ณ ๋ค์ ๋ ๋๋งํ๋ ํจ์
this.setState = (nextState) => {
this.state = nextState;
this.render();
};
//ํ์ฌ ์ํ๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ ๋๋ง (todoes์ ๋ฐฐ์ด์ map์ผ๋ก li์์ฑ)
this.render = () => {
const todoTemplate = `${this.state
.map((todo, idx) => `<li data-index="${idx}">${todo}</div>`)
.join('')}`;
this.$target.innerHTML = todoTemplate;
};
}
๐ ์ฒดํฌํ todo ์ฒ๋ฆฌํ๊ธฐ
this.setState = (nextState) => {
this.state = nextState;
this.render();
};
this.toggleTodo = (e) => {
const todoes = this.state;
};
this.render = () => {
const todoTemplate = `${this.state
.map(
(todo, idx) =>
`<li >
<div class="view">
<input class="toggle" type="checkbox" />
<label class="label">${todo}</label>
<button class="destroy"></button>
</div>
<input class="edit " value=${todo}/>
</li>`
)
.join('')}`;
this.$target.innerHTML = todoTemplate;
};
addEventListner๋ฅผ ํ๊ธฐ ์ํด์ ํ์ฌ <input class 'toggle' ~ /> ์ ๋ณ์๋ก ์ก์์ ํด์ผ ํ์ง๋ง,
ํจ์ ์ ์ธ ๋น์์ ์์ง ์ฒดํฌ๋ฐ์ค๊ฐ ๋ ๋๋์ง ์์์ ์ด๋ป๊ฒ ํด์ผ ํ ์ง ๊ณ ๋ฏผํ๋ค.
--> ์ฝ๋๋ฆฌ๋ทฐ ํ ๋ค๋ฅธ ํ์๋ค๊ณผ ์๊ธฐํด๋ณด๊ณ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ๋ก ํ๋ค.
1. ์ฒดํฌ๋ฐ์ค ํด๋ฆญ ์ ํด๋ฆญํ todoli์ id ์ ๋ฌ
2. ๋ ๋๋ง ์ ํด๋น id์ธ ๊ฒฝ์ฐ์ class ์์ฑ ์ถ๊ฐํด css ๋ค๋ฅด๊ฒ ์ ์ฉ
์๋ ๊ทธ๋ฆผ์ ๋ณด๋ฉด
e |
e.target.className |
e.target |
e.target.dataset |
์ฐจ๋ก๋ก ์ด๊ฒ๋ค์ ์ฐ์ด ๋ณด์๋๋ฐ
todo list ๋ ๋๋ง ์ data-node-id ๋ผ๋ ๊ฐ์ผ๋ก idx๋ฅผ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์
dataset์ ํตํด ํด๋น ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์๋ ๊ฒ์ด๋ค
๐ HTML ์ :before ๊ณผ :after ์ ํ์
HTML DOM ๊ฐ์ฒด์ ๋ด๋ถ์ ์ถ๊ฐ์ ์ธ ์ฝํ ์ธ ๋ฅผ ์ถ๊ฐํ ๋ ์ฌ์ฉํ๋ค.
:before ์ ํ์
DOM ๊ฐ์ฒด ๋ด๋ถ์ ๊ฐ์ฅ ์์ชฝ์ ์ถ๊ฐ
:after ์ ํ์
DOM ๊ฐ์ฒด ๋ด๋ถ์ ๊ฐ์ฅ ๋ท์ชฝ์ ์ถ๊ฐ
.todo-list li .destroy:after {
content: '×';
}
๋ฐ๋ผ์ ์ด๋ ๊ฒ ํ๋ฉด todo-list์ li ๋ด๋ถ ๊ฐ์ฅ ๋ท์ชฝ์ ํญ์ 'X'๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
์ด๋ฌํฅ ์ถ๊ฐํ ์ฝํ ์ธ ์๋ ๋ ์์ ์ธ ์คํ์ผ ์์ฑ ์ง์ ์ด ๊ฐ๋ฅํ๋ฐ,
๊ธฐ๋ณธ์ ์ผ๋ก๋ ๋ถ๋ชจ DOM ์ ์์ฑ์ ์์๋ฐ์ง๋ง, ๋ด๋ถ์ ์ผ๋ก ์ง์ ํ ์์ฑ์ด ์ฐ์ ์ ์ฉ๋๋ค.
:before๊ณผ :after ๋ก ์์ฑ๋ ์ฝํ ์ธ ๋ default ๊ฐ inline์์ฑ์ด๋ฏ๋ก ํด๋น li์ ๊ฐ์ ์ค์ ์๊ฒ ํ๊ณ ์ถ์ผ๋ฉด inline-block ์ด๋ block์ผ๋ก ์ง์ ํด์ฃผ๋ฉด ๋๋ค.
๐ ์ฝ์ง ๋ชจ์
1) ํด๋ฆญํ nodeId ์ dataset์ str์ด๋ค
const deleteTodo = (idx) => {
const todos = this.state.todoes;
const newTodos = todos.filter((todo) => {
console.log('eddddd', idx, todo.idx);
return todo.idx !== idx;
});
console.log(idx);
console.log('todos', todos);
console.log('newTodos', newTodos);
this.setState({
todoes: newTodos,
});
};
์ด๋ ๊ฒ ์ธ๋ฑ์ค๋ฅผ ๋น๊ตํด์ ์ญ์ ํ๋ ค๋๋ฐ ์๋ฌด๋ฆฌ filter๋ฅผ ํด๋ ์๋๋ ๊ฒ์ด๋ค? ์ด๊ฒ๋๋ฌธ์ ์ค๋์๊ฐ์ ์ฝ์งํ์ง๋ฉด ๊ฒฐ๋ก ์ ๋๊ฐ์ type์ด ๋ฌ๋ผ์์๋ค.....
const $node = e.target;
const $viewnode = e.target.closest('.view');
const { nodeId } = $viewnode.dataset;
if ($node.className == 'destroy') {
this.deleteTodoItem(nodeId);
์ด๋ฐ์์ผ๋ก nodeId๋ฅผ dataset์ผ๋ก ๋ฃ์ด์ฃผ๊ณ ์์๋๋ฐ, ์ด๋ ๊ฒ ๋ฃ์ผ๋ฉด nodeId์ ํ์ ์ด string์ด๋ผ๋ ์ ์ด๋ค!!!!!
์ดํ ๋ก ๊ฐ๋จํ ์์ ์!!!!! ์๊ธด๊ฑด TodoList addํ ๋๋ ์ด ๋ฌธ์ ๋๋ฌธ์ parseInt ํด๋จ๋๋ฐ ๋์ค์ ์๊ฐ ์ํ๊ณ ์ง์ฝ์ ์ธ ๋ถ๋ถ์ ํด๋์๋๋ ๋ ๋๊ฐ์ ๋ฌธ์ ์ ๊ฑธ๋ ธ๋ ๊ฒ์ด๋ค. ์์ผ๋ก ์ฝ๋๋ฅผ ๊ตฌํํ ๋ ์ด๋ฐ ๋ถ๋ถ์ ์ฃผ์ํด์ผ ๊ฒ ๋ค.
2) template literal ์ ์์ฑ์ str์ผ๋ก!
์ด๊ธฐ ์ฝ๋
<li class="${todo.state === 'completed' ? 'completed' : ''} ${
todo.state === 'editing' ? 'editing' : ''
}">
<div class="view" data-node-id=${todo.idx} >
<input class="toggle" type="checkbox" />
<label class="label">${todo.content}</label>
<button class="destroy"></button>
</div>
<input class="edit" value=${todo.content}/>
</li>
input ๊ณผ lebel ์ ๋์ผํ๊ฒ todo.content ๋ฅผ ๋ฃ์ด์คซ๋๋ฐ
input ์ value์ ์๊พธ๋ง ๋์ด์ฐ๊ธฐ๊ฐ ์ ์ธ๋๋๊ฒ์ด๋ค?
๋ฌธ์ ๋ ๋ฐ๋ก input์ vlaue๋ฅผ str์ผ๋ก ๋๊ฒจ์ฃผ์ง ์์ ๊ฒ!
<input class="edit" value="${todo.content}"/>
ํด๋น๋ถ๋ถ์ ์ด๋ ๊ฒ ๋ฌธ์์ด๋ก ๋ฐ๊ฟ์ฃผ๋ฉด์ ์ ์ ์๋.
์ ๋ง ์ฌ์ํ ์ค์์๋๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํด์ ๋ ๋ชป์ฐพ์๋ค...
๐ Refactoring
์คํผ๋ํ ๊ตฌํ์ ํ๋ค๋ณด๋ component๋ง๋ค ํจ์๋ฅผ ๋ถ๋ฌ์ค๋ ์์น๊ฐ ๋ฌ๋ผ์ ์ ๋ฆฌ๊ฐ ํ์ํ๋ค.
๊ธฐ๋ณธ์ ์ธ ํ์ ๋ณด๋ฉด TodoApp์์ onToggle์ด๋ผ๋ ํจ์๋ฅผ ๋ค ๊ตฌํํ๊ณ TodoList์์๋ ํด๋น ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์์ ์ฌ์ฉํ๋ ๊ตฌ์กฐ์ธ๋ฐ๋ฐ
๋ ธ๋์ ์ด๋ฒคํธ( $node addEventListener ) ๊ฐ ํ๋์ ๋ณด์ด๊ฒํ๊ธฐ ์ํด ๋ฐ๋ก ํจ์๋ก ( this.toggleTodoItem) ๋ถ๋ฆฌํ์ง๋ง
๋ ธ๋์ ์ด๋ฒคํธ ์์์ ๋ก์ง์ ๋ค์ฒ๋ฆฌํด ๋ฒ๋ ค์ ๋ถ๋ฆฌํ ํจ์๋ ์๋ฏธ๊ฐ ์์ด์ก๋ค.
์๋์ฒ๋ผ ํด๋ฆญ ์ด๋ฒคํธ๊ฐ ํ๋๋ฉด ์๊ด ์์ง๋ง
ํด๋ฆญํ ๋ ธ๋์ ๋ฐ๋ผ์
์ด์ ์ฝ๋
//๋
ธ๋์ ์ด๋ฒคํธ
$nodeTodoList.addEventListener('click', (e) => {
const $node = e.target;
if ($node.className === 'toggle') {
const { nodeId } = $node.closest('.view').parentNode.dataset;
this.toggleTodoItem(parseInt(nodeId));
}
//์ค๋ต
//๋ฐ๋ก ๋ถ๋ฆฌํ ํจ์
this.toggleTodoItem = (nodeId) => {
onToggle(parseInt(nodeId));
};
์๋์ ๊ฐ์ด ํด๋ฆญ ์ด๋ฒคํธ๊ฐ ๋ง์์ง๋ฉด ๋ณต์กํด์ง๋ค.
$nodeTodoList.addEventListener('click', (e) => {
const $node = e.target;
// ์ฒดํฌ๋ฐ์ค ํด๋ฆญ ์
if ($node.className === 'toggle') {
}
// ์ญ์ ํด๋ฆญ ์
if ($node.className === 'destroy') {
}
// ํธ์ง ํด๋ฆญ ์
if ($node.className === 'edit') {
}
});
๊ฐ์ ์ฝ๋!
// ๋
ธ๋์ ์ด๋ฒคํธ
$nodeTodoList.addEventListener('click', (e) => {
const $node = e.target;
if ($node.className === 'toggle') {
this.toggleTodoItem($node);
}
if ($node.className === 'destroy') {
this.deleteTodoItem($node);
}
if ($node.className === 'edit') {
this.editTodoItem($node);
}
});
// ๋ฐ๋ก ๋ถ๋ฆฌํ ํจ์
this.toggleTodoItem = ($node) => {
const { nodeId } = $node.closest('.view').parentNode.dataset;
onToggle(parseInt(nodeId));
};
this.deleteTodoItem = ($node) => {
const { nodeId } = $node.closest('.view').parentNode.dataset;
onDelete(parseInt(nodeId));
};
this.editTodoItem = ($node) => {
if ($node.className === 'edit') {
const { nodeId } = $node.parentNode.dataset;
$node.addEventListener('keydown', (e) => {
//Enter key ์
๋ ฅ
if (e.keyCode === 13) {
onEdit(parseInt(nodeId), true, $node.value);
} //esc key ์
๋ ฅ
else if (e.keyCode === 27) {
onEdit(parseInt(nodeId), false, '');
}
});
} else {
const { nodeId } = $node.closest('.view').parentNode.dataset;
if ($node.className === 'label') {
onEdit(parseInt(nodeId), false, '');
}
}
};
์ด๋ ๊ฒ ๋ถ๋ฆฌํจ์ผ๋ก์จ ํด๋ฆญ ์ด๋ฒคํธ๊ฐ ์ผ์ด๋ฌ์ ๋ ์ด๋ค ํจ์๋ค์ด ์ฐ์ด๋์ง ํ๋์ ๋ณด์ด๊ฒ ๋ณ๊ฒฝํ ์ ์์๋ค.
๐ filter ๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ์ํ๊ด๋ฆฌ ๊ณต์ฌ
์ฒ์ filter๋ฅผ ๊ตฌํํ ๋ ๋ค์๊ณผ ๊ฐ์ ๋ก์ง์ผ๋ก ์๊ฐํ๋ค.
1) ๊ฐ ๋ฒํผ์ ๋๋ ์ ๋ todo ๋ฐ์ดํฐ maping
2) todo data ๊ต์ฒด
๊ทธ๋ฌ๋ค ํํฐ๋ง ํ data์ ์๋ณธ data๋ฅผ ํ ๊ณณ์์ ๊ด๋ฆฌํ ์ ์์๋ค.
์๋ณธ data๊ฐ ํํฐ๋ง ๋๋ฉด์ ๊ธฐ์กด data๊ฐ ๋ ๋ผ๊ฐ๋ ๋๋ถ์์ฌ๊ฐ ์ผ์ด๋๊ณ ..
์ด ํฌ๋๋ฆฌ์คํธ๋ ํ๋ฒ ์๋ฃ์ํ ์ผ์ด ๋ญ์ง ํ์ธํ๋ฉด ์๋ฃํ ์ผ์ด ์์ ์ฌ๋ผ์ ธ ๋ชป๋ณด๊ฒ ๋๋ ํ๋ฐ์ฑ todolist๊ฐ ๋๋ฒ๋ฆฐ๋ค.^^
์ฒ์ ์ฝ๋ (ํ๋ฐ์ฑ)
const filterTodo = (filterType) => {
const todos = this.state.todoes;
const tempTodos = todos.slice();
//์ ์ฒด๋ณด๊ธฐ
if (filterType === 'all selected') {
this.setState({ todoes: todos });
}
// ์๋ฃํ ์ผ
else if (filterType === 'completed') {
const completedTodos = tempTodos.filter(
(todo) => todo.state === 'completed'
);
this.setState({
todoes: completedTodos,
});
}
//ํด์ผํ ์ผ
else if (filterType === 'active') {
const decompletedTodos = tempTodos.filter(
(todo) => todo.state !== 'completed'
);
this.setState({
todoes: decompletedTodos,
});
}
};
์ด๋ ๊ฒ ์ธ๊ฐ์ง ์ผ๋ค์ด ๋ฒ์ด์ง ๋์ ์ํ๋ฅผ ํ ๊ณณ์์ ๋ณด๊ดํ ๊ฒฐ๊ณผ
ํ๋ฒ ํํฐ๋ง์ ํ๋ฉด ์๋ณธ ๋ฐ์ดํฐ๋ ์ฌ๋ผ์ง๋ค..^^
๋ฐ๋ผ์ ๋๋ isFilter์ ๊ฐ์ flag ์กด์ฌ๋ฅผ ๋ง๋ค์ด์
isFilter === true ์ด๋ฉด ํํฐ๋ง ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ ๋๋ง
isFilter === false ๋ผ๋ฉด ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ๋ ๋๋ง
ํ๋๋ก ๋ณ๊ฒฝํ๊ธฐ๋ก ๊ฒฐ์ฌํ๋ค.
๐ ๊ฐ์ ์ ์ํ ๋ ธ๋ ฅ
1) ๋ฉ์ธ์ง ๋ฐ class data const ๋ก ๋ถ๋ฆฌ
export const FILTER_TYPES = {
ALL: 'FILTER_TYPES.ALL',
COMPLETE: 'completed',
ACTIVE: 'active',
};
export const TODO_ITEM_CLASS = {
TOGGLE: 'toggle',
DESTROY: 'destroy',
EDIT: 'edit',
LABEL: 'label',
VIEW: 'view',
};
export const TODO_FILTER_MENU = {
ALL_MENU: '์ ์ฒด๋ณด๊ธฐ',
ACTIVE_MENU: 'ํด์ผํ ์ผ',
COMPLETE_MENU: '์๋ฃํ ์ผ',
};
๊ธฐ์กด ์ฝ๋
$nodeTodoList.addEventListener('click', (e) => {
const $node = e.target;
if ($node.className === 'toggle') {
this.toggleTodoItem($node);
}
if ($node.className === 'destroy') {
this.deleteTodoItem($node);
}
if ($node.className === 'edit') {
this.editTodoItem($node);
}
});
๋ณ๊ฒฝ ์ฝ๋
$nodeTodoList.addEventListener('click', (e) => {
const $node = e.target;
if ($node.className === TODO_ITEM_CLASS.TOGGLE) {
this.toggleTodoItem($node);
}
if ($node.className === TODO_ITEM_CLASS.DESTROY) {
this.deleteTodoItem($node);
}
if ($node.className === TODO_ITEM_CLASS.EDIT) {
this.editTodoItem($node);
}
});
๋ฉ์ธ์ง์ class ๋ฐ์ดํฐ๋ const์์ ํ๋ฒ์ ๊ด๋ฆฌํ์ฌ ๋ณ๊ฒฝ์ด ์ผ์ด๋ ์ ๋์์ ๋ณ๊ฒฝ๋ ์ ์๋๋ก ์ ์ง๋ณด์๊ฐ ์ฝ๊ฒ ๋ณ๊ฒฝํ๋ค.
๐ localStorage ์ ์ฉํด๋ณด๊ธฐ
์ฒ์ localStorage๋ฅผ ๋์ ํ์ ๋, TodoApp์ด ์์ฑ๋๊ธฐ ์ ์ localStorage๋ฅผ ๋ถ๋ฌ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
TodoApp
export default function TodoApp($app) {
// localStorage.clear();
const initialDtate = {
todoes: [
{
idx: 0,
content: 'hiEvery One',
state: '',
},
{
idx: 1,
content: 'Im Tami',
state: '',
},
],
todoesFiltered: [],
filterState: FILTER_TYPES.ALL,
todoesCount: '0',
};
const localData = JSON.parse(localStorage.getItem('state'));
const viewData = localData ? localData : initialDtate;
this.state = viewData;
์ด๋ ๊ฒ TodoApp๋ด๋ถ์์ localStorage๋ฅผ ์ฒ์ ๊ฐ์ ธ์ด์ผ๋ก์จ ํด๊ฒฐํ๋ค.
localStorage ์ฑ๊ณต!!
local์ this.state๋ก๋ง ๊ด๋ฆฌํ๋ ๋ฐ์ดํฐ๋ ์๋ก๊ณ ์นจ ํ์ ์ฌ๋ผ์ก์ง๋ง
localStorage๋ก ๊ด๋ฆฌํจ์ผ๋ก์จ ์๋ก๊ณ ์นจํด๋์ฌ๋ผ์ง์ง ์๊ฒ ๋ฐ์ดํฐ ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ก๋ค.!!
๋๊ธ