[JS] 프로미스(Promise)

javaScript 기초를 탄탄하게 다져보자

Posted by lim.Chuck on December 23, 2024

[JavaScript]

기초

  1. [JS] Js기초
  2. [JS] Js기초 변수
  3. [JS] Js기초 자료형
  4. [JS] Js기초 형변환
  5. [JS] Js기초 연산자
  6. [JS] Js기초 반복문
  7. [JS] Js기초 switch
  8. [JS] Js기초 function
  9. [JS] Js기초 객체
  10. [JS] Js기초 배열

중급

  1. [JS] Js중급 호이스팅(Hoisting)과 TDZ(Temporal Dead Zone)
  2. [JS] Js중급 생성자함수
  3. [JS] 객체 메소드(Object methods), 계산된 프로퍼티(Computed property)
  4. [JS] 심볼(Symbol)
  5. [JS] WeakMap WeakSet
  6. [JS] 숫자, 수학 method (Number, Math)
  7. [JS] 문자열 메소드(String methods)
  8. [JS] 배열 메소드(Array methods)
  9. [JS] 구조 분해 할당 (Destructuring assignment)
  10. [JS] 매개변수 리스트와 전개 문법(Rest parameters and spread syntax)
  11. [JS] 클로저(Closure)
  12. [JS] setTimeout / setInterval
  13. [JS] call / apply / bind
  14. [JS] 상속, 프로토타입(Prototype)
  15. [JS] 클래스(Class)
  16. [JS] 클로미스(Promise)
  17. [JS] 비동기 처리(Async/Await)
  18. [JS] Generator
  19. [JS] 메모리 릭(Memory Leak)

Promise는 비동기 작업을 더 쉽게 처리할 수 있게 해주는 객체야! 🎯

1. Promise 기본

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Promise 생성
const promise = new Promise((resolve, reject) => {
  // 비동기 작업 수행
  const success = true;

  if (success) {
    resolve("성공!"); // 성공 시
  } else {
    reject("실패!"); // 실패 시
  }
});

// Promise 사용
promise
  .then((result) => {
    console.log(result); // "성공!"
  })
  .catch((error) => {
    console.log(error); // "실패!"
  })
  .finally(() => {
    console.log("완료!"); // 성공/실패 상관없이 실행
  });

2. 실제 사용 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// API 호출 함수
function fetchUser(id) {
  return new Promise((resolve, reject) => {
    // API 호출 시뮬레이션
    setTimeout(() => {
      const user = {
        id: id,
        name: "김코딩",
        email: "kim@coding.com",
      };

      if (id <= 0) {
        reject(new Error("잘못된 ID"));
        return;
      }

      resolve(user);
    }, 1000);
  });
}

// 사용
fetchUser(1)
  .then((user) => {
    console.log("사용자:", user);
    return fetchUser(2); // 체이닝
  })
  .then((user2) => {
    console.log("사용자2:", user2);
  })
  .catch((error) => {
    console.error("에러:", error);
  });

3. Promise.all과 Promise.race

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 여러 Promise 동시 처리
const promise1 = fetchUser(1);
const promise2 = fetchUser(2);
const promise3 = fetchUser(3);

// 모든 Promise가 완료될 때까지 기다림
Promise.all([promise1, promise2, promise3])
  .then((users) => {
    console.log("모든 사용자:", users);
  })
  .catch((error) => {
    console.error("하나라도 실패:", error);
  });

// 가장 먼저 완료되는 Promise 결과 반환
Promise.race([promise1, promise2, promise3]).then((firstUser) => {
  console.log("첫번째 완료:", firstUser);
});

4. async/await 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// async/await로 더 깔끔하게 처리
async function getUsers() {
  try {
    const user1 = await fetchUser(1);
    console.log("사용자1:", user1);

    const user2 = await fetchUser(2);
    console.log("사용자2:", user2);

    return [user1, user2];
  } catch (error) {
    console.error("에러 발생:", error);
    throw error;
  }
}

// 병렬 처리
async function getUsersParallel() {
  try {
    const users = await Promise.all([fetchUser(1), fetchUser(2), fetchUser(3)]);

    console.log("모든 사용자:", users);
    return users;
  } catch (error) {
    console.error("에러 발생:", error);
    throw error;
  }
}

5. 실전 활용: API 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class API {
  constructor(baseURL) {
    this.baseURL = baseURL;
  }

  async get(endpoint) {
    try {
      const response = await fetch(this.baseURL + endpoint);

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      return await response.json();
    } catch (error) {
      console.error("API 호출 실패:", error);
      throw error;
    }
  }

  async post(endpoint, data) {
    try {
      const response = await fetch(this.baseURL + endpoint, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(data),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      return await response.json();
    } catch (error) {
      console.error("API 호출 실패:", error);
      throw error;
    }
  }
}

// 사용 예시
const api = new API("https://api.example.com");

async function getUserData() {
  try {
    const user = await api.get("/users/1");
    const posts = await api.get(`/users/${user.id}/posts`);

    return { user, posts };
  } catch (error) {
    console.error("데이터 로딩 실패:", error);
    throw error;
  }
}

6. Promise 상태

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const checkPromiseState = (promise) => {
  let state = "pending";

  promise
    .then(() => {
      state = "fulfilled";
      console.log("상태:", state);
    })
    .catch(() => {
      state = "rejected";
      console.log("상태:", state);
    });

  console.log("초기 상태:", state);
  return state;
};

// Promise 상태 확인
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("완료!");
  }, 2000);
});

checkPromiseState(promise); // "pending" -> "fulfilled"

꿀팁! 🍯

  1. Promise.allSettled 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 모든 Promise의 결과를 받음 (성공/실패 모두)
Promise.allSettled([
  Promise.resolve(1),
  Promise.reject("에러"),
  Promise.resolve(3),
]).then((results) => {
  results.forEach((result) => {
    if (result.status === "fulfilled") {
      console.log("성공:", result.value);
    } else {
      console.log("실패:", result.reason);
    }
  });
});
  1. 타임아웃 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function withTimeout(promise, timeout) {
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => {
      reject(new Error("시간 초과!"));
    }, timeout);
  });

  return Promise.race([promise, timeoutPromise]);
}

// 사용 예시
withTimeout(fetchUser(1), 5000)
  .then((user) => console.log(user))
  .catch((error) => console.error(error));

이제 Promise는 마스터! 😎 비동기 프로그래밍을 자유자재로 할 수 있을 거야!