[Vue] #4. Vue 내부 들여다보기

bien·2023년 7월 27일
0

vue

목록 보기
4/11

Vue의 반응성 소개

vue의 내부작업, 반응성

  • data에서 정의한 내용을 vue가 지속적으로 추적
  • vue는 이 data의 모든 프로퍼티를 전역 프로퍼티와 합쳐서 내부에서 관리하는 하나의 객체로 만든다.
    • 이때, 메서드도 해당 객체에 합쳐진다.
  • this가 해당 전역 객체를 가리키도록 한다.

Proxy

data에 대해 Vue가 하는 일 중 가장 핵심적인 작업
= data 객체를 반응형 data 객체로 바꾸는 일

🧐 반응성이 뭔데?
Vue가 data의 특정 값을 추적하고, 해당 값에 새로운 값이 할당될 때마다 이를 Vue가 인식하고 제어하는 HTML 코드를 스캔하고, 위치를 파악하여 사용자에게 노출되는 페이지를 업데이트 하는 것.

🧐 어떻게 그게 가능하지?
프로퍼티를 JavaScript의 Proxy로 래핑함으로써 가능하다!

일반 JavaScript 코드

  let message= 'Hello!';

  let longMessage = message + 'World!';

  console.log(longMessage);

  message = 'Hello!!!!';
  console.log(longMessage); // Hello! World! 출력

JavaScript는 반응형이 아니므로, 변수에 변경 사항이 생기더라도 변경 사항을 반영하지 않는다.

JavaScript 코드 + Proxy


  const data= { 
    message: 'Hello!',
    longMessage: 'Hello! World!'
  };
  
  const handler = {
    set(target, key, value) {
      if(key === 'message') {
        target.longMessage = value + 'World!';
      }
      target.message = value;
    }
  };
  
  const proxy = new Proxy(data, handler);
  
  proxy.message = 'Hello!!!!';
  
  console.log(proxy.longMessage); //Hello!!!! World!

Proxy로 data를 감싸, data의 변화에 따라 값이 변경하도록 코드를 구현했다.
이 코드를 통해 대략적으로 어떤 방식을 통해 Vue가 반응형을 구현했는지 알 수 있다. 이 같은 반응형 작업을 Vue가 내부적으로 수행하고 있는 것이다.
(실제로는 이 코드보다 훨씬 복잡한 연산 과정을 거친다.)


하나의 앱 vs 여러 앱

페이지당 하나의 앱이 아닌, 여러 앱을 만들 수도 있다.

  <header>
    <h1>Vue Behind The Scenes</h1>
  </header>
  <section id="app">
    <h2>How Vue Works</h2>
    <input type="text" @input="saveInput">
    <button @click="setText">Set Text</button>
    <p>{{ message }}</p>
  </section>
  <section id="app2">
    <p> {{ message }}</p>  // Dose Not Work!!!!
    <p> {{ Pazza }}</p>
  </section>
const app = Vue.createApp({
	data() {
    	return {
        	message: '안녕'
        }
    }
});
app.moount('#app');

const app2 = Vue.createApp({
	data() {
    	return {
        	food: 'Pizza'
        }
    }
});
app.moount('#app2');

이 때, 각각의 Vue 앱들은 독립적으로 움직인다. app에서는 Pizza 데이터 프로퍼티에 접근할 수 없고, app2는 message 데이터 프로퍼티에 접근할 수 없다. 이는 두 앱들 사이에 연결 고리가 없기 때문이다.

따라서, 독립적이지 않고 서로 연동 되어야 하는 경우 해당하는 부분은 모두 동일한 Vue 앱으로 작성되어야 한다!


Ref 활용하기

현재 코드의 구현 방식이 다음과 같다.

  <section id="app">
    <h2>How Vue Works</h2>
    <input type="text" @input="saveInput">
    <button @click="setText">Set Text</button>
    <p>{{ message }}</p>
  </section>
  
  data() {
    return {
      currentUserInput: '',
      message: 'Vue is great!',
    };
  },
  methods: {
    saveInput(event) {
      this.currentUserInput = event.target.value;
    },
    setText() {
      this.message = this.currentUserInput;
    },
  },

input 값을 가져와서 currentUserInput에 잠깐 넣어두고, 이후 message에 해당 문자를 삽입하는 방식이다. input 바인딩 대신에 v-model을 사용할 수도 있다.

