상세 컨텐츠

본문 제목

[Vue] Vue 디렉티브와 computed, watch 속성

Vue

by developia_yeso 2025. 1. 14. 15:48

본문

뷰 디렉티브(directive) 란?

html 태그안에 v- 접두사를 가지는 모든 속성을 일컫는다.

디렉티브는 화면의 요소를 더 쉽게 조작하기 위해 사용하는 기능으로 뷰의 데이터 값이 변경되었을 때 화면의 요소들이 리액티브하게 반응하여 변경된 데이터값에 따라 갱신하게 된다.

이런식으로 화면 요소를 직접 제어할 필요없이 뷰의 디렉티브를 활용하여 화면 요소를 조작할 수 있다.

=> 개발자가 돔 요소를 직접 제어하지않고 프레임워크에 돔 요소 제어 권한을 위임함을 의미.

 

 

** 자주 사용하는 주요 디렉티브

디렉티브명 역할
v-if 지정한 뷰 데이터 값의 참, 거짓 여부에 따라 해당 html 태그를 화면에 표시하거나 표시하지 않음
v-for 지정한 뷰 데이터의 개수만큼 해당 html 태그를 반복 출력
v-show v-if와 유사하게 데이터의 진위 여부에 따라 해당 html 태그를 화면에 표시하거나 표시하지 않지만 v-if는 해당 태그를 완전히 삭제하는 반면 v-show는 css효과만 display:none 으로 주어 실제 태그는 남아 있고 화면상으로 노출되지 않는다.
v-bind  html 태그의 기본 속성과 뷰 데이터 속성을 연결
v-on 화면 요소의 이벤트를 감지하여 처리할 때 사용. 예를 들어 v-on:click 은 해당 태그의 클릭 이벤트를 감지하여 특정 메서드를 실행할 수 있음
v-model 폼(form)에서 주로 사용되는 속성. 폼에 입력한 값을 뷰 인스턴스의 데이터와 즉시 동기화(양방향성) 화면에 입력된 값을 저장하여 서버에 보내거나 watch와 같은 속성을 이용해 추가 로직을 수행. <input>, <select>, <textarea>태그에만 사용가능.

 

 

 

 

** 많이 사용하는 요소 들여다보기

 

1. v-if (참 거짓의 유무에 따라 화면에 노출 - 기본값 true)

 

isEditTitle이 true일 경우에만 노출되는 input요소

 

 

 

2. v-for ( 지정한 뷰 데이터의 개수만큼 해당 html 태그를 반복 출력 )

 

computed에 vuex의 요소 mapState를 불러와 state(상태)값을 가져옴

 

list in board.lists 로 반복 출력, :key="list.pos"로 고유의 key값을 부여 , : -> v-bind의 축약어이다.

 

 

v-for 문에서는 v-for:  list in board.lists와 같이 (in문 = 객체의 속성 이름 또는 배열의 인덱스를 반복) 사용할 수 있지만, v-for: v of data 형식(of문 = 배열, 문자열 등에서 자체를 반복)을 통해 모든 객체요소를 열거형태로 가져올 수 도 있다. (of의 경우, 익스플로어에서 작동하지 않는다.)

 

 

 

여기서 잠깐 짚고 넘어가는 *for...in문과 for...of의 차이

 

for in -> for...in은 객체의 속성(property)을 순차적으로 반복할 때 사용. 배열을 사용할 경우 배열의 인덱스를 반복. 

const person = {
  name: 'John',
  age: 30,
  gender: 'Male'
};

for (let key in person) {
  console.log(key, person[key]);  // key는 속성 이름, person[key]는 속성 값
}

 

* 결과

name John
age 30
gender Male

 

 

 

for..of ->  for...of는 배열, 문자열, Set, Map 등의 반복 가능한 객체(iterable object)을 순차적으로 반복할 때 사용.

for...of는 값 자체를 다루므로 인덱스를 사용하지 않는다.

 

const arr = [10, 20, 30];

for (let value of arr) {
  console.log(value);  // value는 배열의 각 값
}

 

 

*결과

10
20
30

