๐Ÿ“— Vue.js

[Vue.js] ๋ผ์ดํ”„์‚ฌ์ดํด ํ›… (Lifecycle Hooks)

JaeBBang 2025. 4. 16. 16:27

ํฌ์ŠคํŒ… ์ด์ „์— ์•ž์„œ

 

๐Ÿ’ก Vue.js์˜ ๋ผ์ดํ”„์‚ฌ์ดํด(Lifecycle)์ด๋ž€?

Vue ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹จ์ˆœํžˆ ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด์ง€๊ณ  ๋๋‚˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ํƒ„์ƒ๋ถ€ํ„ฐ ์†Œ๋ฉธ๊นŒ์ง€ ์ผ๋ จ์˜ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.
์ด ๊ณผ์ •์„ ์ปดํฌ๋„ŒํŠธ ์ƒ๋ช…์ฃผ๊ธฐ(Lifecycle)๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€
์ƒ์„ฑ๋˜๊ณ  (create), DOM์— ๋ถ™๊ณ  (mount), ์—…๋ฐ์ดํŠธ๋˜๊ณ  (update), ์‚ฌ๋ผ์ง€๊ธฐ๊นŒ์ง€ (unmount)

์ด ์ „์ฒด ํ๋ฆ„์„ Vue๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์š”์†Œ๋Š”
ํŠน์ • ์‹œ์ ๋งˆ๋‹ค ์‹คํ–‰ํ•  ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ๋ฐ”๋กœ! ๋ผ์ดํ”„์‚ฌ์ดํด ํ›…(Lifecycle Hooks) ์ž…๋‹ˆ๋‹ค.

 

Vue 3์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ ๋™์•ˆ ํŠน์ • ์‹œ์ ์— ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ดํ”„์‚ฌ์ดํด ํ›…(Lifecycle Hooks)์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ „ Vue 2์—์„œ๋Š” created, mounted, destroyed ๊ฐ™์€ ์˜ต์…˜์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ,

Vue 3์˜ <script setup> ๋ฌธ๋ฒ•์—์„œ๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅด๊ฒŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ž์ฃผ ์“ฐ์ด๋Š” ํ›…๋“ค๊ณผ, ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ์ •๋ฆฌํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

 

1. ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

<script setup>์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ผ์ดํ”„์‚ฌ์ดํด ํ›…์„ onMounted, onUnmounted, onUpdated ๋“ฑ์˜ ํ•จ์ˆ˜๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ์‚ฌ์šฉํ•˜๋ฉฐ,

Vue์—์„œ ์ œ๊ณตํ•˜๋Š” vue ๋ชจ๋“ˆ์—์„œ importํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

<template>
  <div>๋ผ์ดํ”„์‹ธ์ดํด ์˜ˆ์ œ</div>
</template>
<script setup>
import { onMounted } from 'vue'

onMounted(() => {
  console.log('## onMounted')
})
</script>

 

 

๐Ÿ‘จโ€๐Ÿ’ป ์‹คํ–‰๊ฒฐ๊ณผ

 

์œ„์™€ ๊ฐ™์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์— ์™„์ „ํžˆ ๋งˆ์šดํŠธ ๋  ๋•Œ  ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

2. ์ฃผ์š” ๋ผ์ดํ”„์‚ฌ์ดํด ํ›… ์ •๋ฆฌ

์œ„์—์„œ๋Š” onMounted์— ๋Œ€ํ•ด์„œ๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด์•˜์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ดํ”„์‚ฌ์ดํด ํ›…์ด ๋” ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

  • onBeforeMount
    - ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์— ๋ถ™๊ธฐ ์ „์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • onMounted
    - ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์— ์™„์ „ํžˆ ๋งˆ์šดํŠธ๋œ ํ›„ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. DOM ์กฐ์ž‘์ด๋‚˜ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—ฐ๋™์— ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • onBeforeUpdate
    - ๋ฐ˜์‘ํ˜• ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด DOM์ด ์—…๋ฐ์ดํŠธ๋˜๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • onUpdated
    - ๋ฐ˜์‘ํ˜• ์ƒํƒœ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด DOM์ด ์—…๋ฐ์ดํŠธ๋œ ์งํ›„์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • onBeforeUnmount
    - ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์—์„œ ์ œ๊ฑฐ๋˜๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • onUnmounted
    - ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์™„์ „ํžˆ ์–ธ๋งˆ์šดํŠธ๋œ ํ›„ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ํ•ด์ œ ๊ฐ™์€ ์ •๋ฆฌ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

 

