최근 프로젝트에서 기획자분이 한 사용자가 같은 컴퓨터에서 여러 개의 브라우저 탭을 열어놓고 작업할 때, 'A' 탭에서 데이터를 변경하거나 어떤 처리를 했을 경우, 다른 탭('B' 탭)에 변경 사항이 즉시 반영되지 않는 문제를 해결해달라고 찾아왔다.
이 문제는 사용자 경험에 큰 영향을 미칠 수 있는 상황으로, 웹서비스가 관리자페이지이다보니 실시간 데이터 동기화가 중요한 서비스에서 반드시 해결해야 할 과제였다. 이번 글에서는 문제의 원인을 분석하고, 이를 해결하기 위해 어떤 접근 방식을 사용했는지 공유하고자 한다.
서론
ATab, BTab 이 있는 상황에서 ATab이 로그아웃 할 경우 브라우저 내의 토큰을 제거하는 로직이 이미 구현되어 있었다.
하지만 이렇게 할 경우 BTab 에선 ATab 에서 일어난 로그아웃 이벤트가 전달되지 않았다 (cookie 나 storage에 토큰 제거 되어있는 상태)
그래서 로그인 되어 있는거 같은 화면에서 새로고침을 해야 하는 상황인데
VueUse 의 BroadcastChannel API 를 사용해서 해결하였다. (원래는 web 안에 iframe 과의 통신을 할 때 사용했던 것으로 알고 있었음.)
해당 채널을 만들고 post 함수와 함께 특정 값을 넣어 실행 시켜주면 다른 탭에서도 적용된걸 확인할 수 있다.
문제 정의
'A' Tab에서 데이터를 변경하거나 어떤 처리를 했을 경우 다른 탭('B' Tab)에 적용이 안되는 문제
원인 분석
실시간 데이터 동기화를 구현이 필요
해결 방법
프로젝트에서 A탭에서 로그아웃 하고 다른 계정으로 로그인 했을 때 B탭에도 이를 동기화 하는 방법
👉 Vue.js에서 BroadcastChannel API를 도입하여 실시간 데이터 동기화를 구현해보기로 했다.
참고 링크:
https://vueuse.org/core/useBroadcastChannel/#usebroadcastchannel
https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel
이 문제를 해결하기 위해 로그아웃 기능에 BroadcastChannel API를 적용했다. 이를 통해 한 탭에서 로그아웃을 수행하면 다른 모든 탭에서도 자동으로 로그아웃이 이루어지도록 구현했다. 아래는 그 구현 코드이다:
적용 결과
// 로그아웃에 적용
<template>
<q-list>
<q-item clickable v-close-popup>
<q-item-section @click="handleClickLogout">
<q-item-label>로그아웃</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<script lang="ts">
import { computed, defineComponent, watchEffect } from 'vue'
import { useBroadcastChannel } from '@vueuse/core'
import { useAuthStore } from '@/stores'
...
export default defineComponent({
setup() {
const authStore = useAuthStore()
const router = useRouter()
const { data, post } = useBroadcastChannel({ name: '####' })
watchEffect(async () => {
if (data.value === 'logout') {
await authStore.logout()
await router.push('/login')
}
})
return {
handleClickLogout: async () => {
post('logout')
await authStore.logout()
await router.push('/login')
},
}
},
})
</script>
코드 설명
템플릿 부분:
▫️q-list와 q-item을 사용하여 로그아웃 버튼을 생성합니다.
▫️q-item-section에 @click 이벤트를 추가하여 handleClickLogout 메서드를 호출합니다.
스크립트 부분:
▫️ useBroadcastChannel을 사용하여 auth-channel이라는 이름의 BroadcastChannel을 생성합니다.
▫️ watchEffect를 사용하여 data 값이 'logout'으로 변경되면 authStore.logout()을 호출하고 로그인 페이지로 리디렉션합니다.
▫️ handleClickLogout 메서드는 로그아웃 버튼 클릭 시 호출되며, BroadcastChannel을 통해 'logout' 메시지를 전송하고, 현재 탭에서도 로그아웃을 수행합니다.
결론
이와 같이 BroadcastChannel API를 사용하여 여러 탭 간의 상태 동기화를 구현함으로써, 한 탭에서 로그아웃을 수행하면 다른 모든 탭에서도 자동으로 로그아웃이 이루어지도록 할 수 있다.
VueUse에 다향한 유틸리히 훅들있어서 코드작성이 훨씬 간단해지고, 웬만한 기능들은 잘 찾아보면 있는 것 같다 VueUse 를 적극 활용해서 해결하면 좋을 것 같다 !
'Vue.js' 카테고리의 다른 글
[Vue.js] Vue 프로젝트, ESLint, Prettier (+typescript) 설정하기! (1) | 2024.06.16 |
---|---|
[Vue.js] Vue.js 개발을 위한 필수 VSCode 플러그인 추천 (0) | 2024.06.07 |
[Vue.js] Options API vs Composition API (0) | 2023.02.12 |
[Vue.js] 컴포넌트에 대해 (0) | 2023.02.09 |
[Vue.js] 뷰 컴포넌트 (0) | 2022.05.01 |