프로그래밍 언어/JavaScript

JavaScript Promise 사용법 비동기 프로그래밍과 체이닝 예제 - 자바스크립트 #12

eco7T 2024. 7. 29. 08:13
반응형

이번에는 Promise 객체에 대해 살펴보고, 비동기 작업을 처리하는데 있어서 실제 예제를 통해 Promise의 생성, 사용, 체이닝 등 프로미스를 효율적으로 활용하는 여러 방법에 대해 정리해 보겠습니다.

JavaScript Promise 사용법
JavaScript Promise 사용법

 

자바스크립트 Promise

Promise는 자바스크립트에서 비동기 작업을 처리하는 객체입니다. '비동기 작업'이란 시간이 걸리는 작업을 말하며, 이 작업이 완료될 때까지 다른 코드의 실행을 멈추지 않고 계속 진행할 수 있게 해줍니다.

Promise는 다음 세 가지 상태 중 하나를 가집니다.

  1. 대기(Pending): 초기 상태, 비동기 작업이 아직 완료되지 않음
  2. 이행(Fulfilled): 작업이 성공적으로 완료됨
  3. 거부(Rejected): 작업이 실패함

Promise를 사용하면 비동기 작업의 결과를 처리하는 코드를 더 쉽게 작성할 수 있습니다.

반응형

  Promise 만들기

Promise 객체는 다음과 같이 생성합니다:

