본문 바로가기
IT/javascript

[JS] if else 리펙토링 (객체 + 함수)

by 내일은교양왕 2024. 4. 29.

아래 Youtube 영상의 내용을 거의 그대로 가져온 페이지입니다.

문제가 될 경우 삭제하겠습니다.


 

 

결론

if else가 중복되면 switch case로 변경해보자.

나름의 규칙성을 발견하기 쉬워진다.

규칙을 발견하면 이를 바탕으로 객체로 추출 가능하다

 

객체를 함수 외부로 분리하면 공통로직 / 분기별 실제 동작 정의가 분리되어 읽기도 수월해지고, 수정사항이 생겨도 공통로직은 건드리지 않아도 되어 편리하다. 리펙토링할 소재를 발견할 수 있고, 소재가 발견되지 않더라도 객체형태로 전환한 그 자체로 이미 꽤 깔끔하다

 

분기가 함수일 경우 구조 분해 할당 (destructured assignment)을 이용해 상황별 필요한 데이터 파악이 한결 용이해짐

 

# if else 로직

const naverLogin = (id) => {
  return 'naver'
}

const kakaoLogin = (id) => {
  return 'kakao'
}

const googleLogin = (id) => {
  return 'google'
}

const facebookLogin = (id) => {
  return 'facebook'
}

const socialLogin = (where, id) => {
  let domain;
  if (where === 'naver') {
    domain = naverLogin(id)
  } else if (where === 'kakao') {
    domain = kakaoLogin(id)
  } else if (where === 'google') {
    domain = googleLogin(id)
  } else if (where === 'facebook') {
    domain = facebookLogin(id)
  }
  return `${domain} ${id}`
}

 

가독성이 떨어져서 switch로 변경

const socialLogin = (where, id) => {
  let domain;
  switch(where) {
    case 'naver'
      domain = naverLogin(id)      
      break
    case 'kakao'
      domain = kakaoLogin(id)      
      break
    case 'google'
      domain = googleLogin(id)      
      break
    case 'facebook'
      domain = facebookLogin(id)      
      break
  }
  return `${domain} ${id}`
}

 

 

조금 괜찮아 졌지만 break가 거슬림, break를 제거하기 위해 새로운 함수를 만들어 제거

 

const executeLogin = (where, id) => {
  switch(where) {
    case 'naver'
      return naverLogin(id)      
    case 'kakao'
      return kakaoLogin(id)   
    case 'google'
      return googleLogin(id)   
    case 'facebook'
      return facebookLogin(id)   
  }
}

const socialLogin = (where, id) => {
  const domain = executeLogin(where, id)
  return `${domain} ${id}`
}

 

 

함수만 남아 있기에 object로 변경

const socialLoginMap = {
  naver: naverLogin,
  kakao: kakaoLogin,
  google: googleLogin,
  facebook: facebookLogin,
}

const socialLogin = (where, id) => {
  const domain = socialLoginMap[where](id)
  return `${domain} ${id}`
}

 

if else의 Time Complex는 O(n)이지만, object map 형식으로 처리하면 O(1)로 되어서 성능적으로도 우세하다.

 

# 구간별 적용 사례

const getSeasion = month => {
  if(month >= 3 && month <= 5) return 'spring'
  if(month >= 6 && month <= 8) return 'summer'
  if(month >= 9 && month <= 11) return 'fall'
  if(month >= 12 || month <= 2) return 'winter'
}

 

가독성이 떨어져서 switch로 변경

const getSeasion = month => {
  switch(month)
    case 3:
    case 4:
    case 5:
      return 'spring'
    case 6:
    case 7:
    case 8:
      return 'summer'
    case 9:
    case 10:
    case 11:
      return 'fall'
    case 12:
    case 1:
    case 2:
      return 'winter'
}

 

3개씩 나눈다는 규칙성을 이용해서 다시 리펙토링 해보자

const getSeasion = month => {
  const shiftedMonth = (month + 9) % 12 // (month -3 + 12) % 12
  switch(month)
    case 0:
    case 1:
    case 2:
      return 'spring'
    case 3:
    case 4:
    case 5:
      return 'summer'
    case 6:
    case 7:
    case 8:
      return 'fall'
    case 9:
    case 10:
    case 11:
      return 'winter'
}

 

이젠 보인다!! 3으로 나눈 값에 따라 값을 반환해 주면 된다.

const getSeasion = month => {
  const shiftedMonth = Math.floor((month + 9) % 12 / 3)
  switch(month)
    case 0:
      return 'spring'
    case 1:
      return 'summer'
    case 2:
      return 'fall'
    case 3:
      return 'winter'
}

 

객체로 바꾸어 보자

const seasonMap = {
  0: 'spring',
  1: 'summer',
  2: 'fall',
  3: 'winter'
}
const getSeasion = month => {
  const shiftedMonth = Math.floor((month + 9) % 12 / 3)
  return seasonMap[shiftedMonth]
}

 

객체를 보니 배열로도 할 수 있다라는 알 수 있다.

const seasons = ['spring', 'summer', 'fall', 'winter']
const getSeasion = month => {
  const index = Math.floor((month + 9) % 12 / 3)
  return seasons[index]
}

 

 

 

https://youtu.be/p0YEviesgRM?si=xsjnJOQVIbgzB3tI