[Udemy] React 실전(감정일기장) - LocalStorage를 일기 DB로 사용하기

productuidev·2022년 5월 29일
1

React Study

목록 보기
45/52
post-thumbnail
post-custom-banner

React 실전 (Project)

Udemy - 한입크기로 잘라 먹는 리액트


📌 감정일기장 페이지 구현 - LocalStorage를 일기 DB로 사용하기

☑️ Local Storage

  • 웹 브라우저의 데이터베이스 같은 느낌인 Storage를 사용해 일기 데이터 저장
  • 이전 새 일기를 작성 후 새로고침을 누를 경우 작성했던 일기는 dummydata로 넣은 일기를 제외하고 모두 사라졌다.
  • 휘발성 메모리 : 자바스크립트의 기능을 활용해서 React의 State 값을 추가적으로 저장하더라도 자바스크립트는 클라이언트 사이드인 웹 브라우저에서만 동작하는 그런 데이터이므로 새로고침하게 되면 가지고 있던 것을 싹 비운 다음 새로 다시 받기 때문에 그런 과정에서 데이터들은 초기화 된다.
  • 보통 이런 서비스를 만들 때 DB(데이터베이스)에 값을 저장하고 새로고침을 했을 땐 DB에서 값을 불러오게 만든다.

그런데 현재 우리는 DB가 없고, DB를 배우지 않았는데..?!
이럴 때 굉장히 쉽고 간단하게 비용을 들이거나 추가적인 노동없이 사용할 수 있는 DB가 하나 존재하는데...

☑️ Web Storage API 사용하기

  • Web Storage API
    자바스크립트의 Object를 사용할 때 또는 JSON 객체를 표현할 때 사용했었던 데이터 유형
  • 쿠키보다 훨씬 직관적으로 저장할 수 있는 방법을 제공
  • 복습 : TIL - 쿠키와 세션
  • 브라우저의 데이터를 Key와 Value를 쌍으로 저장하는데, Web Storage에는 sessionStorage와 LocalStorage가 있다.
  • sessionStorage : 각각의 출처에 대해서 독립적인 저장 공간을 페이지 세션이 유지되는 동안 저장 (웹 브라우저가 꺼지면 데이터가 날아간다 > 작성한 일기가 날라갈 수 있다)
  • LocalStorage : sessionStorage와 달리 브라우저가 꺼져도 데이터가 남아있다. 유효기간 없이 데이터를 저장하고 자바스크립트를 사용하거나 브라우저 캐시 또는 로컬 저장 데이터를 지워야만 사라진다. (작성한 일기 데이터를 내 브라우저에 남겨둘 수 있다)

크롬 개발자도구(F12) > Application 탭 > Storage > Local Storage의 3000포트

