Programming/Java Script

📌[JS] Promise 와 async/await

감귤밭호지차 2023. 3. 21. 11:00

 

JavaScript 기본적으로 동기적 언어이지만, V8 엔진과 같은 JS 엔진의 도움?으로 브라우저에서 자동으로 비동기적 수행을 할 수 있습니다. Promise 는 우리가 비동기 흐름을 제어하기 위한 방법이라고 이해하면 될 것 같습니다. ]

 

자바스크립트 동기 비동기

Asynchronous JavaScript_MDN

벨로퍼트와 비동기 처리 다루기

 

Promise

# callback 함수와 promise 의 차이점 

이전에는 callback 함수를 사용해서 비동기 처리를 해왔지만 코드를 잘 작성하지 않으면 어디서 어떤 흐름으로 코드가 작성되는지 파악하기 어렵고, Callback Hell 처럼 쓸데없이 코드가 길어지는 이슈가 발생했습니다. 코드 실행의 성공과 실패에 대해서 규격화된 포멧을 따르는 것이 아니라, 개발자 간에 관습법 처럼 합의된 callback 에러 헨들링을 사용해왔던 것 입니다. Promise 가 표준이 되기 전에는 라이브러리마다 처리방식이 달라서 문제가 많았기 때문에 공통된 인터페이스의 필요성을 느끼고 탄생한 것이 Promise 입니다. 

 

Promise는 일종의 디자인 패턴으로 비동기 작업들을 순차적으로 진행하거나 병렬로 진행하는 등의 컨트롤을 수월하게 처리할 수 있습니다. 예외처리에 대한 구조가 존재하기 때문에 오류 처리를 보다 가시적으로 관리할 수 있습니다. 보통 비동기 연산이 종료된 이후의 결과 값과 실패 이유를 처리하기 위해 사용됩니다. 

 

Promise를 사용함으로써 비동기 메서드에서 동기 메서드 처럼 값을 반환할 수 있지만 실제 결과 값을 반환 하는 것이 아니라 미래 시점에 최종 결과를 제공하겠다는 약속(Promise)를 반환하는 것 입니다. 위에서 언급 했듯이 비동기 작업의 성공과 실패를 개발자가 명확하게 구분할 수 있고 Promise Chaining 을 통해 좀 더 안정적으로 비동기 작업을 처리할 수 있습니다. 

 

 

# then은 무엇이고 resolve, reject 는 뭐고... catch는 또 무엇이란 말인가.

Promise는 성공 ('resolve')실패 ('reject') 라는 두 가지 상태를 가집니다. 이 두 상태를 통해 비동기 함수 로직의 성공과 실패를 명시적으로 제어할 수 있습니다. 

 

Promise는 기본적으로 대기 / 이행 / 거부 의 상태를 가지며 대기 중인 상태의 Promise는 값과 함께 이행되거나 어떤 이유로 거부 될 수 있습니다. (이행이면 -resolve 거부면 reject 가 되는 것이죠.)

이행 시에 Promise는 then 메서드에 의해 비동기로 처리된 값을 반환받거나, 거부일 경우에는 에러 핸들러 처리를 할 수 있습니다. 

 

new 키워드를 사용해서 인스턴스를 생성합니다. 전달 인자에 실행 함수를 전달하는데 이 실행 함수 실행 시 Promise 메서드 resolve, reject가 전달 됩니다. (?) <= 체크 필요. 

 

function makeRequest(){
	return getData()
    	.then((data) => {
        	if(data && data.needMoreREquest()) {
            	return makeMoreRequest(data)
                	.then((moreData) => {
                    	console.log(moreData);
                        return moreData;
                    }).catch((error) => {
                    	console.loog('ERROR in makeMoreRequest', error);
                    });
            } else {
            	console.log(data);
                return data;
            }
        }).catch((error) => {
        	console.log('ERRRPR in getData', error);
        });
}

 

 

 

 

 

Promise.all

# Promise All은 언제 사용하는 것이 좋을까? 

Promise.all( )은 여러 Promise 를 병렬로 실행하고 모든 Promise가 이행될 때까지 기다린 다음 각각의 Promise값을 배열로 반환하는 메소드 입니다. 

 

만약 배열 안의 어떤 Promise 가 거부된다면 해당 거부된 Promise의 이유(에러)를 즉시 반환합니다. 주로 비동기 작업이 시작된 순서를 유지해야 하는 경우 활용됩니다. Promise.all () 은 배열과 같이 순회 가능한 객체를 인자로 받습니다. 

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('프로미스1 완료'), 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('프로미스2 완료'), 2000);
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(() => reject('프로미스3 실패'), 1500);
});

//Promise.all을 사용해서 여러 프로미스를 병렬로 실행합니다. 
Promise.all([promise1, promise2, promise3])
  .then((results) => {
    console.log('모든 프로미스 완료');
    console.log(results);
  })
  .catch((error) => {
    console.log('프로미스 중 하나라도 실패 : error');
  })
  
  // 최종 출력 - 프로미스 중 하나라도 실패 : error

 

 

 

🔹참고 블로그 링크 [ 언제 Promise.all 을 사용하는 것이 좋을까 ]

 

 

async/await

# Promise에서 만족하지 못하고 탄생한 새로운 비동기 코드를 작성하는 방법.

async/await 패턴을 사용하면 절차적 언어에서 작성하는 코드처럼 사용법이 간단하고 이해하기가 쉽다는 특징이 있습니다. 

Promise를 좀더 간결하게 만들어주는 역할로 기존의 Promise 사용 시 지속적인 체이닝으로 인해 코드가 난잡해질 수 있습니다. 따라서 async, await 키워드를 사용해서 동기식으로 순서대로 코드를 작성하는 것처럼 구현할 수 있습니다. 

 

사용 방법

     - function 키워드 앞에 async 붙이기

     - 내부의 promise 를 반환하는 비동기 처리 함수 앞에 await 붙이기

 

async function makeRequest () {
	try {
    	const data = await getData();
        if(data && data.needMoreRequest()){
        	const metaDAta = await makeMoreRequest(data);
            console.log(moreData);
            return moreData;
        }
    } else {
    	console.log(data);
        return data;
    } catch (error) {
    	console.log('에러 발생', error);
    } 
}

 

> Promise 체이닝 : 여러 개의 Promise를 연결해서 사용하는 것 - 연속된 then () 의 향연.

 

 

🔹참고 블로그 링크 [ 캡틴판교_async와 await ]

🔹참고 블로그 링크 : Promise & async 못다한 이야기

 

 

 

🔹[생활코딩-Nodejs-05] fs.readFile(파일 읽는 방법)
🔹비동기 처리를 위한  fs.readFile 
🔹 코드스테이츠 부트캠프 : 0320_Promise section 정리 글