keep-alive는 Vue.js에서 제공하는 내장 컴포넌트로, 컴포넌트를 캐싱하여 페이지 간 전환 시 컴포넌트의 상태를 유지할 수 있게 해줍니다. 일반적으로 Vue에서 페이지 전환이나 컴포넌트가 사라지면 해당 컴포넌트는 언마운트(unmount)되고, 다음에 다시 컴포넌트가 표시되면 새로 마운트됩니다. 하지만 keep-alive를 사용하면 컴포넌트가 언마운트되지 않고 메모리에 캐싱되어 다시 나타날 때 이전 상태를 그대로 유지할 수 있습니다.
사용 예시
<template>
<div>
<button @click="currentComponent = 'ComponentA'">Show Component A</button>
<button @click="currentComponent = 'ComponentB'">Show Component B</button>
<!-- 현재 렌더링되는 컴포넌트를 keep-alive로 감싸서 캐싱 -->
<keep-alive>
<component :is="currentComponent" />
</keep-alive>
</div>
</template>
<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
export default {
components: {
ComponentA,
ComponentB
},
data() {
return {
currentComponent: 'ComponentA'
}
}
}
</script>
위 예시 코드에서, 상단 두 개의 버튼을 이용해 currentComponent가 무엇인지 결정하여 component 태그 위치에 렌더링합니다. 이때, keep-alive로 감싸진 영역은 캐싱되며, 페이지 전환 시 상태가 유지됩니다.
<template>
<div>
<button @click="currentComponent = 'ComponentA'">Show Component A</button>
<button @click="currentComponent = 'ComponentB'">Show Component B</button>
<button @click="currentComponent = 'ComponentC'">Show Component C</button>
<!-- ComponentA와 ComponentB만 캐싱하고, ComponentC는 캐싱하지 않음 -->
<keep-alive include="ComponentA,ComponentB">
<component :is="currentComponent" />
</keep-alive>
</div>
</template>
<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
import ComponentC from './ComponentC.vue'
export default {
components: {
ComponentA,
ComponentB,
ComponentC
},
data() {
return {
currentComponent: 'ComponentA'
}
}
}
</script>
<keep-alive :include="/^Component[A-B]$/">
<component :is="currentComponent" />
</keep-alive>
keep-alive 태그의 include 속성을 이용하면 캐싱될 대상을 지정하여, 지정되지 않은 컴포넌트는 캐싱되지 않도록 설정할 수 있습니다.
Nuxt도 Vue를 기반한 프레임워크이기 때문에 keep-alive를 동일한 방식으로 사용할 수 있습니다. 따라서 Nuxt 한정으로 definePageMeta를 이용한 keep-alive 설정에 대해 알아보겠습니다.
pages/index.vue
<script setup>
export default definePageMeta({
keepalive: true // 페이지를 캐싱하여 상태 유지
})
</script>
<template>
<div>
<h1>Index Page</h1>
<input v-model="inputValue" placeholder="Type something...">
<p>Typed: {{ inputValue }}</p>
</div>
</template>
<script>
export default {
data() {
return {
inputValue: '' // 사용자가 입력한 값을 유지
}
}
}
</script>
pages/about.vue
<script setup>
export default definePageMeta({
keepalive: true // 페이지를 캐싱하여 상태 유지
})
</script>
<template>
<div>
<h1>About Page</h1>
<p>This is the about page content.</p>
</div>
</template>
위와 같이 index.vue와 about.vue를 작성하면 localhost:3000과 localhost:3000/about 간 페이지 이동이 발생해도, 각 화면에서 입력했던 정보들이 그대로 캐싱되어 남게 됩니다.