App.vue

<template>
  <div>
    <button @click="showTest = !showTest">
      {{ showTest ? '์ปดํฌ๋„ŒํŠธ ์ œ๊ฑฐ' : '์ปดํฌ๋„ŒํŠธ ๋‹ค์‹œ ๋ณด์—ฌ์ฃผ๊ธฐ' }}
    </button>

    <Body v-if="showTest" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import Body from '../components/Body.vue'

const showTest = ref(true)
</script>

 

 

Body.vue

<template>
  <div>
    <h2>๋ผ์ดํ”„์‚ฌ์ดํด ํ…Œ์ŠคํŠธ</h2>
    <p>์นด์šดํŠธ: {{ count }}</p>
    <button @click="count++">์นด์šดํŠธ ์ฆ๊ฐ€</button>
  </div>
</template>

<script setup>
import {
  ref,
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted
} from 'vue'

const count = ref(0)

// ๐Ÿ”ต ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„์ง DOM์— ๋ถ™๊ธฐ ์ „, setup() ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ํ˜ธ์ถœ๋จ
onBeforeMount(() => {
  console.log('๐Ÿ”ต onBeforeMount: DOM์— ๋ถ™๊ธฐ ์ง์ „')
})

// ๐ŸŸข ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์— ์™„์ „ํžˆ ๋งˆ์šดํŠธ๋œ ํ›„ ํ˜ธ์ถœ๋จ
// ์ด ์‹œ์ ์—” ์‹ค์ œ HTML ์š”์†Œ์— ์ ‘๊ทผ๊ฐ€๋Šฅ
onMounted(() => {
  console.log('๐ŸŸข onMounted: DOM ๋งˆ์šดํŠธ ์™„๋ฃŒ')
})

// ๐ŸŸก ๋ฐ˜์‘ํ˜• ์ƒํƒœ(count ๋“ฑ)๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด DOM์ด ๋ฐ”๋€Œ๊ธฐ *๋ฐ”๋กœ ์ „*์— ํ˜ธ์ถœ๋จ
// DOM์ด ๋ฐ”๋€Œ๊ธฐ ์ง์ „์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ๋ณ€๊ฒฝ ์ง์ „ ์ฒ˜๋ฆฌํ•  ์ผ์ด ์žˆ๋‹ค๋ฉด ์—ฌ๊ธฐ์—์„œ ์ฒ˜๋ฆฌ
onBeforeUpdate(() => {
  console.log('๐ŸŸก onBeforeUpdate: DOM ์—…๋ฐ์ดํŠธ ์ง์ „')
})

// ๐ŸŸ  ๋ฐ˜์‘ํ˜• ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๊ณ  ์‹ค์ œ DOM๊นŒ์ง€ ๋ฐ”๋€ ํ›„์— ํ˜ธ์ถœ๋จ
// ๋ณ€๊ฒฝ๋œ DOM์„ ํ™•์ธํ•˜๊ฑฐ๋‚˜ ํ›„์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉ๋จ
onUpdated(() => {
  console.log('๐ŸŸ  onUpdated: DOM ์—…๋ฐ์ดํŠธ ์™„๋ฃŒ')
})

