웹 컴포넌트는 HTML, CSS, 자바스크립트를 활용하여 재사용 가능하고 캡슐화된 웹 요소를 만드는 도구입니다. 웹 컴포넌트는 표준 웹 기술을 사용하여 구현하기 때문에 웹 프레임워크나 라이브러리에 의존하지 않고 개발할 수 있습니다. 덕분에 다양한 환경에서 사용될 수 있고, 개발자가 선택할 수 있는 유연성을 제공합니다.
웹 컴포넌트
웹 컴포넌트는 React나 Vue에서 말하는 컴포넌트와 같은 것을 가르킵니다. 즉 재사용이 가능한 코드를 의미합니다. 웹 컴포넌트를 사용하면 다른 컴포넌트를 사용하는 것과 똑같은 이점을 가질 수 있습니다. 웹 개발자들이 쉽게 코드를 재사용하여 생산성을 높이고 동일한 디자인 요소를 가진 코드를 컴포넌트로 만들어 일관된 사용자 인터페이스를 구현할 수 있게 하는 것이 바로 웹 컴포넌트 사용으로 얻어낼 수 있는 이점입니다.
주요 요소
웹 컴포넌트는 커스텀 요소와 Shadow Dom이라는 같은 두 가지 요소로 구성되어 있습니다.
커스텀 요소
커스텀 요소는 새로운 HTML 태그를 정의하여 웹 컴포넌트의 기본 구조를 만드는 기술입니다. HTML 문법을 확장하여 자신만의 태그를 만들고, 이를 재사용할 수 있습니다. 쉽게 말해 HTMLElement를 상속 받아 새로운 HTML 태그를 만들 수 있습니다.
class GreetingElement extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
const name = this.getAttribute("name") || "World";
this.innerHTML = `<p>Hello, ${name}!</p>`;
}
}
customElements.define("greeting-element", GreetingElement);
커스텀 요소를 정의하기 위한 간단한 코드 스니펫입니다. 해당 요소는 name이라는 속성을 받아 innerHTML로 표시하는 기능을 합니다. constructor에서 부모의 constructor를 상속받고 HTML에 처음 그려질 때 connectedCallback이 실행됩니다. 이렇게 만든 greeting-element라는 커스텀 요소는 customElements.define를 통해 등록되고 HTML파일에서 다른 태그들처럼 사용할 수 있습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="./index.js" type="module"></script>
</head>
<body>
<greeting-element name="curt poem"></greeting-element>
</body>
</html>
greeting-element는 앞서 정의한 커스텀 태그이며 소문자로 시작하여 하이픈(-) 가 들어가 있는 케밥케이스를 사용하는 것이 일반적입니다. 이는 커스텀 요소와 기존 HTML 요소를 구분하기 위해서입니다. 하이픈이 없는 이름은 HTML 표준에 의해 정의된 요소로 간주될 수 있기 때문에 혼동을 피하기 위해서입니다. 위와 같이 작성된 HTML은 브라우저에서 다음과 같이 표시됩니다.
상태를 React나 Vue의 Props와 같은 역할로 사용하고 있습니다. 이렇게 재사용이 가능한 컴포넌트를 React나 Vue의 도움없이 정의하고 사용할 수 있습니다. 웹 컴포넌트는 라이브러리나 프레임워크에 종속되지 않기 때문에 React와 Vue에서도 웹 컴포넌트를 자유롭게 사용할 수 있습니다.
앞서 HTMLElement를 상속받을 때, connectedCallback은 해당 요소가 HTML에 그려질 때 실행된다고 하였습니다. 이 외에도 HTML이 DOM에서 제거될 때 실행되는 disconnectedCallback, 해당 태그의 속성이 변경될 때 실행되는 attributeChangedCallback, 컴포넌트가 다른 DOM으로 이동할 때 호출되는 adoptiveCallback 까지 미리 정해져 있는 콜백함수들이 존재합니다. 이 함수들은 컴포넌트의 생명주기와 관련되며, Vue의 Mounted와 같은 생명주기와 비슷한 역할을 합니다.
Shadow Dom
Shdow DOM은 DOM의 일부를 캡슐화하여 외부와 격리된 상태로 유지할 수 있게 해주는 기능입니다. Shadow DOM은 호스트 요소(Host Element) 내부에 독립적인 DOM 트리를 생성하게 됩니다. 이 캡슐화된 DOM 트리는 바깥의 스타일이 내부에 영향을 주지 않고 내부에 정의된 스타일이 바깥의 요소에 영향을 주지 않습니다. 다른 부분과 충돌하지 않기 때문에 CSS의 클래스 명이나 JS의 함수 이름을 간단하게 유지할 수 있습니다.
Shadow DOM은 다음과 같은 방법으로 만들 수 있습니다.
let shadow = elementRef.attachShadow({ mode: "open" });
모든 요소에 shadow root를 부착할 수 있기 때문에 elementRef는 어떤 HTML 요소도 될 수 있습니다. 다만 mode라는 옵션을 가진 매개변수가 필요할 뿐입니다. mode는 open 또는 closed라는 값을 가질 수 있으며, open 은 메인 페이지 맥락에서 작성된 JavaScript를 사용하여 shadow DOM에 접근할 수 있음을 의미합니다. closed는 외부로부터 shadow DOM에 접근할 수 없습니다.
let myShadowDom = myCustomElem.shadowRoot;
위의 코드는 해당 HTML 요소에 부착된 shadow DOM에 접근하는 메서드입니다. mode가 open일 경우 shadow root를 가져올 수 있지만 closed일 경우 null이 됩니다. 다만 웹컴포넌트에서 Shadow DOM을 만들 때 내부에 접근 할 수 있는 메서드를 만든다면 접근이 불가능하지는 않습니다.
결론
웹 컴포넌트는 웹 개발의 생산성을 향상시키고, 유지 관리를 용이하게 하며, 일관된 사용자 인터페이스 구현을 지원합니다. 재사용 가능한 코드를 통해 기능 개발을 간소화하고 코드 기반을 강화하는 데 도움을 줍니다. 웹 컴포넌트는 아직 초기 단계여서 작은 커뮤니티를 가지고 있고 개발을 하기 위해서 개발 환경을 하나부터 열까지 직접 설정해야 합니다. 하지만 React와 Vue와 같은 다른 라이브러리 및 프레임워크와 혼용하여 사용하는 것이 어렵지 않고 현재는 거의 모든 브라우저가 지원하는 기본 웹 API점에서 발전 가능성이 높다고 생각하는 기술입니다.
참고자료
'개발 > JavaScript' 카테고리의 다른 글
JavaScript의 렉시컬 환경과 클로저, 조금 더 자세하게 알아보자 (0) | 2024.06.10 |
---|---|
JSDoc으로 더 나은 주석 작성하기, 그리고 개발 관련 도서 추천 (0) | 2024.06.03 |
JavaScript V8 엔진과 GC(Garbage Collection) (0) | 2024.04.14 |
Axios를 추상화하여 HTTP 통신을 더욱 쉽게 관리하고 제어하기 (0) | 2024.04.02 |
리액트와 Vue는 어떻게 상태의 변화를 감지하여 화면을 다시 그릴까? - 자바스크립트와 옵저버 패턴 (2) | 2024.03.23 |