DEV

Web-component

웹컴포넌트에 대하여

2022-12-01

Web Component ?

웹 컴포넌트는 웹 표준 기반의 재사용 가능한 클라이언트 사이드 컴포넌트이다. 원하는 코드의 기능을 캡슐화하여 재사용 가능한 커스텀 엘리먼트를 생성하고 웹 앱에서 활용할 수 있도록 해주는 다양한 기술들의 모음이다.


사용 이유

Vendor Lock-in

  • 먼저, Vendor Lock-in의 대해 알아볼 필요가 있다. Vendor Lock-in 란, 특정 벤더의 독자적 기술에 크게 의존한 것으로, 다른 벤더가 제공하는 동종 제품 또는 서비스, 시스템 등으로 갈아타기 어려운 현상을 말한다. 쉽게 말해서, 최근들어서 자주 사용되는 React, Vue, Angular 등 Js 프레임워크를 기반으로 둔 컴포넌트를 활용했을 때 수 년이 지나고, 언어가 퇴보 되었을 때 코드 리팩토링하는 것은 굉장히 까다로운 작업이 될 것이다. 그래서 이러한 불편사항을 없애기 위해서 웹 표준 기술을 사용하면, 변화에 유연하게 대처할 수 있다.
  • Web Component는 재사용 가능한 요소에 대하여, 강력한 캡슐화를 제공하며, custom element, shadow DOM, HTML template와 굉장히 친숙하다.

Web Component 의 전망

Image
  • 최근들어, 웹 컴포넌트를 많이 사용하는 추세로 가고있다.
  • Chrome 브라우저에서 동작하는 웹 사이트의 15% 이상이 Custom Element를 사용하는 것으로 나타났다.

실제 사용한, React의 컴포넌트

하단의 이미지는, 스마트케어 업무 중 React 기반의 컴포넌트 HTML 을 작성하여, 업무를 수행한 기록이다. 우측 이미지와 같이 Challenge 폴더 안에 Componets폴더가 존재하고, 그와 같은 위치에 Challenge 및 각종 Challenge 등 과 같은 컨테이너(Container)가 존재하는 것을 볼 수 가 있다. 기본적으로 컨테이너에서 필요한 컴포넌트를 불러와 사용한다.

Image Image

먼저 컴포넌트를 활용하기 위해서는, 기존에 되어있는 디자인을 유심히 볼 필요가 있다. 재 사용을 할 수 있는 것들부터 찾아본 다음, 그것을 직관적인 이름을 가진 컴포넌트로 만들면 된다. 하단의 이미지는, 실제 업무 수행과정 중 Challenge 메인 디자인 시안이다. 이 곳에서 나는 뒷 배경이면서도 모든 element를 담을 수 있는 container인 Wrapper와, 하단의 Card Layout 등 과 같이 컴포넌트로 담았다.

