with React
최근에 리액트로 투두앱 만드는 연습을 했다. 만난 적은 없지만 거의 나에게는 멘토같은 Ellie (엘리의 드림코딩) 의 강의를 들으며 실습을 했다. 강의 내용 중에 localStorage를 사용해서 투두 리스트를 브라우저에 간단하게 저장하는 걸 보게 됏는데, 너무 간단하고 간편해서 메모해둔다 :)
localStorage는 웹 브라우저에서 제공하는 클라이언트 측 웹 스토리지다. 이걸 사용해서 웹 애플리케이션에서 데이터를 로컬에 저장하고, 혹은 다시 꺼내 사용할 수 있다. 일반적으로 다른 데이터베이스와는 다르게 비교적 작은 양의 데이터를 저장하기 위해 사용된다. 이 데이터는 사용자가 해당 웹 사이트를 방문할 때마다 로드되고, 세션 제한이 없어서 브라우저를 닫아도 데이터는 계속 유지된다.
localStorage를 사용하면 키-값 쌍으로 데이터를 저장할 수 있다. 예를 들어, 다음과 같이 코드를 작성하여 'todoItem'이라는 키에 '강아지랑 산책하기'라는 값을 저장할 수 있다
localStorage.setItem('todoItem', '강아지랑 산책하기');
위에 저장된 값을 가져오려면 키 값으로 꺼내올 수 있다.
const item = localStorage.getItem('todoItem');
// item 값은 '강아지랑 산책하기'
투두앱에서 localStorage에 저장해야되는 건 todos, 단순 문자열이 아니라 배열이다. 그래서 배열을 JSON.stringify 함수로 변환해서 저장해준다.
localStorage.setItem('todos', JSON.stringify(todos))
// todos = [{id:1, text:'강아지랑 산책시키기'}, ...]
// JSON.stringify(todos) = '[{id:1, text:'강아지랑 산책시키기'}, ...]'
// JSON.stringify() 는 object든 array든 String 형태로 바꾸어준다.
리액트 TodoApp에서 todos 값이 변경될때마다 업데이트해주면 되니까, useEffect 함수 안에 정의해준다.
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos))
}, [todos]) // todos가 바뀔때마다 실행된다
처음 todos를 불러올때, 이미 브라우저의 localStorage에 저장되어있는 값이 있다면 그걸 불러오고, 아니면 빈 배열([])을 가져와야 하므로, 처음 useState를 할때, 아래와 같이 localStorage로부터 값을 찾는다. 그리고 그걸 다시 JSON.parse로 배열을 만들어준다.
function readTodosFromLocalStorage() {
const todos = localStorage.getItem('todos')
return todos ? JSON.parse(todos) : []
}
const [todos, setTodos] = useState(() => readTodosFromLocalStorage())
* 여기서 주의해야 할 게, useState 안에서 바로 useState(readTodosFromLocalStorage()) 이렇게 콜 하면 안된다는 점이다. 그러면 컴포넌트가 투두가 하나씩 추가될때마다 readTodosFromLocalStorage 함수가 계속 실행된다. useState라는 게 기존의 값을 기억해서 거기에 자동으로 추가된 부분만 기억해서 업데이트해주는 기능인데, 이미 불러온 todos를 다시 localStorgae에서 불러올 필요가 없다. 그래서 처음 init state할 때만 해당 콜백함수가 실행되고, 그 후로는 실행되지 않는다. (좀 어려웠다)