코딩, 개발에 대한 기록 저장소

Vue 3 Composition API에서 ref()와 reactive() 차이 정리


Vue 3 Composition API에서 ref()reactive() 차이 정리

Vue 3 Composition API를 사용하다 보면 가장 먼저 마주치는 개념이 바로 ref()reactive()입니다.
둘 다 반응형 상태를 만들기 위한 API지만, 사용 목적과 특성이 분명히 다릅니다.

이번 글에서는 ref()reactive()의 차이점을 개념, 예제, 실무 기준으로 정리해보겠습니다.


1. 기본 개념

🔹 ref()

  • 단일 값을 반응형으로 만듭니다

  • 값 접근 및 수정 시 **.value**가 필요합니다

  • 원시 타입과 객체 모두 사용 가능

const count = ref(0)

🔹 reactive()

  • 객체 자체를 반응형으로 만듭니다

  • .value 없이 직접 접근합니다

  • 객체, 배열, Map, Set만 가능 (원시 타입 ❌)

const state = reactive({ count: 0 })

2. 사용 예시

📌 ref() 사용 예시

import { ref } from 'vue' const count = ref(0) const name = ref('홍길동') const user = ref({ name: '홍길동', age: 30 }) // 접근 console.log(count.value) // 0 console.log(name.value) // 홍길동 console.log(user.value.name) // 홍길동 // 수정 count.value = 1 name.value = '김철수' user.value.age = 31

📌 reactive() 사용 예시

import { reactive } from 'vue' const state = reactive({ count: 0, name: '홍길동', user: { name: '홍길동', age: 30 } }) // 접근 console.log(state.count) // 0 console.log(state.name) // 홍길동 console.log(state.user.name) // 홍길동 // 수정 state.count = 1 state.name = '김철수' state.user.age = 31

3. 주요 차이점 한눈에 보기

구분ref()reactive()
원시 타입✅ 가능❌ 불가
객체 사용✅ 가능✅ 가능
접근 방식.value 필요직접 접근
템플릿 사용자동 unwrap직접 접근
재할당✅ 가능❌ 불가
구조 분해안전반응성 손실
타입 추론명확상대적으로 약함

4. 실무 코드 예시 (현재 프로젝트 기준)

ref()가 적합한 경우

const listItems = ref([]) // 배열 const currentPage = ref(1) // 숫자 const importDialog = ref(false) const selectedId = ref(null)

단일 값, 재할당이 잦은 상태


reactive()가 적합한 경우

const selectedFile = reactive({ modelWeight: null, modelConfig: null, }) const sort = reactive({ key: 'id', order: 'desc', }) const searchTemp = reactive({ model_name: '', training_kernel_name: '', model_type: null, })

관련된 속성들이 하나의 의미를 가지는 상태


5. 언제 무엇을 사용할까?

ref()를 사용하는 경우

  • string / number / boolean 같은 원시 타입

  • 값 자체가 자주 재할당되는 경우

  • 구조 분해가 필요한 경우

  • 타입 안정성이 중요한 경우

const count = ref(0) const name = ref('') const isLoading = ref(false)

reactive()를 사용하는 경우

  • 여러 속성을 가진 상태 객체

  • 객체 구조가 고정된 경우

  • 폼, 설정, 검색 조건 등

const form = reactive({ username: '', password: '', email: '', }) const config = reactive({ apiUrl: 'https://api.example.com', timeout: 5000, retries: 3, })

6. 주의사항 ⚠️

reactive() 구조 분해 시 반응성 손실

const state = reactive({ count: 0, name: '홍길동' }) // ❌ 반응성 깨짐 const { count, name } = state count++ // 반응성 없음

✅ 해결 방법

import { toRef } from 'vue' const count = toRef(state, 'count') const name = toRef(state, 'name')

reactive() 객체 재할당 문제

let state = reactive({ count: 0 }) // ❌ 기존 반응성 끊김 state = reactive({ count: 1 })

✅ 올바른 방식

state.count = 1