원문: Sean Barry, https://seanbarry.dev/posts/switch-true-pattern
잘 알려져 있진 않지만 훌륭한 패턴이 있다. 필자는 Vortexa의 애플리케이션 개발팀(채용 중)에 합류하기 전까지 이 패턴을 전혀 알지 못했지만 지금은 꽤 자주 사용한다. switch true 라고 불리며, 정말 간단하다.
자바스크립트 개발자 대부분은 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) {
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';
}