관제 시스템 프로젝트 중 로그인 연장 버튼을 누르면 로그인 상태를 연장 시키는 기능을 넣어야 해서 react-idle-timer 라이브러를 활용해서 제작하여 react-idle-timer 사용 방법에 대해 정리해보았습니다.
react-idle-timer
React 애플리케이션에서 사용자가 일정 시간 동안 비활성 상태일 때 특정 작업을 수행하도록 돕는 라이브러리입니다. 예를 들어, 사용자가 일정 시간 동안 키보드나 마우스 등의 입력을 하지 않는 경우 세션을 만료시키거나, 경고 메시지를 띄우는 등의 기능을 구현할 수 있습니다.
👉 선택 이유
- 개발 효율성: react-idle-timer는 다양한 비활성화 이벤트를 기본으로 제공하며, 설정이 간단하여 직접 타이머 기능을 구현하는 것보다 빠르게 프로젝트에 적용할 수 적용할 수 있었습니다. 타이머 기능을 직접 구현했다면 더 많은 시간과 리소스가 필요했을 것입니다.
- React 프로젝트에 최적화 : React Idle Timer는 다양한 React 버전과 호환되며, TypeScript를 지원하여 타입 안정성을 제공합니다.
주요 기능
- 활동 감지: 마우스 움직임, 키보드 입력, 터치 이벤트 등을 감지하여 사용자가 활동 중인지 확인할 수 있습니다.
- 타이머: 사용자가 비활성 상태로 일정 시간이 경과하면 설정된 콜백 함수를 호출하여 특정 작업을 수행할 수 있습다.
- 자동 로그아웃: 세션 만료 시간을 설정해 두고, 사용자가 일정 시간 동안 활동이 없으면 자동으로 로그아웃을 시키는 기능을 구현할 수 있습니다.
- 상태 관리: 사용자가 활동 중인지, 비활성 상태 인지의 상태를 쉽게 추적할 수 있으며, 이에 따라 UI를 동적으로 변경할 수 있습니다.
주요 옵션
- timeout: 사용자가 비활성 상태로 간주되기까지의 시간(ms)
- debounce: 이벤트 처리의 디바운스 시간(ms). (이벤트가 짧은 시간에 여러 번 발생할 경우, 이를 하나의 이벤트로 간주하여 처리)
- events: 사용자의 활동을 감지할 이벤트 타입(기본적으로 마우스와 키보드 이벤트)
❗적용 과정 중 문제 해결
- 타이머 초기화 문제: 초기에 타이머가 제대로 초기화되지 않는 문제가 있었습니다. useIdleTimer의 reset() 함수 호출 시점과 관련이 있는 문제로 해결하기 위해, 로그인 연장 버튼의 onClick 이벤트와 reset() 함수 호출 로직을 재검토하고, 타이머 초기화가 확실하게 이루어지도록 수정했습니다.
- 로그아웃 타이밍 문제: 일부 환경에서 타이머가 만료된 후 로그아웃이 바로 이루어지지 않는 문제가 발생했습니다. 이 문제는 remaining 값이 0이 될 때 알림을 표시하고 signOut 함수를 호출하는 로직을 개선함으로써 해결했습니다.
사용법
npm
Homepage
react-idle-timer 설치
npm i react-idle-timer
// or
yarn add react-idle-timer
import
import { useIdleTimer } from 'react-idle-timer'
1시간 타이머
먼저 시각적으로 1시간이 흐르는 타이머를 보여줍니다.
function millisToMinutesAndSeconds(millis: number) {
const minutes = Math.floor(millis / 60000);
const seconds = Math.floor((millis % 60000) / 1000);
const addZeroMinutes = Number(minutes) < 10 ? "0" + minutes : minutes;
const addZeroSeconds = Number(seconds) < 10 ? "0" + seconds : seconds;
return addZeroMinutes + " : " + addZeroSeconds;
}
react-idle-timer 설정
useIdleTimer에서 getRemainingTime, reset 를 가져옵니다.
timeout : 로그인 유지 시간 (ex. 60분 = 3600000, 10분 = 600000, 1분 = 60000 )
events : 활동을 감시할 DOM 이벤트 종류
- [ ] : 빈칸일 시 활동을 감지하지 않는다
- [ 'mousemove', 'keydown', 'wheel', 'DOMMouseScroll', 'mousewheel', 'mousedown', 'touchstart', 'touchmove', 'MSPointerDown', 'MSPointerMove', 'visibilitychange' ] 리스트 중 원하는 이벤트를 적용하면 해당 행동 시 타임이 다시 리셋 됩니다.
throttle : onAction지연을 밀리 초 단위로 설정하여 기능을 조절합니다. ( 일정 시간 동안 요청이 한 번만 수행되도록 한다.)
const { getRemainingTime, reset } = useIdleTimer({
timeout: 3600000, //60분
events: [],
throttle: 500,
});
이 외에도 다양한 Props 들이 있습니다.
타이머 setInterval
이제 페이지에 진입 했을 때 setInterval 함수를 사용하여 500ms(0.5초)마다 getRemainingTime 함수를 호출하고, 그 결과를 setRemaining 함수를 통해 상태(state)에 업데이트하여 시간을 보여줍니다.
useEffect(() => {
const interval = setInterval(() => {
setRemaining(getRemainingTime());
}, 500);
return () => {
clearInterval(interval);
};
});
자동 로그아웃 & 로그인 연장
그리고 remaining을 관찰하여 remaining이 0이 되면 alert창이 뜨면서 로그아웃이 되며 로그인 페이지로 이동합니다.
만약 onClick 이벤트로 loginExtension 함수가 걸린 버튼을 누르면 useIdleTimer에 있는 reset을 실해해 타임이 다시 리셋 됩니다.
useEffect(() => {
if (remaining === 0) {
alert("토큰이 만료되어 로그인 페이지로 이동합니다.");
signOut({ callbackUrl: `${url}` });
}
}, [remaining]);
const loginExtension = () => {
reset();
};
전체 코드
import { signOut, useSession } from "next-auth/react";
import { useIdleTimer } from "react-idle-timer";
export default function Home() {
// 1시간 카운트
function millisToMinutesAndSeconds(millis: number) {
const minutes = Math.floor(millis / 60000);
const seconds = Math.floor((millis % 60000) / 1000);
const addZeroMinutes = Number(minutes) < 10 ? "0" + minutes : minutes;
const addZeroSeconds = Number(seconds) < 10 ? "0" + seconds : seconds;
return addZeroMinutes + " : " + addZeroSeconds;
}
// 로그인 연장
const url = "/login";
const [remaining, setRemaining] = useState<number>(null);
const { getRemainingTime, reset } = useIdleTimer({
timeout: 3600000, //60분
events: [],
throttle: 500,
});
useEffect(() => {
const interval = setInterval(() => {
setRemaining(getRemainingTime());
}, 500);
return () => {
clearInterval(interval);
};
});
useEffect(() => {
if (remaining === 0) {
alert("토큰이 만료되어 로그인 페이지로 이동합니다.");
signOut({ callbackUrl: `${url}` });
}
}, [remaining]);
const loginExtension = () => {
reset();
};
return (
<>
<Seo />
<section css={HomePage}>
<div>
<span style={{ marginRight: "5px" }}>
{millisToMinutesAndSeconds(remaining)}
</span>
<button
onClick={loginExtension}
style={{
padding: "12px",
marginLeft: "10px",
borderRadius: "10px",
color: "#fff",
backgroundColor: "rgb(215 97 0)",
}}
>
로그인 연장
</button>
</div>
</section>
</>
);
}
로그인 연장
자동 로그아웃
'React' 카테고리의 다른 글
useform 추가 데이터 (0) | 2024.09.06 |
---|---|
react-cookie (1) | 2024.09.04 |
react checkbox 전체 선택 (0) | 2024.09.03 |
리스트 중 하나 선택 (0) | 2024.09.03 |
react-hook-form (useForm) (2) | 2024.08.30 |