[Vue.js] 디렉티브(Directives)란?

토끼는 개발개발·2023년 7월 31일
1

Vue.js

목록 보기
7/19
post-thumbnail

📌 1. 디렉티브(Directives)란?

디렉티브는 v-접두사가 있는 특수 속성이다. 그대로 직역하면 '지시'를 뜻한다.
즉, 디렉티브는 기능상에서 중요한 역할인 컴포넌트(또는 DOM요소)에게 "~~~하게 작동할 것"을 지시해주는 지시문을 말한다.

Vue는 여러가지 내장 디렉티브를 제공한다.

  • v-text
  • v-html
  • v-show
  • v-if
  • v-on
  • v-bind
  • v-model
    ...

이전 포스팅들에서도 썼던 이미 익숙한 디렉티브들도 보인다.
천천히 디렉티브들을 살펴보자.



📌 2. 디렉티브(Directives) 구성

디렉티브는 다음과 같이 구성되어 있다.

  • 디렉티브(directives) : v- 접두사가 있는 특수 속성으로 디렉티브의 값(value)이 변경될 때 특정 효과를 반응적으로 DOM에 적용하는 것을 말한다.
  • 전달인자(Argument) : 일부 디렉티브는 디렉티브명 뒤에 콜론(:)으로 표기되는 전달인자를 가질 수 있다. 예를 들어, v-bind 디렉티브는 반응적으로 HTML 속성을 갱신하는 데 사용한다.
  • 수식어(Modifiers) : 수식어는 점(.)으로 표시되는 특수 접미사로 디렉티브가 특별한 방식으로 바인딩되어야 함을 나타낸다.


📌 3. 디렉티브(Directives) 살펴보기

1) v-text

엘리먼트의 textContent를 업데이트 한다.

  • 요구값: String
<span v-text="msg"></span>
<!-- 같은 방법 -->
<span> {{ msg }} </span>

v-text는 html이 아닌 문자열로 인식한다.
변수에 <p>Hello</p>를 넣고 v-text를 사용했을 때, 'Hello'만 출력되는 것이 아닌 <p>태그를 문자열 그대로 인식하여 <p>Hello</p>가 출력된다.



2) v-cloak

이 디렉티브는 연결된 컴포넌트 인스턴스가 컴파일을 완료 할 때까지 엘리먼트에 남아있는다. 컴파일이 완료된 후에는 자동으로 삭제된다.

<div v-cloak>
  {{ message }}
</div>

쉬운 예제를 하나 생각해보자.

<div id="app"> 
	<p>{{ messge }} </p>
</div>

<script setup>
	const messsage = ref();
	const App = () => {
    	message.value = "안녕하세요";
    }
    
    //3초후에 로딩
    setTimeout(()=> {
    	Vue.createApp(App).mount('#app');
    }, 300)
	
</script>

3초 전까지는 {{ message }}가 그대로 출력된 후, 3초 후에 데이터가 바인딩 되어 안녕하세요가 출력될 것이다.
클라이언트 입장에서 {{ message }}가 그대로 노출된 후, 데이터가 변경되는 것은 꽤나 불편할 것이다.


이럴 때 쓰는 것이 v-cloak이다.

<p v-cloak> {{ message }} </p>

v-cloak는 컴파일이 완료될 때까지 <p v-cloak>으로 남아있다가 컴파일이 완료되면 삭제되어 <p>가 된다.
즉, v-cloak 디렉티브를 사용 후 [v-cloak] { display : none } 과 같은 CSS를 주면 컴파일이 완료될때까지 {{ message }}의 노출을 막을 수 있다.
컴파일이 완료될 때까지 <p v-cloak>이므로 display:none상태였다가 컴파일이 완료된 후 자동 삭제되어 CSS 적용이 해제된다.

위의 예제에 적용하면 3초동안 {{ message }}가 뜨지 않고 display:none상태로 있다가 3초 후 컴파일이 완료되며 안녕하세요만 뜨는 것이다.



3) v-once

엘리먼트와 컴포넌트를 한번(once)만 렌더링한다. 이후에 재렌더링 할 때 엘리먼트/컴포넌트 및 모든 하위 엘리먼트는 정적 컨텐츠로 처리되고 건너 뛴다. 업데이트 성능을 최적화하는데 사용할 수 있다.

<p v-once> 유지 메세지 : {{ message }} </p>

한번 렌더링 된 후에는 message의 데이터가 변경돼도 그대로 유지된다.
즉, 처음 렌더링 된 후 캐싱되도록 지정하는 것이다.

이러한 특성을 사용하여 정적 콘텐츠를 지정할 수 있다.
쉬운 예를 하나 생각해보자.

<template>
  <p v-once>{{ message }}</p> 
  <p>{{ message }}</p>
  <button @click="change()"> 버튼 </button>
</template>

<script setup>
  const message = ref("안녕하세요.");
  const change = () => {
      message.value = "반갑습니다.";
  }
</script>

1) 버튼 클릭 전
안녕하세요.
안녕하세요.

2) 버튼 클릭 후
안녕하세요.
반갑습니다.

v-once 디렉티브가 걸린 {{ message }}는 데이터 변경이 적용되지 않았다.
v-once 디렉티브가 걸리면, 데이터가 변경되어도 처음 렌더링 된 것이 유지된다.

🚫 주의사항

v-once는 남용하지 않는 것이 좋다. 이는 렌더링할 정적 컨텐츠가 굉장히 많은 경우에 편리하게 사용할 수는 있지만, 느리게 렌더링 되는 것을 인지하지 못할 정도라면 필수적이지 않다.
또한, 이런 방식은 v-once에 친숙하지 않은 개발자들에게 템플릿 업데이트 문제에 대해 많은 시간을 소비하게 만들 수 있다.



4) v-memo

(3.2버전부터 사용 가능)

v-once와 비슷하게 리렌더링을 방지한다. 다만, 반응형 데이터가 변경되면 업데이트 되도록 설정할 수 있다.

<div v-memo="[valueA, valueB]">
  ...
</div>

valueA와 valueB가 변경되지 않으면 전체 하위 트리에 대한 업데이트를 생략한다. valueA와 valueB가 변경된 경우에만 업데이트 된다.
(v-memo="[]"의 경우 기능적으로 v-once와 동일하다.)

동일한 입력이 주어졌을 경우 재평가하지 않고 함수가 동일한 값을 반환하도록 하여 성능을 위해 프로그램을 최적화하는 기술이라고 할 수 있다.

공식문서에서는 v-for문에서 반복 횟수가 1000회가 넘을 때(length > 1000) v-memo를 사용하면 아주 좋다고 설명하고 있다.

<div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
  <p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>
  <p>...more child nodes</p>
</div>

여기서 v-memo는 "selected가 변경된 경우에만 업데이트 하십시오." 라는 의미이다.
즉, selected의 영향을 받지 않는 항목들이 이전 VNode를 재사용하고 diffing(비교)을 완전히 건너뛸 수 있다.

자식들의 최신 업데이트를 방지하기 위해 구성요소에 사용할 수 있는 것이다.




참고문헌

https://ko.vuejs.org/api/built-in-directives.html

profile
하이 이것은 나의 깨지고 부서지는 기록들입니다

1개의 댓글

comment-user-thumbnail
2023년 8월 3일

글 잘읽었습니다. 저도 개발자 준비중인데 같이 교류하면서 해요!

답글 달기