
최근에 만든 React 기반 일기장을 웹 스토리지를 이용해 데이터에 브라우저에 저장하고, Vercel에 배포하기까지의 과정을 공유하려고 해요. (웹 스토리지를 이용하면 서버 없이도 사용자가 작성한 일기를 브라우저에 안전하게 저장하고 불러올 수 있음!)
1. localStorage로 일기 저장하기
서버를 따로 두지 않고 데이터를 저장하려면 웹 스토리지(localStorage) 를 사용하는 게 간단하고 편리해요.
localStorage는 브라우저에 key-value 형식으로 데이터를 저장할 수 있는 저장소입니다.
localStorage 기본 사용법
// 저장하기
localStorage.setItem("key", "value");
// 불러오기
const data = localStorage.getItem("key");
// 삭제하기
localStorage.removeItem("key");
// 전부 삭제
localStorage.clear();
하지만 일기처럼 객체/배열 형태의 데이터를 저장할 땐, 문자열로 변환해주는 과정이 필요해요.
객체 저장 & 불러오기 (with JSON) - 실제 적용 코드
useReducer를 사용해 상태를 관리하면서 localStorage에 데이터를 저장하고 불러오는 흐름!
// reducer 함수: 일기 데이터를 관리하는 핵심 로직
function reducer(state, action) {
let nextState;
switch (action.type) {
case "INIT": {
return action.data; // 초기화 시 저장된 데이터로 상태를 설정
}
case "Create": {
nextState = [action.data, ...state];
break;
}
case "UPDATE": {
nextState = state.map((item) =>
String(item.id) === String(action.data.id) ? action.data : item
);
break;
}
case "DELETE": {
nextState = state.filter((item) => String(item.id) !== String(action.id));
break;
}
default:
return state;
}
// 상태가 변경될 때마다 localStorage에 저장 (JSON 문자열로 변환해서 저장)
localStorage.setItem("diary", JSON.stringify(nextState));
return nextState;
}
function App() {
const [isLoading, setIsLoading] = useState(true);
const [data, dispatch] = useReducer(reducer, []);
const idRef = useRef(0);
useEffect(() => {
const storedData = localStorage.getItem("diary"); // 저장된 문자열 가져오기
if (!storedData) {
setIsLoading(false); // 데이터가 없으면 로딩 해제하고 종료
return;
}
const parsedData = JSON.parse(storedData); // 문자열 → 객체로 변환
if (!Array.isArray(parsedData)) {
setIsLoading(false); //배열이 아니면 중단
return;
}
// 최대 ID값 계산 → 새 항목 생성 시 ID 겹치지 않도록
let maxId = 0;
parsedData.forEach((item) => {
if (Number(item.id) > maxId) {
maxId = Number(item.id);
}
});
idRef.current = maxId + 1;
// 초기 데이터로 상태 설정
dispatch({
type: "INIT",
data: parsedData, // 불러온 데이터를 반영
});
setIsLoading(false);
}, []);
// ...onCreate, onUpdate, onDelete 등 dispatch 처리
포인트 정리
작업 | 코드에서 하는 일 |
localStorage.setItem() | 객체를 JSON 문자열로 변환해 저장 |
localStorage.getItem() | 저장된 JSON 문자열 불러오기 |
JSON.parse() | 문자열을 JavaScript 객체로 변환 |
useEffect() | 앱이 처음 실행될 때 데이터 불러오기 |
2. 배포 전 프로젝트 빌드
npm run build

터미널에 작성하고 나면 해당과 같은 배포 가능한 정적 파일이 준비가 된다. 이후 Vercel에 연결해서 배포만 하면 된다!
3. Vercel CLI 설치하기
npm i -g vercel
- 맥을 사용할 경우 앞에 sudo를 붙여줍니다.
- -g를 붙여서 전역 설치!
4. Vercel 로그인하기
vercel login
- vercel에 가입된 본인 계정으로 로그인 해주면 됩니다. 저는 github으로 로그인 했어요!
- 이메일의 경우 이메일 주소를 입력하면 인증 메일이 오니 확인해주세요~!
5. 프로젝트 폴더에서 vercel 실행하기
vercel
처음 실행하면 몇 가지 질문을 받게 됩니다.
질문 | 답변 |
"Set up and deploy?" (이 위치에 있는 파일들을 배포하시겠습니까?) |
Y 또는 Enter |
"Which scope should it be deployed to?" (어떤 계정에 배포 하시겠습니까?) |
로그인 한 계정 선택 |
"Link to existing project?" (이미 존재하는 프로젝트에 연결하시겠습니까?) |
N |
"What’s your project’s name?" (프로젝트의 네임은 무엇입니까?) |
원하면 이름 변경 (아니면 기본값) |
"In which directory is your code located?" (어느 위치에 코드가 위치해있습니까?) |
대부분 . 입력 (현재 폴더) |
"Want to modify these settings?" (설정을 변경하시겠습니까?) |
n (저는 바이트를 사용해서 리액트 프로젝트를 만들었기 때문에, vercel에서 빌드 설정을 자동으로 해주었습니다.) |
6. 배포 완료!
질문에 모두 답하고 나면 배포가 완료됩니다! 배포를 모두 마치면, production: 주소가 하나 뜹니다.
근데 저는 여기서 이 주소로 접속하면 정상적으로 앱이 열리긴 하지만, 문제가 있었어요. 카카오톡이나 SNS에 링크를 보낼 때 썸네일 미리보기 이미지가 뜨지 않고, 다른 사람이 접속할 때 access 요청을 하라고 뜨더라구요...?
그래서 더 찾아보니 Vercel의 기본 설정 중 ‘배포 보호(Deployment Protection)’ 기능이 그 원인이었습니다.
해결 방법

[프로젝트] → Settings → Deployment Protection
Vercel 프로젝트 페이지에서 해당 이미지와 같이 다음 경로로 이동해서 Vercel authentication이라는 항목을 보면,
production 배포 주소 외에 다음과 같은 형식의 공개 주소들이 함께 제공됩니다. 이 주소를 사용하면 문제가 해결됩니다!
이번 프로젝트를 하면서도 새로운 걸 많이 배운 것 같아요. 투두리스트에서 쪼끔 뭐가 더 많아졌다고 상태관리가 더 다양해지는 점도 그렇고... 그래도 프로젝트를 하나 만들고, 배포까지 하고나니 정말 뿌듯했습니다! 끝까지 하는건 늘 중요한 것 같아요. 이번에 제가 만든 감정 일기장은 여기서 확인 가능합니다~!