[TIL] 자바스크립트 실행 컨텍스트와 웹 컴포넌트

샤이니·2023년 4월 17일
0

learned.log

목록 보기
25/46

오늘의 나는 무엇을 잘했을까?

  1. Week4의 컴포넌트들을 제작해서 적용했다. 로직이 아직은 하드하지만 조금더 재사용성이 좋고, 은닉을 하는 코드로 변경 예정이다. (새벽 코딩 나이스..🙌)
  2. 이젠 css grid랑 flex 등 레이아웃 사용을 아주 자유자재로 할 수 있다. 잘 정리된 개념과 활용을 해보면서 완전히 내것으로 만들었다.

오늘의 나는 무엇을 배웠을까?

[1] 웹컴포넌트

: 사용자가 정의할 수 있고, 재사용가능하고, 캡슐화 가능한 HTML 태그를 생성할 수 있는 웹 플랫폼 API

  • Custom elements: 사용자 인터페이스에서 원하는대로 사용할 수있는 사용자 정의 요소 및 해당 동작을 정의 할 수있는 JavaScript API 세트
    • jsx 처럼 <app-drawer/> 과 같이 사용할 수 없다.
  • Shadow DOM: 캡슐화된 "그림자" DOM 트리를 엘리먼트(메인 다큐먼트 DOM 으로부터 독립적으로 렌더링 되는)를 추가하고 연관된 기능을 제어하기 위한 JavaScript API 의 집합. 이 방법으로 엘리먼트의 기능을 프라이빗하게 유지할 수 있어, 다큐먼트의 다른 부분과의 충돌에 대한 걱정 없이 스크립트와 스타일을 작성할 수 있다.
  • HTML 템플릿[<template>](https://developer.mozilla.org/ko/docs/Web/HTML/Element/template) 과 [<slot>](https://developer.mozilla.org/ko/docs/Web/HTML/Element/slot) 엘리먼트는 렌더링된 페이지에 나타나지 않는 마크업 템플릿을 작성할 수 있게 해준다. 그 후, 커스텀 엘리먼트의 구조를 기반으로 여러번 재사용할 수 있다.

생명주기에 대해..

  1. constructor
    • instance 가 생성될 때 호출
    • 사용예시
      • 상태를 초기화할 때
      • 해당 customElement 를 shadow dom 으로 설정할 때
  2. connectedCallback
    • 요소가 DOM에 삽입될 때마다 호출
    • 리액트의 componentDidMount 와 유사함
    • 사용예시
      • fetch 등으로 외부 resource 가져오기
  3. disconnectedCallback
    • DOM에서 요소가 제거될 때마다 호출
    • 사용예시
      • connectedCallback 에서 설정한 타이머나 subscribe 등을 해제할 때
  4. attributeChangedCallback
    • 인자로 넘긴 속성이 변경되었을 때 호출
    • 사용예시
      • app-drawer 의 open 속성을 예로들면 기본값을 false 로 설정한 다음 open 속성이 true 로 변경되었을 때 css 를 변경시킨다던지 하면 좋을 것 같음
  5. adoptedCallback
    • customElement 가 새 요소로 이동되었을 때

생명주기에 넣은 함수들은 동기적으로 작동한다.

예를들어  el.setAttribute() 요소를 호출하면 브라우저는 즉시 attributeChangedCallback()을 호출된다.

disconnectedCallback()도 마찬가지로, el.remove() 을 사용해 요소가 DOM에서 제거된 직후 호출된다.

render() 함수를 따로 생성해서 connectedCallback, attributeChangedCallback()에서 사용해주면 편리하다.

[2] 자바스크립트 실행 컨텍스트

: 실행할 코드에 제공할 환경 정보들을 모아놓은 객체로 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념입니다.

자바스크립트는 실행 컨텍스트가 활성화되는 시점에 다음과 같은 현상이 발생합니다

  1. 호이스팅이 발생합니다. (선언된 변수를 위로 끌어 올립니다)
  2. 외부 환경 정보를 구성합니다.
  3. this 값을 설정합니다.

동일한 환경이 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트로 구성하고, 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련된 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장합니다.

  • 여기서 동일한 환경은 하나의 실행 컨텍스트가 구성할 수 있는 방법입니다. 대체적으로 함수를 실행하면 실행 컨텍스트를 구성할 수 있습니다.
    • 전역공간, eval() 함수, 함수 등이 있습니다.
var a = 1; // 전역 컨텍스트 
function outer () { 
  function inner () {
    console.log(a); // undefined
    var a = 3;
  }
  inner();  // ②
  console.log(a); // 1
}
outer(); // ③
console.log(a); // 1
  • ① 처음 자바스크립트 코드를 실행하는 순간 전역 컨텍스트가 콜스택에 담깁니다. 콜스택에 전역 컨텍스트 외 다른 덩어리가 없기 때문에 전역 컨텍스트와 관련된 코드들을 순차로 진행하다가
  • ③에서 outer 함수를 호출하면 js 엔진은 outer에 대한 환경 정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜스택에 담습니다.
  • 콜스택 맨 위에 outer 실행 컨텍스트가 놓인 상태가 되었으므로 전역 컨텍스트와 관련된 코드의 실행을 일시 중단하고 대신 outer실행 컨텍스트와 관련된 코드(outer 함수 내부)들을 순차로 실행합니다.
  • 다시 ②에서 innter 함수의 실행 컨텍스트가 콜스택의 가장 위에 담기면 outer 컨텍스트와 관련된 코드의 실행을 중단하고 inner 함수 내부의 코드를 순서대로 진행합니다.
  • inner 함수 내에서 a 변수에 값 3을 할당하고 나면 inner 함수의 실행이 종료되면서 inner 실행 컨텍스트가 콜스택에서 제거됩니다.
  • 중단되었던 outer 컨텍스트와 관련된 코드의 실행을 이어가고,console.log(a)를 하고나면 outer 컨텍스트도 콜스택에서 제거됩니다.
  • 중단 되었던 전역 컨텍스트와 관련된 코드의 실행을 이어가고 console.log(a)를 출력하고나면 전역공간에는 더는 실행할 코드가 남아있지 않아 전역 컨텍스트가 제거되고, 콜스택에는 아무것도 남지 않은 상태로 종료!

이렇게 어떤 실행 컨텍스트가 활성화될 때 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데 필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장합니다.

  • 이 객체는 자바스크립트 엔진이 활용할 목적으로 생성되며 개발자는 확인 X
  • 다음의 3가지 정보들이 담깁니다.
    • VariableEnvironment
      • 현재 컨텍스트 내의 식별자(변수)들에 대한 정보 및 외부 환경 정보
      • 선언 시점의 LexicalEnvironment의 스냅샷(변경사항 반영 X)
    • LexicalEnvironment
      • 처음에는 VariableEnvironment와 같음
      • 변경 사항이 실시간으로 반영됨
    • ThisBinding
      • 식별자가 바라봐야 할 대상 객체

실행 컨텍스트를 생성할 때는 VariableEnvironmentLexicalEnvironment가 동일한 내용으로 구성되지만, LexicalEnvironment는 함수 실행도중에 변경사항이 즉시 반영되고, VariableEnvironment는 초기상태를 유지합니다.

  • VariableEnvironmentLexicalEnvironment
    • environmentRecord- 매개변수명, 변수의 식별자, 선언한 함수의 함수명 등을 수집함

    • outerEnvironmentReference - 바로 직전 컨텍스트의 LexicalEnvironment 정보를 참조함

      로 구성되어있습니다.

호이스팅

호이스팅은 코드 해석을 좀 더 수월하게 하기 위해 environmentRecord의 수집 과정을 추상화한 개념으로, 실행 컨텍스트가 관여하는 코드 집단의 최상단으로 끌어올린다고 해석하는 것입니다.

변수 선언과 값 할당이 동시에 이뤄진 문장은 ‘선언부’만을 호이스팅하고, 할당과정은 원래 자리에 남아있게 되는데, 여기서 함수 선언문과 함수 표현식의 차이가 발생합니다!!

스코프

변수의 유효범위를 말합니다.

outerEnvironmentReference 는 해당 함수가 선언된 LexicalEnvironment를 참조합니다.

코드 상 어떤 변수에 접근하려 하면 현재 컨텍스트의 LexicalEnvironment를 탐색해서 발견되면 그 값을 반환하고, 발견하지 못할 경우 다시 outerEnvironmentReference 에 담긴 LexicalEnvironment를 참색하는 과정을 거칩니다.

  • 전역 컨텍스트의 LexicalEnvironment까지 탐색해도 해당 변수를 찾지 못하면 undefined를 반환합니다.

this

this에는 실행 컨텍스트를 활성화하는 당시에 지정된 this가 저장됩니다. 함수를 호출하는 방법에 따라 값이 달라지며 지정되지 않은 경우에는 전역 객체가 저장됩니다.

오늘의 나는 어떤 어려움이 있었을까?

  1. 웹 컨텍스트에서 observer가 변경되는 attirbute를 인식을 못하는 이슈

    • attributeChangedCallback을 사용해서 star를 toggle하는 기능을 구현하려고 했지만 setAttribute로 아무리 속성을 변경해도 적용이 안됐다.
    • 대략의 코드
    static get observedAttributes() {
        return ["isStarred"];
      }
    
    ...
    
    this.addEventListener("click", (event) => {
          event.stopPropagation();
          this.setAttribute("isStarred", !isStarred);
        });

    → 케니’s 조언 : 아마 Camel 형식이라 그렇지 않을까? HTML에서의 attribute는 다 소문자로 변경됨 (← OMG 확인이 필요하다😭😭)

내일의 나는 무엇을 해야할까?

  • Week4 gnb logged에 따른 요소 변경 구현
  • self code review

0개의 댓글