cover

메뉴를 클릭할 때 서브 메뉴가 나타나거나, 검색에서 글을 쓰면 결과가 미리 나오는 등 상황에 따라 태그가 나타나거나 사라지게 하고 싶은 경우가 있습니다. Vue에서는 v-ifv-show를 이용하면 쉽게 구현가능합니다. 자세히 알아볼까요?


v-if 미리보기

v-if

v-if 디렉티브는 조건에 따라 요소들을 렌더링할 때 사용합니다.

v-if 문법

html
      <태그 v-if="(condition)">내용</태그>
    

v-if의 단짝 v-else-if, v-else

Javascript에서 if의 조건이 맞지 않을 때에 대한 처리로 else if와 else를 사용하죠? v-eles-ifv-else도 마찬가지 입니다.

html
      <태그 v-if="(condition1)">1</태그>
<태그 v-else-if="(condition2)">2</태그>
<태그 v-else>3</태그>
    
condition1이 true → 1이 나타남
condition1이 false
condition2이 true → 2가 나타남
condition2이 false → 3이 나타남

v-show

v-show 디렉티브도 마찬가지로 조건에 따라 요소를 렌더링할 때 사용합니다.

html
      <태그 v-show="(condition)">내용</태그>
    

v-if vs v-show

v-if와 v-show는 겉보기엔 동일하지만 다른 점들이 몇 가지 있습니다.

1. template 지원 여부
2. 용도
3. v-for와 같이 쓸 때

template 지원 여부

<template> 태그는 HTML에서 페이지가 로드될 때 렌더링되지 않아서 사용자에게 보이지 않습니다.

html
      <div>
	<template>
		<span>1</span>
		<span>2</span>
		<span>3</span>
	</template>
</div>
    

렌더링 결과는 다음과 같습니다.

html
      <div>
	<span>1</span>
	<span>2</span>
	<span>3</span>
</div>
    

template 태그는 실제로 존재하는 태그가 아니기 때문에 style (display: none)을 넣을 수 없습니다. 그래서 v-show는 쓸 수 없지만 v-if는 적용할 수 있습니다.

html
      <template>
  <div id="app">
    <template v-if="show">v-if</template>
		<template v-else>v-else</template>
		<template v-show="show">v-show</template>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: false,
    };
  },
};
</script>
    

show값이 false입니다. 따라서 v-if가 아닌 v-else가 적용되어 나와야하고 v-show는 나오지 않길 바라지만. 하지만 실제로는 v-show가 나타납니다.

image

따라서 template 태그는 v-if는 적용되고 v-show는 적용이 안된다는 걸 알 수 있습니다.

용도

v-if
장점: 조건이 false라면 초기에 렌더링하지 않기 때문에 사이트에 들어가는 시간이 절약됩니다.
단점: 조건이 true라면 태그를 렌더링하기 때문에 태그 내용이 많을수록 렌더링 시간이 많이 걸립니다.
처음에 사이트를 들어갈 때 로드하지 않거나 자주 사용하지 않는 경우 사용
v-show
장점: display 속성만 바뀌기 때문에 시간이 짧게 걸립니다.
단점: 불필요한 경우에도 처음 사이트를 접속할 때 그려야하기 때문에 불필요한 시간이 걸릴 수 있습니다.
자주 보였다가 사라져야하는 경우에 사용

이해를 위해 간단하게 코드를 보겠습니다.

html
      <template>
  <div id="app">
    <div v-if="show">v-if</div>
		<div v-show="show">v-show</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: true,
    };
  },
};
</script>
    

show 값에 따라 HTML의 결과가 완전히 달라집니다.

if show === true
image
if show === false
image

v-if는 DOM 내용 자체가 나타났다가 사라지기 때문에 그리는 시간이 많이 걸리지만 처음에 그리지 않는다면 초기에 로딩 시간을 절약할 수 있습니다.

v-show의 경우 조건에 상관없이 무조건 렌더링되기 때문에 시간을 잡아먹습니다. 하지만 이후 조건이 변함에 따라 속성만 바뀌기 때문에 나타났다가 사라지는 시간은 빠릅니다.

v-if를 v-for와 같이 쓸 때

만약 v-for와 같이 쓴다면 어떻게 될까요? v-for를 모르신다면 다음 링크를 참조해주세요!

v-show의 경우 v-for와 같이 사용해도 크게 문제가 없지만 v-if는 문제가 생길 수 있습니다. 예를 들면 1부터 5까지 그리는 리스트가 있고 3이상만 그리고 싶다고 해보겠습니다.

html
      <!-- list = [1,2,3,4,5] -->
<ul>
	<li v-for="item of list" :key="item" v-if="item.length > 3">{{ item }}</li>
</ul>
    

예상과 달리 에러가 발생합니다. 왜냐하면 v-if가 우선순위가 높기 때문에 v-for가 실해외기 전인 v-if에서는 아직 item값이 없거든요. 그래서 Vue.js 공식 가이드에 v-for와 v-if를 같이 사용하지 않기를 권장합니다.

v-for와 v-if를 같이 사용한다면 두 가지 의도로 사용하고 싶을 수 있습니다.

1. 목록의 각 항목을 조건에 따라 렌더링할 때
html
      <태그 v-for="item of list" v-if="item > 3"></태그>
    
2. 목록 자체를 조건에 따라 렌더링할 때
html
      <태그 v-for="item of list" v-if="list.length > 3"></태그>
    

그래서 가이드에서는 이를 다음과 같이 바꿔서 사용하길 권합니다.

1. computed로 active가 true인 item값들만 가진 list를 사용하거나 상위 template에서 v-for 사용하기
html
      <!-- item > 3인 값만 있는 activedList -->
<태그 v-for="item of activedList"></태그>
    
html
      <template v-for="item of list">
	<태그 v-if="item > 3"></태그>
</template>
    
2. template이나 상위 요소에 v-if 사용하기
html
      <template v-if="list.length > 3">
	<태그 v-for="item of list"></태그>
</template>
    

마무리하며

이번 글에서는 조건에 따라 렌더링해주는 디렉티브 v-ifv-show에 대해 알아보았습니다. 다음 글에서는 잠시 살펴본 v-for에 대해 다뤄보겠습니다.