Vue.js를 사용하다 보면 v-if
와 v-show
사이에서 헷갈리게 되는 일이 종종 있습니다. 저도 그 중 한 사람으로, 오늘은 제가 왜 v-show
와 v-if
의 차이를 제대로 이해하지 못해서 발생한 문제를 해결하기 위해 얼마나 고군분투했는지 공유하려 합니다.
문제의 시작은 아주 평범했습니다. Vue 프로젝트에 jQuery를 섞어 사용하는 상황이었고, 특정 DOM 요소를 조작하려고 했습니다.
결과는?
Uncaught TypeError: $ is not a function
혹은
Cannot read properties of null (reading 'find')
"에이, 설마 jQuery를 import를 잘못했나?"라는 생각으로 한참을 삽질했죠.
Vue 컴포넌트에서 아래와 같은 DOM 조작을 하려 했습니다.
onMounted(() => {
$(".templSelect-wrap").each(function () {
const templSelect = $(this);
templSelect.find(".sel-label").click(function () {
templSelect.toggleClass("active");
});
});
});
코드는 단순했습니다. jQuery로 .templSelect-wrap
이라는 클래스를 가진 DOM 요소들을 선택하고, 클릭 이벤트를 설정하려고 했습니다. 그런데 jQuery가 요소를 찾지 못해 문제가 발생했습니다.
디버깅을 시작하면서 다음 사실들을 확인했습니다.
$
가 정상적으로 로드되고 있음.mounted
훅이 정상적으로 실행되고 있음.Vue의 조건부 렌더링인 v-if
를 사용하고 있었던 겁니다. v-if
는 조건이 참일 때만 DOM을 렌더링하므로, jQuery가 DOM을 찾지 못했던 거죠.
v-if
와 v-show
의 진실을 깨닫다v-if
v-if
는 조건이 true
일 때만 DOM을 생성합니다. 초기 렌더링 시점에 DOM이 아예 존재하지 않기 때문에, jQuery 같은 외부 라이브러리로 DOM을 조작하려 하면 문제가 발생합니다.
v-show
반면, v-show
는 DOM을 항상 렌더링해 두고, CSS의 display: none
을 통해 보이거나 숨깁니다. DOM이 항상 존재하므로 jQuery로 조작이 가능합니다.
v-if
와 싸우다v-if
를 사용한 코드처음 작성했던 코드는 다음과 같습니다.
<div v-if="isVisible" class="templSelect-wrap">
<!-- 템플릿 내용 -->
</div>
여기서 isVisible
이 false
일 때 DOM이 아예 렌더링되지 않으므로, jQuery가 해당 요소를 찾을 수 없었습니다.
v-show
로 전환문제를 해결하기 위해 v-show
로 바꿨습니다.
<div v-show="isVisible" class="templSelect-wrap">
<!-- 템플릿 내용 -->
</div>
DOM이 항상 존재했기 때문에, jQuery 코드가 정상적으로 동작했습니다.
$nextTick
을 활용그런데 v-if
를 써야만 하는 상황도 있었습니다. 이때는 Vue의 $nextTick
을 활용하여 DOM이 렌더링된 후에 jQuery 초기화를 실행했습니다.
onMounted(() => {
nextTick(() => {
$(".templSelect-wrap").each(function () {
const templSelect = $(this);
templSelect.find(".sel-label").click(function () {
templSelect.toggleClass("active");
});
});
});
});
watch
로 상태 변화 감지또 다른 방법으로 watch
를 사용하여 DOM이 렌더링된 시점에서 초기화를 실행할 수 있었습니다.
watch(
() => isVisible,
(newVal) => {
if (newVal) {
$(".templSelect-wrap").each(function () {
const templSelect = $(this);
templSelect.find(".sel-label").click(function () {
templSelect.toggleClass("active");
});
});
}
}
);
Vue.js는 정말 강력하지만, 가상 DOM과 조건부 렌더링의 원리를 이해하지 못하면 이런 디버깅 지옥에 빠질 수 있습니다. 특히 외부 라이브러리(jQuery 같은)를 사용하면 DOM의 존재 여부가 중요한데, v-if
와 v-show
의 동작 차이를 몰랐다면 지금도 헤매고 있었을 겁니다.
v-if
와 v-show
를 사용할까?사용 상황 | 선택 | 이유 |
---|---|---|
DOM을 동적으로 생성/제거해야 할 때 | v-if | 필요할 때만 DOM을 생성하여 성능 향상 |
DOM을 항상 유지해야 할 때 | v-show | DOM이 항상 있어야 초기화 코드가 안정적으로 동작 |
렌더링 이후 DOM 조작이 필요한 경우 | v-show | DOM이 존재하므로 외부 라이브러리와 충돌 없음 |
이 사건 이후로 v-if
와 v-show
를 무조건 교체하지 않고, 상황에 맞게 사용할 수 있게 되었습니다. 디버깅 과정을 통해 Vue.js의 렌더링 원리를 깊이 이해하게 되었고, 앞으로의 코드 작성에 큰 도움이 될 것입니다.
여러분도 비슷한 문제를 겪고 있다면, v-if
와 v-show
의 동작 차이를 꼭 점검해 보세요! 👌
추신: 삽질은 개발자의 친구지만, 때론 조금 덜 친해도 좋겠다는 생각이 듭니다. 😅