이번 단계에서는 React 버전 메모장에 localStorage 저장 기능을 추가했다.
이전까지는 메모를 추가, 수정, 삭제할 수 있었지만 새로고침하면 데이터가 사라졌다.
그 이유는 메모가 React state인 memos 안에만 있었기 때문이다.
const [memos, setMemos] = useState([])
브라우저를 새로고침하면 React 앱이 다시 시작되고, state는 다시 초기값으로 돌아간다.
즉, 새로고침하면 memos는 다시 빈 배열이 된다.
그래서 메모를 브라우저에 남겨두기 위해 localStorage를 사용했다.
useEffect 추가하기
localStorage 작업을 처리하기 위해 useEffect를 사용했다.
기존에는 useState만 import하고 있었다.
import { useState } from 'react'
여기에 useEffect를 추가했다.
import { useState, useEffect } from 'react'
useState는 화면에 영향을 주는 데이터를 관리하는 기능이고,
useEffect는 렌더링 이후에 실행할 작업을 처리하는 기능이다.
이번 프로젝트에서는 localStorage에서 데이터를 불러오거나 저장하는 작업에 useEffect를 사용했다.
처음 실행될 때 localStorage에서 불러오기
먼저 앱이 처음 열릴 때 localStorage에 저장된 메모를 가져오도록 했다.
useEffect(() => {
const savedMemos = localStorage.getItem('memos')
if (savedMemos !== null) {
setMemos(JSON.parse(savedMemos))
}
}, [])
이 코드는 앱이 처음 렌더링된 뒤 한 번 실행된다.
마지막에 있는 빈 배열 []이 중요하다.
}, [])
이 뜻은 다음과 같다.
처음 렌더링된 뒤 한 번만 실행해라.
JavaScript에서 만들었던 loadMemos()와 비슷한 역할이다.
localStorage.getItem
저장된 메모를 가져올 때는 localStorage.getItem()을 사용했다.
const savedMemos = localStorage.getItem('memos')
이 코드는 localStorage에서 memos라는 이름으로 저장된 값을 가져온다.
localStorage에 값이 없으면 null이 나온다.
그래서 바로 사용하지 않고 먼저 확인했다.
if (savedMemos !== null) {
setMemos(JSON.parse(savedMemos))
}
저장된 값이 있을 때만 setMemos()를 실행한다.
JSON.parse가 필요한 이유
localStorage는 배열이나 객체를 그대로 저장하지 못한다.
문자열만 저장할 수 있다.
그래서 저장할 때는 배열을 문자열로 바꿔야 한다.
JSON.stringify(memos)
반대로 꺼낼 때는 문자열을 다시 배열로 바꿔야 한다.
JSON.parse(savedMemos)
그래서 다음 코드는,
setMemos(JSON.parse(savedMemos))
이렇게 이해할 수 있다.
localStorage에서 꺼낸 문자열을
JSON.parse로 배열로 바꾼 뒤
setMemos로 memos state에 넣는다.
풀어 쓰면 다음 코드와 같다.
const parsedMemos = JSON.parse(savedMemos)
setMemos(parsedMemos)
memos가 바뀔 때마다 localStorage에 저장하기
불러오기만 하면 부족하다.
메모를 추가, 수정, 삭제했을 때 변경된 memos를 다시 localStorage에 저장해야 한다.
그래서 두 번째 useEffect를 추가했다.
useEffect(() => {
localStorage.setItem('memos', JSON.stringify(memos))
}, [memos])
여기서 마지막에 있는 [memos]가 중요하다.
}, [memos])
이 뜻은 다음과 같다.
memos state가 바뀔 때마다 이 useEffect를 실행해라.
그래서 메모를 추가하면 다음 순서로 동작한다.
setMemos 실행
→ memos state 변경
→ useEffect 실행
→ localStorage 저장
삭제해도 마찬가지다.
setMemos 실행
→ memos state 변경
→ useEffect 실행
→ localStorage 저장
수정해도 같은 흐름이다.
setMemos 실행
→ memos state 변경
→ useEffect 실행
→ localStorage 저장
localStorage.setItem
저장할 때는 localStorage.setItem()을 사용했다.
localStorage.setItem('memos', JSON.stringify(memos))
이 코드는 현재 memos 배열을 localStorage에 저장한다.
다만 localStorage에는 문자열만 저장할 수 있으므로 JSON.stringify()를 사용한다.
JSON.stringify(memos)
이 코드는 배열을 문자열로 바꿔준다.
예를 들어 배열이 이렇게 있다면,
[
{ id: 1, title: 'A', content: 'aaa' }
]
문자열로 바뀌면 이런 형태가 된다.
'[{"id":1,"title":"A","content":"aaa"}]'
이 문자열이 localStorage에 저장된다.
useEffect의 역할 정리
이번 단계에서 사용한 useEffect는 두 개다.
첫 번째 useEffect는 앱이 처음 실행될 때 저장된 메모를 불러온다.
useEffect(() => {
const savedMemos = localStorage.getItem('memos')
if (savedMemos !== null) {
setMemos(JSON.parse(savedMemos))
}
}, [])
두 번째 useEffect는 memos가 바뀔 때마다 저장한다.
useEffect(() => {
localStorage.setItem('memos', JSON.stringify(memos))
}, [memos])
정리하면 다음과 같다.
useState
→ React가 기억해야 하는 화면 데이터 관리
useEffect
→ 렌더링 이후에 실행해야 하는 부가 작업 처리
localStorage는 화면을 그리는 JSX가 아니라 브라우저 저장소와 관련된 작업이므로 useEffect에서 처리했다.
새로고침했을 때의 흐름
이제 새로고침을 하면 다음 순서로 동작한다.
1. React 앱이 다시 시작된다.
2. memos state는 처음에 빈 배열로 시작한다.
3. 화면이 한 번 렌더링된다.
4. 첫 번째 useEffect가 실행된다.
5. localStorage에서 저장된 문자열을 가져온다.
6. JSON.parse로 배열로 바꾼다.
7. setMemos로 memos state에 넣는다.
8. memos가 바뀌었으므로 React가 다시 렌더링한다.
9. 저장돼 있던 메모가 화면에 보인다.
즉, 새로고침해도 메모가 유지된다.
메모 추가, 수정, 삭제 후의 흐름
메모를 추가하면 다음처럼 동작한다.
새 메모 객체 생성
→ setMemos로 memos state 변경
→ React가 다시 렌더링
→ 두 번째 useEffect 실행
→ 변경된 memos를 localStorage에 저장
메모를 수정해도 흐름은 같다.
수정된 새 배열 생성
→ setMemos로 memos state 변경
→ React가 다시 렌더링
→ 두 번째 useEffect 실행
→ 변경된 memos를 localStorage에 저장
메모를 삭제해도 마찬가지다.
삭제된 새 배열 생성
→ setMemos로 memos state 변경
→ React가 다시 렌더링
→ 두 번째 useEffect 실행
→ 변경된 memos를 localStorage에 저장
이번 단계의 핵심은 memos state와 localStorage를 연결한 것이다.
앱이 처음 열릴 때
→ localStorage에서 메모를 불러온다.
memos가 바뀔 때마다
→ localStorage에 다시 저장한다.
이제 React 버전 메모장도 새로고침 후 데이터가 유지된다.
'Project > Memo Evolution' 카테고리의 다른 글
| #16 HTML/CSS/JS 메모장을 React로 고도화 정리 (0) | 2026.06.20 |
|---|---|
| #15 컴포넌트 분리와 props 이해하기 (0) | 2026.06.20 |
| #13 React에서 메모 삭제 기능 구현하기 (0) | 2026.06.18 |
| #12 React 프로젝트 시작과 입력값 상태 관리 (0) | 2026.06.16 |
| #11 React 시작하기 (0) | 2026.06.15 |