const myPromise = new Promise((resolve, reject) => { // 비동기 작업을 여기에 작성합니다 // 작업이 성공하면 resolve를 호출하고, // 실패하면 reject를 호출합니다 });

여기서 resolvereject는 함수입니다. resolve는 Promise가 성공적으로 완료되었을 때 호출하고, reject는 실패했을 때 호출합니다.

예를 들어, 5초 후에 무작위로 성공 또는 실패하는 Promise를 만들어 보겠습니다:

const randomPromise = new Promise((resolve, reject) => { console.log("Promise 시작: 5초 후에 결과가 나옵니다."); setTimeout(() => { const randomNumber = Math.random(); if (randomNumber > 0.5) { resolve("성공! 숫자는 " + randomNumber + "입니다."); } else { reject("실패! 숫자는 " + randomNumber + "입니다."); } }, 5000); }); console.log("Promise를 생성했습니다. 결과를 기다리는 중..."); randomPromise .then((result) => { console.log("Promise 성공:", result); }) .catch((error) => { console.log("Promise 실패:", error); }); console.log("이 메시지는 Promise 결과와 상관없이 바로 출력됩니다.");

이 예제를 실행하면 다음과 같은 순서로 콘솔에 출력됩니다.

  1. "Promise 시작: 5초 후에 결과가 나옵니다."
  2. "Promise를 생성했습니다. 결과를 기다리는 중..."
  3. "이 메시지는 Promise 결과와 상관없이 바로 출력됩니다."
  4. (5초 후) "Promise 성공: 성공! 숫자는 X입니다." 또는 "Promise 실패: 실패! 숫자는 X입니다."

이 예제에서 볼 수 있듯이, Promise를 사용하면 비동기 작업의 결과를 기다리는 동안 다른 코드를 실행할 수 있습니다.

  Promise 사용하기

Promise를 사용할 때는 주로 다음 메서드를 활용합니다.

 

then()

then() 메서드는 Promise가 성공적으로 완료되었을 때 실행될 콜백 함수를 등록합니다.

myPromise.then((result) => { console.log("성공:", result); });

 

catch()

catch() 메서드는 Promise가 실패했을 때 실행될 콜백 함수를 등록합니다.

myPromise.catch((error) => { console.log("실패:", error); });

 

finally()

finally() 메서드는 Promise가 성공하든 실패하든 상관없이 항상 실행될 콜백 함수를 등록합니다.

myPromise.finally(() => { console.log("Promise 작업이 완료되었습니다."); });

이 세 메서드를 모두 사용한 예제입니다.

function fetchData(shouldSucceed) { return new Promise((resolve, reject) => { setTimeout(() => { if (shouldSucceed) { resolve("데이터를 성공적으로 가져왔습니다."); } else { reject("데이터 가져오기에 실패했습니다."); } }, 2000); }); } console.log("데이터 요청을 시작합니다..."); fetchData(true) // true를 false로 바꿔보세요 .then((result) => { console.log("성공:", result); }) .catch((error) => { console.log("실패:", error); }) .finally(() => { console.log("데이터 요청 작업이 완료되었습니다."); }); console.log("데이터 요청이 진행 중입니다.");

이 예제를 실행하면 다음과 같은 순서로 출력됩니다.

  1. "데이터 요청을 시작합니다..."
  2. "데이터 요청이 진행 중입니다."
  3. (2초 후) "성공: 데이터를 성공적으로 가져왔습니다." 또는 "실패: 데이터 가져오기에 실패했습니다."
  4. "데이터 요청 작업이 완료되었습니다."

fetchData 함수에 전달하는 인자를 false로 바꾸면 실패 케이스를 볼 수 있습니다.

  Promise 체이닝

Promise의 강력한 기능 중 하나는 여러 개의 비동기 작업을 연속적으로 처리할 수 있다는 것입니다. 이를 'Promise 체이닝'이라고 합니다.

then() 메서드는 새로운 Promise를 반환하므로, 이를 이용해 여러 작업을 연결할 수 있습니다.

function fetchUserData(userId) { return new Promise((resolve, reject) => { setTimeout(() => { if (userId === 1) { resolve({ id: 1, name: "김철수" }); } else { reject("사용자를 찾을 수 없습니다."); } }, 1000); }); } function fetchUserPosts(userName) { return new Promise((resolve, reject) => { setTimeout(() => { if (userName === "김철수") { resolve(["안녕하세요", "반갑습니다"]); } else { reject("게시물을 가져올 수 없습니다."); } }, 1000); }); } console.log("사용자 데이터와 게시물을 가져오는 중..."); fetchUserData(1) .then((user) => { console.log("사용자 정보:", user); return fetchUserPosts(user.name); }) .then((posts) => { console.log("사용자의 게시물:", posts); }) .catch((error) => { console.log("오류 발생:", error); }) .finally(() => { console.log("모든 작업이 완료되었습니다."); }); console.log("데이터 요청이 진행 중입니다.");

이를 실행하면 다음과 같은 순서로 출력됩니다.

  1. "사용자 데이터와 게시물을 가져오는 중..."
  2. "데이터 요청이 진행 중입니다."
  3. (1초 후) "사용자 정보: { id: 1, name: '김철수' }"
  4. (추가 1초 후) "사용자의 게시물: ['안녕하세요', '반갑습니다']"
  5. "모든 작업이 완료되었습니다."

이 예제에서는 첫 번째 Promise(fetchUserData)가 완료된 후, 그 결과를 이용해 두 번째 Promise(fetchUserPosts)를 실행합니다. 이렇게 여러 비동기 작업을 순차적으로 처리할 수 있습니다.

  Promise.all()

여러 개의 Promise를 동시에 실행하고 모든 Promise가 완료될 때까지 기다리려면 Promise.all()을 사용합니다.

function fetchData(id) { return new Promise((resolve, reject) => { setTimeout(() => { if (id <= 3) { resolve(`데이터 ${id}`); } else { reject(`ID ${id}에 해당하는 데이터가 없습니다.`); } }, 1000); }); } console.log("여러 개의 데이터를 동시에 가져오는 중..."); Promise.all([ fetchData(1), fetchData(2), fetchData(3) ]) .then((results) => { console.log("모든 데이터를 성공적으로 가져왔습니다:", results); }) .catch((error) => { console.log("데이터 가져오기 실패:", error); }); console.log("데이터 요청들이 진행 중입니다.");

이 예제를 실행하면 다음과 같은 순서로 출력됩니다.

  1. "여러 개의 데이터를 동시에 가져오는 중..."
  2. "데이터 요청들이 진행 중입니다."
  3. (약 1초 후) "모든 데이터를 성공적으로 가져왔습니다: ['데이터 1', '데이터 2', '데이터 3']"

Promise.all()은 배열 내의 모든 Promise가 성공적으로 완료되었을 때만 결과를 반환합니다. 만약 하나라도 실패하면 즉시 실패로 처리됩니다.

반응형