꾸준하게 거북이처럼

비동기 처리 방식: Callback vs Promise vs Async Await 본문

개인공부/JS

비동기 처리 방식: Callback vs Promise vs Async Await

somm12 2022. 8. 2. 14:57

비동기처리는 '특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 것을 말한다.

반대로 동기는 현재 실행 중인 코드가 끝나야 다음 코드를 실행한다. 

JS는 비동기 통신 처리 방식을 지원하며 대표적으로 3가지 방식 callback, promise, async await 이 있다.

callback

callback은 함수의 매개변수인 함수 통해서 어떠한 비동기 처리를 했을때 그 후에 실행되는 함수(나중에 호출되는 함수) callback 함수를 말한다.  

함수로 등록해놓은 후에 어떤 event가 발생했거나 특정 시점에 도달했을 때, 시스템에서 호출하는 함수이다. 파리미터로 함수를 전달받아서 함수의 내부에서 실행된다.

callback 패턴의 문제점은 callback 함수의 중첩이 많아질수록 가독성이 심하게 나빠지는 것으로, callback 지옥이라는 말도 유명하다.

그 유명한 콜백지옥 from Google 이미지검색.

 

callback을 사용하면 비동기 로직의 결과값을 처리하기 위해서는 callback안에서만 처리를 해야하고, 콜백 밖에서는 비동기에서 온 값을 알 수가 없다. 하지만 promise를 사용하면 비동기에에서 온 값이 promise 객체에 저장되기 때문에 코드 작성이 용이해진다.

Promise

promise는 자바스크립트에서 비동기를 간편하게 처리해주는 객체이다. callback함수의 에러처리의 어려움, 중첩으로 인한 복잡도 증가라는 단점으로 ES6에서 프로미스 객체를 지원한다.

프로미스는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용되는데, 즉,일반적으로 웹 애플리케이션을 구현할 때 서버에서 데이터를 요청하고 받아오기 위해 API를 사용하는데,API가 실행되면 서버에다가 데이터 보내달라는 요청을 보내고,여기서 데이터를 받아오기도 전에 마치 데이터를 다 받아온 것 마냥 화면에 데이터를 표시하려고 하면 오류가 발생하거나 빈 화면이 뜬다.이같은 문제를 해결하기 위해 프로미스를 사용한다.

프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있다. 다만 최종 결과를 반환하는 것이 아니고, 미래의 어떤 시점에 결과를 제공하겠다는 '약속'(프로미스)을 반환한다.

Promise는 pending, fullfilled, rejected(대기 이행 실패) 3가지 상태(states)가 존재하고,

  • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

이행을 할 때 (성공시) resolve()를 실행하면 이행상태가 된다.

예제 코드

let myFirstPromise = new Promise((resolve, reject) => {
  // 우리가 수행한 비동기 작업이 성공한 경우 resolve(...)를 호출하고, 실패한 경우 reject(...)를 호출합니다.
  // 이 예제에서는 setTimeout()을 사용해 비동기 코드를 흉내냅니다.
  // 실제로는 여기서 XHR이나 HTML5 API를 사용할 것입니다.
  setTimeout( function() {
    resolve("성공!")  // 와! 문제 없음!
  }, 250)
})

myFirstPromise.then((successMessage) => {
  // successMessage는 위에서 resolve(...) 호출에 제공한 값입니다.
  // 문자열이어야 하는 법은 없지만, 위에서 문자열을 줬으니 아마 문자열일 것입니다.
  console.log("와! " + successMessage)
});
const promise = new Promise((resolve, reject)=> {
	//처리 내용
})

promise.then(
	//resolve가 호출되면 then이 실행
)
.catch(
	//reject가 호출되면 catch가 실행
)
.finally(
	//콜백 작업을 마치고 무조건 실행되는 finally -> 생략가능.
)

이행 상태가 되면 then을 이용하여 처리 결과 값을 받을 수 있고 실패는 reject()로 실행하여 실패상태가 된다.

Async Await

async & await는 비동기시 코드를 동기식으로 표현하여 간단하게 나타내는 것이다.

기존의 비동기 처리 방식인 Callback 함수의 단점을 보완을 위해 Promise사용 -> 하지만 코드가 장황하다는 단점

이런 단점을 해결하기 위해 ES8에서 도입된 비동기 처리 방식의 가장 최신 문법이다.

특징 및 문법

  • 함수의 앞에 async라는 예약어를 붙인다.
  • 함수의 내부 로직 중 HTTP 통신을 하는 비동기 처리 코드 앞에 await를 붙인다.(ex) axios)
  • async & await는 Promise 객체를 반환한다. ( then을 사용할 수 있음 )
  • **비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await가 의도한 대로 동작한다.

예제 코드

async function getText() {
    await delay(2000);
    return 'abc';
}
getText().then(console.log)// 결과 : abc

예외 처리 코드 ( try, catch 구문 사용)

async function loadData(){
    try {
    	const result = await fetchData();//axios로 API 호출하는 경우도 될 수 있겠다.
        console.log(result);
    } catch(e){
    	console.log(e);
    }
    
}

Promise는 아무래도 클래스이다 보니 함수형 컴포넌트가 대세가 된 지금은 함수에 바로 적용 가능한 async-await가 문법적으로 더 잘 맞고 async-awiat가 비동기 코드를 동기 형태로 만들어 가독성을 더 높이는 것에 큰 차이가 있다.

 

참고자료

 

비동기적 방식 처리 방법 (Callback, Promise, async &await)

비동기적 방식 처리 방법 Callback 함수 Promises async & await Callback 함수 Callback 이란? 다른 함수가 실행을 끝낸 뒤 실행(call back)되는 함수(⇒ 나중에 호출되는 함수)를 말한다. 다시 말해 코드를..

hi-zini.tistory.com

 

 

Promise - JavaScript | MDN

Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.

developer.mozilla.org

 

Comments