데이터를 매핑하는 작업을 하다보니 프론트엔드 개발의 대부분이 분기처리 작업이 아닌가 하는 생각이 들었다.
최근 예시로 프로젝트에서 A컬럼에서 들어오는 데이터의 종류가 총 5개였고, A컬럼 데이터에 따라 보여줘야하는 컬럼 종류를 다르게 매핑해야하는 로직을 구현해야하는 일이 있었다.
아직 신입의 위치여서 그런 업무를 맡은지는 모르겠지만, 선임이 짠 코드를 보아도 조건 처리는 대부분 사용되는 부분이었다.
분기 처리를 어떤 방법으로 하면 가독성이 좋고 유지보수하기 좋을지 많은 생각이 들었고, 여러가지 조건 처리 방법을 한번 나열해보고자 한다.
예로 사용할 데이터는 아래와 같다. type에 들어오는 데이터에 따라 item[type]에 해당하는 값을 return 해주는 방식의 로직을 구현해야 한다.
data:{ type: A, // type에는 A, B, C, D, E 중 하나가 들어온다. itemA: 1, itemB: 2, itemC: 3, itemD: 4, itemE: 5 }
위에서 return은 itemA의 값인 1이 되어야 한다.
먼저 제일 대중적으로 사용되는 else if문이다.
const useIfElse = (data) =>{
if(data.type === 'A'){
return data.itemA;
}else if(data.type === 'B'){
return data.itemB;
}else if(data.type === 'c'){
return data.itemC;
}else if(data.type === 'D'){
return data.itemD;
}else if(data.type === 'E'){
return data.itemE;
}
return 'NO_ITEM';
}
이 방법의 제일 큰 장점은 많은 사람들이 사용하는 방법이기 때문에 인수인계없이 코드를 처음 보는 사람이더라도 이 코드가 조건을 처리하는 것이라는 사실을 알 수 있다.
하지만 위 처럼 조건문을 한번 들어가서 바로 값을 return 하는 경우라면, else문을 사용하지 않고 if문으로만 구성하여 코드를 작성하는 것이 더 깔끔할 수 있다.
아래의 코드는 if문만 사용하여 작성한 코드이다.
const useIf = (data) =>{
if(data.type === 'A'){
return data.itemA;
}
if(data.type === 'B'){
return data.itemB;
}
if(data.type === 'c'){
return data.itemC;
}
if(data.type === 'D'){
return data.itemD;
}
if(data.type === 'E'){
return data.itemE;
}
return 'NO_ITEM';
}
코드가 조건별로 영역이 분리되어 있는 것 처럼 보이기도 하고, 불필요한 문자가 제거되어 가독성이 좋아진 것을 확인할 수 있다. 연속되게 검증할 값이 아니라면, else문을 제거하고 if문 만으로 값을 return하는 방법도 좋을 것 같다.
const useSwitch = (data) => {
switch (data.type)
case 'A': return data.itemA;
case 'B': return data.itemB;
case 'C': return data.itemC;
case 'D': return data.itemD;
case 'E': return data.itemE;
default: 'NO_ITEM';
}
switch문이 꽤나 깔끔해보인다. 예전에는 비교 조건문이 3개 이상일 때는 switch문이 성능이 좋다는 이점이 있었다. 하지만 컴퓨터의 성능이 좋아졌기 때문에 성능의 차이는 현재 무의미하다고 한다.
그렇다면 어떤 방법을 사용하는게 좋을까? 지금 해결해야하는 문제는 일치여부에 따라 값을 return 하는 것이기 때문에 switch문을 사용할 수 있지만, 크거나 작음 그리고 불일치관련 조건의 경우 switch문에서 사용할 수 없기 때문에 문제에 따라서 취사 선책하여 사용하면 되겠다. 혹은 컨벤션에 따라서 사용하면 되겠다.
위의 3가지 방법은 일반적으로 잘 알려진 방법이었지만 올해 새로 알게된 Map 객체를 활용한 조건문 처리 방법도 소개해보고자 한다.
const useMap = (data) => {
const itemTypeList = new Map([
['A', data.itemA],
['B', data.itemB],
['C', data.itemC],
['D', data.itemD],
['E', data.itemE],
['DEFAULT', 'NO_ITEM']
]);
return itemTypeList.get(data.type) || itemTypeList.get('DEFAULT')
}
Object가 아닌 Map 객체로 예시를 가져온 이유는 Object의 key는 숫자 혹은 문자만 사용가는 하지만 Map 객체의 경우 형태가 자유롭기 때문이다. 더불어 Map 객체의 내장 함수(get)로 값을 불러오기 간편하다는 장점이 있다.
이 방법의 단점은 Map 객체로 조건 처리를 하지 않은 사람의 경우 코드를 해석해야하는 시간이 필요하다. 인수인계가 잘 이루어 질 수 있는 상황이라면 사용하기 괜찮은 방법이 될 수 있을 것 같다.
현재 조건의 경우 간단하게 구성되어 있어 Map의 사용이 불필요할 수 있다. 분기문이 if문으로 해결하기 복잡한 상황일 때 한번 고려해보면 좋을 것 같다.
상황에 맞게 사용하자!