조건문 다루기 (feat. else if 지옥 벗어나기)

김상민·2024년 2월 6일
0

Javascript

목록 보기
4/5
post-thumbnail

바닐라 자바스크립트로 프로젝트를 할 때 비중이 큰 작업 중 하나가 이벤트 위임을 사용해서 이벤트를 잡아내는 것이었다.
app이라는 최상위 태그에 click 이벤트 리스너를 달아놓고 event target에 따라 이벤트 핸들러를 실행하는 방식을 사용했다.
이 때문에 이벤트 리스너의 콜백에서 아주 많은 분기처리가 필요했는데 그때 조건문을 다루면서 코드를 개선시킨 경험을 정리해보겠다.

😵‍💫 if else

사실 아래의 상황이 되기 전에 코드를 개선하긴 했지만 조건문을 개선하지 않았다면 아래와 같은 코드를 짜게 되었을 것이다. 보기만 해도 어지럽다...

import * as handler from "../handler";

const {
  main: { column },
  history,
  header,
} = handler;

const onClick = ({ target }) => {
  if (target.classList.contains("js-openHistory")) {
    header.showHistory(target);
  } else if (target.classList.contains("js-closeHistory")) {
    history.closeHistory(target);
  } else if (target.classList.contains("js-addCardBtn")) {
    column.openAddCardForm(target);
  } else if (target.classList.contains("js-editCardBtn")) {
    column.card.openEditCardForm(target);
  } else if (target.classList.contains("js-deleteCardBtn")) {
    column.card.clickDeleteCard(target);
  } else if (target.classList.contains("js-addFormCancel")) {
    column.cardForm.closeAddCardForm(target);
  } else if (target.classList.contains("js-editFormCancel")) {
    column.cardForm.closeEditCardForm(target);
  } else if (target.classList.contains("js-deleteHistory")) {
    history.deleteHistory(target);
  } else if (target.classList.contains("js-deleteCancel")) {
    column.card.cancelDeleteCard(target);
  } else if (target.classList.contains("js-deleteConfirm")) {
    column.card.deleteCard(target);
  } 
};

🤨 switch case

위와 같이 많은 조건들을 처리할 때 조금 더 가독성을 높일 수 있는 것이 switch case문인데 이를 이용해서 코드를 개선해보면 아래와 같다.
전보다 조금 더 나아지긴 했지만 여전히 반복이 많고 코드의 흐름을 파악하려면 위에서부터 타고내려오면서 읽어야한다는 단점이 있다.
또한 조건이 추가될 때 또다시 case와 break를 써야한다.

import * as handler from "../handler";

const {
  main: { column },
  history,
  header,
} = handler;

const onClick = ({ target }) => {
  const className = target.classList[0];

  switch (className) {
    case "js-openHistory":
      header.showHistory(target);
      break;
    case "js-closeHistory":
      history.closeHistory(target);
      break;
    case "js-addCardBtn":
      column.openAddCardForm(target);
      break;
    case "js-editCardBtn":
      column.card.openEditCardForm(target);
      break;
    case "js-deleteCardBtn":
      column.card.clickDeleteCard(target);
      break;
    case "js-addFormCancel":
      column.cardForm.closeAddCardForm(target);
      break;
    case "js-editFormCancel":
      column.cardForm.closeEditCardForm(target);
      break;
    case "js-deleteHistory":
      history.deleteHistory(target);
      break;
    case "js-deleteCancel":
      column.card.cancelDeleteCard(target);
      break;
    case "js-deleteConfirm":
      column.card.deleteCard(target);
      break;
    default:
      break;
  }
};

😎 look up table

가독성을 더 높이고 추가 삭제가 용이한 방법을 찾아본 결과 handlerMap 객체를 만들어서 사용하는 방법을 알게되었다.

핸들러 함수와 target의 선택자를 매핑하는 방식으로 가독성을 높이고 핸들러의 추가 삭제가 쉽도록 했다.


import * as handler from "../handler";

const {
  main: { column },
  history,
  header,
} = handler;

const clickHandlerMap = {
  "js-openHistory": header.showHistory,
  "js-closeHistory": history.closeHistory,
  "js-addCardBtn": column.openAddCardForm,
  "js-editCardBtn": column.card.openEditCardForm,
  "js-deleteCardBtn": column.card.clickDeleteCard,
  "js-addFormCancel": column.cardForm.closeAddCardForm,
  "js-editFormCancel": column.cardForm.closeEditCardForm,
  "js-deleteHistory": history.deleteHistory,
  "js-deleteCancel": column.card.cancelDeleteCard,
  "js-deleteConfirm": column.card.deleteCard,
};

const onClick = ({ target }) => {
  const executeHandler = clickHandlerMap[target.classList[0]];
  if (executeHandler) {
    executeHandler(target);
  }
};

😁 회고

else if를 코드에서 줄이는 것이 좋다는 말을 많이 들었는데 다양한 방법으로 조건문을 다뤄보니까 왜 else if를 줄여야하는지 조금 더 와닿았다.

profile
성장하는 웹 프론트엔드 개발자 입니다.

0개의 댓글