[TIL] 컴포넌트

JaeungE·2022년 4월 4일
0

TIL

목록 보기
8/29
post-thumbnail

컴포넌트 방식으로 사고하기


이전에 Vanilla JS를 이용해서 간단한 토이 프로젝트를 해본 경험이 있었는데, 말만 Vanilla JS지 지금 와서 보면 아주 무식하기 짝이 없는 방식으로 코드를 짰었다....😥

나중에 컴포넌트형으로 리팩토링을 기약하며, 어떤 것이 좋지 못한 방식인지 버튼을 이용한 간단한 예제로 비교를 통해 알아보자.



명령형으로 구현

먼저 버튼을 만들고, 클릭하면 버튼의 배경색을 변경하는 코드를 보자.


const $app = document.querySelector('.app');
const $button = document.createElement('button');
$button.textContent = 'Button';
$app.appendChild($button);

const handleButton = $button => {
  if ($button.style.background === '') {
    $button.style.background = 'yellow';
  } else {
    $button.style.background = '';
  }
}

$button.addEventListener('click', e => {
  handleButton(e.target);
});

그럭저럭 나쁘지는 않아 보이는데.... 버튼의 갯수를 늘리면 어떨까?
const $app = document.querySelector('.app');

const $button1 = document.createElement('button');
$button1.textContent = 'Button 1';

const $button2 = document.createElement('button');
$button2.textContent = 'Button 2';

const $button3 = document.createElement('button');
$button3.textContent = 'Button 3';

$app.appendChild($button1);
$app.appendChild($button2);
$app.appendChild($button3);

const $buttons = document.querySelectorAll('.app button');

const handleButton = $button => {
  if ($button.style.background === '') {
    $button.style.background = 'yellow';
  } else {
    $button.style.background = '';
  }
}

$buttons.forEach($button => {
  $button.addEventListener('click', e => {
    handleButton(e.target);
  })
})

와우,

동작은 원하는 대로 이루어졌지만, 버튼의 개수가 늘어난 만큼 버튼 생성 및 추가에서 하드 코딩을 하고 있다.

지금이야 간단한 기능만 가지고 있어서 문제가 없지만, 만약 버튼마다 추가되는 이벤트의 종류가 달라지거나 서로 다른 기능이 필요하다면 더더욱 코드가 복잡해질 것이다.

그럼 컴포넌트 방식으로 구현하는 예제를 보자.



컴포넌트 방식으로 구현

버튼을 추상화 시킨 컴포넌트를 통해 명령형에서 구현했던 코드와 동일한 동작을 하도록 만들어보자.


const $app = document.querySelector('.app');

function ButtonComponent({ $target, text }) {
  if (!new.target) {
    return new ButtonComponent({ $target, text });
  }

  const $button = document.createElement('button');
  $target.appendChild($button);

  this.state = {
    toggled: false
  }

  this.setState = nextState => {
    this.state = nextState;
    this.render();
  }

  this.handleButton = () => {
    this.setState({
      toggled: !this.state.toggled
    })
  }

  this.render = () => {
    $button.textContent = text;
    $button.style.background = this.state.toggled ? 'yellow' : '';
  }

  $button.addEventListener('click', this.handleButton);
  this.render();
}

new ButtonComponent({ $target: $app, text: 'button1'});
new ButtonComponent({ $target: $app, text: 'button2'});
new ButtonComponent({ $target: $app, text: 'button3'});

이 코드도 아직 고칠 점이 많지만, 위에서 명령형으로 구현한 코드와 동일한 동작을 한다.

이렇게 컴포넌트 방식으로 구현하면 확장이 쉬워지고, 읽기도 쉬울뿐더러 재사용하기에도 훨씬 편리하다.



0개의 댓글