본문으로 건너뛰기
개발 머꼬
개발 노트Vue
hohyeon.dev15

탭을 옮겼다 돌아오면 입력하던 값이 사라진 이유

  • #Engineering Note
  • #Vue

문제 발생

탭 UI에서 다른 탭을 보고 돌아오면 스크롤 위치와 입력 중이던 값이 초기화됐습니다.

<component :is="activeTab" />

onMounted에서 하던 데이터 조회도 돌아올 때마다 다시 실행됐습니다.

원인 분석

전환은 곧 언마운트입니다. Vue 문서가 <KeepAlive>를 소개하며 설명하는 그대로 — 여러 컴포넌트를 동적으로 전환할 때 기본 동작은 언마운트되어 상태를 잃는 것이고, <KeepAlive>는 그 대신 인스턴스를 캐시에 보존해 돌아왔을 때 복원합니다.

그래서 상태 보존이 필요하면 두 가지를 함께 정해야 합니다: 캐시할 것인가, 그리고 다시 보일 때 무엇을 할 것인가입니다. 캐시된 컴포넌트는 다시 마운트되지 않으므로 onMounted가 더 이상 불리지 않습니다. 문서는 전용 훅을 제공합니다 — onActivated는 최초 마운트 시점과 캐시에서 다시 삽입될 때마다 호출되고, onDeactivated는 DOM에서 캐시로 빠질 때와 언마운트될 때 호출됩니다.

해결 방안

  1. 보존이 필요한 영역만 감쌉니다.
<KeepAlive>
  <component :is="activeTab" />
</KeepAlive>
  1. 다시 보일 때 해야 할 일은 onActivated로 옮깁니다. 최신 데이터가 필요하면 여기서 갱신합니다.
<script setup>
import { onActivated, onDeactivated } from "vue";

onActivated(() => refresh());
onDeactivated(() => pausePolling());
</script>
  1. 정리 코드를 두 훅 모두에서 점검합니다. 타이머·구독은 언마운트되지 않으므로 onUnmounted만 믿으면 캐시된 채로 계속 돕니다. onDeactivated에서 멈춥니다.

  2. 캐시 대상을 좁힙니다. 문서 설명대로 include/exclude컴포넌트의 name 옵션과 대조하며(SFC는 파일명에서 추론), 콤마 문자열·정규식·배열을 받습니다.

<KeepAlive :include="['TabPosts', 'TabComments']">
  1. 메모리 상한을 둡니다. max는 문서 설명대로 LRU 캐시로 동작해 한도를 넘으면 가장 오래 사용되지 않은 인스턴스를 파괴합니다. 사용자가 많은 항목을 오가는 화면에서는 필수입니다.
<KeepAlive :max="10">
  1. 보존이 정말 맞는지 먼저 묻습니다. "돌아오면 최신이어야 하는" 화면을 캐시하면 오래된 데이터를 보여주는 버그가 됩니다. 입력 중이던 폼처럼 사용자의 작업이 남아야 하는 곳에 씁니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.