Vue

[Vue 3] markRaw 함수 언제쓰나?

머지?는 병합입니다 2023. 3. 22. 11:34

 

Vue.js에서 markRaw 함수는  말 그대로 반응형이 아닌 파라미터를 날것으로 만든다는 뜻입니다.

(객체든 컴포넌트든)

 

이 함수는 주로 성능 최적화나 특정 객체를 반응형으로 만들고 싶지 않을 때 사용합니다.


기본 사용법

<script setup>
import { ref, markRaw, watch } from 'vue'

const state = ref({
  user: { name: '호로롤로', age: 30 }
  // user: markRaw({ name: '호로롤로', age: 30 })
})

console.log('Initial age:', state.value.user.age) // 30

state.value.user.age = 31

console.log('Updated age:', state.value.user.age) // 31

// watch를 사용해도 변경을 감지하지 못함
watch(
  () => state.value.user,
  (newVal) => {
    console.log('User changed:', newVal)
  },
  { deep: true }
)

// 이 변경은 watch에 의해 감지되지 않음
state.value.user.age = 32
</script>

<template>
  <div>{{ state.user.name }} 의 나이는 {{ state.user.age }}</div>
  <button @click="state.user.age++">나이먹어라...많이 먹어라...</button>
</template>



 

32살로 변경된 값이 먼저 보이면서 버튼을 누르면 값이 바뀌면서 watch 메서드를 타지만

markRaw 함수를 사용하면 초기나이 바뀐나이의 로그만 나오고 버튼을 눌러도 watch 메서드를 안타는 걸 

확인 가능합니다.

 

언제 쓸까??

1. 성능 최적화

   큰 데이터나 복잡한 객체를 다룰 때 Vue 의 반응성 시스템이 모든 속성을 추적하지 않도록 하여, 성능향상

 

<script setup>
import { ref, markRaw } from 'vue'

const hugeList = ref(markRaw(Array.from({ length: 10000 }, (_, i) => ({ id: i, value: `Item ${i}` }))))
</script>

<template>
  <div v-for="item in hugeList" :key="item.id">{{ item.value }}</div>
</template>

 

2. 외부 라이브러리 출동 방지

Vue와 호환되지 않는 외부 라이브러리를 사용할 때, 해당 라이브러리의 객체를 반응형으로 만들지 않아 충돌을 방지합니다.

<script setup>
import { ref, markRaw, onMounted } from 'vue'
import Chart from 'chart.js'

const chartRef = ref(null)
const chart = ref(null)

onMounted(() => {
  chart.value = markRaw(new Chart(chartRef.value, {
    // 차트 설정
  }))
})
</script>

<template>
  <canvas ref="chartRef"></canvas>
</template>

markRaw를 빼면 위처럼 오류가 발생한다

 

3. 읽기 전용 데이터

데이터 변경 방지 처리할 때 

<script setup>
import { reactive, markRaw } from 'vue'

const state = reactive({
  user: markRaw({
    id: 1,
    name: '퇴근할래',
    permissions: ['read', 'write']
  })
})

// state.user의 속성을 변경해도 반응형 업데이트 안됩니다.
</script>

 

4. 컴포넌트 동적 로딩

동적으로 로드되는 컴포넌트를 반응형으로 만들지 않을 때 사용합니다.

 

<script setup>
import { ref, markRaw, defineAsyncComponent } from 'vue'

const AsyncComponent = markRaw(defineAsyncComponent(() => import('./AsyncComponent.vue')))
const showComponent = ref(false)
</script>

<template>
  <button @click="showComponent = !showComponent">Toggle Component</button>
  <AsyncComponent v-if="showComponent" />
</template>