Image
  • Challenge Componets

  • 먼저 실제 사용한 Challenge 컨테이너(Container)의 코드이다. 아래와 같이 크게 <Wrapper> <Header> <MainMenu> <Container> <Layout> <CouponLayout /> 등 세부적으로 컴포넌트를 생성했고, props를 통해서 실제 컴포넌트의 필요한 데이터들을 보내주며 코드를 작성했다. 앞서 작성한 것과 같이 React, Vue, Angular의 프레임워크를 기반으로 한 것들은 해당 언어의 문법이나 규칙 등을 알아야만 활용 할 수 있다는 단점이 존재한다.

    const ChallengePage = () => {
      const [isTabnavOn, setIsTabnavOn] = useState(false);
      const [isMenuType, setMenuType] = useState("benefit");
      const [hasList, setHasList] = useState(true);
    
      return (
        <React.Fragment>
          <Wrapper>
            <Header
              title="케어존"
              isTabnavOn={isTabnavOn}
            >
              <MainMenu
                MenuType={setMenuType}
                isMenuType={isMenuType}
              />
            </Header>
            <Container>
              {
                isMenuType === "benefit"  ?
                <>
                  <Layout
                    hasList={false}
                    contentTitle="혜택 모아보기"
                    cont="12"
                    imgNum="1"
                    text="2022.10.01 ~ 2024.10.01"
                    personnel="1,234"
                    type3={true}
                  />
                </>
                :
                isMenuType === "coupon" ?
                <>
                  <CouponLayout />
                </>
                :
                null
              }
            </Container>
          </Wrapper>
        </React.Fragment>
      )
    }
    
    const Wrapper = ({
      seeAllTruth,
      badgesTruth,
      detailsTruth,
      clearTruth,
      readTruth,
      children
    }) => {
      return (
        <>
          <div
            className={cn({
              [ChallengeCSS.Wrapper]: true,
              [ChallengeCSS.seeAll]: seeAllTruth,
              [ChallengeCSS.badges]: badgesTruth,
              [ChallengeCSS.details]: detailsTruth,
              [ChallengeCSS.clear]: clearTruth,
              [ChallengeCSS.read]: readTruth,
            })}
          >
            {children}
          </div>
        </>
      )
    }
    
  • Web Componets

    웹 컴포넌트는 다른 프레임워크 언어와 쓰임새나 사용방법은 같지만, 작성하는 방법 등 차이가 있다. 실제 기본 HTML과 Javascript를 기반으로 두었기 때문에 오히려 더 친숙할 수 있다. 웹 컴포넌트에는 3가지 구현방법이 존재하는데, 다음과 같으며 하단에서 각각 기능과 장점에 대하여 서술하겠다.

    • Custom Element

    • Shadow DOM

    • HTML Template

    1. Custom Element
      • HTML Element와 Javascript Class를 하나로 만들어 캡슐화하여 재사용 가능.

      • 사용자 지정 태그를 작성 가능(원하는 클래스 네이밍 사용)

    사용방법

    class TestModal extends HTMLElement {
      constructor() {
        super();
      }
    	  this.innerHTML = `
    			<div class="modal">
    				TEST Modal
    			</div>
    		`
    }
    customElements.define('test-modal', TestModal);
    
    <test-modal></test-modal>
    

    사용규칙

    • Custom Elements를 사용할 Class는 반드시 HTMLElement를 상속 받아야한다.
    • Custom Elements에는 React와 비슷하게 생명주기가 존재한다.
    • customElements.define을 이용해서 Custom Elements를 만들 수 있다. 첫번째 인자는 태그의 이름을 적어주면 되고 두번째 인자는 해당 Class의 이름을 적으면 된다. 이때 태그의 이름엔 반드시 - 가 들어가야 한다. (구분과 상속의 이유)

    생명주기

    • connectedCallback

    • disconnectedCallback

    • attributeChangedCallback

    • adoptedCallback

    1. Shadow DOM

      • HTML의 <video> , <input type="range"> 와 같은 내부에 요소가 포함된 태그이다.
      • DOM 트리를 일반 DOM 트리의 요소에 첨부가능하다.
      • Shadow DOM 트리는 모든 요소에 첨부할 수 있는 Shadow 루트로 시작한다.
      Image

    사용방법

    <div id="shadow"></div>
    
    document.querySelector('#shadow').attachShadow({mode : 'open'})
    // mode는 'open' 과 'closed'가 있다.
    
    document.querySelector('#shadow').shadowRoot.innerHTML =
    '<p>쉐도우 돔 설명입니다.</p>'
    

    사용규칙

    • 노드와 같은 방식으로 Shadow DOM 노드에 영향을 줄 수 있다.
    • Shadow DOM의 내부 코드는 외부에 영향을 줄 수 없으므로 캡슐화를 허용한다.
    • Shadow DOM의 상세정보들은 개발자도구에서 셋팅을 필요로한다.
    Image
    • 개발자도구 → Settings → Show user agent shadow DOM 체크

    1. HTML Template
      • HTML <template> 요소는 페이지가 렌더링 되고나서 그려지지 않는다.
      • Javascript를 사용해 인스턴스를 생성할 수 있는 html 코드를 담을 방법을 제공한다.
      • 이 요소는 전역 특성만 포함된다.

    사용방법

    <template id="template">
        <h3>제목</h3>
    	  <p>제목설명입니다.</p>
    </template>
    
    <div id="wrap"></div>
    
    let temp = document.querySelector('#template');
    let target = document.querySelector('#wrap');
    
    let newContent = document.importNode(temp.content,true);
    
    target.innerHTML = '';
    target.appendChild(newContent);