[JavaScript] 한국 시간으로 저장했는데 꺼내보면 다른 경우

sean·2023년 2월 10일
0

Web

목록 보기
14/22

문제 상황

인턴 사전과제로 최근 검색어 기능에 대해서 다음과 같은 요구사항을 받았다.

  • 검색어 입력 시 최대 30개까지 저장
  • X 클릭 시 삭제
  • 검색 후 10분 지나면 자동 삭제

따라서 나는 다음과 같이 구현하려고 생각했다.

  1. 검색어 입력하고 엔터를 누를 시 localStorage에 recent-keywords의 키에 해당하는 값에 { 검색어1: 시간1, 검색어2: 시간2, ... }의 객체로 저장한다.

  2. 다음 번에 다시 돋보기 버튼을 눌러서 검색 페이지를 여는 순간 localStorage의 recent-keywords 키에 해당하는 값을 JSON.parse()해서 실제 객체(A라고 하자)로 얻어낸다.

  3. for (const key in A)를 통해서 모든 검색어들을 순회하며 현재 시간과 비교했을 때 10분 이상 차이가 난다면 그러한 검색어들은 필터링을 해주고 남은 것들만 최근 검색어로 띄운다.

그런데, 로직은 문제가 없는 것 같았으나 3번 과정을 실행했을 때 모든 검색어들이 다 10분 이상 차이가 나서 최근 검색어가 뜨지 않았다. 그래서 검색어들과 연결된 시간들을 console.log()로 찍어보며 문제를 찾아냈다.

원인은, 분명히 내가 저장할 때 시간을 console.log()로 찍었을 때도 한국시간으로 저장이 되는 걸 확인했는데, 나중에 localStorage에서 꺼내서 그걸 console.log()로 찍으니 미국 시간으로 찍혀서 현재 시간과 엄청난 차이가 났기 때문이다.

엔터를 눌렀을 때 로컬스토리지에 해당 검색어를 현재 시간과 함께 저장하는 함수를 보면서 어떻게 해결했는지 설명해 보겠다.

해결 이전의 코드

import { useState } from "react";
import { useRouter } from "next/router";

const storeRecentKeyword = (keyword: string) => {
  if (typeof window !== "undefined") {
    const keywords = localStorage.getItem("recent-keywords");
    
    // 유효 기간 10분으로 설정
    const date = new Date();
    date.setSeconds(date.getSeconds() + 600);

    if (keywords) {
      const keywords_JSON = JSON.parse(keywords);
      keywords_JSON[keyword] = date;
      localStorage.setItem("recent-keywords", JSON.stringify(keywords_JSON));
    } else {
      localStorage.setItem(
        "recent-keywords",
        JSON.stringify({ keyword: date })
      );
    }
  }
};

해결한 코드

/*
import { useState } from "react";
import { useRouter } from "next/router";

const storeRecentKeyword = (keyword: string) => {
  if (typeof window !== "undefined") {
    const keywords = localStorage.getItem("recent-keywords");
    
    // 유효 기간 10분으로 설정
    const date = new Date();
    date.setSeconds(date.getSeconds() + 600);

    if (keywords) {
      const keywords_JSON = JSON.parse(keywords);
      */
      
      !! 여기서 date를 그대로 넣어주지 않고 date를 문자열로 바꿔서 넣어줌 !!
      keywords_JSON[keyword] = new String(date);
/*
      localStorage.setItem("recent-keywords", JSON.stringify(keywords_JSON));
    } else {
      localStorage.setItem(
        "recent-keywords",
        */
        !! 마찬가지로 date를 문자열로 바꿔서 넣어줌 !!
        JSON.stringify({ keyword: new String(date) })
      );
    }
  }
};

위처럼 현재 시간을 저장할 때 그대로 넣어주지 않고 문자열로 변환한 후에 그 문자열을 넣어주었다. 따라서, 나중에 꺼내 볼 때는 다시 Date로 변환한 후에 현재 시간과 비교를 하게 된다.

10분 경과한 최근 검색어 필터링

// keywords는 최근 검색어들을 저장하고 있는 전역 상태이다.
/*
const [keywords, setKeywords] = useRecoilState(recentKeywordState);

useEffect(() => {
    if (typeof window !== "undefined") {
      const recentKeywords = localStorage.getItem("recent-keywords");
      if (
        recentKeywords &&
        JSON.stringify(keywords) !== JSON.stringify(recentKeywords)
      ) {
        const JSONKeywords = JSON.parse(recentKeywords);
        setKeywords([]);
        */
        for (const key in JSONKeywords) {
          const now = new Date();
          
          !! 여기서 Date 형식으로 변환한 다음에 현재 시간과 비교 !!
          if (new Date(JSONKeywords[key]) >= now)
            setKeywords((prev) => prev.concat(key));
        }
/*
        setKeywords((prev) => {
          const temp = Array.from(prev);
          return temp.reverse().slice(0, 30);
        });
      }
    }
  }, []);

결론

날짜를 저장할 때 안전빵(?)으로 하려면 문자열로 저장해 논 다음에 꺼내볼 때 다시 Date 형식으로 바꿔서 보는 방법도 사용해 볼 수 있다!

profile
여러 프로젝트보다 하나라도 제대로, 깔끔하게.

0개의 댓글