Vue 3에서 Keep alive

발행: (2026년 3월 12일 오후 08:32 GMT+9)
5 분 소요
원문: Dev.to

Source: Dev.to

위의 링크에 있는 전체 글을 번역해 주시면 됩니다.
(코드 블록, URL, 마크다운 구문 및 기술 용어는 그대로 유지하고, 본문 텍스트만 한국어로 번역해 주세요.)

문제

두 개의 탭이 있는 화면 – **Dúvidas (FAQ)**와 Formulário – 에서 사용자는 탭을 전환할 때 폼에 입력한 모든 내용을 잃어버렸습니다. 폼 컴포넌트가 파괴되고 다시 생성되어 상태가 사라졌습니다.

초기 솔루션 (번거로운)

localStorage의 변경마다 데이터를 저장하고, 폼을 제출할 때 키를 삭제합니다. 작동하지만 많은 수동 코드와 외부 상태 관리가 필요합니다.

Vue를 사용한 우아한 솔루션

Vue에는 <keep-alive> 컴포넌트가 있습니다(내장 및 추상). 이 컴포넌트는 실제 HTML 요소를 생성하지 않으며, 탭을 전환할 때 컴포넌트를 파괴하는 대신 캐시하도록 Vue에 지시합니다. 따라서 폼과 그 데이터가 최소한의 노력으로 메모리에 유지됩니다.

1️⃣ 탭을 받는 페이지

import { shallowRef } from "vue";
import AbaFormulario from "../components/AbaFormulario.vue";
import AbaDuvidas from "../components/AbaDuvidas.vue";

const abaAtual = shallowRef(AbaFormulario);
<div class="botoes-abas">
  <button @click="abaAtual = AbaFormulario" :class="{ ativo: abaAtual === AbaFormulario }">
    Preencher Formulário
  </button>
  <button @click="abaAtual = AbaDuvidas" :class="{ ativo: abaAtual === AbaDuvidas }">
    Dúvidas Frequentes
  </button>
</div>

<keep-alive>
  <component :is="abaAtual" />
</keep-alive>
.ativo {
  font-weight: bold;
  background-color: #e0e0e0;
  color: var(--black);
}

.botoes-abas {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

<keep-alive>는 동적 컴포넌트를 감싸줍니다. 예시에서는 탭을 사용했지만, 어떤 .vue 컴포넌트든 (심지어 페이지도) 사용할 수 있습니다.

2️⃣ 컴포넌트 AbaFormulario

<script setup>
import { ref, onActivated, onDeactivated } from "vue";

const formData = ref({
  nome: "",
  email: "",
  mensagem: "",
});

onActivated(() => {
  console.log("Formulário ATIVADO (Recuperado do cache)");
});

onDeactivated(() => {
  console.log("Formulário DESATIVADO (Guardado no cache)");
});
</script>

<template>
  <div class="formulario-container">
    <h2>데이터를 입력하세요</h2>
    <p>타이핑을 시작하고, 탭을 바꾼 뒤 다시 돌아오세요. 입력한 데이터가 여기 남아 있습니다!</p>

    <div class="campo">
      <label>이름:</label>
      <input v-model="formData.nome" type="text" />
    </div>

    <div class="campo">
      <label>이메일:</label>
      <input v-model="formData.email" type="email" />
    </div>

    <div class="campo">
      <label>메시지:</label>
      <textarea v-model="formData.mensagem"></textarea>
    </div>

    <button>보내기</button>
  </div>
</template>
.formulario-container {
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 8px;
}

.campo {
  margin-bottom: 15px;
  display: flex;
  flex-direction: column;
}

input,
textarea {
  padding: 8px;
  margin-top: 5px;
  border: 1px solid #999;
  border-radius: 4px;
}

button {
  padding: 10px 15px;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

<keep-alive>와 함께하는 라이프사이클

후크언제 트리거되는가
onActivated컴포넌트 인스턴스가 캐시에서 DOM에 삽입된 후.
onDeactivated컴포넌트 인스턴스가 DOM에서 제거되고 캐시에 저장된 후.

3️⃣ 컴포넌트 AbaDuvidas

<template>
  <div class="duvidas-container">
    <h2>Dúvidas Frequentes (FAQ)</h2>
    <p>Aqui estão as respostas para as perguntas mais comuns.</p>

    <div class="faq-item">
      <h3>Preciso preencher todos os campos do formulário?</h3>
      <p>Sim, todos os campos são obrigatórios para que possamos entrar em contato de forma eficiente.</p>
    </div>

    <div class="faq-item">
      <h3>Qual o prazo de resposta?</h3>
      <p>Nossa equipe geralmente responde em até 24 horas úteis.</p>
    </div>
  </div>
</template>
.duvidas-container {
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 8px;
  background-color: var(--black);
}

.faq-item {
  margin-top: 15px;
  padding-bottom: 10px;
  border-bottom: 1px dashed #ccc;
}

h3 {
  margin-bottom: 5px;
  color: var(--white);
  font-size: 1.1em;
}

결론

<keep-alive>onActivated / onDeactivated 훅을 사용하면, 탭을 전환할 때 폼의 상태를 보존할 수 있으며, localStorage나 외부 상태 관리가 필요하지 않습니다. 구현은 짧고 깔끔하며 사용자 경험을 크게 향상시킵니다.

전체 화면 모드 종료

keep-alive에 대한 주의사항

페이지를 reload로 다시 로드해야 할 경우, 데이터가 손실됩니다. 데이터는 메모리(캐시) 내 컴포넌트에 저장되어 있기 때문입니다.

keep-alive를 클라이언트 측에서 사용합니다 – SPA 애플리케이션에 매우 좋습니다.

참고

  • (목록 없음)
0 조회
Back to Blog

관련 글

더 보기 »

트라비고

Gemini와 함께 말하는 속도만큼 빠르게 여행하세요! 라이브 에이전트가 몰입형 스토리텔링 및 3D 내비게이션과 만나는 곳. 이 프로젝트는 Gemini Live Ag...에 진입하기 위해 만들어졌습니다.