일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Prometheus
- swiper
- 우테코
- 우아한테크코스 레벨3
- browserslist
- react
- docker-compose
- HTML
- fastify
- CSS
- GitHub Pages
- 무선랜카드 교체
- custom element
- javascript
- webpack
- Grafana
- AX210
- Shadow DOM
- Docker
- 유한 상태 머신
- typescript
- react-dom
- web component
- scroll-snap
- live share
- 데모데이
- github Actions
- 우아한테크코스
- 터치 스와이프
- RTL8852BE
- Today
- Total
IT일상
[Web Component] VanillaJS에서 React처럼 개발하기. HTML Custom Elements 소개 본문
[Web Component] VanillaJS에서 React처럼 개발하기. HTML Custom Elements 소개
solo5star 2023. 2. 23. 17:55리뉴얼 된 블로그로 보기: https://solo5star.dev/posts/25/
본 글에서는 Custom Element를 적용해보는 위주로 다룹니다. 상세한 내용을 확인하려면 아래의 링크를 참고해주세요.
- WHATWG Spec: https://html.spec.whatwg.org/multipage/custom-elements.html
- MDN - Using custom elemtns: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
- More capable form controls: https://web.dev/more-capable-form-controls/
- Custom Elements best practice: https://web.dev/custom-elements-best-practices/
<cr-button id="addShortcut" tabindex="0" noink="" title="바로가기 추가" aria-label="바로가기 추가" role="button" aria-disabled="false">
<!-- ... -->
</cr-button>
브라우저에서 이와 같은 엘리먼트를 보신 적 있으신가요? 분명 HTML엔 없는 버튼인데, 뭔가 사이트 측에서 커스텀한 느낌입니다.
위의 코드는 사실 크롬에서 새 탭(chrome://new-tab-page)을 열었을 때 나타나는 "바로가기 추가" 에 해당되는 엘리먼트입니다.
이와 같이 사용자가 정의한 엘리먼트를 Custom Element 라고 합니다.
Custom Element
<body>
<my-alert></my-alert>
</body>
<script>
customElements.define('my-alert', class MyAlert extends HTMLElement {
constructor() {
super();
this.innerHTML = `
<style>
div {
padding: 12px;
background-color: yellow;
color: red;
}
</style>
<div>경고가 발생하였습니다</div>
`;
}
});
</script>
조금 길지만, Custom Element의 innerHTML 을 제외하면 그렇게 많진 않습니다. 보시면 아시겠지만, innerHTML은 Custom Element가 가지는 내부 HTML 코드입니다.
코드를 실행했을 때, 이렇게 나타납니다.
이걸 활용하면 반복되는 번거로운 태그들(div, img 등)을 하나로 묶어 관리할 수 있습니다. 이 외에도 다른 기능들을 알아봅시다.
connectedCallback / disconnectedCallback
Custom Element가 document에 추가되었을 때 호출됩니다. 기본적으로 document에 추가된 직후 한 번만 호출되지만, 만약 document에서 지웠다가 추가하는 것을 반복할 경우 여러 번 호출될 수 있습니다.
customElements.define('my-input', class MyInput extends HTMLElement {
constructor() {
super();
this.innerHTML = `
<style>
input {
padding: 10px;
border: 1px solid grey;
}
</style>
<input>
<p>당신의 입력은?: <span></span></p>
`;
}
onInput(event) {
this.querySelector('span').innerText = event.target.value;
}
connectedCallback() {
console.log('connected');
this.querySelector('input').addEventListener('change', this.onInput.bind(this));
}
disconnectedCallback() {
console.log('disconnected');
this.querySelector('input').removeEventListener('change', this.onInput);
}
});
setTimeout, setInterval, addEventListener / clearTimeout, clearInterval, removeEventListener 등, DOM의 생성과 소멸 시 수행해야 할 동작이 있을 때 유용합니다.
observedAttributes / attributesChangedCallback
observedAttributes는 관찰할 속성(attribute)들 입니다. attributesChangedCallback은 observedAttributes로 관찰한 속성에 변경이 생겼을 때 호출됩니다.
customElements.define('my-alert', class MyAlert extends HTMLElement {
constructor() {
super();
this.innerHTML = `
<style>
div { padding: 12px; }
[data-severity="warn"] { background: yellow; }
[data-severity="error"] { background: red; }
[data-severity="info"] { background: grey; }
</style>
<div data-severity="warn">문제가 발생하였습니다.</div>
`;
}
static get observedAttributes() {
return ['severity'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'severity') {
this.querySelector('div').dataset.severity = newValue;
}
}
});
Custom Element를 사용하는 이유?
잘 비유된 그림이 있어 가져와 봤습니다. 보편적으로는, Javascript가 HTML, CSS를 직접 조작하여 UI 로직을 수행합니다. Javascript가 조작하는 HTML, CSS는 굉장히 중첩되어 있는 div일 수도 있고, 아주아주~긴 CSS 클래스 이름일 수도 있습니다.
<body>
<div class="app__container">
<div class="app__header">
<div class="app__title">
<div class="app__title-main-text"></div>
<div class="app__title-sub-text"></div>
</div>
<div class="app__navigation-container">
<div class="app__navigation-main-items">
<div>
<body>
<app-header><!-- ... --></app-header>
<app-navigation>
<app-navigation-item></app-navigation-item>
</app-navigation>
<!-- ... -->
하지만 Custom Element는 컴포넌트 단위로 묶어 작업을 할 수 있게 해주기 때문에, UI 개발을 훨씬 쉽게 해 줍니다.
마무리하며...
이미 이러한 문제를 해결하기 위한 솔루션이 많습니다. 컴포넌트 단위로 작업을 가능케 해주는 React, Vue.js, Svelte 같은 프레임워크를 보통 많이 사용합니다.
따라서 라이브러리를 사용하지 못하는 환경이 아닌 이상 더 많은 도구를 제공해주고, 더 편리하고, 레퍼런스가 많은 React 같은 프론트엔드 프레임워크를 선택할 것입니다.
그렇지만 Vanilla JS에도 기존의 문제를 해결하기 위한, 이러한 방법이 존재한다는 사실을 기억해주면 좋을 것 같습니다!
'프론트엔드' 카테고리의 다른 글
[Web Component] 커스텀 폼 컨트롤, form associated 컴포넌트 만들기 (2) | 2023.03.07 |
---|---|
[Web Component] Custom Element에서 slot 사용하기 (2) | 2023.03.06 |
[Web Component] 컴포넌트 내부 요소를 격리하기. HTML Custom Elements + Shadow DOM (0) | 2023.02.27 |
GitHub Actions: Webpack 빌드 + GitHub Pages 배포 자동화하기 (15) | 2023.02.24 |
CSS로 3D 회전하는 효과 만들기 (6) | 2023.02.18 |