실행 컨텍스트와 Javascript 성능

Photo by Fredy Jacob on Unsplash

실행 컨텍스트와 Javascript 성능

실행 컨텍스트가 성능에 영향을 미치는 케이스 정리

·

3 min read

실행 컨텍스트가 성능에 영향을 미칠 수 있는 부분을 정리해보고 싶어 글을 쓰게 됐습니다. 먼저 실행 컨텍스트가 무엇이고 어떤 구조인지 알아보겠습니다.

자바스크립트의 실행 컨텍스트(execution context)는 코드가 실행되기 위한 환경이나 상태를 말합니다. 내부에는 스코프, 변수, 객체, this값 등의 코드 실해에 필요한 정보들을 갖고 있습니다.

그리고 자바스크립트 엔진은 이 실행 컨텍스트를 관리하기 위해 실행 컨텍스트 스택(execution context stack), 호출 스택(call stack)이라는 구조를 사용합니다. 이 구조를 이용하여 자바스크립트 코드 실행 중 발생하는 모든 실행 컨텍스트를 추적할 수 있습니다.

메모리 사용

  • 실행 컨텍스트는 함수 호출마다 생성되며, 각 컨텍스트는 스코프 체인, 변수 객체, 함수 선언, this 바인딩 정보 등을 저장하는 데 필요한 메모리를 할당 받습니다. 함수 호출이 많아지면, 실행 컨텍스트 생성도 많아져 메모리 사용량이 증가하게 되며, 결국 어플리케이션 메모리 사용량에 영향을 미치게 됩니다.

  • 예시: 함수 호출로 인한 메모리 사용

      function heavyComputation(num) {
          const bigArray = new Array(10000).fill('😒');
          return num + bigArray.length;
      }
    
      for (let i = 0; i < 100; ++i) {
          console.log(heavyComputation(i));
      }
    
  • 이 예시에서 heavyComputation 함수는 큰 배열을 생성합니다. 함수가 반복적으로 호출될 때마다, 큰 메모리 할당이 발생하며, 이는 전체 메모리 사용량을 증가 시킵니다.

클로저의 영향

  • 클로저는 실행 컨텍스트와 직접적인 관련이 있습니다. 클로저는 외부 함수의 실행 컨텍스트에 대한 참조를 유지하기 때문에, 해당 컨텍스트는 클로저가 존재하는 한 가비지 컬렉션(=메모리 정리)될 수 없습니다.

  • 예시: 클로저와 메모리 누수

      function createClosure() {
          const largeObj = new Array(10000).fill('🔨');
          return function() {
              return largeObj.length;
          }
      }
    
      const closures = [];
      for (let i = 0; i < 100; ++i) {
          closures.push(createClosure());
      }
    
  • 이 예시에서 createClosure 함수는 큰 배열을 포함하는 클로저를 생성하고 반환합니다. 이 배열은 클로저가 존재하는 한 메모리에서 제거되지 않습니다. 많은 수의 클로저를 생성하면, 이 배열들이 메모리에 계속 남아있어 메모리 사용량이 증가합니다.

스코프 체인 검색

  • 변수나 함수를 찾기 위해 스코프 체인을 검색하는 과정도 성능에 영향을 줄 수 있습니다. 이 검색 과정은 필요한 정보를 찾기 위해 여러 실행 컨텍스트의 스코프를 거쳐야 할 가능성이 있으며, 이는 성능에 부담이 될 수 있습니다. 특히 긴 스코프 체인은 변수 접근 시간을 증가 시킬 수 있습니다.

  • 예시: 스코프 체인 검색

      let globalVariable = 'global';
    
      function outer() {
          let outerVariable = 'outer';
          function inner() {
              let innerVariable = 'inner';
    
              console.log(innerVariable); // 가장 가까운 스코프. 빠름
              console.log(outerVariable); // 바로 바깥 스코프, 조금 느림
              console.log(globalVariable); // 전역 스코프, 가장 느림
          }
    
          inner();
      }
    
      outer();
    
  • 이 예시는 스코프 체인 검색 과정을 보여줍니다. inner 함수에서 세 가지 변수에 접근할 때, 자바스크립트 엔진은 현재 스코프에서 시작하여 필요한 변수를 찾을 때까지 바깥 스코프로 이동합니다. 이 과정은 특히 긴 스코프 체인이 있을 때 성능에 영향을 미칠 수 있습니다.

성능 개선을 위한 팁

  • 필요없는 변수는 적극적으로 해제: 사용이 끝난 변수는 null 이나 적절한 값으로 초기화해서 GC(가비지 컬렉션) 대상이 되도록 해줍니다.

  • 전역 변수 사용 최소화: 가능한 지역 변수를 사용하고, 필요한 경우만 전역 변수를 사용합니다.

  • 함수 길이 단축 및 재사용성 높이기: 너무 많은 작업을 수행하는 대형 함수를 쓰면 각 함수의 실행 컨텍스트 생성과 관리 비용을 줄일 수 있습니다.

마치며

  • 간단하게 실행 컨텍스트가 무엇이고, 성능에 영향을 미치는 부분은 메모리 사용량, 클로저의 활용, 스코프 체인을 통해 변수등에 접근하는 경우가 있다는 것, 그리고 성능 개선을 위한 팁을 정리해봤습니다.

  • 만약 내용을 모르셨던 분이라면 위 내용을 읽으며 성능이 많이 느려졌을 때 실행 컨텍스트 관점에서 성능을 개선 시킬 수 있는 관점을 고려해볼 수 있게 되신다면 좋겠습니다.