favicon

Jayden { do: smite }

231213(수)

🌱 성장일지 8.0

행복한 이기주의자(웨인 다이어)의 내용에 자극받아 시작하는 소박한 성장기록

  • 살아있는 꽃과 죽은 꽃은 어떻게 구별하는가?
  • 성장하고 있는 것이 살아 있는 것이다.
  • 생명의 유일한 증거는 성장이다!

⚛ (8.0)<완전 개편> 그 날의 키워드 중심으로 간단하게 정리하되 매일 꾸준히 작성할 수 있는 공간을 만들어보자.

Vue.js composition API의 ref와 reactive

ref와 reactive의 차이점이 무엇일까?

결론부터 간단하게 말하자면 ref는 primitive type의 데이터를 reactive하게 만들어주는 반면, reactive는 object type의 데이터를 reactive하게 만들어준다. 물론 정해진 규칙은 아니지만, 일반적으로는 그렇게 사용한다.

  • ref는 primitive type의 데이터를 reactive하게 만들어준다.
<script setup> import { ref } from 'vue'; const count = ref(0); </script> <template> <h1>테스트</h1> <div>{{ count }}</div> <input v-model="count" /> </template>
  • reactive는 object type의 데이터를 reactive하게 만들어준다.
<script setup> import { reactive } from 'vue'; const state = reactive({ count: 0, }); </script> <template> <h1>테스트</h1> <div>{{ state.count }}</div> <input v-model="state.count" /> </template>

여기서 하나 더 알아보자면, reactive의 경우 객체의 속성에 reactive를 주입하는만큼, deep하게 reactive하게 만들어준다. 즉, 객체의 속성에 객체가 있을 경우, 그 객체의 속성까지 reactive하게 만들어준다.

<script setup> import { reactive } from 'vue'; const state = reactive({ middle: { count: 0, }, }); </script> <template> <h1>테스트</h1> <div>{{ state.middle.count }}</div> <input v-model="state.middle.count" /> </template>

그러면 그런 생각이 들 수 있다. ref는 script에서 사용할 때, .value를 붙여야하고 객체 타입이 아닌 원시 타입에만 reactive를 부여하는데 굳이 왜 사용해야할까? 그냥 reactive를 사용하면 되는 것 아닌가?

그 이유에는 여러가지가 있겠지만, 일단은 원시 타입에 대해 깔끔하게 reactive를 부여할 수 있다는 점과 위에서 봤듯이 reactive는 그 객체 내부의 모든 속성을 reactive하게 만들기 때문에 아무래도 성능적인 면에서는 ref가 더 좋다고 한다.(이 부분은 추후에 좀더 자세한 내용을 알아봐야겠다.)

Vue.js composition API의 watch와 watchEffect

watchwatchEffect의 차이점이 무엇일까? 이것도 아주 간단하게 내가 이해한 바로 정리해보면 아래와 같다.

  • watch는 특정 데이터의 변화를 감지하여 특정 로직을 실행한다. 즉, 어떤 데이터 하나를 콕 집어서 쳐다보는 것이다.

그래서 watch는 말그대로 effect가 없다. 간단하게 말하면 watch는 처음 렌더링 시에는 실행되지 않는다는 것이다. 말 그대로 감시하고 있는 데이터가 변화했을 때만 실행된다.

<script setup> import { ref, watch } from 'vue'; const count = ref(0); watch(count, (newVal, oldVal) => { console.log('새로운 값: ', newVal); console.log('이전 값: ', oldVal); }); </script> <template> <h1>테스트</h1> <div>{{ count }}</div> <input v-model="count" /> </template>
  • watchEffect는 그냥 콜백함수만 넣어주면 된다. 그리고 그 콜백함수 내부에 있는 reactive한 데이터가 변화할 때마다 콜백함수를 실행한다.
  • 리액트의 useEffect와 비슷하다고 생각하면 된다. 대신 자동으로 내부에서 사용된 모든 의존성을 알아서 추적한다는 점이 다르다.(사실 리액트의 useEffect에도 모든 의존성을 전달해줘야하는 게 맞다.)
<script setup> import { ref, watchEffect } from 'vue'; const count = ref(0); watchEffect(() => { console.log('count: ', count.value); }); </script> <template> <h1>테스트</h1> <div>{{ count }}</div> <input v-model="count" /> </template>

아래와 같이 2개의 reactive한 데이터를 통해 비교해볼 수 있다.

