프로그래밍-학습기록/Javascript

클래스 리스트 순서에 따른 구현은 위험하다!

leesche 2021. 4. 1. 12:22

HTML 엘리먼트에 접근할 때 클래스 이름으로 접근하고는 한다. 그리고 클래스 이름을 아예 데이터로 저장하기도 했다. 그리고 심지어 나는 클래스 리스트를 복제해 그 리스트의 요소를 pop하며 사용했는데 이는 안 좋은 행동인 것이 확실하다. 결론부터 말하자면, HTML에 작성된 클래스 순서가 영원히 보장되지 않고, 배포 주체에 따라 바뀔 수 있다.

예를 들어 보자. 아래와 같은 옵션이 있다. 옵션은 플레이 옵션(혼자, 대결)과 보드 크기(작은, 큰) 두 종류이며 각 옵션들 중 한 개씩 선택할 수 있다.

// index.html

<div class="game-options">
      <button class="option option--player solo" >혼자 하기</button>
      <button class="option option--player duo" >대결하기</button>
      <button class="option option--size small" >작은 게임 보드</button>
      <button class="option option--size big" >큰 게임 보드</button>
</div>

나는 아래와 같이 선택한 옵션 엘리먼트의 클래스 리스트를 받은 다음 pop하여 optionTypeoptionName에 할당했다. 로컬 서버 환경에서는 잘 구현이 됐다. 하지만 Netlify로 배포를 하자 문제가 생겼다.

// GameController.js

export default class GameController {
/* ... */
  #handleClickGameOption = ({ target }) => {
  /* ... */
  const targetClassList = Array.from(target.classList);
  const [optionType, optionName] = [targetClassList.pop(), targetClassList.pop()];
  /* ... */
  }
/* ... */
}

Netlify에서는 HTML 파일의 클래스 순서가 바뀌어 출력된 것이다! 여기서는 알파벳 순서대로 바뀌어 출력됐다.

// index.html

<div class="game-options"> 
  <button class="option option--player solo">혼자 하기</button>
  <button class="duo option option--player">대결하기</button> 
  <button class="option option--size small">작은 게임 보드</button> 
  <button class="big option option--size" >큰 게임 보드</button>
</div>

따라서 클래스 순서에 따른 구현은 불가능했고, 다른 대책을 찾아야 했다. 이후 찾은 결론은 data-* 속성이었다. 클래스는 스타일에, 데이터는 data-* 속성에. 의미와 맥락에서도 일관적인 느낌이었다.

data-* 속성을 이용한 구현은 다음과 같다.

// index.html

<div class="game-options">
      <button class="option" data-option-type="player" data-option-name="solo">혼자 하기</button>
      <button class="option" data-option-type="player" data-option-name="duo">대결하기</button>
      <button class="option" data-option-type="size" data-option-name="10">작은 게임 보드</button>
      <button class="option" data-option-type="size" data-option-name="100">큰 게임 보드</button>
</div>
// GameController.js

export default class GameController {
/* ... */
  #handleClickGameOption = ({ target }) => {
  /* ... */
  const [optionName, optionType] = [target.dataset.optionName, target.dataset.optionType];
  /* ... */
  }
/* ... */
}

HTML은 요소가 어떤 역할인지 좀 더 명확해졌고, 자바스크립트 코드도 좀 더 깔끔해졌다!

처음으로 돌아가서, 이 버그를 겪었을 때 왜 그런지 정말 당황하고 의문에 가득 찼었는데 의외로 간단한(클래스 순서가 바뀌는) 문제이고, 내가 너무 안일하게 구현을 했구나 반성을 했다.

위 해결 방법이 정답은 아니다. data-* 속성을 쓰는 것이 코드의 복잡성을 증가시킬 수도 있다. 또, 클래스 리스트를 매번 특정 규칙으로 정렬(sort)하여 데이터를 안정적으로 추출할 수 있기도 할 것이다.

다음은 이번 일을 겪은 나에게 하는 말이다. data-* 속성만 쓴다고 또 고집부리지 말자. 한 길만 고집하지 말고 부딪치며 실력을 갈고 닦자. 안전한 곳에 머무르지 말고 계속 도전하는 개발자가 됐으면 좋겠다. 빠이팅!


참고 및 출처