본문 바로가기
Frontend

Javascript 디자인패턴 - 1. Callback 패턴

by 구라미 2021. 4. 14.

Callback 패턴

콜백은 나중에 실행할 부차 함수에 인자로 넣어지는 함수입니다. 자바스크립트에서 함수는 일급 객체로 여겨지기 때문에 함수도 다른 함수에 인자로 전달할 수 있습니다. 여기서 콜백이 실행될 나중 시점이 부차 함수의 실행 완료 이전이면 전부 동기 콜백이지만, 비동기 콜백도 적용기법은 같습니다. 프로미스는 비동기 콜백에서만 사용됩니다. 콜백 패턴은 자바스크립트에서 정말 중요한 패턴입니다. 

function getResult(callback) {
    console.log("result");
	callback(); //인자로 넘겨받은 add() 함수가 실행된다.
}

//인자로 넣어지는 콜백함수
function add(a, b) {
	return a + b;
}

콜백 패턴을 테스트할 때 확인해야 할 점으로는

  • 콜백 실행횟수가 정확해야 한다.
  • 콜백이 실행될 때마다 알맞은 인자가 전달되어야 한다.

이런 것들이 있는데요, 또한 콜백 패턴을 사용할 때는 두 가지를 조심해야 하는데 하나는 콜백 지옥과 나머지 하나는 this가 참조하는 값입니다.

1) 콜백지옥

익명 콜백 함수를 남발하면 함수가 화살모양으로 계속 중첩되는 모습을 볼 수 있게 되는데요. 그런 콜백 지옥이 생기게 되면 가독성도 떨어지고 유지보수가 힘들어지며, 단위 테스트는 사실상 불가능하게 됩니다. 콜백 지옥의 예시로는 아래와 같은 코드를 볼 수 있어요.

fs.readdir(source, function (err, files) {
  if (err) {
    console.log('Error finding files: ' + err)
  } else {
    files.forEach(function (filename, fileIndex) {
      console.log(filename)
      gm(source + filename).size(function (err, values) {
        if (err) {
          console.log('Error identifying file size: ' + err)
        } else {
          console.log(filename + ' : ' + values)
          aspect = (values.width / values.height)
          widths.forEach(function (width, widthIndex) {
            height = Math.round(width / aspect)
            console.log('resizing ' + filename + 'to ' + height + 'x' + height)
            this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
              if (err) console.log('Error writing file: ' + err)
            })
          }.bind(this))
        }
      })
    })
  }
})

계속 첩첩이 겹친 함수 때문에 매우 가독성이 안 좋고 코드를 이해하기가 힘든 걸 확인할 수 있습니다. 코드를 작성할 때 이러한 중첩 콜백 지옥을 만들지 말고, 차라리 눌러서 편 코드가 훨씬 낫습니다.

2) this가 참조하는 값 주의하기

Javascript에서 this가 참조하는 값은 때때로 달라질 수 있는데요. 자바스크립트에서 this키워드는 bit를 실행하는 객체를 말합니다. 모든 자바스크립트 함수는 실행할 때 this는 현재의 실행 콘텍스트를 참조하는데요. 실행 콘텍스트는 어떻게 함수를 호출하는 지를 뜻합니다. 즉 this 키워드는 함수 실행 시 결정되므로, this를 이해하기 위해서는 함수가 언제 어떻게 어디서 호출되는지 알면 됩니다. 그렇기 때문에 this는 가끔 전혀 엉뚱한 값을 참조할 수 있습니다. 

댓글