Daily/원티드 프리온보딩 프론트엔드 과정

[원티드 프리온보딩 프론트엔드 인턴십 8기] Week 5-2(End)

호밀이 2023. 1. 20. 15:37

오늘은 원티드 프리온보딩 프론트엔드 인턴십의 마지막날이다. 처음엔 나에게 도움이 될까라는 생각을 많이했지만 현직자의 실시간 강의와 자료를 보며 내가 몰랐던 것에 대해서 많은 것을 알아가게 되었고, 내가 알고 있는 내용이 정확한 내용인지 정확하게 알 수 있었으며, 기업과제를 수행하고 팀원들의 코드를 보면서 Best Practice를 선별하며 다른 사람의 코드를 읽는 능력 또한 향상 되었다.

면접 준비를 하면서 가장 많이 보았던 실행 컨텍스트와 클로저에 대해서 강의를 진행해주셨다.

 

📝 강의내용

스코프와 this, 호이스팅, 클로저의 공통점

모두 실행 컨텍스트라는 개념에 근간을 두고 있다.

 

실행 컨텍스트?

JavaScript가 실행되는 환경을 정의한다. this, 변수, 객체, 함수 등 코드의 실행에 필요한 기반을 환경이라 의미한다.

코드를 실행하는데 필요한 환경을 제공하고, 관리한다.

식별자, 스코프, this 등은 실행 컨텍스트의 렉시컬 환경을 기반으로 관리된다.

코드의 실행 순서는 콜스택(실행 컨텍스트 스택)을 통해서 관리된다.

 

실행 컨텍스트의 종류

  • Global Execution Context: 처음으로 JavaScript 코드가 실행될 때 생성되는 실행 컨텍스트이다. 전역에서 관리되는 값들을 관리한다.
  • Funcution Execution Context: 함수가 호출될 때 마다 생성되는 실행 컨테스트이다. 
  • Eval Execution Context: eval 함수로 실행한 코드의 컨텍스트이며, 보안상의 이슈로 권장되지 않고 사용하지 않는다.
  • Module Execution Context

실행 컨텍스트 스택(콜스택)

스택은 LIFO(Last In, First Out)의 특징을 가징 자료구조이다.

JavaScript는 스택에 실행 컨텍스트를 순차적으로 추가하고 제거하면서 코드의 순서를 관리하면서 실행한다.

 

클로저

공식문서: 함수와 함수가 선언된 어휘적 환경의 조합이다.

클로저는 자신이 생성될 때의 환경을 기억하고, 그를 사용하는 함수이다.

함수를 일급객체로 사용하는 모든 언어에서 사용되는 특성도 있다.

function makeAddNumFunc(num) {
  const toAdd = num

  return function (num) {
    return num + toAdd
  }
}

const add5 = makeAddNumFunc(5)

add5(3) // 8
add5(8) // 13
add5(15) // 20

 

클로저의 원리

본인이 생성될 때의 환경을 기억하고, 본인이 호출될 때 그 환경에 있는 변수들을 참조할 수 있게된다.

 

클로저의 활용 예시

  • 상태 기억
  • 상태 은닉
  • 상태 공유

React에서 클로저의 실제 활용

React에서 사용하는 useState, useEffect 등 함수 컴포넌트에서 사용하는 모든 Hook들은 클로저를 기반으로 동작하고 있다.

  const useState = (initialValue) => {
    const state = hooks[hookIndex] || initialValue;
    hooks[hookIndex] = state;

    const setState = (function () {
      const currentHookIndex = hookIndex;

      return (value) => {
        hooks[currentHookIndex] = value;
        hookIndex = 0;
        render();
      };
    })();

    increaseIndex();
    return [state, setState];
  };

  const useEffect = (effect, deps) => {
    const prevDeps = hooks[hookIndex];

    const hasChanged = isFirstCall(prevDeps) || isDepsChanged(prevDeps, deps);

    if (hasChanged) {
      effect();
    }

    hooks[hookIndex] = deps;
    increaseIndex();
  };