of문 형태의 반복문 예시

 

 

 

3. v-bind ( html 태그의 기본 속성과 뷰 데이터 속성을 연결 )

 

- v-bind:속성명

- v-bind는 축약해서 : 로 사용할 수 있다.

- 단방향성 데이터 바인딩이다.

- vue 인스턴스 내부에 선언된 data의 속성값들을 변수처럼 이용하여 html 문서상의 문자열로 표현된 변수자리에 넣어준다.

- v-bind 뒤에는 HTML 속성명 또는 컴포넌트의 prop 이름을 사용한다.

- v-bind는 기본적으로 HTML 요소의 속성이나 **컴포넌트의 props**를 동적으로 바인딩하는 데 사용하지만
   v-bind는 HTML의 표준 속성뿐만 아니라, **Vue 컴포넌트에서 정의된 사용자 정의 속성(Props)**에도 사용할 수 있다.

ex. HTML 표준 속성 바인딩
vue에서 v-bind를 사용하여 HTML 요소의 속성을 동적으로 바인딩할 때, v-bind 뒤에는 HTML 속성명 (예: href, src, class, style 등)을 사용.

 

v-bind:속성명을 가져온 경우

 

 

ex. Vue 컴포넌트의 Props 바인딩
vue에서는 컴포넌트에 전달하는 props도 동적으로 바인딩할 수 있다. v-bind 뒤에 사용하는 이름은 컴포넌트의 props 이름이어야 한다.

 

:data-list-id의 경우, props의 이름으로 사용되었다.

 

 

 

4. v-on (화면 요소의 이벤트를 감지하여 처리할 때 사용.)

 

- v-on:이벤트명 = "함수호출문"

- v-on은 @을 축약어로 사용할 수 있다.

- 뷰 내부에서 키보드 또는 마우스를 이용하여 제어하는 형식의 이벤트를 표시해준다. 사용자에 의한 이벤트가 발생했을 때 

사용자와 브라우저간의 상호작용시 사용.

- 함수호출문은 vue 인스턴스내 methods에 저장된다.

 

@click 이벤트를 통해 함수를 호출

 

 

 

5.v-model (폼(form)에서 주로 사용되는 속성. 폼에 입력한 값을 뷰 인스턴스의 데이터와 즉시 동기화(양방향성)

)

 

- 어떤 입력값에 대한 내용을 실시간으로 표시하는 양방향 데이터를 구현할 수 있다.

- <input>, <select>, <textarea> 태그에만 사용가능

- 양방향성 데이터 바인딩이다.

 

inputTitle의 데이터 변화에 따른 input값의 변화 v-model의 양방향성 데이터 구현

 

inputTitle은 data내에 있다.

 

 

 

 

 

 

 

 

데이터를 가공하는 등의 복잡한 연산은 뷰 인스턴스 안에서 하고 html에는 최종적으로 데이터를 표현해야 한다. 

앞서 vuex를 통해 상태값을 가져와 담은 vue인스턴스의 속성에는 computed가 있었다. 

computed와 watch 속성에 대해서 알아보자.

 

 

1. computed 

 

- 데이터 연산들을 정의하는 영역이다.

- data 속성 값의 변화에 따라 자동으로 다시 연산한다. computed 속성에서 사용하고 있는 data속성 값이 변경되면 전체값을 다시 한 번 계산한다

- 캐싱이 가능하다 = 동일한 연산을 반복해서 하지 않기 위해 연산의 결과 값을 미리 저장하고 있다가 필요할 때 불러오는 동작

 

vuex를 통해 mapState를 호출 한 뒤 board, inShowBoardSettings 값을 연산

 

이 경우,  board의 데이터 값에 변화가 있을 시 자동으로 computed는 board값을 다시 계산한다. 이것은 html내 board.title의 변화에도 영향을 주게 된다.

 

 

여기서 캐싱이란?

computed 속성은 값이 변경되지 않는 한, 다시 계산하지 않도록 자동으로 캐싱된다. 즉, computed 속성은 처음 계산된 후 그 값을 메모리에 저장하고, 그 값에 의존하는 데이터가 변경되지 않는 한 다시 계산하지 않는다.

 

 

