FrontEnd/JavaScript

[JavaScript] Promise 란?

데브슈 2025. 3. 23. 01:31
Promise

비동기 작업을 보다 쉽게 다룰 수 있도록 도와주는 객체

기존 콜백 함수 방식보다 가독성/유지보수 ↑

 

→ 비동기 연산의 최종 완료(실패) 여부와 그 결과 값을 나타내는 객체

최종 결과를 반환하는 것이 아닌 미래 어떤 시점에서 결과를 제공해주는 것


1. Promise 상태 → 한 번 변경되면 재변경 x

1) 대기 (Pending) : 초기 상태로 비동기 작업이 완료되지 않은 상태

2) 이행 (Fulfilled) : 작업이 성공적으로 완료된 상태

3) 거부 (Rejected) : 작업 실패 상태


2. Promise 기본 문법

1) Promise 객체 생성

const myPromise = new Promise((resolve, reject) => {
	const success = true;
    
    if (success) {
    	resolve("작업이 성공적으로 완료되었습니다.");
    } else {
    	reject ("작업이 실패하였습니다.");
    }
});

Promise 객체를 생성하려면 new 키워드 + Promise 생성자 함수를 사용하면 된다.

Promise 생성자 안에 두개의 매개변수의 첫 번째 인수작업 성공(resolve)을 알려주는 객체,

두 번째 인수작업 실패(reject) 를 알려주는 오류 객체이다.

 

→ 작업 성공 시 resolve() 호출, 실패 시 reject() 호출

 

2) then(), catch(), finally() 사용

then() : 프로미스가 이행 (fulfilled) 됐을 때 실행할 콜백 함수 등록, 새로운 프로미스 반환

catch() :  프로미스가 거부 (rejected) 됐을 때 실행할 콜백 함수 등로그 새로운 프로미스 반환

finally() : 프로미스가 이행 혹은 거부 상관없이 실행할 콜백함수 등록, 새로운 프로미스 반환

myPromise
    .then(result => {
    	console.log("성공 :", resule);
  	})
    .catch(error => {
    	console.log("실패 :", error);
    })
    .finally(() => {
    	console.log("작업 완료 여부 관계없이 실행");
    });

Promise가 성공하면 then(), 실패하면 catch()를 사용하여 결과가 처리된다.

finally() 의 경우, 성공과 실패 여부 없이 항상 실행된다.

 

3) Promise 함수 사용

프로미스 안에 함수를 선언하여 실행해보면 3초 뒤 순서대로 실행이 되는 것을 볼 수 있다.

여기서 resolvethen을 실행시기키 위한 일종의 트리거 역할을 하며 then이전 함수 결과를 토대로 연계하여 실행(직렬)된다.

만약 위와 같이 then 안에 함수가 복수 개인 경우,

resolve 는 첫번째 함수를 받으며 reject 는 두번째 함수를 받는다.

→ resovle 혹은 reject 둘중 하나 트리거링 되는 순간 밑에 로직은 모두 무시된다. (동시 사용x)

추가로 reject가 실행된 이후의 다음 함수는 정상인 것 처럼 처리된다.

return 값이 없는 경우 다음 함수의 매개 변수는 undefined 처리된다.

만약 위와 같이 동기화 로직이 2개 이상이라면 promise를 재선언 해주어야 정상적으로 작동한다.

동기화 로직이 복수개이나 promise가 상단에 하나뿐이라면 동기화가 발생하지 않는다.

 

4) throw new Error

throw new Error : 예외를 강제로 발생시키는 역할

→ 주로 비정상적인 상황을 감지했을 때 실행을 중단하고 에러 처리 위해 사용

throw new Error 를 사용하면 명시적으로 에러 처리를 할 수 있는데

해당 경우 정상 로직을 트리거링해도 실행되지 않으며 무조건 reject 로직을 실행한다.

 

참고로 에러 실행 이후 만들어진 함수들은 resolve 값이 적용된다.

 

5) then

만약 then을 연결하여 생성하는 것이 아닌 독립적으로 생성한다면 어떻게 될까?

console.log 를 보면 then을 연결한 로직은 동기화가 적용되었으며, 독립적으로 연결한 로직은 동기화가 적용되지 않아 독자적으로 행동하는 모습을 볼 수 있다.

 

이를 통해 우리는 독립적으로 두개 이상의 로직을 구성할 경우 어떤 에러가 발생할지 예상할 수 없다는 점을 알 수 있는데

바로 이러한 부분 때문에 then을 하나로 합쳐서 써야한다!

throw new Error, catch 그리고 finally를 같이 써보았는데 console.log를 보면

throw new Error ("에러!") 가 즉시 실행되면서 catch가 바로 실행되고 finally가 실행된 것을 알 수 있다. 

또한 3초 후 실행되나 이미 reject 상태이므로 then이 실행되지 않는다.

 

→ throw new Error 를 지울 경우, then이 실행될 것 

 

6) promise.all

promise.all : 비동기 처리가 이행될 때까지 기다렸다가 모든 프로미스가 완료되면 then 핸들러가 실행되는 형태 (직렬 x / 병렬 o)

→ 정렬되어 있는 결과값을 배열 형태로 출력 (실행 순서에 따라 출력 x)

다수 데이터 싱크를 맞춰서 처리할 경우 유용하기에 여러 개의 API 요청을 보내고 모든 응답을 받는 경우에 주로 사용 가능하다.

그러나 단 하나라도 에러가 발생할 경우 모두 에러 처리가 난다는 단점이 있다.