post-custom-banner

예시 코드를 실행할 때 콘솔에 출력될 값과 이유를 설명해주세요.

// 1번
let num = 1;

// 2번
setTimeout(() => {
  num = 2;
}, 0);

// 3번
num = 3;

// 4번
console.log(num);

내가 생각하는 정답은 (두구두구두구) 3이다. 그리고 실제로도 3이다.

console에 출력되는 값이 3인 이유는 다음과 같다. 실행 흐름을 설명하자면

  1. 먼저 num이라는 변수 선언과 동시에 1이 할당된다. (1번)
  2. setTimeout 함수의 콜백은 선언한 지연 시간만큼 실행이 지연된다. 따라서 내부 콜백은 0초 뒤에 실행이 되게 되는데, 문제는 프로미스 콜백, async 함수, setTimeout, setInterval 등의 비동기 함수들은 콜스택이 아니라 queue(이하 큐)에 저장된다는 것에 있다. 즉 지금 이 0초 실행 지연된 setTimeout의 콜백 이벤트는 큐에서 대기하게 되고, 이하의 전역 컨텍스트에 있는 다른 실행문들이 먼저 실행되게 된다. (2번, setTimeout 함수 자체는 실행된 상태이며 콜백이 대기중)
  3. 따라서 변수 num은 1에서 3으로 재할당 된다. (3번)
  4. 4번에서도 num은 여전히 3인 상태이므로 콘솔에는 3이 출력된다.
  5. 콜스택 내의 모든 실행이 종료된 것을 확인하면 큐에 있던 이벤트를 "순서대로" 실행한다. 이제 변수 num은 2다...

좀 더 세부적으로 말해보자면, 콜스택 내부에 쌓이는 실행문들은 전역 컨텍스트부터 시작해서 위->아래로 코드를 읽어가며 함수 등 다른 컨텍스트를 발견시 전역 컨텍스트를 무시하고!! 그 위에 새 컨텍스트를 쌓은 다음 컨텍스트 내부 일들을 수행하다가... 새로 쌓인 컨텍스트 내부의 일이 끝나면 그걸 pop하고 다시 전역 컨텍스트로 돌아가 순서대로 수행하고... 이런 형태인데, 결과적으로 가장 마지막에 종료되는 건 전역 컨텍스트다. 스택은 선입후출 형태이기 때문에... 이거 말로 설명하려니까 어렵다 ㅠ

큐는 콜스택에서 처리하던 이벤트 중에 비동기 이벤트가 있을 경우 해당 이벤트들이 대기하는 곳인데, 콜스택이 다 비어야지만 큐에 있는 이벤트가 실행된다. 콜스택과의 차이점은 선입선출이라는 점!!

그런데 큐에도 마이크로 큐가 있고 매크로 큐가 있다. 마이크로 큐는 Promise, async/await 이벤트들이 들어가고 매크로 큐는 전통적인 비동기 함수들(setTimeout..)의 콜백 이벤트가 들어가게 되는데, 마이크로 큐가 매크로 큐보다 더 빨리 실행된다. 즉 마이크로 큐가 다 비어야 매크로 큐가 실행된다.

결과적으로 setTimeout 함수같은 경우 내가 설정한 지연 시간을 보장할 수 없는 함수이다. 물론 최소한은 보장되겠지만, 딱 설정했던 지연 시간 만큼의 지연을 할 것이라는 보장이 없다. 더 긴 시간이 걸릴지도...

그렇기때문에 위 예시 코드에서 setTimeout에 설정한 지연시간은 0초로, 일반적으로는 바로 실행이 되어 변수 num이 1->2->3 순서로 할당 되어야겠으나, 실제로는 1->3->2 순서로 할당되는 것이다.

사실 이 문제에서 console에 출력되는 값이 무엇이냐는 질문은 무의미한것 같다. (아님 내가 문제 이해를 잘못한걸까?)

리액트에서 Virtual DOM이 무엇인지, 이를 사용하는 이유는 무엇인지 설명해 주세요.