캐싱을 알기 위해선 computed와 methods의 차이를 알 필요가 있다.

methods의 속성은 호출할 때만 해당 로직이 수행되고, computed 속성은 대상 데이터의 값이 변경되면 자동적으로 수행된다. 

한마디로 methods 는 수동적으로 데이터를 갱신, computed는 능동적으로 데이터를 갱신한다.

 

methods의 경우, 어떠한 이벤트로 인해 발생하는 함수문을 주로 담고 있다. 

 

메서드내의 함수문들 -> 클릭이벤트를 통해서 이벤트를 호출하는 경우의 예시 또는 하나의 함수를 여러 번 사용하게 되는 경우의 예시

 

 

캐싱면에서 두 속성을 보면 methods 속성은 수행할 때마다 연산을 하기 때문에 별도로 캐싱을 하지 않지만, computed 속성은 데이터가 변경되지 않는 한 이전의 계산 값을 가지고 있다가(캐싱하고 있다가) 필요할 때 바로 반환해준다.

이는 복잡한 연산을 반복해서 수행해야하는 경우, 성능을 최적화하고 불필요한 계산을 방지할 수 있다. 

 

board, isShowBoardSettins 의 값을 가지고 있다가 데이터의 변경이 일어나면 자동으로 데이터 변경을 수행해준다.

 

 

 

 

 

2. watch (비동기 데이터 처리)

 

- 데이터 변화를 감지하여 자동으로 특정 로직을 수행.

- computed와 유사하지만 computed의 경우 내장 api를 활용한 간단한 연산 정도로 적합(vuex)한 반면, watch 속성은 데이터 호출과 같이 시간이 상대적으로 더 많이 소모되는 비동기 처리에 적합

- 지속적인 상태 추적: watch는 특정 데이터가 변경될 때마다 반응하므로, 상태 변화를 지속적으로 추적하면서 필요한 작업을 실행.

- 폼 유효성 검사, 배열/객체 변화 처리, 비동기 요청이나 API 호출 등 외부 데이터를 처리할 때 매우 유용

-> 폼 입력이나 사용자 입력을 추적하는데 유용

예를 들어, 사용자가 입력할 때마다 유효성 검사를 하고, 결과를 실시간으로 반영.

(사용자가 입력할 때마다 서버에서 데이터를 받아오는 경우 -> 입력값이 바뀔 때마다 이를 처리할 수 있음)

 

* 비동기 처리 로직이란?

웹,앱에서 데이터를 호출할 때 일반적으로 서버에 http 요청을 보낸다. 그러나 자바스크립트 코드가 실행되는 시점에서 서버에 보낸 요청이 

언제 응답이 올 지는 알 수 없으므로 다른 자바스크립트 연산에 영향을 주지 못하도록 별도의 영역(실행 컨택스트)에서 해당 데이터를 요청하고 응답을 기다리는 것을 자바스크립트 비동기 처리 로직이라고 한다.

 

input 값 -> 데이터 양방향성 v-model 속성

 

input값이 있을 경우, input이 노출이 되도록 watch 속성에 input 관련 비동기 로직을 추가

 

 

여기서 주의할 점은

watch**는 **data()**에서 정의된 변수의 변화를 감지한다는 것.

v-model="input"**에서의 **input**은 data() 내의 input 속성과 연결되어야만 watch에서 이 값을 감지할 수 있다.

다만, watch의 key는 data()의 속성 이름과 일치해야한다.

 

 

data()내의 input 변수의 변화를 실시간으로 watch()에서 감지한다.

 

 

 

왜그런걸까?

v-model="input" 은 data.input 과 양방향 바인딩을 설정하는 것. 즉, 템플릿의 input 필드와 data.input 값이 연결되어 실시간으로 값이 갱신된다.

watch 는 data의 속성에 대해 변화를 감지한다. v-model로 바인딩한 값이 data()의 input 속성에 저장되기 때문에, watch는 그 속성의 변화를 감지하는 것.

 

* 만약 data()에 input 속성이 없다면?

