if else 리팩토링
리팩토링 관련 영상이다. 해당 영상을 참고해 실제로 회사에서의 reducer코드를 개선했다. 기타 다른 코드도 객체나 Map으로 개선시키는 등 실제로 유익한 팁이었다.
조건에 따른 소셜로그인이다.
const naverLogin = (id) => {
// ~~
return "naver"
}
const kakaoLogin = (id) => {
// ~~
return "kakao"
}
const facebookLogin = (id) => {
// ~~
return "facebook"
}
const googleLogin = (id) => {
// ~~
return "google"
}
const socialLogin = (where, id) => {
let domain;
if(where === 'naver') {
domain = naverLogin(id)
} else if(where === 'kakao') {
domain = kakaoLogin(id)
} else if(where === 'facebook') {
domain = facebookLogin(id)
} else if(where === 'google') {
domain = googleLogin(id)
}
return `${domain} ${id}`
}
console.log(socialLogin('naver', 'malza')) // naver malza
console.log(socialLogin('google', 'malza')) // google malza
if와 else if문은 switch로 대체 가능하다.
const socialLogin = (where, id) => {
let domain;
switch (where) {
case 'naver':
domain = naverLogin(id)
break
case 'kakao':
domain = kakaoLogin(id)
break
case 'facebook':
domain = facebookLogin(id)
break
case 'google':
domain = googleLogin(id)
break
}
return `${domain} ${id}`
}
여기서 switch부분만 함수로 쏘옥 빼보자.
const excuteLogin = (where, id) => {
switch (where) {
case 'naver':
return naverLogin(id)
case 'kakao':
return kakaoLogin(id)
case 'facebook':
return facebookLogin(id)
case 'google':
return googleLogin(id)
}
}
const socialLogin = (where, id) => {
const domain = excuteLogin(where, id);
return `${domain} ${id}`
}
역시 잘 동작한다. 함수에 return만 남아있으니 이를 객체로 맵핑해보자!
const naverLogin = (id) => {
// ~~
return "naver"
}
const kakaoLogin = (id) => {
// ~~
return "kakao"
}
const facebookLogin = (id) => {
// ~~
return "facebook"
}
const googleLogin = (id) => {
// ~~
return "google"
}
const SocialLoginMap = {
'naver': naverLogin,
'kakao': kakaoLogin,
'facebook': facebookLogin,
'google': googleLogin,
}
const socialLogin = (where, id) => {
const domain = SocialLoginMap[where](id);
return `${domain} ${id}`
}
음~ 보기 좋다.
const getSeason = month => {
if(month >= 3 && month <= 5) return '봄'
else if(month >= 6 && month <= 8) return '여름'
else if(month >= 9 && month <= 11) return '가을'
else if(month >= 12 || month <= 2) return '겨울'
}
역시 switch case문으로 바꿔보자.
const getSeason = month => {
switch(month) {
case 3:
case 4:
case 5:
return '봄'
case 6:
case 7:
case 8:
return '여름'
case 9:
case 10:
case 11:
return '가을'
case 12:
case 1:
case 2:
return '겨울'
}
}
12 다음 1,2가 나오는것도 그렇고, case가 3부터 시작하는것도 그렇고 불편하다. case를 0부터 시작하도로록 3을 빼면?
case 1, 2였던 친구들이 -2, -1이 되서 또 불편하다~😥 그래도 일단 0 ~ 9 까지 case문이 생성되겠다.
const getSeason = month => {
const shiftedMonth = month - 3
switch(shiftedMonth) {
case 0:
case 1:
case 2:
return '봄'
case 3:
case 4:
case 5:
return '여름'
case 6:
case 7:
case 8:
return '가을'
case 9:
case -2:
case -1:
return '겨울'
}
}
-2와 -1 두 친구가 규칙에 맞게 10, 11이 세팅되면 참 좋겠다.
// 기존의 const shiftedMonth = month - 3 에서 변형
const getSeason = month => {
const shiftedMonth = (month + 9) % 12
switch(shiftedMonth) {
case 0:
case 1:
case 2:
return '봄'
case 3:
case 4:
case 5:
return '여름'
case 6:
case 7:
case 8:
return '가을'
case 9:
case 10:
case 11:
return '겨울'
}
}
이제 shiftedMonth는 1월이 오면 10, 2월이 오면 11이 된다. 나머지 애들은 기존 그대로다!
여기서 또 규칙을 찾을 수 있다. 0~2는 3으로 나누면 몫이 0, 3~5는 1, 6~8은 2, 9~11은 3이 떨어진다.
const getSeason = month => {
const shiftedMonth = Math.floor((month + 9) % 12 / 3) // 소수점 아래를 버리면 딱 떨어진다.
switch(shiftedMonth) {
case 0:
return '봄'
case 1:
return '여름'
case 2:
return '가을'
case 3:
return '겨울'
}
}
ohhhh my goddd! 이제 객체로 맵핑 해 보자.
const SeasonMap = {
0: '봄',
1: '여름',
2: '가을',
3: '겨울',
}
const getSeason = month => {
const shiftedMonth = Math.floor((month + 9) % 12 / 3)
return SeasonMap[shiftedMonth]
}
와우~ 잘 된다. 여기서 0,1,2,3 을 배열로 바꿔버리면
const seasons = ['봄','여름','가을','겨울']
const getSeason = month => seasons[Math.floor((month + 9) % 12 / 3)]
오마갓~ 가독성이 많이 올라갔다. 리팩토링에서 규칙을 찾는것이 중요해 보인다.
0 미만 : 몹시 추워용
0 이상 10미만 : 추워용
10 이상 20미만 : 선선해용
20 이상 30미만 : 조금 더워용
30 이상 40미만 : 더워용
40 이상: 몹시 더워용
const getWeather = (temperature) => {
if(temperature < 0) return '몹시 추워용'
if(temperature < 10) return '추워용'
if(temperature < 20) return '선선해용'
if(temperature < 30) return '조금 더워용'
if(temperature < 40) return '더워용'
return '몹시 더워용'
}
역시 switch로 바꿔!
const getWeather = (temperature) => {
const score = Math.floor(temperature / 10)
switch (score) {
case 0:
return '추워요'
case 1:
return '선선해용'
case 2:
return '조금 더워용'
case 3:
return '더워용'
default: {
if(score < 0) return '몹시 추워요'
return '몹시 더워요'
}
}
}
default가 매우 몹시 거슬리므로, 이 또한 규칙성을 찾는게 관건으로 보인다.
// 이렇게 바꾸고 싶다.
const getWeather = (temperature) => {
const score = Math.floor(temperature / 10) // 이 부분을 건드려야겠다.
switch (score) {
case -1:
return '몹시 추워요'
case 0:
return '추워요'
case 1:
return '선선해용'
case 2:
return '조금 더워용'
case 3:
return '더워용'
case 4:
return '몹시 더워용'
}
}
Math.max(Math.floor(temperature / 10), -1)
// -55도를 10으로 나누면 -5.5고, 이를 floor하면 -6이다. 그리고 max를 구하면 -1이 나온다. -1보다 작으면 반드시 -1이 반환될것이다.
Math.min(Math.max(Math.floor(temperature / 10), -1), 4)
// 40도 이상이면 min으로 4와 비교한다.
즉, 0미만은 -1로 수렴하도록 강제하고, 4이상은 모두 4로 수렴한다. 자! 이제 또 객체로 바꿀수 있을것 같다.
const TemperatureMap = {
-1: '몹시 추워요',
0: '추워요',
1: '선선해용',
2: '조금 더워용',
3: '더워용',
4: '몹시 더워용',
}
const getWeather = (temperature) => {
return TemperatureMap[Math.min(Math.max(Math.floor(temperature / 10), -1), 4)]
} // -1 이 문제네~
아차차! -1때문에 에러를 뱉는다! 그냥 string 처리 해도 된다! 근데 난 0으로 바꾸고 싶어! 하면?
const TemperatureMap = {
0: '몹시 추워요',
1: '추워요',
2: '선선해용',
3: '조금 더워용',
4: '더워용',
5: '몹시 더워용',
}
const getWeather = (temperature) => {
return TemperatureMap[Math.min(Math.max(Math.ceil(temperature / 10), 0), 5)] // 0과 5로 수렴하게끔 한다.
}
역시 0~5 인덱스라면 배열로 가능하겠다.
const Temperatures = ['몹시 추워요', '추워요', '선선해용', '조금 더워용', '더워용', '몹시 더워용']
const getWeather = (temperature) => {
return Temperatures[Math.min(Math.max(Math.ceil(temperature / 10), 0), 5)] // 0과 5로 수렴하게끔 한다.
}
이후는 마찬가지로 함수로 빼거나 arrow function의 특징인 return 제거같은것으로 더 줄일 수 있겠다.
switch case로 쓰여진 reducer를 프로젝트에서 객체 매핑으로 바꾼 결과다.
const reducerMap = {
[GridContants.LAYOUT]: produce((state, { value }) => {
state.layout = value;
}),
//...
[GridContants.REMOVE_ITEM]: produce((state, { index }) => {
state.layout.splice(index, 1);
}),
[GridContants.CHANGE_INFO]: produce((state, { title, fontSize, color, index }) => {
state.layout[index].i = title;
state.layout[index].fontSize = fontSize;
state.layout[index].color = color;
}),
};
export const GridReducer = (state, action) =>
reducerMap[action.type]?.(state, action) || state;
보기 좋아진거 같은가? :)