본문 바로가기
짧은 글

로컬 스토리지로 모달창(팝업) 24시간 동안 안보이기 구현

by jaeeedev 2023. 3. 18.

팝업 만들 일이 생겨서 만들었는데 사용되지 않은 관계로... 기록

HTML

<body>
    <div class="popup-test">
      <div class="popup-test__info">
        <a
          class="popup-test__link"
          href="#!"
          target="_blank"
        >
          <img src="./source/temp.png" alt="test 이미지" />
        </a>
      </div>
      <div class="popup-test__buttons">
        <button class="popup-test__close24h">24시간동안 보지 않기</button>
        <button class="popup-test__close">닫기</button>
      </div>
    </div>

    <script src="./js/index.js"></script>
  </body>

JS

const setTimeLimit = () => {
  const { currentTime, popupElement } = popupVariables();
  localStorage.setItem("test-popup", currentTime);
  popupElement.style.display = "none";
};

const popupVariables = () => {
  const date = new Date();
  const setTime = localStorage.getItem("test-popup");
  const currentTime = date.getTime();
  const popupElement = document.querySelector(".popup-test");
  const popupCloseBtn = document.querySelector(".popup-test__close");
  const popup24CloseBtn = document.querySelector(".popup-test__close24h");

  return {
    date,
    setTime,
    currentTime,
    popupElement,
    popupCloseBtn,
    popup24CloseBtn,
  };
};

(function initTestPopup() {
  const { setTime, currentTime, popupElement, popupCloseBtn, popup24CloseBtn } =
    popupVariables();

  popup24CloseBtn.addEventListener("click", setTimeLimit);
  popupCloseBtn.addEventListener("click", () => {
    popupElement.style.display = "none";
  });

  if (!setTime) return;
  // 로컬 스토리지에 만료일이 있을 경우
  const isOver = (currentTime - setTime) / (1000 * 60 * 60 * 24) >= 1;

  if (isOver) {
    // 1일이 지났을 경우 다시 팝업을 노출
    localStorage.removeItem("test-popup");
    popupElement.style.display = "block";
  } else {
    popupElement.style.display = "none";
  }
})();

구현 방식

쿠키로 구현하는 방식이 많은 것 같은데 로컬스토리지가 익숙해서 로컬스토리지를 선택했다.
사이트에 진입하자마자 팝업에 관한 코드들이 실행되어야 하니 즉시실행함수를 썼다.

 

24시간동안 안보기 버튼을 클릭하면 그 클릭한 시간이 세팅된다(setTime).

그리고 페이지에 다시 진입할 때마다 현재 시간을 체크한다(currentTime)

로컬스토리지에 세팅된 시간이 있다면 다시 진입한 시간과 세팅된 시간의 차이를 계산한다.

하루가 지났다면 차이가 1일보다 커야한다.

 

Date 객체의 getTime은 밀리초 단위로 시간을 반환한다.

그래서 이것을 일 단위로 변환하려면 (24 * 60 * 60 * 1000) 로 나눠주면 된다.

각각 시간, 분, 초, 밀리초를 의미한다.

세팅된 시간과 다시 진입한 시간의 차이를 (24 * 60 * 60 * 1000)로 나눈 값이 1보다 크다면 하루가 지났다는 뜻이 된다.

그래서 1보다 크다면 로컬스토리지에 세팅된 시간을 지우고 모달의 display를 block으로 변경하여 다시 보이게 만들어준다.

 

변수들을 그냥 바깥에 덜렁 내버려두는게 지저분한것같아서 객체에 넣을까? 하다가 함수에 넣었다.

currentTime 같은건 여기저기 쓸 수 있을것 같기도 하니까

여담

굳이 모달로 구현한 이유는 팝업 구현을 요구한 사이트의 레퍼런스 사이트가 모달 형태였음

 

리액트만 줄창 만지다가 다시 돔을 일일이 잡는게 여간 귀찮은 일이 아니라고 느꼈다
리액트의 장점이 뭐냐고 물으면 기계적으로 기술면접 답안같은 대답만 줄줄 늘어놓았었는데 내 수준에서 진심으로 체감하는건 jsx를 통한 생산성 향상이라고 생각함

 

그리고 세팅된 시간을 나타내는 변수 이름을 setTime 으로 정했는데 이게 변수가 아니라 함수(setState같은)처럼 읽히는 것 같다. 근데 set의 과거분사는 set이 맞잖아???? 애매해

댓글