우테코 3월 1주차 - 컴포넌트와 웹 컴포넌트

hyerin·2024년 3월 11일
post-thumbnail

이번 우테코의 미션의 핵심 키워드는 '컴포넌트'였다. 컴포넌트를 나누는 기준과 목적을 생각하면서 어떻게 해야 컴포넌트로 효과적으로 나눌 수 있는지 생각해보는 것이었다.

개인적으로 리액트 기반으로 코드를 많이 짜봐서 컴포넌트라는 개념이 어색하지 않다. 보통 재사용 가능한 Button, Modal 같은 공용 모듈을 기반으로 Basic Component를 만든후 해당 컴포넌트를 사용해 변형된 컴포넌트를 만들었다!

하지만 이번 미션은 전 주차와 마찬가지로 Banilla JS 로 구현해야 했다..(리액트가 없으면 아무것도 못한다구요 리액트 내놔)

우선 컴포넌트에 대해 잘 알필요가 있었고, CBA 라는 컴포넌트 정의를 알게 되었다

컴포넌트 기반 아키텍처(CBA)

: 컴포넌트의 재사용성에 초점을 맞춘 개발방법론

⚙️ 1. 모듈성:

소프트웨어는 독립적인 컴포넌트로 나눠며, 각 컴포넌트는 특정 기능을 수행하는 모듈 역할을 한다.

이는 컴포넌트의 기본적인 정의와 관련이 있는 것 같다. 컴포넌트는 현실세계의 부품과 같다. 각각의 컴포넌트는 자신만의 역할과 목적이 있다. 마치 자동차라는 '완성품'을 만들기 위해 만들어지는 몇백개의 부품으로 비유할 수가 있다. 자동차는 사실 보면 이러한 무수한 부품이 만들어낸 것이다. 이 무수한 부품 중 하나라도 빠지면 어떻게 될까? 자동차의 어느 부분에 흠이 생길 것이다. 따라서 소프트웨어를 자동차, 그 안의 컴포넌트를 자동차의 부품으로 비유할 수 있을 것이다.

⚙️ 2.재사용성:

컴포넌트는 다양한 애플리케이션에서 재사용할 수 있어야 한다.

=> 내가 이번 미션을 하면서 가장 고려했던 부분이 재사용성이었다. 보통 비슷한 <태그>를 보면서 재사용 가능한 부분을 찾는 편인데, 이번 미션에서는 버튼,셀렉트 박스,모달,인풋 등을 재사용 대상으로 선정했다. 이러한 모듈은 모든 페이지에서 디자인이 유사할 뿐만 아니라, 자주 사용되는 모듈이었기 때문이다.

이왕 똑같은 모양의 제품이면, 한번의 공장 작업을 통해 한번에 여러개를 찍어놓고 사용하는 것이 날 것 이다. 때문에 컴포넌트에서 재사용성의 개념은 중요하다고 생각한다.

⚙️ 3. 독립성

: 컴포넌트는 독립적으로 운영될 수 있으며, 다른 컴포넌트에 최대한 의존하지 않아야 한다.

컴포넌트는 소프트웨어라는 완성품을 만들기 위한 부품이다. 하지만 부품은 부품 그 자체로도 완전해야 한다. A 부품이 있다고 해보자. A 부품은 B 부품과 연관되어 B 부품이 없으면 A 부품을 사용할 수 없다. 이 경우는 컴포넌트의 독립성 이 없다고 할 수 있다.
컴포넌트는 그 자체로 쓸 수 있는 하나의 독립적인 작은 완성품 이라고 생각한다.

앞에서 언급했듯이 나는 리액트로 컴포넌트를 짜는 것이 익숙하다. JSX 문법을 활용해서 컴포넌트를 만들고, export 하고... 이렇게 쉬운 것을 바닐라 JS에서는 할 수 없다는 게 슬펐다😥 하지만 불가능 한 것은 아니니..!!

바닐라 JS에서 컴포넌트를 만들고 싶어!!
웹 컴포넌트✅

웹 API와 HTML 태그를 사용하면 웹 컴포넌트를 만들수 있다. 모던 웹 API에 HTML 태그를 다룰 수 있는 여러 메서드들을 제공하기 때문이다. 이 중에서는 웹 컴포넌트 를 만들 수 있는 API 도 제공하는데 이는 웹 컴포넌트 API 라고 부른다고 한다.

