자바스크립트에서 switch (true) 패턴 사용하기


원문: Sean Barry, https://seanbarry.dev/posts/switch-true-pattern

잘 알려져 있진 않지만 훌륭한 패턴이 있다. 필자는 Vortexa의 애플리케이션 개발팀(채용 중)에 합류하기 전까지 이 패턴을 전혀 알지 못했지만 지금은 꽤 자주 사용한다. switch true 라고 불리며, 정말 간단하다.

기본적인 switch

자바스크립트 개발자 대부분은 switch 문(MDN 문서)에 익숙할테지만, 자바스크립트 입문자들을 위해 간단히 짚고 넘어가겠다.

switch 문을 사용하면 표현식을 여러 가지 조건문 중 하나에 일치시킬 수 있다.

const city = "London";

const getCountryByCity = () => {
  switch (city) {
    case "Edinburgh":
      return "Edinburgh is the capital city of Scotland";
    case "Madrid":
      return "Madrid is the capital city of Spain";
    case "London":
      return "London is the capital city of England";
    default:
      return "Cannot find which country this city is the capital of.";
  }
};

표현식(city 변수)을 switch 문의 각 조건문과 비교한다. 만약 조건문이 표현식의 결과와 일치한다면 그 조건이 실행된다. 위 예시에서는 문자열이 반환된다.

switch (true)

switch true 패턴의 기본적인 원리는 switch 문은 값 뿐만 아니라 표현식과도 비교할 수 있다는 것이다. 조건문에 표현식을 사용하면 비교되기 전 평가된다. 만약 조건문에서 사용한 표현식이 true로 평가된다면, 이 조건문과 일치하게 되는 것이다.

switch (true) {
  case 1 + 1 === 2:
    // 이는 true 이므로 해당 조건문이 실행된다.
    break;
  default:
    // 해당 코드는 실행되지 않는다.
    break;
}

이 패턴이 유용한 이유

이 패턴은 다양한 상황에서 쓰일 수 있다. 그리고 종종 복잡한 if/else 문 대신 사용될 수도 있다.

유용하게 사용될 수 있는 일반적인 시나리오는 데이터 유효성 검사가 실패하게 되는 일련의 기준들이 있고, 이를 이용해 데이터가 유효한지 검증할 때이다.

const user = {
  firstName: "Seán",
  lastName: "Barry",
  email: "my.address@email.com",
  number: "00447123456789",
};

if (!user) {
  throw new Error("User must be defined.");
}

if (!user.firstName) {
  throw new Error("User's first name must be defined");
}

if (typeof user.firstName !== "string") {
  throw new Error("User's first name must be a string");
}

// ...더 많은 유효성 검사들

return user;

위 코드는 switch true를 이용하여 아래처럼 바꿀 수 있다.

const user = {
  firstName: "Seán",
  lastName: "Barry",
  email: "my.address@email.com",
  number: "00447123456789",
};

switch (true) {
  case !user:
    throw new Error("User must be defined.");
  case !user.firstName:
    throw new Error("User's first name must be defined");
  case typeof user.firstName !== "string":
    throw new Error("User's first name must be a string");
  // ...더 많은 유효성 검사들
  default:
    return user;
}

if/else문과 switch true 모두 더 나은 가독성을 위해 추상화된 유효성 검사로 작성할 수 있다.

switch (true) {
  case !isDefined(user):
    throw new Error("User must be defined.");
  case !isString(user.firstName):
    throw new Error("User's first name must be a string");
  case !isValidEmail(user.email):
    throw new Error("User's email address must be a valid email address");
  case !isValidPhoneNumber(user.number):
    throw new Error("User's phone number must be a valid phone number");
  // ...더 많은 유효성 검사들
  default:
    return user;
}

요약

필자는 다양한 조건을 확인해야 할 때 많은 if/else 블록을 쓰는 것보다 이 패턴이 더 깔끔하여 가독성이 좋다고 생각한다. 이는 사람들마다 꽤 의견이 갈릴 것이라 생각하지만, 적절한 상황에서 사용할 수 있도록 이 패턴을 인지하고 있는 건 항상 도움이 될 것이다.

이 패턴에 대해 의견이 있다면 Twitter @SeanBarryUK로 알려달라!

역자가 덧붙이는 내용

현재(2021-06-02) Sean Barry의 트위터에 다양한 의견이 달렸다. (참고: @SeanBarryUK 트윗, @JavaScriptDaily 트윗). 대부분 가독성이 떨어진다는 이유로 이 패턴을 좋아하지 않는다. 또한 본문의 if/else 문 예시도 충분히 가독성이 좋다는 의견이 많았다. switch true 패턴을 지지하는 의견 중 하나는 아래 예시처럼 OR이 많은 조건문을 사용할 때는 if/else 문보다 가독성이 좋다고 하였다. (참고: @rix1의 트윗)

function testSwitch(user) {
  switch (true) {
    case user.age > 40:
    case user.name.startsWith('B'):
    case user.name === 'Sam' && user.age === 31:
    case user.name === 'Alice' && user.age === 28:
      return `Welcome ${user.name}!`;
    default:
      return 'Welcome unknown user';
  }
}

function testIf(user) {
  if (
    user.age > 40 || user.name.startsWith('B') || (user.name === 'Sam' && user.age === 31) || (user.name === 'Alice' && user.age === 28)
  ) {
    return `Welcome ${user.name}!`;
  }

  return 'Welcome unknown user';
}
곽희나2021.06.03
Back to list