ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Vue3] ref VS reactive
    SPA/Vue.js 2024. 4. 27. 17:15

    앞서 Composition API에 대해 알아봤을 당시 ref와 reactive에 대해서도 스쳐가듯 알아봤다.

    https://chaeng03.tistory.com/entry/Vue-Composition-API

     

    [Vue] Composition API

    Vue2와 Vue3의 차이점을 정리하던 중 제일 큰 차이점인 Composition API는 따로 정리해야 할 것 같아 글을 작성하게 되었다. 1. Composition API란? Composition API는 함수 기반의 API로, 컴포넌트 내에서 사용하

    chaeng03.tistory.com

     

    그러나 너무 스쳐가듯 알아본 것일까..?

    ref와 reactive에 대해 설명해보라는 팀장님의 말씀에 그 누구도 자신 있게 대답하지 못했다.

     

    그래서 시작된 본격! ref와 reactive 알아보기!!


     

    우선 refreactive는 Vue3(Composition API)에서 반응형 data를 사용하는 방법이다.

    그렇다면 반응형 데이터(Reactive Data)란 무엇일까?

     

    1. 반응형 데이터(Reactive Data)

    반응형 데이터데이터의 변경 사항이 자동으로 화면에 반영되는 것을 의미한다.

    예를 들어 Vue 애플리케이션에서 보여지는 데이터 내용이 변경되면 그에 따라 해당 데이터를 사용하는 화면 요소들이 자동으로 업데이트된다는 말씀!

     

    2. ref란?

    Vue2에서도 봤는데..? 싶다면 정상입니다.

    Vue3 이전에는 Vue 템플릿의 DOM 또는 컴포넌트를 가리키는 속성이었지만 Vue3에서는 reactive reference를 의미한다.

     

    일단 Vue는 상태의 변경을 proxy로 감시하는데 proxy는 객체이기에 참조가 없는 원시타입(Number, String 등)은 proxy로 만들 수가 없다.

    그래서 생긴 게 ref다!

    즉, proxy로 사용하기 위해 object 형태로 변경됨으로써 ref로 생성된 값에 접근하려면 .value 속성을 사용해야 한다.

     

    단, 객체의 경우 ref로 감싸면 해당 객체가 변경되어도 참조는 변경되지 않는다.

    즉, 참조가 변경되어도 반응성이 없어 객체의 변경을 감지하는 데 한계가 있다.

    import { ref } from 'vue';
    
    const count = ref(0); // 반응형 참조 생성
    
    console.log(count.value); // 0 출력
    count.value++; // 값 변경
    console.log(count.value); // 1 출력

     

    그러나 Component나 view에서 해당 ref를 사용할 때에는 내부값을 자동으로 언래핑하기에 .value의 사용없이도 사용 가능하다.

    <template>
    	{{ count }}
    </template>

     

    (1) isRef()

    isRef는 이름에서 알 수 있듯이 값이 ref 객체인지 확인해준다.

    const age = 23;
    console.log(isRef(age)); // false

     

    (2) toRef()

    하나의 property에 대해 부모 object와의 연결성을 유지한 채로 reactive를 반환하며 이 변화는 부모에게도 반영이 되어 추적된다.

    const person = reactive({name:"kimBoolean",age:23})
    const age = toRef(person, age)

     

    (3) toRefs()

    toRefs는 reactive의 모든 property에 대해 toRef를 적용해 반환하며 이를 활용해 destructing(구조 분해 할당)을 사용할 수 있다.

    const person = reactive({name:"kimBoolean", age:23})
    const { name, age } = toRefs(person)

     

    (4) shallowRef()

    ref의 얕은 버전으로, ref와 달리 내부 값은 그대로 저장되고 노출되지만 내부 깊숙이 반응형으로 동작하지는 않는다.

    일반적으로 대규모 데이터 구조의 성능 최적화 또는 외부 상태 관리 시스템과의 통합에 사용된다고 한다.

    const person = shallowRef({ age: 23 })
    
    // change(변경)을 트리거하지 않음
    person.value.age = 24

     

    (5) triggerRef()

    shallowRef()의 강제 트리커 이펙트로, 일반적으로 shallowRef 내부 값을 변경 후 관련 이펙트를 강제로 트리거하기 위해 사용한다.

    const shallow = shallowRef({ name: 'kimBoolean' })
    
    watchEffect(() => {
      console.log(shallow.value.name);
    })
    
    shallow.value.name = 'Boolean'
    
    // 강제 이펙트 트리거
    triggerRef(shallow); // "Boolean"

     

    (6) customRef()

    의존성 추적 및 업데이트 트리거를 명시적으로 제어하기 위한 커스텀 ref를 만든다.

    인자로 track과 trigger를 인자로 받는 팩토리 함수를 받으며, get과 set 메서드가 포함된 객체를 반환한다.

    export function useDebouncedRef(value, delay = 200) {
      let timeout
      return customRef((track, trigger) => {
        return {
          get() {
            track()
            return value
          },
          set(newValue) {
            clearTimeout(timeout)
            timeout = setTimeout(() => {
              value = newValue
              trigger()
            }, delay)
          }
        }
      })
    }

     


    3. reactive란?

    reactive는 원시 타입은 사용할 수 없고 Object 타입(Object, Array, Map, Set)만 반응형으로 만들어주며 아래와 같이 함수도 집어넣을 수 있다.

    const Plus = reactive({
    	number: 1,
        plusNumber: computed(() => state.number + 2 )
    })

     

    또한 객체의 모든 속성이 반응적으로 추적되기에 객체 내부의 속성이 변경되면 관련된 컴포넌트가 재렌더링된다.

    즉, 객체에 대해 깊은 감지가 가능하다!

     

    reactive는 ref와 달리 일반적인 javascript 객체처럼 접근이 가능하다.

    import { reactive } from 'vue';
    
    const state = reactive({
      count: 0,
      message: 'Hello'
    }); // 반응형 객체 생성
    
    console.log(state.count); // 0 출력
    state.count++; // 속성 변경
    console.log(state.count); // 1 출력

     

    (1) isReactive()

    객체가 reactive 또는 shallowReactive에 의해 생성된 proxy인지 확인한다.

     

    (2) shallowReactive()

    reactive의 얕은 버전으로, 루트 수준의 속성 변경에 대해서만 반응형인 객체이다.

    속성이 ref인 경우, 자동으로 언래핑되지 않는다.

    const person = shallowReactive({
      age: 23,
      nested: {
        home: 'seoul'
      }
    })
    
    // 상태의 자체 속성 변경은 반응형으로 동작함
    person.age++
    
    // ...하지만 중첩된 객체는 그렇지 않음
    isReactive(person.nested) // false
    
    // 반응형이 아님
    person.nested.home = 'incheon'

     


    4. 그럼 뭘 사용해야 할까?

    사실 팀 내 코드 컨벤션에 따르는 게 맞지만 정해져 있지 않은 상황이라면 ref를 쓰는 것이 변수명.value로 접근이 가능하기에 가독성 및 유지보수에 좋다고 한다.

    그도 그럴 게 reactive는 일반 변수와 같이 변수명을 그대로 사용할 수 있으므로 여타 일반 변수와 구분이 어려워질 것이기 때문이다.

    'SPA > Vue.js' 카테고리의 다른 글

    [Vue] ClientOnly로 client side / server side 이해하기  (0) 2024.06.30
    [Vue] Filter로 데이터 필터링하기  (0) 2024.05.27
    [Vue] Vue2 VS Vue3 차이점  (0) 2024.04.08
    [Vue] Composition API  (2) 2024.04.03
    [Vue] v-deep 셀렉터  (0) 2024.01.09
Designed by Tistory.