Javascript/NuxtJS

[Nuxt3] storeToRefs()

kyoulho 2025. 3. 12. 22:24
728x90

storeToRefs()는 Pinia에서 ref()로 변환된 반응형 상태를 개별적으로 추출하는 함수입니다.

  1. Pinia 스토어의 state 속성들을 ref()로 변환하여 개별적으로 추출
  2. 반응형 유지 – storeToRefs()를 사용하면 ref()가 유지되므로 값이 변경될 때 UI가 자동으로 업데이트됨
  3. 객체 분해(구조 분해 할당) 시 반응성 유지

 

언제 storeToRefs()를 사용해야 할까?

상황 storeToRefs() 필요 여부
state를 구조 분해 할 때 ✅ 필요
state를 그대로 사용할 때 ❌ 필요 없음
actions와 getters를 구조 분해 할 때 ❌ 필요 없음

 

storeToRefs() 없이 사용하는 경우

Pinia 스토어에서 상태를 가져올 때, 구조 분해 할당을 직접 하면 반응성을 잃어버릴 수 있음.

import { defineStore } from "pinia";

export const useCounterStore = defineStore("counter", {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++;
    }
  }
});

storeToRefs() 없이 구조 분해 할당하면 반응성이 깨짐!

<script setup>
import { useCounterStore } from "~/store/counter";

const store = useCounterStore();
const { count } = store; // 반응성 깨짐!

console.log(count); // 0

store.increment();
console.log(count); // 여전히 0 (반응성 X)
</script>

왜 반응성이 깨질까?

  • { count } = store에서 count는 일반 변수로 할당됨
  • store.count가 변경되어도 { count } 변수는 자동으로 업데이트되지 않음
  • Vue가 count의 변화를 감지할 수 없음


storeToRefs()를 사용하면?

Pinia의 state를 구조 분해 할당하면서도 반응성을 유지할 수 있습니다.

<script setup>
import { useCounterStore } from "~/store/counter";
import { storeToRefs } from "pinia";

const store = useCounterStore();

// ✅ storeToRefs() 사용하여 반응형 상태 유지
const { count } = storeToRefs(store);

console.log(count.value); // 0

store.increment();
console.log(count.value); // 1 (자동 업데이트)
</script>

storeToRefs()의 역할

  • count가 ref()로 변환됨 (count = ref(store.count))
  • count.value를 통해 값을 읽고, 변경 가능
  • store.increment()가 실행되면 count.value도 자동으로 업데이트됨


storeToRefs()가 필요한 이유

Pinia의 state는 반응형이지만, 구조 분해 할당을 하면 반응성이 깨질 수 있음. 따라서 storeToRefs()를 사용해야 Vue가 상태 변경을 추적할 수 있습니다.

사용 방식 반응형 유지됨? 설명
const count = store.count; count는 일반 변수로 변환되어 반응성 X
const { count } = store; store.count의 값이 복사되므로 반응성 X
const { count } = storeToRefs(store); store.count를 ref()로 변환하여 반응성 유지


storeToRefs() vs toRefs()

Vue의 toRefs()도 비슷한 역할을 하지만, Pinia에서는 반드시 storeToRefs()를 사용해야 합니다.

import { toRefs } from "vue";
import { storeToRefs } from "pinia";

const store = useCounterStore();
const { count } = storeToRefs(store); // ✅ 올바른 방법 (Pinia 전용)

// ❌ Vue의 toRefs()를 사용하면 actions, getters도 ref()로 변환되므로 비효율적!
const { count } = toRefs(store);

왜 storeToRefs()를 사용해야 할까?

  • toRefs()를 사용하면 actions와 getters까지 ref()로 변환하려고 시도함 → 에러 발생 가능
  • storeToRefs()는 Pinia의 state만 ref()로 변환하므로 안전함


storeToRefs()와 computed() 함께 사용하기

storeToRefs()를 활용하면 computed()와 결합하여 더 복잡한 상태를 만들 수도 있습니다.

<script setup>
import { useCounterStore } from "~/store/counter";
import { storeToRefs } from "pinia";
import { computed } from "vue";

const store = useCounterStore();
const { count } = storeToRefs(store);

// ✅ computed()와 함께 사용 가능
const doubleCount = computed(() => count.value * 2);
</script>

<template>
  <p>Count: {{ count }}</p>
  <p>Double Count: {{ doubleCount }}</p>
  <button @click="store.increment">+</button>
</template>

count는 storeToRefs()로 ref()로 변환되었으므로, computed() 안에서 count.value를 사용하여 doubleCount를 만들 수 있습니다.


storeToRefs() 사용이 필요 없는 경우

1️⃣ 반응형 상태를 직접 사용할 때

<script setup>
import { useCounterStore } from "~/store/counter";

const store = useCounterStore();
</script>

<template>
  <p>Count: {{ store.count }}</p> <!-- 직접 접근해도 반응성 유지됨 -->
</template>

2️⃣ actions나 getters만 구조 분해 할 때

반응형이 깨지는 것은 state일 때만 해당되므로, actions와 getters는 구조 분해 할당해도 괜찮습니다.

const { increment } = useCounterStore(); // actions는 storeToRefs()가 필요 없음
increment();
728x90

'Javascript > NuxtJS' 카테고리의 다른 글

[Nuxt3] Nitro  (0) 2025.03.15
[Nuxt3] Server  (0) 2025.03.15
[Nuxt3] ref()와 computed() 차이점  (0) 2025.03.12
[Nuxt3] 상태 관리  (0) 2025.03.09
[Nuxt3] 라우트 미들웨어  (0) 2025.03.09