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
watch
와 watchEffect
의 차이점이 무엇일까? 이것도 아주 간단하게 내가 이해한 바로 정리해보면 아래와 같다.
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-if
와 v-else-if
와 같은 조건부 렌더링을 좀더 깔끔하게 사용할 수 있게 해준다.
개인적으로 아직 Vue.js에 대해 잘 모르는 상태라서
v-if
와v-else-if
,v-else
를 사용하는 것이 더 직관적인 것 같다. 다만, 조건문이 많아질수록component
태그를 사용하는 것이 더 깔끔해질 것 같다.
먼저 아래와 같이 Odd.vue
와 Even.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에서 컴포넌트를 캐싱하는 기능을 제공한다. 즉, 컴포넌트에 대한 상태를 유지할 수 있게 해준다. 이 때, include
와 exclude
를 사용하여 캐싱할 컴포넌트와 캐싱하지 않을 컴포넌트를 설정할 수 있다.
<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
태그로 감싸주면 된다. 그리고 include
와 exclude
를 사용하여 캐싱할 컴포넌트와 캐싱하지 않을 컴포넌트를 설정할 수 있다.(즉, 특정 컴포넌트만 캐싱을 하거나 특정 컴포넌트만 캐싱하지 않을 수 있다. 사용법은 그냥 include
와 exclude
에 배열로 컴포넌트를 넣어주면 된다.)
📝 회고
후아... 그래도 아주 조금씩 Vue.js 코드가 눈에 들어오기 시작했다. 물론 아직 reactivity에 대한 부분이 쪼끔 헷갈리기도 하고 특히나 emit의 경우는 아직도 보기가 어렵다. 처음엔 리액트만 해오던 내가 와 이게 뭐야
싶던 코드가 조금씩 눈에 익으니까 신기하기도 하고 이런 재미이가 있구나 싶기도 하다. 각 라이브러리가 추구하는 방향이나 철학이 다른 것도 체감되는 것 같고..! React도 잘 모르는 터라 Vue를 한다는 게 걱정이 되긴 했는데, 오히려 지금은 시야를 넓게 가져보는 것도 굉장히 좋은 경험이라는 생각이 든다.