쿠키의 만료기간(expires) 옵션을 활용하여 "n일동안 보지 않기" 기능을 구현해봤습니다.
모달용 쿠키를 만들어 해당 쿠키가 존재하면 모달을 띄우지 않는 방식으로 간단하게 구현했습니다.
리액트에서 쿠키를 쉽게 접근하기 위해 react-cookie 라이브러리를 설치합니다.
npm install react-cookie
yarn add react-cookie
1. 모달
먼저 모달을 만듭니다.
import React from "react";
import styled from "styled-components";
const Container = styled.div`
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
z-index: 1000;
`;
const ModalBackground = styled.div`
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.75);
z-index: 1000;
`;
const ModalContainer = styled.div`
z-index: 1001;
`;
const ModalContent = styled.div`
width: 100%;
background-color: #fff;
`;
const ModalCloseWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
p {
cursor: pointer;
}
`;
function Modal() {
return (
<Container>
<ModalBackground />
<ModalContainer>
<ModalContent>
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ratione
labore sint impedit, optio mollitia quae soluta possimus itaque
obcaecati unde expedita laudantium ducimus distinctio quasi rerum
molestiae velit, quibusdam cum.
</ModalContent>
<ModalCloseWrapper>
<p>오늘 하루 더 이상 보지 않기</p>
<p>닫기</p>
</ModalCloseWrapper>
</ModalContainer>
</Container>
);
}
export default Modal;
2. 모달 불러오기
모달을 불러와 state에 따라 모달을 띄울지 말지 설정해줍니다.
import { useEffect, useState } from "react";
import Modal from "./Modal";
export default function App() {
const [openModal, setOpenModal] = useState(true);
return (
<div className="App">
{openModal && <Modal closeModal={() => setOpenModal(false)} />}
</div>
);
}
...
interface IModalProps {
closeModal: () => void;
}
function Modal({ closeModal }: IModalProps) {
...
<Container>
...
<ModalCloseWrapper>
<p>오늘 하루 더 이상 보지 않기</p>
<p onClick={closeModal}>닫기</p>
</ModalCloseWrapper>
...
</Container>
...
저는 마운트 되자마자 모달이 떴으면 하므로, openModal의 초기값을 true 로 설정했습니다.
그리고 Modal의 닫기를 클릭하면 해당 모달이 꺼지도록 setOpenModal(false) 함수를 prop으로 보내줍니다.
여기까지는 일반적인 모달 ON/OFF 방식입니다.
이제 추가적으로 쿠키를 적용하여 쿠키가 만료되기 전까지는 모달이 안뜨도록 해보겠습니다.
3. 쿠키 설정
react-cookie 라이브러리 문서에 따라 App 컴포넌트를 <CookieProvider>로 감싸줍니다.
https://www.npmjs.com/package/react-cookie
import React from 'react';
import App from './App';
import { CookiesProvider } from 'react-cookie';
export default function Root() {
return (
<CookiesProvider>
<App />
</CookiesProvider>
);
}
그리고 App 컴포넌트로 돌아와 react-cookie에서 제공하는 useCookies Hook을 이용해 쿠키 목록을 불러옵니다.
import { useCookies } from "react-cookie";
const [appCookies, setAppCookies] = useCookies();
(console.log(appCokies)를 해보시면 쿠키 목록을 확인하실 수 있습니다.)
만료시기를 설정하는 함수 getExpiredDate를 작성했습니다.
일 수를 입력하면, 현재 시간에서 해당 일수를 더한 시기를 반환합니다.
const getExpiredDate = (days: number) => {
const date = new Date();
date.setDate(date.getDate() + days);
return date;
};
유효기간이 1일인 쿠키를 생성하고 모달을 닫는 함수를 작성합니다.
const closeModalUntilExpires = () => {
if (!appCookies) return;
const expires = getExpiredDate(1);
setAppCookies("MODAL_EXPIRES", true, { path: "/", expires });
setOpenModal(false);
};
useEffect로 해당 쿠키가 존재하면 모달이 안뜨고, 없으면 모달이 뜨도록 해주겠습니다.
hasCookie 라는 state를 추가적으로 생성하여 관리했습니다.
그리고 Modal 컴포넌트에 closeModalUnitlExpires 함수도 prop으로 넘겨
"오늘 하루 더 이상 보지 않기" 문구의 onClick 이벤트에 지정해줍니다.
import { useEffect, useState } from "react";
import { useCookies } from "react-cookie";
import Modal from "./Modal";
export default function App() {
const [openModal, setOpenModal] = useState(true);
const [hasCookie, setHasCookie] = useState(true);
const [appCookies, setAppCookies] = useCookies();
const getExpiredDate = (days: number) => {
const date = new Date();
date.setDate(date.getDate() + days);
return date;
};
const closeModalUntilExpires = () => {
if (!appCookies) return;
const expires = getExpiredDate(1);
setAppCookies("MODAL_EXPIRES", true, { path: "/", expires });
setOpenModal(false);
};
useEffect(() => {
if (appCookies["MODAL_EXPIRES"]) return;
console.log(appCookies["MODAL_EXPIRES"]);
setHasCookie(false);
}, []);
return (
<div className="App">
<button onClick={() => setOpenModal(true)}>모달 오픈</button>
{openModal && !hasCookie && (
<Modal
closeModal={() => setOpenModal(false)}
closeModalUntilExpires={closeModalUntilExpires}
/>
)}
</div>
);
}
...
interface IModalProps {
closeModal: () => void;
closeModalUntilExpires: () => void;
}
function Modal({ closeModal, closeModalUntilExpires }: IModalProps) {
return (
<Container>
<ModalBackground />
<ModalContainer>
...
<ModalCloseWrapper>
<p onClick={closeModalUntilExpires}>오늘 하루 더 이상 보지 않기</p>
<p onClick={closeModal}>닫기</p>
</ModalCloseWrapper>
</ModalContainer>
</Container>
);
}
export default Modal;
결과
오늘 하루 더 이상 보지 않기 문구를 클릭하면 아래와 같이 2월 28일 만료되는 쿠키가 생성됩니다. (작성일자 2월 27일)
그리고 새로고침 해보면 해당 모달이 더 이상 뜨지 않는 것을 확인할 수 있습니다.
코드샌드박스에 예시 코드를 올려놨습니닷. 코드샌박에선 쿠키를 못불러오네요.
로컬에서 해당 코드로 테스트해보시면 잘 되는 걸 확인하실 수 있습니다.
https://codesandbox.io/s/elegant-clarke-me3z8i?file=/src/App.tsx
댓글