
우리는 길들여지기를 다중 조건문 속에서 살고 있다.
const changeSomething (state) => {
if(state === "hungry") {
eatSomething();
} else if (state === "full") {
relax();
} else {
readBooks(); // watchYoutube();
}
}
if else에서 다뤄야 하는 조건이 많지 않다면 사용하지 않을 이유가 없지만, 만약 조건이 많아져 로직이 복잡해진다면?

물론 이 경우는 장난이지만, 실제로 구별해야 하는 상태가 수십가지라면, 코드는 하염없이 if/else if/else로 절여질 것이다.
뭐? 하지만 if/else를 리팩토링할 수 있는 switch 문법이 있다고??

const changeSomething (state) => {
switch(state) {
case "hungry" :
eatSomething();
break;
case "full" :
relax();
break;
default :
readBooks();
}
보기에는 간결해보이나, break을 명시하여서 switch문이 이탈하게끔 해야 한다. 즉, if/else 처럼 위에서 아래로 불필요한 연산이 증가하게 된다. 만약 state가 sleepy라면 , 위에서 hungry와 full 까지 연산을 마친 후에야 readBooks()를 실행하게 된다. 피곤하면 자야지;;
그러므로 조건을 다루는데 있어 if/else문과 switch는 성능이 동일하며, 조건이 들어남에 따라 코드를 더럽고 보기 힘들게 만드는 요인이 된다.
그렇다면 조건문 연산에 있어 이 문제를 해결할 방법은 없는 것일까?
바로 action object를 사용하는 것이다!

const changeSomething (state = "default") => {
actions[state]();
}
const actions = {
hungry : () => eatSomething(),
full : () => relax(),
default : () => readBooks(),
}
우리는 객체를 데이터를 담는 공간으로 주로 사용하는데, 일반적인 원시 타입의 데이터가 아니라 함수까지 담을 수 있다! 즉 행동을 담고 있는 객체라고 하여 action object로 불리는 것이다.
if/else나 switch같은 문법은 조건 연산 후 실행할 행동이 외부로 노출되어 있는 상태이다. 하지만 action object를 사용하여 action을 하나의 object로 캡슐화하여 은닉하고 추상화한다. 이를 통해 구조화는 물론 간결한 코드 작성이 가능하다.
객체는 포인터이다. 즉, 조건이 맞니 아니니 계산하는 것이 아니라 객체 안의 property를 가리키는 것이다. 그러므로 객체에 state라는 변수의 데이터와 같은 property를 가리키는 행위는 연산을 1번만 수행해도 된다.
if/else는 어느것도 충족하지 않는 경우에 else로 넘어가지만, 객체는 특성상 존재하지 않는 property를 가리키는 경우 에러를 내뱉는다. default state를 정의한다고 하더라도 객체 내 정의되지 않는 property에 접근하는 것까지 막을 수는 없다. 물론 typescript를 사용하는 경우엔 인수로 받아오는 state에 대해 type을 지정하여 이를 해결할 수 있지만 바닐라 자바스크립트의 경우엔 다음 방법으로 해결할 수 있겠다.
const changeSomething (state = "default") => {
try {
actions[state]();
} catch (err) {
// do something();
}
}
const actions = {
hungry : () => eatSomething(),
full : () => relax(),
default : () => readBooks(),
}
changeSomething("sleepy"); // do Something 실행
이걸 어디다가 쓸 수 있겠냐고? react 쓰는 사람이면 무조건 당장 적용가능하다.
const [userData, setUserData] = useState({
id : undefined,
pw : undefined,
file : undefined
});
const changeState = (e) => {
const id = e.target.name;
const value = e.target?.value;
if (id === "id" || id ==="pw") {
setUserData({...userData, [id] : value});
} else if (id === "reset") {
setUserData({})
} else if (id === "file") {
// file upload logic ...
} else {
// do something ...
}
};
const [userData, setUserData] = useState({
id : undefined,
pw : undefined,
file : undefined
});
const actions = {
profile : (id,value) => setUserData({...userData, [id] : value}),
reset : () => setUserData({}),
file : () => { // do Something ...
},
}
const changeState = (e) => {
const id = e.target.name;
const value = e.target?.value;
try {
actions[id](id,value);
} catch (err) {
// do something ...
}
};
잘 봤습니다~ 조건이 두개 이상일 때도 애매할 수 있겠네요.