Vue에는 필요할 때만 DOM 요소로부터 값을 가져오는 기능이 있다. 이 기능을 ref라고 부른다.

ref

	<h2>How Vue Works</h2>
    <input type="text" ref="userText">
    <button @click="setText">Set Text</button>
    <p>{{ message }}</p>
    
    methods: {
    saveInput(event) {
      this.currentUserInput = event.target.value;
    },
    setText() {
      this.message = this.$refs.userText.value // input 엑세스 획득
      console.log(this.$refs.userText)
    },
  },
  • Vue는 ref를 감시하고 이를 저장한다.
  • $: Vue가 지원하는 모든 프로퍼티는 $로 시작한다.(내장 프로퍼티임을 표현하기 위함)
  • 키-값 쌍으로 저장된다.(userText-입력값)
  • ref를 통해 input요소에 대한 엑세스를 획득하고, 메서드에서 이를 실행함으로써 필요할때만 기능을 수행하도록 만들었다. (이제 input에 값을 입력할때마다 실행되는것이 아니라, setText() 메서드가 실행될때에만 해당 값을 추적한다.)

Vue가 DOM을 업데이트 하는 방법

🧐 뷰는 어떤 방식으로 DOM을 업데이트하는걸까?

뷰는 화면 전체가 아니라 값이 달라진 일부만 부분적으로 수정한다. 어떻게 이런것이 가능할까? 뷰는 가상 DOM(Virtual DOM)으로 업데이트를 진행한다. 가상 DOM은 무엇이고, 왜 이 방식으로 업데이트를 진행하는걸까?

Virtual DOM

한쪽에는 개발자가 작업하는 Vue Instance가 있고, 그 끝부분에 최종적으로 웹사이트에 제공되는 BrowserDOM이 있다고 가장하자.

  • 브라우저 DOM은 Vue가 제어하는 템플릿을 DOM에 렌더링한다.
    • Stores data, computed, properties, method,... 등이 제거되며 실제 값이 출력된다.
    • ex) {{ message }} => <p>WoW!</p>
    • Vue에 대한 지시사항은 템플릿이 DOM에 렌더링되고 나면 Vue에 의해 삭제된다.
  • data, computed 프로퍼티 변경 시, 전체가 아닌 부분적으로 업데이트를 수행한다.

🧐 어떻게 이런 것들이 가능하지?

🤔 가설: 매번 이전의 DOM과 새로운 DOM을 비교해서 콘텐츠의 차이가 있으면 즉각적으로 업데이트하면 되지않을까?

이는 큰 성능저하를 야기하므로 실제로는 이렇게 진행하지 않는다.

대신, 가상 DOM이란 개념을 사용한다.

VirtualDOM

  • 실제 DOM의 가상 복사본
  • 전적으로 JavaScript가 관리하는 JS기반 DOM이며 메모리에 위치한다.
  • JavaScript 객체의 집합으로 Vue는 여기서 어떤 HTML 태그가 필요하며 해당 태그의 콘텐츠가 무엇인지를 기억한다.
    • in Vue Instance) title: 'Hello!', text:'Not the title'
    • Virtual DOM) {el:'h2', child:'Hello!}, ...
    • in 브라우저 DOM) <h2>Hello!</h2> <p>Not the title</p>
  • 데이터의 업데이트 발생 시 새로운 가상 DOM을 생성해 새로운 가상 DOM과 기존 가상 DOM을 비교한다.
    • 이후, 실제 두 가상 DOM 간 차이점만 실제 DOM에 쓰인다.
    • 이는 비교 및 업데이트 작업을 전적으로 메모리에서 수행하므로 실제 DOM에서 해당 작업을 수행하는 것 보다 훨씬 효율적이다.

📋 정리해보자, 화면에서 변화가 발생할때, Vue의 내부에는 무슨 일이 벌어질까?

  1. Vue가 반응성(proxy, ...)을 통해 변화를 발견한다.
  2. 새로운 가상 DOM을 생성해 이를 기존 가상 DOM과 비교한다.
  3. 변화 감지 후 해당 부분을 변화가 감지된 실제 DOM에 업데이트 한다.

Vue 앱 생명 주기 - 이론


Vue 앱 생명 주기 - 실습


Reference

Udemy:【한글자막】 Vue - 완벽 가이드 (Router 및 Composition API 포함)

profile
Good Luck!

1개의 댓글

comment-user-thumbnail
2023년 7월 27일

정보 감사합니다.

답글 달기