Javascript 콜백함수, Promise, async, await

📌 콜백함수

🔔 동기적 VS 비동기적

  • 동기적(Synchronous) : 일이 처리될 때 얼마나 걸리는지는 상관없이 기다렸다가 이후일을 처리.
  • 비동기적(Asynchronous) : 병렬적으로 동시에 여러가지 일을 처리

이미지 출처 : https://evan-moon.github.io/2019/09/19/sync-async-blocking-non-blocking/

🔔 Javascript의 동기적 성질

  1. 자바스크립트는 싱글 스레드이다.
  2. 자바스크립트는 동기적으로 동작한다.(synchronous)
    → 호이스팅이 된 이후부터 코드가 작성한 순서에 맞춰서 하나씩 동기적으로 실행된다.
    ※ 호이스팅 : var, function 등의 선언이 최상단으로 올려져 작동하는 것.

자바스크립트에서 비동기 처리는 왜 필요할까?

만약 서버로부터 데이터를 받아올 때 비동기로 처리하지 않고 동기적으로 이를 구성한다면 데이터를 받아 오기까지 기다린 다음 브라우저가 실행이 될 것이다.

동기적으로 처리된다면 위와 같은 로딩 화면을 자주 마주쳐야 할 것이다.
→ 이런 불편을 없애기 위해 데이터를 수신하는 코드와 페이지를 표시하는 것을 비동기적으로 처리를 한다. 이 때 Javascript에서는 콜백 함수를 이용한다.

🔔 콜백함수란?

콜백함수(Callback function) : 나중에 호출할 함수, 어떤 이벤트가 발생한 후 수행될 함수

  • 콜백은 자바스크립트에서 비동기 동작을 처리하는 좋은 방법이다.
  • 콜백함수는 문법적 특징을 가지고 있는 것이 아니라, 호출방식에 의한 구분이다.

콜백 함수를 사용하는 이유

  1. 사용자 이벤트 처리
    브라우저 화면에서 발생하는 사용자의 이벤트는 예측이 불가능하다.
    따라서 이런 화면이벤트를 관리담당하는 녀석에게 우리는 특정이벤트가 발생할 때 호출을 원하는 내용을 callback 함수에 전달하게 된다.

  2. 네트워크 응답 처리
    화면단에서 서버에게 요청을 보냈을 때, 그 응답이 언제 올지 알 수 없다.
    따라서 이런 서버에 대한 응답처리 등도 비동기적으로 처리해야 한다.

  3. 의도적으로 시간 지연을 사용하는 기능(알람 등)

🔔 콜백 지옥

그러나 위와 같이 콜백 함수 연달아서 사용하다보면 의도하지 않은 콜백 지옥 현상이 나타날 수 있다.

콜백 지옥
: 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 깊어지는 현상.

이러한 콜백 지옥은 가독성이 떨어지고 코드 수정이 어렵다는 단점이 있다. 이러한 콜백 지옥을 탈출하기 위해서 PromiseAsync + Await가 사용된다.



📌 프로미스(Promise)

🔔 프로미스(Promise)

프로미스
: 자바스크립트에서 제공하는 비동기적 이벤트를 간편하게 처리할 수 있도록 도와주는 객체이다.(Object).

Promise 문법

const promise = new Promise((resolve, reject) => {
  // code 작성
  // Promise는 Promise 생성자 함수를 통해 인스턴스화하여 사용하고,
  // 비동기 작업을 수행할 콜백 함수(resolve, reject)를 인자로 받는다.
});
  • resolve(value) : 일이 성공적으로 끝난 경우 그 결과를 나타내는 value와 함께 호출
  • reject(error) : 일이 실패하거나 에러 발생 시 에러 객체를 나타내는 error와 함께 호출

Promise 상태(states)

프로미스를 사용할 때 알아야 하는 가장 기본적인 개념으로 프로미스의 상태(states)가 있다. 여기서 말하는 상태란 프로미스의 처리 과정을 의미하고, new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖는다.

  1. Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태 (Result = undefined)
  2. Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태 (resule = value)
  3. Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태 (Result = error)

Promise 후속 처리 메서드

  1. .then
    then 메소드는 두 개의 콜백 함수를 인자로 전달 받는다. 첫 번째 콜백 함수는 성공(fulfilled, resolve 함수가 호출된 상태) 시 호출되고 두 번째 함수는 실패(rejected, reject 함수가 호출된 상태) 시 호출된다.

  2. .catch
    예외(비동기 처리에서 발생한 에러와 then 메소드에서 발생한 에러)가 발생하면 호출된다.

  3. .finally
    resolve, reject, 예외로 발생한 error 등 상관 없이 모든 과정이 종료되었을 때 호출된다.

function1()
  .then(
    resolve(){}, // promise의 state = fulfilled일 때 resolve콜백 함수 동작.
    reject(){}) // promise의 state = rejected일 때 reject콜백 함수 동작.
  .catch(function error(){}) // 비동기적인 일 처리 중 Error 발생 시 해당 error 콜백 함수 동작.(state = rejected)
  .finally(function final(){}); // function1의 모든 비동기적 과정이 종료된 후 final 콜백 함수 동작.

Promise 체이닝

비동기 함수의 처리 결과를 가지고 다른 비동기 함수를 호출해야 하는 경우, 함수의 호출이 중첩(nesting)이 되어 복잡도가 높아지는 콜백 헬이 발생한다. 프로미스는 후속 처리 메소드를 체이닝(chainning)하여 여러 개의 프로미스를 연결하여 사용할 수 있다. 이로써 콜백 헬을 해결한다.

function1()
  .then(() => function2())
  .then(() => function3())
  .then(() => function4()) // 이렇게 후속 처리 메소드를 체이닝할 수 있다.
  .catch(() => error())
  .finally(() => final())


📌 async / await

async, await

  • async : 프로미스를 더 간편하게 쓸 수 있는 문법적 설탕(syntactic sugar).
    → 함수 앞에 async를 붙여서 사용하게 되면 결과를 직접 반환하는게 아니라 프로미스를 반환한다.
  • await : async 함수 내에서만 사용할 수 있는 키워드.

async, await 문법

async function promise() { // function 앞에 async를 붙이면 promise가 반환된다.
  await function(); // await를 적으면 비동기적인 처리가 모두 완료될때까지 기다렸다가 완료되면 함수가 동작한다.
  
  return result;
}

async, await 특징

  1. async 키워드는 꼭 function 앞에 사용해야 한다.
  2. await는 async function 안에서만 쓸 수 있습니다.


📌 참고한 사이트

https://velog.io/@kimdlzp/%EC%BD%9C%EB%B0%B1callback
https://joshua1988.github.io/web-development/javascript/promise-for-beginners/
https://dev.to/yatharth1706/promises-4a0
https://poiemaweb.com/es6-promise

좋은 웹페이지 즐겨찾기