로그인 후 사용자에게서 5분간 아무런 이벤트가 발생하지않을 시 자동로그아웃 되는 기능을 만들어보았다.
나의 경우에는 클릭이벤트로 감지를 하였다.
- 로그인 시 타이머시작 (0초부터 ++1 하는 방식)
- 클릭 이벤트 발생 시 타이머 초기화
- 클릭 이벤트 미발생시엔 maxCount에 다다를시 로그아웃 로직 실행
<template>
<div>
<main />
</div>
</template>
<script>
import { mapMutations, mapState } from 'vuex';
export default {
name: 'Main',
data() {
return {
timerCount: 0,
maxCount: 300, // 5분
timerInterval: null,
};
},
mounted() {
this.startTimer();
document.addEventListener('mousedown', this.handleMouseClick);
},
beforeDestroy() {
clearInterval(this.timerInterval);
document.removeEventListener('mousedown', this.handleMouseClick);
},
methods: {
// 타이머 5분 카운트 시작
startTimer() {
this.timerInterval = setInterval(() => {
if (this.timerCount < this.maxCount) {
this.timerCount++;
} else {
clearInterval(this.timerInterval);
alert('5분간 미사용으로 인한 로그아웃');
this.$router.push('/login');
}
}, 1000); // 1초마다 타이머 증가
},
// 리셋 타이머
resetTimer() {
clearInterval(this.timerInterval);
this.timerCount = 0;
},
handleMouseClick() {
this.resetTimer(); // 클릭 이벤트 발생 시 타이머를 초기화하고 0초부터 다시 시작
this.startTimer();
},
},
};
</script>
메인페이지 내에 이와 같이 작성했다.
이게 효율적으로 짠건지는 의문이 들긴하지만.. 구현은 잘 되었다.
24.04 기준으로 해당 타이머에 버그사항을 발견했다. 크롬이나 사파리 등 웹 안에서 동일한 도메인웹사이트를 여러개 띄울때(중복탭을 이용해서) 하나의 탭에서만 타이머가 작동하고, 백그라운드에 있는 활성화되어있지않은 탭은 타이머가 멈춰있는 것이었다. 수없이 QA를 돌려보다가 어떤때는 되고 어떤 때에는 안되어서 보니 저렇게 시나리오가 나왔다. 그 원인을 찾아보니 크롬 브라우저에서는 사용자가 현재 보고 있지 않은 탭의 웹 사이트에서 자바스크립트 함수가 실행되는 빈도를 제한한다는 기사를 확인했다.(https://www.itworld.co.kr/news/103916#csidx4eb5cd320d50e39a31f8ea4b5db62cf
https://www.itworld.co.kr/news/103916)
그래서 타이머함수가 작동하지않았던 것 !!
어떻게 수정을 해야할까 고민을 하다가, 현재 시간과 탭이 열려있던 마지막 시간을 기준으로 5분 이상 차이가 나면 로그아웃 시키는 방향으로 수정했다.
기존에 data에 담아두었던 timerCount, maxCount 변수는 사용하지않아지웠고, timerInterval만 commonStore로 전역으로 쓸 수 있게끔 남겨두었다.
// pages 내 index.vue
<script>
import { mapMutations, mapState } from 'vuex';
export default {
name: 'MainLayout',
computed: {
...mapState('common', ['isLoading', 'timerInterval', 'modal']),
},
mounted() {
this.getNowTime();
// 기존 로직
this.START_TIMER();
document.addEventListener('mousedown', this.handleMouseClick);
},
beforeDestroy() {
this.RESET_TIMER();
document.removeEventListener('mousedown', this.handleMouseClick);
},
methods: {
...mapMutations('dashBoard', ['CLEARINTERVAL_FUNCTION']),
...mapMutations('common', [
'START_TIMER',
'RESET_TIMER',
'SET_STANDARD_DATE',
]),
...mapMutations('auth', ['REMOVE_TOKEN']),
async handleMouseClick() {
if (this.timerInterval !== null) {
await this.getNowTime(); // 클릭 이벤트 발생 시, 클릭한 시간으로 업데이트
await this.RESET_TIMER();
await this.START_TIMER();
}
},
async getNowTime() {
const nowDate = new Date();
this.SET_STANDARD_DATE(nowDate);
},
},
};
</script>
index.vue에서는 commonStore에 있는 메서드들을 불러와서 사용토록 했다.
START_TIMER(state) {
state.timerInterval = setInterval(() => {
const nowDate = new Date();
const saveDate = new Date(state.standardDate);
const differenceMillis = Math.abs(nowDate - saveDate);
const differenceSeconds = Math.floor(differenceMillis / 1000);
switch (true) {
// 5분을 넘지않았을 경우
case differenceSeconds < state.maxCount:
// console.log('return', differenceSeconds);
break;
// 5분 초과~6분 미만일 경우
case differenceSeconds >= state.maxCount &&
differenceSeconds <= state.maxCount + state.modalMaxCount:
// 로그아웃 안내 모달창을 띄우고, 로그아웃_오토 로직 실행
clearInterval(state.timerInterval);
store.commit('auth/LOGOUT_AUTO');
break;
// 최종 6분 경과 후
case differenceSeconds >= state.maxCount + state.modalMaxCount:
default:
store.commit('auth/LOGOUT_MINUTE');
break;
}
}, 1000);
},
RESET_TIMER(state) {
clearInterval(state.timerInterval);
state.timerInterval = null;
},
컴포넌트단에서 처음에 mounted 될 때에 methods의START_TIMER를 호출하는데 가장 먼저 getNowTime 함수를 통해서 클릭한 시간으로 업데이트 시킨다. 그 뒤에 SET_STANDARD_DATE 뮤테이션을 통하여 store 내 standardDate에 업데이트된 시간을 저장한다.
START_TIMER()가 호출되면 store 단의 mutation에서 해당 로직이 진행된다. 또 한번 현재 시간을 받아오고, saveDate라는 변수에 받아왔던 현재 시간을 저장한다.(상태관리를 위해 mutation에 작성하였다)
✨✨ 여기서부터가 핵심이 되는 로직인데 현재시간에서 기존 클릭했던 시간의 차이를 구하는 것이다!!!!
(발생한 지 얼마나 지났는지 계산)
현재 밀리초 단위로 계산이되기 때문에, Math.floor를 사용하여 초단위로 받아왔다.
📎 결과적으로 지금까지 여러탭에서 테스트를 진행했을 때 동일하게 로그아웃 로직이 수행된다. 탭이 비활성화되어있을 때 자바스크립트 로직이 동작하지않는다는 사실은 새로 깨달았다.. 큰 배움이 되었다.
그리고 마지막 업데이트 시각과 현재 시간을 비교하여 로직을 수행하는 것 말고도 또 좋은 방안이 있을 것 같아 차차 고민을 해보아야 겠다는 생각도 했다!