☑️ useEffect 활용 일기 데이터 저장 TEST

  • Web Storage의 LocalStorage에 작성한 일기 데이터를 실시간으로 저장하고 새로고침이 일어났을 때(= App 컴포넌트가 Mount 됐을 때 LocalStorage에 저장된 데이터를 확인하기

src/App.js

LocalStorage의 데이터를 어떻게 저장하고 어떻게 꺼낼 수 있는지?

function App() {
  useEffect(()=>{
    localStorage.setItem("item1", 10);
    localStorage.setItem("item2", "20");
	localStorage.setItem("item3", JSON.stringify({value:30}));
  }, []);
  • JSON.stringify : json 객체를 String 객체로 변환 (직렬화)

function App() {
  useEffect(()=>{
    const item1 = localStorage.getItem("item1");
    const item2 = localStorage.getItem("item2");
    const item3 = JSON.parse(localStorage.getItem("item3"));
    console.log({item1, item2, item3});
  }, []);
  • JSON.parse : string 객체를 json 객체로 변환

☑️ LocalStorage에 내 일기 데이터 저장하기 구현

  • 기존의 dummyData는 삭제하고 useReducer의 초기값도 빈 배열로 변경
const [data, dispatch] = useReducer(reducer, []);
  • 일기 데이터를 변경할 때마다 LocalStorage 값을 넣을 수 있게 저장하는 것부터 구현하는데 변경되는 로직을 처리하는 한 가지 통로 생각하기 => Reducer
  • 모든 데이터 수정은 모두 다 Reducer를 거쳐서 수행되기 때문에 newState가 변화할 때마다 LocalStorage의 데이터를 넣어주면 됨
const reducer = (state, action) => {
  let newState = [];
  switch(action.type){
    case "INIT" : {
      return action.data;
    }
    case "CREATE" : {
      // const newItem = { ...action.data };
      newState = [action.data, ...state]; // 변경될 값
      break;
    }
    case "REMOVE" : {
      newState = state.filter((it)=>it.id !== action.targetId);
      break;
    }
    case "EDIT" : {
      newState = state.map((it)=>it.id === action.data.id ? {...action.data} : it);
      break;
    }
    default:
      return state;
  }

  // reducer를 거쳐서 일기 렌더링
  // newState가 return되기 전 localStorage에 저장 (직렬화)
  
  localStorage.setItem("diary", JSON.stringify(newState));
  return newState;
};
  • 새로고침 후 새로운 일기 아무거나 작성해서 실시간으로 LocalStorage에 저장되는지 확인하기
  • 저장된 일기를 수정하여 수정된 내용도 LocalStorage에 저장되는지 확인하기

☑️ 삭제하기 기능 추가하여 LocalStorage에서 제거되는지 확인

  • DiaryEditor 컴포넌트의 MyHeader 오른쪽상단에 삭제하기 버튼 추가 (수정하기로 들어왔을 때)

src/components/DiaryEditor.js

      <MyHeader
        headText={isEdit ? "일기 수정하기" : "새 일기쓰기"}
        leftChild={<MyButton text={"< 뒤로가기"} onClick={()=>navigate(-1)} />}
        rightChild={isEdit && (<MyButton text={"삭제하기"} type={"negative"} />)}
      />
  • App 컴포넌트에서 onRemove를 Prop으로 공급받기
  • 일기를 삭제하는 handleRemove 함수를 만들고 삭제 후 Home 경로로 이동 (replace:true로 뒤로가기 접근 못하게 막기)
   // 삭제하기 onRemove 공급
  const {onCreate, onEdit, onRemove} = useContext(DiaryDispatchContext);
  
  // 삭제하기
  const handleRemove = () => {
    if(window.confirm("정말 삭제하시겠습니까?")) {
      onRemove(originData.id);
      navigate('/',{replace:true});
    }
  };
  • 삭제하기 버튼에 handleRemove를 onClick 이벤트의 Prop으로 전달
      <MyHeader
        headText={isEdit ? "일기 수정하기" : "새 일기쓰기"}
        leftChild={<MyButton text={"< 뒤로가기"} onClick={()=>navigate(-1)} />}
        rightChild={isEdit && (<MyButton text={"삭제하기"} type={"negative"} onClick={handleRemove} />)}
      />
  • 삭제했을 때 Local Strage의 데이터가 삭제되었는지 확인

☑️ LocalStorage의 값을 꺼내서 dataState의 기초값으로 사용하기

  • LocalStorage에 저장은 되어있지만 아직 이 데이터를 꺼내서 App 컴포넌트에 적용하지 않았기 때문에 반영되지 않음
  • App 컴포넌트가 Mount되었을 때 LocalStorage에 있는 값을 꺼내서 dataState의 기초값으로 사용해보기 (useEffect 활용)
  • localData에 LocalStorage의 diary 아이템을 가져오기(getItem)
  • localData가 있으면 diaryList의 id 값을 정렬 (현재 dataId의 값은 가져온 데이터 중 가장 높은 아이디를 가질 때 +1) -> 정렬을 내림차순으로 diaryList에서 0번째 요소를 뽑은 다음 그 id에 +1을 해주는 것
  • dispatch의 초기값에 diaryList 전달
  • dummyData를 지웠으므로 dataId는 0부터 시작
  useEffect(()=>{
    const localData = localStorage.getItem("diary");
    if(localData) {
      const diaryList = JSON.parse(localData).sort(
        (a,b) => parseInt(b.id) - parseInt(a.id)
      );
      dataId.current = parseInt(diaryList[0].id) + 1

	 // 초기값을 설정해주는 액션
      dispatch({type:"INIT", data:diaryList});
    }
  }, []);
  
  // key 초기값 변경
  const dataId = useRef(0);

☑️ 새 일기 작성 및 저장해보기

  • LocalStorage를 모두 delete한 후 새로고침하여 새 일기 여러개 작성 후 저장해보기
  • LocalStorage에 1번 id부터 잘 저장되었는지 확인


💬 이제 최적화 후 배포&빌드만 남음!!

profile
필요한 내용을 공부하고 저장합니다.
post-custom-banner

0개의 댓글