제어의 역전(IoC)이란 뭘까?

filter라는 메서드를 구현한다고 했을 때, 아래와 같이 구현을 해본다고 하자.

function filter(array) {
  let newArray = []
  for (let index = 0; index < array.length; index++) {
    const element = array[index]
    if (element !== null && element !== undefined) {
      newArray[newArray.length] = element
    }
  }
  return newArray
}

// 사용처
filter([0, 1, undefined, 2, null, 3, 'four', ''])


만약 위의 코드에서 0만 필터링 해주는 기능을 추가한다고 하면 어떨까?
filter 메서드에 매개변수를 추가하고, 내부의 분기문을 하나 더 추가하고 하며 점점 더 filter 함수가 비대해진다. 이렇게 비대해지는 함수는 유지보수에 취약하다.

제어의 역전 사용해보기

function filter(array, filterFn) {
  let newArray = []
  for (let index = 0; index < array.length; index++) {
    const element = array[index]
    if (filterFn(element)) {
      newArray[newArray.length] = element
    }
  }
  return newArray
}

filter(
  [0, 1, undefined, 2, null, 3, 'four', ''],
  el => el !== null && el !== undefined
)


위와 같이 구현하게 된다면 filter 함수는 여러 요구사항에 맞춰서 대응될 필요가 없다.
즉 필터링하는 책임을 filter메서드에서 제어하는게 아니라, 사용처에 위임한 것이다. 그래서 제어의 역전이다.

그렇다고 무조건 제어의 역전이 정답일까?
언제나 그렇듯 과한 추상화는 경계하자. 유즈케이스가 많아질 때 추상화를 해도 늦지 않다.