[js] 안다고 생각했는데 몰랐던 바로 그 callback

hyobbang·2022년 9월 18일
0
post-thumbnail

해당 포스팅은 드림코딩 엘리님의 강의를 참고하여 만들어졌다.

callback? 그거 이거 아냐?

전에 뉴딜에서의 프로젝트 당시 jsp에서 ajax를 호출하고 나서 return 값을 핸들링하는 함수 이름에 callback을 붙여서 사용했었다.
대략적으로 알긴 안다... callback이 뭔지...
비동기처리 후에 return 값을 핸들링 하는 함수...
그러나 느낌적 느낌으로만 아는 그 느낌...
너무 찝찝했다.
특히나 promise를 공부하고 나서 callback을 제대로 모른다는 사실이 더 체감됐다.


그래서 callback이 뭔데?

callback 함수를 사용하는 방식은 언어마다 다를 수 있다.

js에서의 callback은 이러하다.
어떤 함수의 인자로 또다른 함수가 들어가는 것.
이때 인자에 들어가있는 함수를 callback 함수라고 표현한다.

내가 callback에 대해 전혀 몰랐다는 걸 깨달은 건 바로 이 지점이다.
callback은 비동기일 때만 사용하는 것이 아니다!

  • 동기적 callback
function printImmediately(print) {
  print();
}

printImmediately(() => console.log("hello"));

위 소스에서 print라는 callback 함수가 사용되었다.
그리고 print 함수는 콘솔에 hello를 찍게 한다.
보다시피 여기서 비동기적 방식이 쓰인 곳은 없다.
이렇게 동기적인 상태여도 callback은 쓰일 수 있다.

  • 비동기적 callback
function printWithDelay(print, timeout) {
  setTimeout(print, timeout);
}

printWithDelay(() => console.log("async callback"), 2000);

위 소스에서는 print라는 callback 함수가 timeout이라는 변수와 함께 인자로 사용되었다.
print 함수는 콘솔에 async callback을 찍게 하고,
timeout 자리에 적은 2000으로 인해 2초 후에 콘솔에 찍히게 된다.
setTimeout은 비동기 방식으로 처리되는 메소드이기 때문에 위 callback이 내가 원래 알고 있던 방식의 callback이라고 할 수 있다.

콜백지옥

프론트 초짜의 흔히 하는 실수... 콜백지옥이란 무엇일까?
예제 코드를 통해 살펴보자.

class UserStorage {
  loginUser(id, password, onSuccess, onError) {
    setTimeout(() => {
      if (
        (id === 'hyobbang' && password === 'great') ||
        (id === 'coder' && password === 'academy')
      ) {
        onSuccess(id);
      } else {
        onError(new Error('not found'));
      }
    }, 2000);
  }

  getRoles(user, onSuccess, onError) {
    setTimeout(() => {
      if (user === 'hyobbang') {
        onSuccess({ name: 'hyobbang', role: 'admin' });
      } else {
        onError(new Error('no access'));
      }
    }, 1000);
  }
}

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser( //로그인 진행
  id,
  password,
  user => { //loginUser 성공시
    userStorage.getRoles( 
      user,
      userWithRole => { //getRoles성공
        alert( //로그인이 잘 됐다는 메세지 출력
          `Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
        );
      },
      error => { //getRoles실패
        console.log(error);
      }
    );
  },
  error => { //loginUser 실패시 
    console.log(error);
  }
);

위 코드는 setTimeout을 이용해 딜레이를 줘서 서버와의 통신이 이루어지는 것처럼 제작한 간단한 로그인 기능이다.

보다시피 작동은 아주 잘한다.
그럼 이 코드가 대체 뭐가 문제인 걸까?

  1. 가독성이 떨어진다.
  2. 에러가 발생했을 때 디버깅을 하기가 어렵다.
  3. 유지보수가 어렵다

사실 가독성이 떨어지면 연쇄적으로 일어날 수 밖에 없는 단점들이다.
코드 작성은 나만 이해하게끔 짜는게 아니고,
최대한 설명을 하지 않고도 팀원들이 이해를 할 수 있게끔 짜야하기 때문에 가독성을 반드시 챙겨야한다.

profile
매일 따끈따끈한 빵을 굽는 베이커리처럼 코딩하기

0개의 댓글