본문으로 바로가기

해외 사이트에서는 좀처럼 보지 못하지만 한국 웹에서는 매우 자주 볼 수 있는 팝업을 만들어보려고 합니다.

보통 php 기반 웹에서 많이 보이는 형태는 아래 같습니다.

 

원리는 Modal과 완전히 동일하고, 접속 시간을 Cookie 혹은 Local Storage로 관리한다는 점만 유일하게 다릅니다.

 

팝업

 

레이아웃은 일반 modal과 다를 것이 없으므로 설명을 생략하겠습니다.

여기서 중요한 건, '오늘 하루 보지 않기'를 클릭 했을 경우의 로직입니다.

n일, n시간 등도 로직이 같으므로 저는 하루를 기준으로 잡겠습니다.

import React from 'react';
import styled from 'styled-components';

interface IPopUpProps {
  showPopUp: boolean;
  setshowPopUp: Function;
}

function PopUp({ showPopUp, setshowPopUp }: IPopUpProps) {
  // 하루 동안 팝업 보여지지 않기
  const onPopUpNotShot = () => {
    // logic
  };

  return (
    <>
      {showPopUp ? (
        <S.Wrapper>
          <S.ImageWrapper className="notice-img">
            <img src="/partners/roy/roy1.jpg" alt="" />
          </S.ImageWrapper>
          <S.TodayWrapper className="todays">
            <button className="today-not-show" onClick={onPopUpNotShot}>
              오늘 하루 보지 않기
            </button>
            <button className="close" onClick={() => setshowPopUp(false)}>
              닫기
            </button>
          </S.TodayWrapper>
        </S.Wrapper>
      ) : (
        ''
      )}
    </>
  );
}

export default PopUp;

 

 

로직은 간단하다.

 

1. 보지 않기 버튼을 누르면 팝업을 닫고, (버튼을 누른 시간, 즉, 현재시간)을 cookie나 LS에 저장한다.
2. 재접속시 보지 않기 (버튼을 누른 시간 + expired time)과 현재 시간을 비교한다.
3. (버튼을 누른 시간 + expired time) > 현재 시간 => 아직 시간이 안 지났으므로 팝업을 키지 않는다.
4. (버튼을 누른 시간 + expired time) < 현재 시간 => 시간이 지났으므로 팝업을 킨다.

 

코드로 구현하면 다음과 같습니다.

function Home() {
  const [showPopUp, setshowPopUp] = useState(false);

  useEffect(() => {
    const fuzePopUpNotShow = localStorage.getItem('fuzePopUpNotShow'); // ISO
    const fuzePopUpNotShowUNIX = Date.parse(fuzePopUpNotShow); // UNIX
    const whenWillBeExpired = fuzePopUpNotShowUNIX + 1000 * 60; // 우선 1분만

    const currentUNIX = Math.floor(new Date().getTime());

    console.log(fuzePopUpNotShowUNIX);
    console.log(currentUNIX);
    console.log(whenWillBeExpired);

    // 아무 정보가 없으면 팝업을 띄우자. (처음 들어온 사람)
    if (Number.isNaN(fuzePopUpNotShowUNIX)) {
      setshowPopUp(true);
    }

    // 제한 시간을 지났으므로 팝업을 띄울 것
    if (whenWillBeExpired < currentUNIX) {
      setshowPopUp(true);
    }
  }, []);
  
  ... 이하 중략

 

 

 

팁 및 주의점

 

1. 시간 비교 이놈 참, 쯧...

 

LS에 저장하는 과정에서 Date 타입은 손실되고 단순 number인 UNIX, 단순 string인 ISO 둘 중 하나로 받았을 것이다. 수작업을 가급적 줄이기 위해서는

Date => ISO 저장 => Date.parse 메서드를 활용하여 UNIX 변환 => 숫자 타입으로 비교 연산

이 그나마 편하다.

 

 

2. NaN 주의!

 

value === NaN 은 당연히 false입니다.

Number.isNan()이나 isNan()을 사용하도록합시다.

 

NaN은 다른 모든 값과 비교(==, !=, ===, !==)했을 때 같지 않으며, 다른 NaN과도 같지 않습니다. NaN의 판별은 Number.isNaN() 또는 isNaN()을 사용하면 제일 분명하게 수행할 수 있습니다.

 

developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/NaN

 

NaN - JavaScript | MDN

전역 NaN 속성은 Not-A-Number(숫자가 아님)를 나타냅니다. Writable no Enumerable no Configurable no The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, ple

developer.mozilla.org

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체