v-model="input"이 data.input과 연결될 수 없으므로, watch는 아무런 값을 감지하지 못한다.

즉, watch가 동작하지 않거나 값이 **undefined**로 처리될 수 있다.

watch는 data()에 정의된 속성만 감지한다. 따라서  v-model="input" 을 사용하려면 data()에 input 속성을 반드시 정의해야 watch가 해당 값을 실시간으로 인지할 수 있다.

 

 

💡  watch와 computed 의 차이점

    computed 속성과 watch는 둘 다 상태 변화에 반응하지만, 캐싱이라는 측면에서 중요한 차이점이 있다.

  • computed: 자동 캐싱의존성 추적을 제공하여, 값이 변경되지 않으면 불필요한 재계산을 방지.
  • watch: 특정 데이터의 변화를 감지하여 작업을 수행. watch는 값이 변경될 때마다 무조건 실행되며, 캐싱을 제공하지 않는다.

 

✅  watch 속성에서도 computed 속성 추적이 가능할까? 

-> 가능하다

 

** computed()속성을 감시하는 watch의 예시

computed: {
    userInfo() { 
      return this.$__USER_INFO; //사용자 정보를 반환
    }
  },
  watch: { //computed()의 userInfo()를 감시
    userInfo(val) {
      console.log("사용자정보:", val); //로그인,로그아웃을 통한 사용자정보 변동을 감지
        // 로그인 여부 판단 >> 로그인시 특정 data의 flag에 변동
        if (val && Object.keys(val).length > 0) {
          this.loginFlag = true;
        } else {
          this.loginFlag = false;
        }
    }
  }

 

⚠️ 참고로 주의할 점

computed는 "계산된 값을 반환"하는 용도이므로 그 안에서 this.xxx =처럼 데이터를 직접 변경하는 것은 권장되지 않는다.

대신 mounted()나 watch() 등 다른 곳에서 값을 설정하고 computed는 "읽기 전용"처럼 사용해야 부작용이 없다.

 

+ 과정설명

1. computed()의 경우, 어떤 특정한 값을 반환하고 있다. (사용자정보관련)

2. watch()의 경우, computed()의 값이 변경되는 경우 특정 data의 플래그를 true / false로 반환한다 (데이터변경)

 

computed는 자동 캐싱과 의존성 추적을 제공하여, 값이 변경되지 않으면 불필요한 재계산을 방지한다. 

로그인과 로그아웃을 통해 값이 변경되는 경우 재계산이 이루어진다 -> 재계산이 이루어지면서 computed속성을 감시하고

있는 watch에도 값의 변경이 추적되면서 특정 flag의 동작처리를 이루어낸다.

 

 

 

 watch()속성이 데이터명을 함수명으로 그대로 가져다 쓴다면 computed()도 가능할까?

- 예시

  • data() { return { input: '' } } 와 같은 형태로 input이라는 데이터를 사용 중
  • 이 input 값의 변경을 감지해서 다른 작업을 하고 싶을 때
  • computed 속성에 input()이란 이름으로 사용해도 될까?

= 불가능하다

 

다시 정리하면:
 
구분 역할 함수명 예시 주의사항
data 상태를 저장하는 곳 input data() { return { input: '' } }
watch 특정 데이터의 변경을 감지해서 로직 실행 input watch: { input(newVal) { ... } } ✅ 이름 같아야 함
computed 데이터를 가공하거나 계산된 값을 반환 input ❌, processedInput ✅ computed: { processedInput() { return this.input + '님'; } } ⚠️ data의 input과 이름이 겹치면 computed는 무시됨

 

📝 요약

목적 사용방식 함수명 가능 여부
계산된 값 반환 (읽기용) computed input() ❌ (이름 충돌)
값 변경 감시 (반응형 처리) watch input() ✅ (watch에서만)

✅ 추천

  • 값을 처리하거나 가공해서 보여줄 목적이면 computed + 다른 이름 (processedInput, formattedInput 등)
  • 값을 감시하고 부수 효과(side effect)를 줄 목적이면 watch: { input() {} } 사용

 

 

관련글 더보기