Thief of Wealth
article thumbnail

우테코 내에서 하고있는 일이 있어서, 간단한 미션을 구현할 일이 생겼다.

아마 커밋링크를 올렸다가 추후에 문제가 있을 수 있기 때문에 적당한 코드들만 직접 첨부하겠다.

 

우테코 레벨1처럼 순수하게 바닐라 자바스크립트로만 작성을 해야했는데, 갑자기 예전에 다른 크루가 공유해준 유투브가 생각났다.

https://www.youtube.com/watch?v=RtvSgptpfnY&ab_channel=%EC%BD%94%EB%94%A9%EC%95%A0%ED%94%8C 

 

 

보면 재밌다.

그 유명한 깃허브가 react 같은거 없이 작성되어있다니!

(설마, 가끔씩 comment가 2번 등록되거나 하는 버그들이 그것때문이려나? 라는 생각도 들었다.)

 

깃허브는 자바스크립트에서 기본적으로 제공해주는 WebComponent라는 것을 사용하고 있다고 한다.

자바스크립트가 이렇게 기본적으로 제공해줄줄 알았으면, 레벨1때 적용해보는건데 ㅜㅜㅜㅜ

 

그래서! 이번에 슥ㅡ삭 구현해보았다.

할일이 많지만 새로운 지식을 빨리 흡수하고 싶었다.

 

일단 WebComponent는 class형으로 작성되어야하므로, 바로 상속받을 수 있게 틀을 만들었다.

이 중에는 내 멋대로 추가한 녀석들도 있다.

 

export class Component extends HTMLElement {
  // 고유의 태그이름이 필요함
  // static get componentNameWithHyphen() {
  //   return "default-component";
  // }

  constructor() {
    // 초기값을 셋팅합니다.
    super();
  }

  connectedCallback() {
    // 엘리먼트가 생성될때 실행됩니다.

    this.render();
  }

  clear() {
    this.innerHTML = "";
  }

  adoptCallback() {
    // 해당 요소가 새로운 문서로 이동될때 실행됩니다.
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    // observedAttributes에 등록된 요소의 속성이 추가, 제거, 업데이트, 교체되는 부분을 관찰하고 호출된다.
  }

  static get observedAttributes() {
    //attributeChangedCallback 에서 관찰하는 항목을 리턴한다.
    // return ["title"];
  }

  //   get title() {
  //     return this.getAttribute("title");
  //   }

  disconnectedCallback() {
    // custom element 가 제거될때 호출된다.
    // alert("bye bye");
  }

  // custom method
  render() {
    // this.innerHTML = ` <h1>${this.title}</h1> `;
  }
}


// 초기화 해주어야함. index.js
// [Component1, Component2].forEach((customComponent) => {
//   if (!window.customElements.get(customComponent.componentNameWithHyphen)) {
//     window.customElements.define(
//       customComponent.componentNameWithHyphen,
//       customComponent
//     );
//   }
// });

이렇게 많은 기능들을 그냥 제공해준다.

mount될때와 unmount될때와 render와 속성이 변경되었을때와... 모든 것을 그냥 기본적으로 제공해준다.

이제야 안것이 매우 안타깝다. 레벨1때 알았으면 유레카를 외쳤을텐데...

내년 기수들한테 알려줘야겠다.

그리고 나도 잘외워뒀다가 취업 과제전형때 써먹어야지 ㅎㅎ

 

아무튼 이렇게 작성하면, html가 다음과 같이 생성된다.

무조건 -(하이픈)이 있어야된다는게 단점 아닌 단점이지만, 커스텀 태그를 내맘대로 이름을 붙여서 쓸 수 있으니, styled-component느낌도 났다.

 

커스텀 엘리먼트를 생성할 수 있다.

 

 

여기에 재사용가능한 옵저버패턴의 Store를 구현해서 전역 상태관리가 되도록 하였다.

export class Store {
  #state = {};
  #listeners = [];

  constructor(initialState) {
    this.initialState = initialState;
    this.#listeners = [];
    this.#state = initialState;
  }

  notify() {
    this.#listeners.forEach((func) => func());
  }

  subscribe(func) {
    this.#listeners.push(func);
  }

  resetState() {
    this.setState(JSON.parse(JSON.stringify(this.initialState)));
  }

  get state() {
    return JSON.parse(JSON.stringify(this.#state));
  }

  set state(newState) {
    this.#state = newState;
  }

  setState(newState) {
    if (newState) {
      this.#state = newState;
      this.notify();
    }
  }
}

 

코드를 모두 보여줄수는 없지만 webcomponent와 store를 사용하니 바닐라 자바스크립트로도, 상대적으로 특정기능을 깔끔하게 구현하고 보기에도 좋은 디렉토리 구조가 완성될 수 있었다.

 

어쩌면, 나중에 react가 퇴화될때 webcomponent가 대세가 될 수도 있지 않을까? 라는 생각도 했지만

 

단점도 있기때문에 아직 확실치 않다.

내가 사용하면서 느낀 단점은, window객체에 해당 tag를 define하는 과정이 필요한데,

그 말은 전역에서 같은 이름의 태그를 한번만 쓸 수 있다는 것이다.

만약 app이 복잡해진다면, 워우... 태그 이름관리가 엄청 힘들어질것같다.

일단 그렇게 큰 프로젝트는 아니었으니 다행이다.

 

 

profile on loading

Loading...