Parallel Request(병렬호출)

Odyssey·2025년 1월 14일

Next.js_study

목록 보기
12/58
post-thumbnail

2025.1.14 화요일의 공부기록

API를 통해 여러 데이터를 Fetch해야 할 때, 기본적으로 순차 처리 방식을 사용하면 각 호출이 끝난 후에 다음 호출이 진행되므로 비효율적이고 느린 방식이 될 수 있다. 이를 해결하기 위해 Promise.all()을 사용하여 병렬 처리(Parallel Requests)를 구현할 수 있다.


기존 방식: 순차 처리

기존 코드

import { API_URL } from "../../../(home)/page";

type Props = {
  params: { id: string };
  searchParams: { region: string; page: string };
};

async function getMovie(id: string) {
  const response = await fetch(`${API_URL}/${id}`);
  return response.json();
}

async function getVideos(id: string) {
  const response = await fetch(`${API_URL}/${id}/videos`);
  return response.json();
}

export default async function MovieDetail({ params, searchParams }: Props) {
  const { id } = await params;
  const { region, page } = await searchParams;

  // 순차적으로 API 호출
  const movie = await getMovie(id);   // 첫 번째 호출
  const videos = await getVideos(id); // 두 번째 호출

  return <h1>{movie.title}</h1>;
}

문제점

  1. 순차 처리
    첫 번째 API 호출(getMovie)이 완료될 때까지 두 번째 호출(getVideos)이 대기한다.
  2. 시간 낭비
    두 API가 서로 독립적인 경우에도 순차적으로 실행되므로 비효율적이다.
  3. 성능 저하
    비동기 작업을 병렬로 처리할 수 있는 환경에서 순차 처리를 사용하면 불필요하게 느려질 수 있다.

병렬 처리: Promise.all()

Promise.all()의 개념

Promise.all()은 여러 Promise를 병렬로 실행하고, 모든 Promise가 완료될 때까지 기다린 뒤, 결과를 배열 형태로 반환한다.
이를 통해 여러 비동기 작업을 동시에 처리할 수 있어 성능이 크게 향상된다.

수정된 코드: 병렬 처리 적용

import { API_URL } from "../../../(home)/page";

type Props = {
  params: { id: string };
  searchParams: { region: string; page: string };
};

async function getMovie(id: string) {
  const response = await fetch(`${API_URL}/${id}`);
  return response.json();
}

async function getVideos(id: string) {
  const response = await fetch(`${API_URL}/${id}/videos`);
  return response.json();
}

export default async function MovieDetail({ params, searchParams }: Props) {
  const { id } = await params;
  const { region, page } = await searchParams;

  // 병렬로 API 호출
  const [movie, videos] = await Promise.all([getMovie(id), getVideos(id)]);

  return <h1>{movie.title}</h1>;
}

병렬 처리 동작 방식

  1. getMovie(id)getVideos(id)동시에 실행된다.
  2. 두 작업이 완료될 때까지 기다린 뒤, 결과를 배열 형태로 반환한다.
    • movie: 첫 번째 Promise(getMovie)의 결과.
    • videos: 두 번째 Promise(getVideos)의 결과.
  3. 모든 작업이 완료되면 결과를 활용하여 UI를 렌더링한다.

Promise.all()의 장점

  1. 성능 향상
    여러 API 호출을 병렬로 실행하므로 전체 처리 시간이 단축된다.

  2. 효율성 증가
    독립적인 비동기 작업을 동시에 실행하여 리소스를 효율적으로 활용한다.

  3. 코드 간결화
    모든 비동기 작업의 결과를 배열로 관리하므로 코드가 깔끔해진다.


Promise.all() 사용 시 주의점

  1. 실패 처리
    Promise.all()은 하나의 Promise가 실패하면 나머지 Promise의 결과도 반환되지 않고 전체가 실패한다.
    • 이를 방지하려면 개별 Promise에 try-catch를 추가하거나 Promise.allSettled()를 사용할 수 있다.

Promise.allSettled() 예제

const results = await Promise.allSettled([getMovie(id), getVideos(id)]);
results.forEach((result) => {
  if (result.status === "fulfilled") {
    console.log(result.value); // 성공한 값
  } else {
    console.error(result.reason); // 실패 이유
  }
});
  1. 네트워크 병목
    병렬 처리로 인해 서버나 네트워크에 과도한 요청이 발생할 수 있으므로 필요한 요청만 병렬로 처리해야 한다.

병렬 처리와 순차 처리 비교

특징순차 처리병렬 처리
처리 방식한 작업이 끝난 후 다음 작업 실행모든 작업을 동시에 실행
처리 시간모든 작업의 합가장 오래 걸리는 작업의 시간
코드 구조상대적으로 간단배열로 관리하며 약간의 복잡성 증가
성능느림빠름
실패 처리개별 처리 가능하나 실패 시 전체 실패 (Promise.allSettled로 해결 가능)

결론

Promise.all()은 여러 API 호출을 병렬로 처리할 수 있어 비동기 작업의 효율성과 성능을 크게 향상시킨다.
특히, 독립적인 데이터를 Fetch하거나 비동기 작업이 많을 경우 병렬 처리를 통해 사용자 경험을 개선할 수 있다.
단, 요청 실패와 네트워크 부하에 주의하면서 적절히 활용하는 것이 중요하다.

0개의 댓글