호이스팅, 클로저, 렉시컬 환경, 실행 컨텍스트, 가상 DOM

Judo·2021년 7월 10일
0

헷갈린 개념들에 대해 다시 정리한 내용입니다.

호이스팅(Hoisting)

개념

  • 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것

대상

  • var 변수 선언과 함수 선언문
  • let/const 변수 선언과 함수 표현식은 대상🚫

var와 let/const 사이의 차이가 발생하는 이유

  • 이유를 알기 위해 변수가 메모리에 저장될 때 과정을 이해해야 한다.
    변수가 메모리에 저장되는 과정 (3단계)
    1. 선언 단계: 실행 컨텍스트 변수 객체에 등록
    2. 초기화 단계: 변수 객체에 대한 메모리 할당 및 변수를 undefined로 초기화
    3. 할당 단계: undefined로 초기화 된 변수에 값 할당
  • 위 3단계 과정에서 var와 const/let 사이에 차이가 발생하는데 var는 1,2단계가 동시에 진행되면서 호이스팅이 되고, const/let은 1,2단계가 분리되어 진행되므로 1단계만 진행되면서 호이스팅이 된다. 호이스팅이 된 시점을 봐보면 var의 경우 변수에 undefined가 할당되어 있는 상태고, const/let은 undefined로 초기화되지 않았으므로 ReferenceError가 발생한다.

클로저

개념

  • 함수와 렉시컬 환경의 혼합 개념으로, 자식 스코프가 부모 스코프의 변수 환경의 정보를 기억하고 이에 접근할 수 있는 것.

이점

  • 메모리 효율성

    // Bad
    function makeBigArray(index) {
    	const bigArray = new Array(10000).fill(true);
    	return bigArray[index];
    }
    makeBigArray(500);
    makeBigArray(500);
    makeBigArray(500);
    
    // Good
    function makeBigArray() {
    	const bigArray = new Array(10000).fill(true);
    	return function(index) {
        return bigArray[index];
    		// 내부 함수는 선언 당시 렉시컬 환경을 기억하기 때문에 bigArray를 기억한다.
    	}
    }
    const test = makeBigArray();
    test(500); // test가 여러번 실행되어도 bigArray 배열은 한번만 만들어짐.
    • 내부적으로 리턴되는 함수의 경우 함수가 선언되었을 당시의 렉시컬 환경을 기억하기 때문에 bigArray배열은 한번만 만들어진다.
  • 은닉화

렉시컬 환경

개념

  • 특정 코드가 작성, 선언된 환경. 쉽게 말해, 실행 컨텍스트의 부모 스코프와 비슷하다.

알아야 하는 이유

  • 변수나 함수는 어떤 렉시컬 환경에 속해있는지에 따라 값이 달라지는데 렉시컬 환경을 이해한다면, 즉 어디에서 선언됐는지를 파악한다면 해당 변수, 함수의 값을 정확히 알 수 있게 된다.
function makeYourName(lastName) {
	const firstName = "coding";
	return firstName + lastName;
}
  • 위 코드에선 1개의 글로벌 실행 컨텍스트와 1개의 개별 실행 컨텍스트가 존재한다.

    여기서 변수, 함수의 렉시컬 환경을 찾아보자.

    makeYourName 함수의 렉시컬 환경은 global

    firstName 변수의 렉시컬 환경은 makeYourName함수다.

실행 컨텍스트

개념

  • 자바스크립트 엔진이 코드 실행 전 변수와 함수의 유효 범위들을 설정하는데 이 범위를 뜻한다

구성

  • Global 객체, this, Outer Environment, Code가 존재한다.
  • 하나의 자바스크립트 파일 내에서 선언된 변수, 함수 등은 글로벌 실행 컨텍스트 내부에 존재하는 global 객체의 Property가 된다.

흐름

  • 자바스크립트 엔진이 함수의 실행을 만나면 함수 실행 컨텍스트가 생성되고, 해당 함수 실행 컨텍스트가 실행 컨텍스트 스택에 푸쉬가 된 뒤 해당 함수가 실행되는 흐름을 갖고 있습니다.
    함수 호출 -> 함수 실행 컨텍스트 생성 => 실행 컨텍스트 스택(콜 스택)에 푸쉬 => 함수 실행
  • 위 흐름이 발생할 때 실행 컨텍스트의 모습은 아래와 같습니다.
const foo = () => {};
const bar = () => {};

foo();
bar();

![https://velog.velcdn.com/images%2Fjing07161%2Fpost%2Fa8572ce5-ed77-4f98-b8ee-a62158c872b6%2FIMG_0012.jpg%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Fjing07161%2Fpost%2Fa8572ce5-ed77-4f98-b8ee-a62158c872b6%2FIMG_0012.jpg)

자바스크립트 엔진은 위와 같은 실행 컨텍스트 스택을 단 하나만 갖는데 이를 싱글 스레드 방식으로 동작한다고 합니다.
싱글 스레드 방식은 단 하나의 태스크만 실행할 수 있기 때문에 블로킹이 발생합니다.

Virtual DOM? 썼을 때의 장점

개념

  • DOM을 추상화한 가상의 객체
  • 여기서 DOM은 HTML문서를 파싱하여 문서의 구성요소들을 객체로 구조화하여 나타낸 것
  • DOM => 추상화한 가상의 객체 => Virtual DOM

필요성

  • DOM 조작에 의한 렌더링이 비효율적인 문제
    • DOM을 직접 조작하게 되면 repaint, refloat가 계속 발생하기 때문에 비효율적
    • 실제론 Batched DOM Update 방식으로 DOM을 제어하는 메서드에 따라 배치로 작업할 수도 있음.
  • SPA 특징으로 DOM 복잡도 증가에 따른 최적화 및 유지보수가 어려워지는 문제

활용 방법 및 장점

  • DOM을 추상화한 가상의 객체를 메모리에 만들고 가상의 객체에 변화를 준다. Virtual DOM은 변경 내역을 한번에 모으고(버퍼링) 실제 DOM과 차이 비교를 한 뒤, 변경이 있는 부분만 찾아 변경하고 한번의 렌더링만 한다.
  • 위와 같이 직접 DOM을 조작하지 않기 때문에 비용 측면에서 효율적이다.

한계

  • Virtual DOM은 변경 내역을 한번에 모은다고 했는데 0.1초마다 화면에 데이터가 변경된다면 0.5초씩 변경 내역을 모아서 렌더링을 할 수 있을까? ⇒ 동시에 변경되는 것에 한해서 렌더링된다.
  • DOM과 비슷한 Virtual DOM가 메모리에 존재하기 때문에 메모리의 사용이 많이 늘어난다.
  • DOM을 직접 제어하는것에 비해 상대적으로 비용이 적게 들 , Virtual DOM의 조작이 늘어난다면 오버헤드가 생긴다.

출처

https://jeong-pro.tistory.com/210
https://mygumi.tistory.com/190
https://d2.naver.com/helloworld/59361
https://soldonii.tistory.com/100

profile
즐거운 코딩

0개의 댓글