본 포스팅은 JavaScript에서 조건문을 객체로 작성하는 방법을 소개합니다.
개요
JavaScript는 두 개의 조건문인 if와 switch 그리고 조건문의 축약된 형태인 삼항 연산자를 제공한다. 일반적으로 복잡한 조건식은 if-else 문을 사용하고 간단한 조건식은 삼항 연산자를 사용하므로 JavaScript에서 switch 문이 사용될 일은 거의 없다.
switch 문은 가독성이 떨어지고 JavaScript의 데이터 타입이 유연하기에 case 문에서 값을 비교하기 어려우며, 개발자가 case문을 추가할 때 실수할 수 있어서 JavaScript에서 사용하기 좋은 조건문은 아니다.
그리고 JSON 창시자인 더글라스 크락포드(Douglas Crockford)가 집필한 「자바스크립트는 왜 그 모양일까?」에서 switch 문 대신 객체를 사용하는 것을 권장하고 switch 문보다 if 문이 좋다고 언급했다.
다음 예시를 통해 JavaScript에서 조건문을 객체로 변환하는 방법을 알아보자.
조건문을 객체로 변환
다음은 숫자를 전달받아 특정 조건식을 만족하면 문자열을 콘솔에 출력하는 로직이 if-else 문으로 구현된 함수다.
function printStringOfNumber(number) {
if (number === 0) {
console.log("Zero");
} else if(number === 1) {
console.log("One");
} else if(number === 2) {
console.log("Two");
} else {
console.log("Not Satisfied");
}
}
printStringOfNumber(0); // Zero
printStringOfNumber(1); // One
printStringOfNumber(3); // Not Satisfied
위 코드의 getStringOfNumber() 함수를 객체로 변환하면 다음과 같다.
const prints = {
0: "Zero",
1: "One",
2: "Two"
};
console.log(prints[0] || "Not Satisfied"); // Zero
console.log(prints[1] || "Not Satisfied"); // One
console.log(prints[3] || "Not Satisfied"); // Not Satisfied
위 예제는 정상적으로 실행되지만, 두 가지 문제점이 존재한다.
- else 문 혹은 switch의 default 문을 처리하기 위해 매번 || 연산자를 사용
- getStringOfNumber() 함수의 목적은 문자열을 콘솔에 출력하는 용도라는 것
위 두 가지 문제를 해결하기 위해 객체에 default 값을 처리하는 키-값을 추가하고 문자열을 콘솔에 출력하는 함수를 값에 할당한다.
const prints = {
0: () => console.log("Zero"),
1: () => console.log("One"),
2: () => console.log("Two"),
default: () => console.log("Not Satisfied")
};
function printStringOfNumber(number) {
// 함수를 호출하는 것이므로 소괄호를 붙여야한다.
(prints[number] || prints['default'])();
}
printStringOfNumber(0); // Zero
printStringOfNumber(1); // One
printStringOfNumber(3); // Not Satisfie
위 예제에서 주의할 점은 객체의 값이 함수일 때, 함수를 호출하기 위해 객체 뒤에 소괄호()를 붙여야 한다는 것이다.
중첩된 조건문을 객체로 변환
다음은 성별이 조건식에 맞으면 주소를 검사하는 로직이 중첩된 if-else 문으로 구현된 함수다.
function printHuman(human) {
if(human.gender === 'M') {
if(human.address === 'Seoul') {
console.log('서울에 살고 있는 남자입니다.');
} else if(human.address === 'Busan') {
console.log('부산에 살고 있는 남자입니다.');
} else {
console.log('올바르지 않은 주소입니다.');
}
} else if(human.gender === 'F') {
if(human.address === 'Seoul') {
console.log('서울에 살고 있는 여자입니다.');
} else if(human.address === 'Busan') {
console.log('부산에 살고 있는 여자입니다.');
} else {
console.log('올바르지 않은 주소입니다.');
}
} else {
console.log('올바르지 않은 성별입니다.');
}
}
printHuman({gender: 'M', address: 'Seoul'}); // 서울에 살고 있는 남자입니다.
printHuman({gender: 'F', address: 'Busan'}); // 부산에 살고 있는 여자입니다.
printHuman({gender: '', address: ''}); // 올바르지 않은 성별입니다.
printHuman({gender: 'M', address: ''}); // 올바르지 않은 주소입니다.
조건문을 객체로 변환하는 것처럼 중첩된 조건문은 중첩된 객체로 변환하면 된다. 다음은 위 코드의 printHuman() 함수를 중첩된 객체로 변환한다.
const prints = {
M:{
Seoul: () => console.log('서울에 살고 있는 남자입니다.'),
Busan: () => console.log('부산에 살고 있는 남자입니다.'),
default: () => console.log('올바르지 않은 주소입니다.')
},
F:{
Seoul: () => console.log('서울에 살고 있는 여자입니다.'),
Busan: () => console.log('부산에 살고 있는 여자입니다.'),
default: () => console.log('올바르지 않은 주소입니다.')
},
default:() => console.log('올바르지 않은 성별입니다.')
}
function printHuman(human) {
if(human.gender) {
if(human.address) {
prints[human.gender][human.address]();
} else {
prints[human.gender]['default']();
}
} else {
prints['default']();
}
}
printHuman({gender: 'M', address: 'Seoul'}); // 서울에 살고 있는 남자입니다.
printHuman({gender: 'F', address: 'Busan'}); // 부산에 살고 있는 여자입니다.
printHuman({gender: '', address: ''}); // 올바르지 않은 성별입니다.
printHuman({gender: 'M', address: ''}); // 올바르지 않은 주소입니다.
중첩된 조건문을 중첩된 객체로 변환하더라도 default 값을 처리하기 위해 printHuman() 함수에서 if-else 문을 사용한 것을 볼 수 있다. if-else 문 대신 || 연산자를 사용할 수 있지만, 코드가 복잡해지고 가독성을 저하시킨다는 문제점이 존재한다. 따라서, 중첩된 조건문은 객체보다 if-else 문을 권장한다.
Conclusion
JavaScript에서 조건문을 객체로 작성하는 방법을 알아보았다.
- switch 문보다는 객체 또는 if 문을 사용하는 것이 좋다.
- 중첩된 조건문은 if-else 문을 사용하는 것이 좋다.
- 순수 함수 스타일로 코드를 작성하고 싶다면, 삼항 연산자를 사용하는 것이 좋다.
조건문을 작성하는 방법은 취향에 따라 다르지만, 상황에 따라 가독성 있고 유지보수하기 쉬운 방법을 선택할 수 있어야한다.