원리는 간단하다. 우리가 기본적으로 사용하는 태그처럼 사용자 정의 태그 를 만들어서 사용하는 것이다.

<main>
  <filter-container class="restaurant-filter-container"></filter-container>
  <restaurant-list></restaurant-list>
</main>

위에는 나의 미션 코드이다. 위와 같은 태그들이 기본적으로 내장되어 있을리 없다! 다 내가 만든 웹 컴포넌트 들이다. 위와 같이 사용자 정의 태그를 사용해서 웹 컴포넌트를 사용할 수 있다. 웹 컴포넌트의 이름에는 컨벤션이 있다. - 를 꼭 넣어주어야 한다. header(❌)

웹 컴포넌트는 HTMLElement 라는 기본 태그 Element를 사용해서 만들어주는 것이다. 클래스에서 HTMLElement를 상속하여 나만의 클래스명을 정의해준다. 그 클래스 안의 생성자에서super()를 통해 HTMLElement의 속성을 상속받은 후 컴포넌트의 속성을 정의하면 된다.

우리 팀의 경우는 다음과 같이 BaseComponent 를 만들어 커스텀 웹 컴포넌트를 만들 때마다 해당 베이스 코드를 상속해 사용하였다.


class BaseComponent extends HTMLElement {
  connectedCallback() {
    this.render();
    this.setEvent();
  }
  render() {}

export default BaseComponent;

위 코드에서 connectedCallback 이 생소하게 느껴질 수 있다. 웹 컴포넌트 API 중 하나인 라이프 사이클 함수 중 하나이다. 종류로는 다음과 같은 것들이 있다.
connectedCallback : 커스텀 컴포넌트가 DOM에 추가될 때 호출
disconnectedCallback : 커스텀 컴포넌트가 DOM에 해제될 때 호출
adoptedCallback : 커스텀 컴포넌트가 새로운 DOM으로 이동할 때 호출
attributeChangedCallback : 커스텀 컴포넌트 속성에 변경이 생겼을 때 호출

위와 같은 라이프 사이클 API 를 사용하면, 필요한 함수들을 커스텀 컴포넌트가 렌더링 되거나 없어질 때 자동으로 실행시킬 수 있다. 우리 팀은 render() : 컴포넌트가 렌더링 되는 코드, setEvent() : 컴포넌트에 이벤트를 등록, 실행하는 코드connectedCallback 에 넣어 컴포넌트가 렌더링 될 때 자동 실행되게 하였다.

다음과 같이 브라우져에 내가 만든 소중한⭐️ 컴포넌트를 등록한다. 이 과정이 없이 커스텀 컴포넌트를 사용하면, 에러가 뜬다!! 꼭 있어야 하는 코드이다.

customElements.define('restaurant-list', RestaurantList);

이 외에도 이번 미션에서는...

📍 innerHTML을 지양하고 createElement를 사용하여 XSS 공격의 취약점 개선
📍 TS로 어떻게 효과적인 도메인 객체 모델을 짤 수 있을지 고민
도메인의 entityservice 의 분리 등등

고민을 해보야할 점은...

📍 웹 컴포넌트의 shadow DOM, template 등 다른 기능에 대해서 공부
📍 웹 컴포넌트의 이름을 어떻게 하면 더 Semantic하게 짤 수 있을지에 대해 고민

등이 있다!!

이번 우테코 미션은 TDD, typescript, 웹 컴포넌트까지 정말 많은 시도를 한 과제였다. 욕심을 많이 부린만큼, 퀄리티 높은 코드가 나와서 만족하고 있다. (너무 부려서 제출 버튼을 마감시간보다 2분 늦게 누름..) 솔직히 혼자였으면, 이 중 하나는 포기했을 것 같고, 나의 페어 제이드 덕분에 빠르게 개념을 습득하며 적용할 수 있었다고 생각한다.
(고마워요 제이드😄)

링크

https://yozm.wishket.com/magazine/detail/2217/
https://haeminmoon.github.io/2020/02/08/web-component/

profile
글쓰기의 시작은 나를 위해, 끝은 읽는 당신을 위해

2개의 댓글

comment-user-thumbnail
2024년 3월 12일

리안! 컴포넌트에 대한 비유가 정말 좋은 것 같아요@@! 다양한 시도를 해보신게 정말 멋지신걸요.. 그리고 아마 대부분의 크루들이 시간 부족 이슈가 있지 않았을까...ㅎ.ㅎ(일단나부터) 생각됩니다 🥹

1개의 답글