본문으로 건너뛰기

Web Components 기초

zenoPortfolio는 React나 Vue 없이 브라우저 기본 기능인 Custom Elements를 사용합니다.

Custom Elements란?

Custom Elements는 내가 직접 HTML 태그를 만드는 기능입니다.

예를 들어 이 태그는 HTML 기본 태그가 아닙니다.

<portfolio-card></portfolio-card>

JavaScript에서 직접 등록해야 브라우저가 컴포넌트로 인식합니다.

customElements.define('portfolio-card', PortfolioCard);

HTMLElement 상속

컴포넌트 클래스는 HTMLElement를 상속합니다.

class PortfolioCard extends HTMLElement {
connectedCallback() {
this.loadStyle();
this.render();
}
}

HTMLElement는 모든 HTML 요소의 기본 클래스입니다.
이걸 상속하면 내가 만든 클래스도 HTML 요소처럼 동작할 수 있습니다.

connectedCallback

connectedCallback() {
this.loadStyle();
this.render();
}

connectedCallback()은 커스텀 요소가 DOM에 붙었을 때 자동 실행됩니다.

<portfolio-card>가 화면에 들어옴
-> connectedCallback 실행
-> CSS 로드
-> HTML 렌더링

observedAttributes

PortfolioCard는 attribute 변화를 감지합니다.

static get observedAttributes() {
return ['category', 'tech', 'order', 'href', 'image', 'title', 'desc'];
}

여기에 적은 attribute가 바뀌면 attributeChangedCallback()이 실행됩니다.

attributeChangedCallback() {
if (this.isConnected) this.render();
}

뜻은 이렇습니다.

title attribute가 바뀜
-> attributeChangedCallback 실행
-> render() 다시 실행
-> 카드 화면 갱신

Light DOM

이 프로젝트는 Shadow DOM을 쓰지 않습니다.

this.innerHTML = `...`;

컴포넌트 내부 HTML을 일반 DOM에 넣습니다.
그래서 전역 CSS와 일반 querySelector가 그대로 작동합니다.

장점:

  • 구조가 단순함
  • 기존 CSS와 JS를 그대로 쓰기 쉬움
  • 디버깅이 쉬움

단점:

  • 컴포넌트 스타일이 완전히 격리되지는 않음
  • 클래스 이름 충돌을 조심해야 함

import.meta.url

컴포넌트 CSS 경로를 만들 때 이 코드를 사용합니다.

const COMPONENT_STYLE = new URL('./PortfolioCard.css', import.meta.url).href;

import.meta.url은 현재 JS 파일의 위치입니다.
이 위치를 기준으로 CSS 파일 경로를 계산합니다.

덕분에 폴더 위치가 바뀌어도 상대 경로를 안정적으로 계산할 수 있습니다.

중복 style 로드 방지

if (document.querySelector(`link[href="${COMPONENT_STYLE}"]`)) return;

이미 같은 CSS가 로드되어 있으면 다시 추가하지 않습니다.

카드가 여러 개 렌더링되어도 PortfolioCard.css는 한 번만 로드됩니다.

용어 정리

용어
Custom Element직접 만든 HTML 태그
HTMLElementHTML 요소의 기본 클래스
connectedCallback요소가 DOM에 붙을 때 실행되는 메서드
observedAttributes감지할 attribute 목록
attributeChangedCallbackattribute가 바뀔 때 실행되는 메서드
Light DOMShadow DOM 없이 일반 DOM에 렌더링하는 방식
Shadow DOM스타일과 DOM을 컴포넌트 안에 격리하는 방식