GeehDev

[Vue3] Vue 템플릿 문법 (Mustache, Directive) 본문

Study/Vue.js

[Vue3] Vue 템플릿 문법 (Mustache, Directive)

geehyun 2025. 3. 2. 01:08

Index

    반응형

    [Vue3] Vue 템플릿 문법 (Mustache, Directive)


    Vue 탬플릿 문법

    탬플릿(Template)란 기본적으로 UI를 구성하는 틀로, 웹 개발에서는 HTML을 기반으로 화면을 구성하는 요소를 탬플릿이라 볼 수 있다.
    Vue에서는 단순 정적 탬플릿이 아니라 데이터의 변화에 따라 동적으로 반응하여, 반응형 데이터를 바인딩할 수 있도록 설계되어 있다.

    1. Mustache 문법

    <p>{{ message }}</p>

     

    {{}} 형식으로 작성하는 문법으로, 데이터를 바인딩할 때 쓰인다.
    {{ 변수 }} 형식으로 작성하여 변수에 들어있는 데이터를 화면에 표시해주는 역할을 한다.

    📌나 Mustache 라는걸 들어봤어요! 어디서 들었더라?
    Mustache.js라는 탬플릿엔진에서 쓰이던 문법으로 원래는 HTML을 그리는 시점에 들어온 데이터를 바인딩하는 정적 데이터 바인딩 문법이었으나, Vue에서 이를 차용하여 반응형 데이터를 바인딩할 수 있도록 지원하는 Vue Mustache 문법을 제공한다.

    특징

    • 단방향 데이터 바인딩
      • {{}} 안에 들어있는 변수의 데이터가 변경되면 자동으로 UI가 업데이트된다.
      • 다만, 사용자가 값을 변경할 수는 없는 단방향 데이터 바인딩 방식.
    • 자바스크립트 표현식 사용가능
      • 다만 if/else, for와 같은 문법은 구현 불가
    <p>{{ text.toUpperCase() }}</p>
    <p>{{ count * 2 }}</p>

    사용법

    작성 코드

    <script setup lang="ts">
    import {ref} from "vue";
    
    const name = ref('지현');
    </script>
    
    <template>
      <h1>Vue 탬플릿 문법</h1>
    
      <h2>1. Mustache </h2>
      <div>안녕하세요? {{ name }} 님! Vue 세상에 오신걸 환영합니다.</div>
    </template>

    출력 화면

    mustache 문법 사용예시

     

    2. 디렉티브(Directive)

    Vue에서 HTML 요소를 조작하거나 HTML 요소의 속성을 조작할 수 있다.
    v- 접두어로 시작하면 HTML 태그의 속성처럼 작성하여 사용한다. (thymeleaf 에서 th- 문법과 유사)

    1) v-bind

    • HTML 속성 값을 동적으로 바인딩할 수 있다.
    • v-bind:속성이름="값" 또는 :속성이름="값" 의 형식으로 작성한다.

    작성 코드

    <script setup lang="ts">
        import { ref } from 'vue'
        const geeDevBlog = ref('https://geehyun.tistory.com/');
    </script>
    <template>
        <strong>1. 기본형</strong>
        <a v-bind:href="geeDevBlog">GeeDev 블로그에 놀러오세요 1</a>
    
        <strong>2. 단축형</strong>
        <a :href="geeDevBlog">GeeDev 블로그에 놀러오세요 2</a>
    </template>

    출력 화면

    v-bind 문법 사용예시

    2) v-if

    • 입력된 조건이 true일 경우만 해당 태그를 렌더링 한다.
    • 즉, 조건이 false일 경우 렌더링 된 HTML 문서상 아예 존재하지 않는다. (DOM 에서 아예 존재 X)
    • v-if="조건" 의 형식으로 사용되며, 조건에서 간단한 연산자나 함수를 사용할 수 있다.

    작성 코드

    <script setup lang="ts">
        import { ref } from 'vue'
        const cost1 = ref(5000);
        const cost2 = ref(20000);
    </script>
    <template>
        <p>{{cost1}} <span v-if="cost1 > 10000">만원 초과!!!</span><span v-else>만원 미초과!!!</span></p>
        <p>{{cost2}} <span v-if="cost2 > 10000">만원 초과!!!</span><span v-else>만원 미초과!!!</span></p>
    </template>

    출력 화면

    v-if 문법 사용예시

    3) v-show

    • 입력된 조건이 true일 경우만 화면에 표시한다.
    • 조건이 truefalse이든 렌더링은 하며, 다만, 조건이 false일 경우 display:none; 처리된다. (조건이 false 이더라도 DOM 에는 존재함)
    • 그 외 사용법은 v-if와 동일하다.

    작성코드

    <script setup lang="ts">
        import { ref } from 'vue'
        const odd = ref(5);
    </script>
    <template>
        <p>{{odd}}는</p>
        <p v-show="odd % 2 != 0">홀수</p>
        <p v-show="odd % 2 == 0">짝수</p>
        <p>입니다.</p>
    </template>

    출력화면

    v-show 문법 사용예시

    4) v-for

    • 배열이나 객체를 반복하여 작성한 요소를 자동으로 생성한다.
    • v-for="변수 in 배열(또는 객체)" 로 사용하거나, v-for="(변수, 인덱스변수) in 배열(또는 객체)"로 인덱스(또는 키)를 사용할 수 있다.
    • :key 로 해당 배열(또는 객체)의 고유의 식별자를 지정해 줄 수 있다.
      • 식별자의 경우 객체의 key처럼 중복되지 않은 고유한 값을 사용해야 한다. (없으면 인덱스라도 사용 권장)
      • vue가 해당 배열(또는 객체)의 데이터를 구분하는 고유한 식별자로 성능 최적화, 올바른 업데이트 등을 위해 사용하는 것이 좋다.

    작성코드

    <script setup lang="ts">
        import { ref } from 'vue'
        const nameArray = ref(['지현', '김아무개', '홍길동', '김철수', '김영희']);
        const nameObj = ref<Record<string, any>>({"name": "geehyun", "age": "5살", "gender" : "female"});
    </script>
    <template>
        <strong>1. for of 사용</strong>
        <p v-for="name of nameArray">저는 {{name}} 입니다.</p>
    
        <strong>2. for index 사용</strong>
        <p v-for="(item, index) of nameArray" :key="index">저는 {{index + 1}} 번째 이름 {{item}} 입니다.</p>
        <hr>
        <p v-for="(item, id) of nameObj" :key="id">저의 {{id}} 는 {{item}} 입니다.</p>
    </template>

    출력화면

    v-for 문법 사용예시

    5) v-model

    • 양방향 데이터 바인딩을 제공한다.
    • input, textarea, select 등의 form 요소와 연결하여 사용자가 값을 입력(또는 선택) 할 시 자동으로 Vue 데이터도 변경되고, Vue 데이터가 변경되면 입력 필드의 값이 변경되는 양방향 데이터 바인딩 기능이다.

    작성코드

    <script setup lang="ts">
        const input = ref('입력 전');
    </script>
    <template>
        <input v-model="input" placeholder="이름을 입력하세요">
        <br>
        <p>저는 {{input}} 입니다.</p>
    </template>

    출력화면

    v-model 문법 사용예시 (사용자 입력 전)
    v-model 문법 사용예시 (사용자 입력 후)

    6) v-on

    • 각 이벤트 별 이벤트 핸들러를 등록할 수 있다.
    • v-on:이벤트명="값" 또는 @이벤트명="값"의 형태로 사용할 수 있다.

    작성코드

    <script setup lang="ts">
        const count1 = ref(0);
        const count2 = ref(0);
        const count3 = ref(0);
        const count4 = ref(0 as number);
        const inputNum = ref(0);
        const add1 = ()=>{count3.value++;};
        const addNum = (num:number)=>{count4.value+=num;};
    </script>
    <template>
        <strong>1. 기본형</strong>
        <button v-on:click="count1++">+1</button>
        <p>count1 : {{count1}}</p>
    
        <strong>2. 단축형</strong>
        <button @click="count2++">+1</button>
        <p>count2 : {{count2}}</p>
    
        <strong>3. 함수사용 : 인자없음</strong>
        <button @click="add1">add1</button>
        <p>count3 : {{count3}}</p>
    
        <strong>4. 함수사용 : 인자있음</strong>
        <input v-model="inputNum" type="number"></input>
        <button @click="addNum(inputNum)">+</button>
        <p>count4 : {{count4}}</p>
    </template>

    출력화면

    v-on 문법 사용예시 (이벤트 발생 전)
    v-on 문법 사용예시 (이벤트 발생 후)

    7) v-html

    • HTML 태그가 포함된 문자열을 실제 HTML로 렌더링 할 수 있다. (JavaScript에서 innerHTML과 유사)
    • 단, 사용 시 사용자 입력 값을 v-html로 바로 출력하는 것은 보완적으로 위험할 수 있으며, XSS 공격에 유의해야 한다.

    작성코드

    <script setup lang="ts">
        const htmlContents = ref(`<table style="border: 1px solid black"><tr><th>항목 1</th><td>항목2</td></tr><tr><td>내용 1</td><td>내용 2</td></tr></table>`);
    </script>
    
    <template>
        <strong> 1. v-html 로 넣었을 때</strong>
        <div v-html="htmlContents"></div>
        <strong v-pre> 2. {{}} 로 넣었을 때</strong>
        <div>{{htmlContents}}</div>
    </template>

    출력화면

    v-html 문법 사용예시

    8) v-text

    • 내용을 텍스트로 삽입할 때 사용된다. (JavaScript에서 textContent와 유사)
    • HTML 또는 JavsScript 등 코드가 들어와도 텍스트 그대로 화면에 출력한다.

    작성코드

    <template>
        <strong> 1. v-text 로 넣었을 때</strong>
        <div v-text="htmlContents"></div>
        <strong v-pre> 2. {{}} 로 넣었을 때</strong>
        <div>{{htmlContents}}</div>
    </template>
    
    <script setup lang="ts">
        const htmlContents = ref(`<table style="border: 1px solid black"><tr><th>항목 1</th><td>항목2</td></tr><tr><td>내용 1</td><td>내용 2</td></tr></table>`);
    </script>

    출력화면

    v-text 문법 사용예시

    9) v-slot

    • slot이란 vue에서 부모 컴포넌트가 자식 컴포넌트의 특정 영역을 직접 정의하는 기능으로, v-slot으로 이러한 slot을 제어할 수 있다.
    • 부모 컴포넌트에서 slot <template v-slot:슬릇명>으로 슬롯을 지정하고, 자식 컴포넌트에서 <slot name="슬릇이름"> 으로 사용할 수 있다.
    • <template v-slot:슬릇명> 또는 <template #슬릇명> 으로 사용할 수 있다. 또한, <template v-slot:default> 로 default로 설정한 slot에 대해서는 자식 컴포넌트에서 <slot>의 형식만으로도 사용할 수 있다.
    • 또한, slot을 사용할 때 부모 컴포넌트는 자식 컴포넌트의 데이터를 받아 해당 데이터를 활용하여 해당 slot 내에서 사용할 수 있다. 이를 Scoped Slot 이라 한다.

    작성코드

    <!-- 부모 영역 : Parent.vue -->
    <template>
        <ChildComponent>
            <template v-slot:default>
                <p>안녕 난 부모 영역이야! 이름 없는 slot 이지!</p>
            </template>
            <template v-slot:test1>
                <p>난 test1 라는 이름의 slot 이야. 기본형으로 사용했지 </p>
            </template>
            <template #test2>
                <p>난 test2 라는 이름의 slot 이야. 단축형으로 사용했어 </p>
            </template>
            <template #test3="{data}">
                <p>난 test3 라는 이름의 slot 이야. 아래는 자식 컴포넌트에서 받은 데이터로 출력한거야</p>
                <p v-for="(item, key) in data" :key="key">key : {{ key }} / item : {{ item }}</p>
            </template>
        </ChildComponent>
    </template>
    
    <!-- 자식 영역 : ChildComponent.vue -->
    <template>
        <strong> 1. default slot 사용</strong>
        <slot></slot>
        <strong> 2. named slot 사용 : 기본형</strong>
        <slot name="test1"></slot>
        <strong> 3. named slot 사용 : 단축형</strong>
        <slot name="test2"></slot>
        <strong> 4. scoped slot 활용</strong>
        <slot name="test3" :data="childData"></slot>
    </template>

    출력화면

    v-slot 문법 사용예시 (작성코드)
    v-slot 문법 사용예시 (출력 내용)

    10) v-cloak

    • Vue가 화면을 완전히 로드할 때까지 해당 태그를 아예 화면에서 보이지 않게 처리할 수 있게 할 수 있다.
    • 네트워크 환경이 느리거나, 불러올 요소가 많은 경우 Vue가 화면을 완전히 렌더링 하기 전 {{변수}}와 같은 vue 문법들이 텍스트 그대로 화면에 표시되는 경우가 있다. 이를 방지하기 위해 v-cloak을 사용할 수 있다.
    • Vue가 화면을 완전히 렌더링 하기 전 v-cloak을 넣은 요소에 v-cloak HTML 속성에 추가하여 CSS Style 로 display:none 처리 또는 커스텀 로딩중 처리 등으로 사용할 수 있다. (v-cloak 속성 자체가 처리해 주는 게 아니기 때문에 별도 CSS 처리 필요)
    • v-cloak 사용 시 렌더링 완료 전 v-cloak HTML 속성이 추가되며, 렌더링 완료 후 v-cloak HTML 속성이 제거된다.

    작성코드

    <script setup lang="ts">
        const message = ref('로딩 완료~');
    </script>
    
    <template>
        <div v-cloak>{{message}}</div>
    </template>
    
    <style>
        [v-cloak] {
            display: none;
        }
    </style>

    출력화면

    v-cloak 문법 사용예시
    v-slot 문법 사용예시 (로딩 완료 후 html 요소에 v-cloak 속성 없는 부분 확인)

     

    해당 문법의 경우! 보이지 않는 걸 캡처하기 어려워 랜더링 된 상태만 확인

    11) v-pre

    • 해당 디렉티브 문법을 사용 시 해당 HTML 요소 하위에 있는 요소에서 Vue 탬플릿 문법을 해석하지 않도록 처리한다.
    • HTML 기본 태그 중 pre코드가 해당 태그 내 HTML 문법으로 작성된 내용도 HTML 문법으로 읽지 않고 텍스트 그대로 표시하는 것처럼, v-pre{{}} 등의 Vue 문법을 해석하지 않고 텍스트 그대로 표시하게 한다.

    작성코드

    <script setup lang="ts">
        const mustache = ref('전 mustache 에요! 콧수염같이 생겨서 이름이 이렇답니다.');
    </script>
    
    <template>
        <strong> 1. v-pre 사용</strong>
        <div v-pre>{{mustache}}</div>
        <strong> 2. v-pre 미사용</strong>
        <div>{{mustache}}</div>
    </template>

    출력화면

    v-pre 문법 사용예시

    12) v-memo

    • Vue3에서 새로 추가된 기능이며, 캐싱을 이용해 성능을 최적화할 수 있는 기능이다.
    • v-memo 에 입력된 값 기준으로 데이터의 변경 여부를 판단하여, 해당 값이 변경되지 않으면 다시 렌더링 하지 않도록 한다.
    • 배열, 객체 데이터에서 특정 항목 기준으로 변경 여부를 판단하고, 그 외 다른 값이 변경되는 것은 변경으로 보지 않도록 하여 불필요한 렌더링을 줄이고, 성능을 최적화할 수 있다.

    작성코드

    <script setup lang="ts">
        const count = ref(0);
        const memo = ref('초기 값');
    </script>
    
    <template>
        <strong> 1. v-memo 사용</strong>
        <p v-memo="[count]"> count : {{count}} / memo : {{memo}}</p>
        <!-- count 값이 변경될 때만 렌더링 되며, memo의 값만이 변경될 때는 렌더링 되지 않는다. -->
    
        <strong> 2. v-memo 미사용</strong>
        <p> count : {{count}} / memo : {{memo}}</p>
        <!-- count, memo 값 각각 변경될 때마다 렌더링 된다. -->
    
        <button @click="count++">1 증가</button>
        <button @click="memo+= '+' + count">메모 더하기</button>
    </template>

    출력화면

    v-memo 문법 사용예시 (값 변경 전)
    v-memo 문법 사용예시 (count 값 변경 => v-memo 사용/미사용 모두 같이 변경된 값으로 렌더링 됨.)
    v-memo 문법 사용예시 (memo 값 변경 => v-memo 사용한경우 변경되지 않고, 미사용한 경우에만 변경 됨.)

     

    마치며

    vue 탬플릿 문법에 대해 공부해 봤는데, thymeleaf를 먼저 사용해 왔던 사람으로서 꽤나 thymeleaf 문법과 유사하다고 느껴졌다.

    기존 HTML/CSS/JavaScript 로도 구현이 가능하지만, Vue를 이용한다면 더욱 편하게 사용할 수 있을 것 같다.

    특히 v-memo와 v-slot 은 공부하면서 많이 신기했고 앞으로 공부할 Vue 컴포넌트와 함께 Vue 만의 특화된 기능으로 여러 가지 상황에서 활용할 수 있을 것 같다.

     

    꽤나 흥미롭게 Vue 공부를 하고 있다.

    728x90

    'Study > Vue.js' 카테고리의 다른 글

    [Vue3] 반응형 데이터 : ref() 와 reactive()  (0) 2025.03.15
    [Vue3] Vue.js 소개 및 개발환경 셋팅  (0) 2025.02.24