Transition과 TransitionGroup
Transition은 엘리먼트가 DOM에 들어오거나 나갈 때 애니메이션을 적용하는 Vue의 내장 컴포넌트입니다.
면접에서 직접 물어보는 경우는 드물지만, 포트폴리오에서 부드러운 전환을 구현했다면 UX 감각을 보여줄 수 있는 좋은 포인트입니다.
Transition 기본
<script setup lang="ts">
import { ref } from 'vue'
const show = ref(true)
</script>
<template>
<button @click="show = !show">토글</button>
<Transition name="fade">
<p v-if="show">안녕하세요!</p>
</Transition>
</template>
<style>
/* 진입 애니메이션 */
.fade-enter-active {
transition: opacity 0.3s ease;
}
/* 퇴장 애니메이션 */
.fade-leave-active {
transition: opacity 0.3s ease;
}
/* 진입 시작 상태 / 퇴장 종료 상태 */
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
CSS 클래스 흐름
진입: enter-from → enter-active → enter-to
퇴장: leave-from → leave-active → leave-to
| 클래스 | 적용 시점 | 제거 시점 |
|---|---|---|
v-enter-from | 삽입 전 | 삽입 후 1프레임 |
v-enter-active | 삽입 전 | 전환 완료 |
v-enter-to | 삽입 후 1프레임 | 전환 완료 |
v-leave-from | 퇴장 시작 | 퇴장 후 1프레임 |
v-leave-active | 퇴장 시작 | 전환 완료 |
v-leave-to | 퇴장 후 1프레임 | 전환 완료 |
전환 모드 (mode)
<template>
<!-- out-in: 현재 엘리먼트가 나간 후 새 엘리먼트가 들어옴 -->
<Transition name="fade" mode="out-in">
<component :is="currentComponent" :key="currentKey" />
</Transition>
<!-- in-out: 새 엘리먼트가 들어온 후 현재 엘리먼트가 나감 -->
<Transition name="fade" mode="in-out">
<component :is="currentComponent" :key="currentKey" />
</Transition>
</template>
CSS 애니메이션 (@keyframes)
<template>
<Transition name="bounce">
<p v-if="show">바운스 애니메이션!</p>
</Transition>
</template>
<style>
.bounce-enter-active {
animation: bounce-in 0.5s;
}
.bounce-leave-active {
animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
0% { transform: scale(0); }
50% { transform: scale(1.25); }
100% { transform: scale(1); }
}
</style>
JavaScript Hooks
CSS 대신 JavaScript로 애니메이션을 제어할 수 있습니다.
<template>
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
:css="false"
>
<div v-if="show">JS 애니메이션</div>
</Transition>
</template>
<script setup lang="ts">
const onEnter = (el: Element, done: () => void) => {
const element = el as HTMLElement
element.style.opacity = '0'
// Web Animation API 또는 GSAP 등 사용
element.animate(
[{ opacity: 0 }, { opacity: 1 }],
{ duration: 300, easing: 'ease-out' }
).onfinish = done
}
const onLeave = (el: Element, done: () => void) => {
const element = el as HTMLElement
element.animate(
[{ opacity: 1 }, { opacity: 0 }],
{ duration: 300, easing: 'ease-in' }
).onfinish = done
}
</script>
TransitionGroup — 리스트 전환
<script setup lang="ts">
import { ref } from 'vue'
const items = ref([1, 2, 3, 4, 5])
let nextId = 6
const addItem = () => {
const index = Math.floor(Math.random() * items.value.length)
items.value.splice(index, 0, nextId++)
}
const removeItem = (item: number) => {
items.value = items.value.filter(i => i !== item)
}
</script>
<template>
<button @click="addItem">추가</button>
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item" @click="removeItem(item)">
{{ item }}
</li>
</TransitionGroup>
</template>
<style>
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* FLIP 애니메이션 — 이동하는 아이템도 부드럽게 */
.list-move {
transition: transform 0.5s ease;
}
/* 떠나는 아이템이 공간을 차지하지 않도록 */
.list-leave-active {
position: absolute;
}
</style>
appear — 초기 렌더링 시 전환
<template>
<!-- 컴포넌트가 처음 렌더링될 때도 전환 적용 -->
<Transition name="fade" appear>
<div>처음부터 페이드인</div>
</Transition>
</template>
면접 팁
- TransitionGroup의 **FLIP 기법 **(First, Last, Invert, Play)을 알고 있으면 애니메이션 성능에 대한 이해도를 보여줄 수 있습니다
mode="out-in"은 ** 컴포넌트 전환에서 깜빡임을 방지 **하는 가장 일반적인 패턴입니다- CSS
transform과opacity만 애니메이션하는 것이 성능에 좋습니다 (GPU 가속)
요약
Transition은 단일 엘리먼트의 진입/퇴장을, TransitionGroup은 리스트의 추가/제거/이동을 애니메이션합니다. CSS transition/animation 또는 JavaScript hooks로 구현하며, mode와 appear 옵션으로 전환 동작을 제어합니다.
댓글 로딩 중...