<script setup> import { ref, watch, watchEffect } from 'vue'; const firstCount = ref(0); const secondCount = ref(0); watch(firstCount, () => { console.log('first 값을 감시중이다.', firstCount.value); }); watchEffect(() => { console.log('first 값을 감시중이다.', firstCount.value); console.log('second 값을 감시중이다.', secondCount.value); }); </script> <template> <h1>first</h1> <div>{{ firstCount }}</div> <input v-model="firstCount" /> <div>----------</div> <h1>second</h1> <div>{{ secondCount }}</div> <input v-model="secondCount" /> </template>

Vue.js의 component와 keep-alive 활용

component 태그

component 태그는 Vue.js에서 동적으로 컴포넌트를 렌더링할 때 사용한다. 즉, v-ifv-else-if와 같은 조건부 렌더링을 좀더 깔끔하게 사용할 수 있게 해준다.

개인적으로 아직 Vue.js에 대해 잘 모르는 상태라서 v-ifv-else-if, v-else를 사용하는 것이 더 직관적인 것 같다. 다만, 조건문이 많아질수록 component 태그를 사용하는 것이 더 깔끔해질 것 같다.

먼저 아래와 같이 Odd.vueEven.vue를 만들어보자.

Odd.vue

<script setup> import { ref } from 'vue'; const count = ref(0); </script> <template> <h1>Odd 입니다.</h1> <h2>{{ count }}</h2> <input v-model="count" /> </template>

Even.vue

<script setup> import { ref } from 'vue'; const count = ref(0); </script> <template> <h1>Even 입니다.</h1> <h2>{{ count }}</h2> <input v-model="count" /> </template>

App.vue

<script setup> import { ref } from 'vue'; import Odd from './Odd.vue'; import Even from './Even.vue'; const count = ref(0); const isShow = ref(false); </script> <template> <h1>테스트</h1> <div>{{ count }}</div> <input v-model="count" /> <button @click="isShow = !isShow">토글</button> <component :is="isShow ? Odd : Even" /> </template>

위와 같이 버튼을 클릭하면 Odd 컴포넌트와 Even 컴포넌트가 토글되는 것을 확인할 수 있다. 그런데 이 때, 중요한 점은 Odd 컴포넌트의 상태를 변경한 뒤 Even 컴포넌트로 토글하면 Odd 컴포넌트의 상태가 초기화된다는 것이다. 그럼 이런 상황에서 Odd 컴포넌트의 상태를 유지하고 싶다면 어떻게 해야할까? 이 때, keep-alive를 사용하면 된다.

keep-alive

keep-alive는 Vue.js에서 컴포넌트를 캐싱하는 기능을 제공한다. 즉, 컴포넌트에 대한 상태를 유지할 수 있게 해준다. 이 때, includeexclude를 사용하여 캐싱할 컴포넌트와 캐싱하지 않을 컴포넌트를 설정할 수 있다.

<script setup> import { ref } from 'vue'; import Odd from './Odd.vue'; import Even from './Even.vue'; const count = ref(0); const isShow = ref(false); </script> <template> <h1>테스트</h1> <div>{{ count }}</div> <input v-model="count" /> <button @click="isShow = !isShow">토글</button> <KeepAlive> <component :is="isShow ? Odd : Even" /> </KeepAlive> </template>

위와 같이 KeepAlive 태그로 감싸주면 된다. 그리고 includeexclude를 사용하여 캐싱할 컴포넌트와 캐싱하지 않을 컴포넌트를 설정할 수 있다.(즉, 특정 컴포넌트만 캐싱을 하거나 특정 컴포넌트만 캐싱하지 않을 수 있다. 사용법은 그냥 includeexclude에 배열로 컴포넌트를 넣어주면 된다.)

📝 회고

후아... 그래도 아주 조금씩 Vue.js 코드가 눈에 들어오기 시작했다. 물론 아직 reactivity에 대한 부분이 쪼끔 헷갈리기도 하고 특히나 emit의 경우는 아직도 보기가 어렵다. 처음엔 리액트만 해오던 내가 와 이게 뭐야 싶던 코드가 조금씩 눈에 익으니까 신기하기도 하고 이런 재미이가 있구나 싶기도 하다. 각 라이브러리가 추구하는 방향이나 철학이 다른 것도 체감되는 것 같고..! React도 잘 모르는 터라 Vue를 한다는 게 걱정이 되긴 했는데, 오히려 지금은 시야를 넓게 가져보는 것도 굉장히 좋은 경험이라는 생각이 든다.

참고

Copyright 2023. all rights reserved by Jayden