Virtual DOM이란 일반 DOM의 경량된 자바스크립트 표현이라고 하는데, 이를 이해하려면 일반 DOM이 무엇인지에 대한 이해부터 필요하다.

DOM은 document object model의 줄임말로 HTML과 XML 문서에 접근하기 위해 웹 브라우저에 내장된 API라고 한다. 프로그램이나 스크립트가 웹 페이지 안의 구성 요소에 접근해서 내용이나 스타일을 변경할 수 있게 해준다. 즉, 동적인 페이지를 만들고자 할 때 필수적인 요소이자 개념이라고 할 수 있다. JS에서 DOM 요소에 접근한다고 할 때의 그 DOM이 바로 이 DOM이다.

DOM의 렌더링 방식은 아래와 같다.

  1. DOM 트리 구축을 위한 HTML 파싱
  • 브라우저가 HTML 파일을 받으면 렌더링 엔진이 HTML을 파싱한다.
  • DOM Node로 이루어진 트리를 만든다.
  1. 렌더 트리 구축
  • 렌더 트리는 외부 CSS 파일을 파싱해 스타일 정보를 돔 트리에 입힌 것이다.
  • 이 때 각 노드의 스타일, 위치 등이 계산된다.
  1. 렌더 트리 배치 및 페인팅
  • 계산된 렌더 트리의 모양대로 웹 페이지에 배치된다.
  • 정확한 위치에 표시된 노드들을 그리는 과정이다.
  1. 그리고 이렇게 생성된 페이지는 노드가 하나 변경될 때마다 전체 과정이 반복된다.

노드가 하나만 변경되어도 전체를 다시 렌더링하기 때문에, 성능과 속도가 떨어지고 리소스 소모가 많다는 단점이 있다.

React나 Vue.js같은 선언적 웹 프레임워크에서는 이런 단점을 극복하기 위해 virtual DOM(이하 가상 돔)을 도입했는데, 일반 돔은 브라우저가 화면을 그리는데에 필요한 모든 정보다 들어있는 반면 가상 돔은 구현에 필요한 부분만 복사한 경량 복사본이므로 상대적으로 가볍다.

리액트를 기준으로 설명했을 때, 가상 돔도 JSX 요소를 렌더링할 때 모든 가상 돔이 업데이트(렌더링)되는 것은 동일하지만 이때 렌더링 전의 가상 돔의 모습(스냅샷)과 후의 모습을 비교해서 변화가 발생한 부분만 캐치한 다음, 이것을 일반 돔에 전달한다.

일반 돔은 전달받은 대상만 다시 렌더링한다. 즉 일반 돔이 맡아서 해야했을 연산의 횟수가 줄어들게 된다.

state를 통해 각 컴포넌트의 상태를 관리하고 변화시키는 리액트는 동적인 처리가 필요한 경우가 많기 때문에, 이같은 처리를 대신 맡아줄 가상의 DOM을 사용하는 것이다. 이로 인해 변경 사항들을 효율적으로 처리할 수 있고, 속도 및 성능 면에서 장점을 가지고 있다고 할 수 있다.

개발자가 직접 DOM 노드를 신경 쓸 필요가 없어 단순하고 깔끔한 코드를 작성할 수 있다는 장점도 있는데 이건 아마 state를 통한 상태 관리 얘기인 것 같다..? JS로 DOM 요소의 상태를 관리하는 것보다는 훨씬 편리하게/짧은 코드로/직관적으로 관리할 수 있기 때문이다.

단, 동적인 페이지가 아닌 정적인 페이지라면 오히려 일반 돔을 사용하는 것이 효율적일 수 있다고 한다. 앞으로 웹페이지 유행 흐름이 어떻게 될지는 모르겠지만, 일단 지금은 인터랙티브 웹이 유행이니 가상 돔을 훨씬 많이 활용하게 될 것 같다!

profile
기어서라도 간ㄷ ㅏ.
post-custom-banner

0개의 댓글