no.23 - JS Callback

3188 단어 TILjs비동기TIL

자바스크립트 callstack

비동기적 실행을 알아보기 전에 자바스크립트의 코드 실행과정을 알아보겠습니다.
JavaScript는 싱글스레드 언어이다. callstack이 1개, 한번에 하나의 작업만 수행한다는 의미이다.
call stack은 스택 형태의 저장소로 JavaScript 엔진은 함수 호출과 관련된 정보를 이 곳에서 관리한다.

function stack3() {
  console.log('function stack3 is called')
  throw new Error('에러발생!!')
}

function stack2() {
  console.log('function stack2 is called')
  stack3()
}

function stack() {
  console.log('function stack is called')
  stack2()
}

stack()

3개의 함수 stack , stack2, stack3이 있다.

  • stack 함수 : stack2함수를 호출(call)되고 callstack에 stack2함수가 push된다.
  • stack2 함수 : stack3함수를 호출(call)되고 callstack에 stack3함수가 push된다.
  • stack3 함수 : Error(throw)

stack overflow

function overflow() {
  overflow()
}

overflow()

해당함수는 overflow()함수를 재귀호출하는 코드이다.
실행이 되면 계속 함수가 돌고돌아 callstack에 멈추지 않고 쌓이게 되어 callstack size가 초과되는 오류가 발생한다.

작업 큐(Task Queue)

웹 브라우저에서 16ms 안에 코드의 실행이 완료되지 않으면 화면이 뚝뚝 끊기는 현상이 발생한다. 하지만 모든 작업을 16ms 안에 처리할 수 없다. 그래서 어떤 이벤트가 일어날 때까지 기다리거나, 큰 데이터를 처리의 완료를 기다리거나 이와 같은 상황에서 브라우저는 다음과 같은 순서로 일을 처리한다.

  1. 기다려야 하는 일은 JavaScript엔진에서 처리하지 않고 Web API를 통해 브라우저에 전달한다. 여기서 앞의 작업이 완료되면 실행시킬 callback을 등록한다.
  2. 전달된 일이 완료되면 , 그 결과와 callback을 작업 큐에 추가한다.
  3. 브라우저는 call stack이 비워질 때마다 작업 큐에 추가된 작업을 가져와 callback을 실행한다. 이 과정이 끊임 없이 반복되는데 이를 이벤트 루프(event loop)라고 부른다
setTimeout(() => {
  console.log('B');
}, 0); // 작업 큐에 callback이 추가됨

console.log('A');

A
B

해당 코드에서 브라우저는 setTimeout의 callback을 작업 큐에 등록하고 callstack이 비워진 후 작업 큐의 callback을 가져와 실행한다.

callback

자바스크립트는 코드가 호이스팅된 이후 코드가 작성된 순서대로 동기적으로 우선 실행된다.
하지만 웹에서는 사용자가 어떤 행동을 할지 예측할 수 없기 때문에 비동기적인 코드 실행이 필요하다.

callback 함수란?
다른 함수의 파라미터로 전달되거나 객체의 프로퍼티로 사용 등 나중에 호출되어 사용되는 함수를 의미한다.

console.log('1');
setTimeout(function() {
	console.log('2')
}, 1000)
console.log('3')

// 결과
1
3
2

해당 코드가 동기적으로 실행되면 console.log('1')을 실행하고 setTimeout을 만났을때 브라우저 API로 전달 후 Task Queue에서 대기 하다가 console.log('3')을 실행하고 1초가 지난후 setTimeout 함수를 실행하도록 한다. 이때 비동기적으로 실행된 함수를 callback 함수라고 한다.
코드 실행에 있어 비동기성을 관리하는 일반적인 방법이다.

JavaScript에서 코드가 비동기적으로 작동하는 경우

  • 서버 API 호출
  • DB 호출
  • setTimeout 함수
  • 이벤트 핸들링
  • 무한 루프

callback 지옥

매우 유연하고 편리한 비동기식 언어이지만 비동기적 언어를 순차적으로 사용하면 콜백지옥에 갇히게 된다.

setTimeout(function() {
    console.log('A');
    setTimeout(function() {
        console.log('B');
        setTimeout(function() {
            console.log('C');
            setTimeout(function() {
                console.log('D');
            }, 4000);
        }, 3000);
    }, 2000);
}, 1000);

해당코드는 타이머를 순차적으로 실행하는 callback 함수 구조이다.
콜백지옥의 문제는 우선 가독성이 너무 떨어지고 에러가 발생시 어느 부분에서 문제가 발생했는지 파악 및 수정이 어렵다.

좋은 웹페이지 즐겨찾기