// ๐Ÿ”ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ DOM์—์„œ ์ œ๊ฑฐ๋˜๊ธฐ ์ง์ „ ํ˜ธ์ถœ๋จ
// ์ œ๊ฑฐ ์ „์— ๋ฆฌ์†Œ์Šค๋ฅผ ์ •๋ฆฌํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž ํ™•์ธ ๋ชจ๋‹ฌ ๋“ฑ์„ ๋„์šธ ์ˆ˜๋„ ์žˆ์Œ
onBeforeUnmount(() => {
  console.log('๐Ÿ”ด onBeforeUnmount: DOM ์ œ๊ฑฐ ์ง์ „')
})

// โšซ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์™„์ „ํžˆ ์ œ๊ฑฐ๋œ ํ›„ ํ˜ธ์ถœ๋จ
// ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ํ•ด์ œ, ํƒ€์ด๋จธ ์ œ๊ฑฐ ๋“ฑ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ์ •๋ฆฌ ์ž‘์—…์— ์ ํ•ฉ
onUnmounted(() => {
  console.log('โšซ onUnmounted: DOM ์ œ๊ฑฐ ์™„๋ฃŒ')
})
</script>

 

 

๐Ÿ‘จโ€๐Ÿ’ป ์‹คํ–‰๊ฒฐ๊ณผ

 

โœ… 1. ํ™”๋ฉด์ด ๋ Œ๋”๋ง(mount) ๋˜์—ˆ์„ ๋•Œ

 

์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ์ƒ๊ธธ ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

onBeforeMount, onMounted

 

 

โœ… 2. ๋ฐ˜์‘ํ˜• ์ƒํƒœ ๋“ฑ์ด ๋ณ€๊ฒฝ๋˜์–ด ํ™”๋ฉด์ด ์—…๋ฐ์ดํŠธ๋  ๋•Œ

 

์นด์šดํŠธ ํด๋ฆญ ์‹œ ref ๊ฐ’(count)์„ ์ฆ๊ฐ€์‹œํ‚ฌ ๋•Œ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋ฉด์„œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

onBeforeUpdate, onUpdated

 

 

โœ… 3. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ œ๊ฑฐ(unmount) ๋  ๋•Œ

 

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ v-if๋กœ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

onBeforeUnmount, onUnmounted

 

 

์ด ์™ธ์—๋„ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ผ์ดํ”„์‚ฌ์ดํด๋„ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š” !

  • onActivated
    - <keep-alive>๋กœ ๊ฐ์‹ผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™œ์„ฑํ™”๋  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • onDeactivated
    - <keep-alive>๋กœ ๊ฐ์‹ผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • onErrorCaptured
    - ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • onRenderTracked
    - ๋ฐ˜์‘ํ˜• ๋ Œ๋”๋ง ์‹œ ์–ด๋–ค ๊ฐ’์ด ์ถ”์ ๋๋Š”์ง€ ๋””๋ฒ„๊น…์šฉ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • onRenderTriggered
    - ์–ด๋–ค ๋ฐ˜์‘ํ˜• ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด ๋ Œ๋”๋ง์ด ํŠธ๋ฆฌ๊ฑฐ๋˜์—ˆ๋Š”์ง€ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

3. Pinia๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ

Pinia๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์Šคํ† ์–ด์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋  ๋•Œ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ตฌ์กฐ๋ฅผ ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<script setup>
import { onMounted } from 'vue'
import { useUserStore } from '@/stores/user'

const userStore = useUserStore()

onMounted(async () => {
  await userStore.fetchUserData()
  console.log('์‚ฌ์šฉ์ž ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์™„๋ฃŒ!')
})
</script>

 

onMounted ์•ˆ์—์„œ ๋น„๋™๊ธฐ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ฉด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚  ๋•Œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Vue 3์˜ ๋ผ์ดํ”„์‚ฌ์ดํด ํ›…์€ ์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•˜๊ณ  ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ๋Š” onMounted์—์„œ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํŒจํ„ด์„ ์šฉ์ดํ•˜๊ฒŒ ์ž์ฃผ ์“ฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž

๋Œ“๊ธ€์ˆ˜0