본문 바로가기
C.W.K.
Stream
Lesson 06 of 09 · published

병렬 요청과 순차 요청 구분하기

~20 min · Promise.all, waterfall, perf

Level 0호기심
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

연달아 쓴 await는 폭포가 돼

각 줄에서 기다리면 다음 요청은 앞 요청이 끝난 뒤에야 시작해. 서로 독립적인 200ms, 300ms, 250ms 요청 세 개를 순서대로 실행하면 전체 렌더링은 약 750ms가 걸려. 프레임워크가 JavaScript의 순서를 몰래 바꿔 주지는 않아.

독립적이면 함께 시작해

한 요청이 다른 요청의 결과를 필요로 하지 않는다면 Promise들을 먼저 만들고 Promise.all로 함께 기다려. 전체 시간은 합계가 아니라 가장 느린 요청에 가까워져. 실패를 각각 다르게 다뤄야 한다면 경계와 오류 정책도 함께 설계해.

의존한다면 순차 실행이 맞아

getUser(id)의 결과인 user.id가 있어야 getPostsByAuthor(user.id)를 호출할 수 있다면 두 번째 요청은 기다리는 게 맞아. 폭포라는 단어가 나쁘게 들린다고 억지로 병렬화하면 존재하지 않는 입력을 만들 뿐이야.

Suspense는 대기 시간을 가릴 수 있어

순서가 꼭 필요한 느린 부분을 Suspense 경계 안에 두면 페이지 전체가 함께 기다리지 않아. 헤더와 빠른 내용은 먼저 보내고, 의존 요청이 끝난 영역만 나중에 스트리밍할 수 있어.

서버 trace에서 요청 시작·종료 시간을 나란히 놓아 폭포를 찾아. 서로 독립적인 데이터는 함수 호출 자체를 먼저 시작한 다음 한 번에 기다리고, 일부 실패를 허용한다면 Promise.allSettled와 영역별 오류 경계를 검토해. 측정 전후의 TTFB와 스트리밍 순서를 함께 비교해.

병렬화는 공짜가 아니야. DB connection pool보다 많은 query를 한꺼번에 시작하거나 외부 API rate limit을 넘기면 개별 요청은 빨라도 시스템 전체가 느려져. 의존성뿐 아니라 하류 서비스가 감당할 동시성까지 포함해 실행 폭을 정해. 200·300·250ms 모의 요청을 순차와 병렬로 실행해 합계와 최대값의 차이를 trace로 확인해. DB pool을 작게 줄인 상태에서도 같은 시험을 해 과도한 병렬화가 대기열을 만드는지 보고, 의존 요청은 Suspense로 어느 부분까지 먼저 보낼 수 있는지 측정해. 병렬 요청 하나가 실패할 때 전체를 버릴지 일부 화면을 살릴지도 먼저 정해. Promise.all의 빠른 실패가 제품 요구와 맞지 않으면 데이터 그룹을 나누고 각 Suspense·오류 경계가 독립적으로 복구하게 해.

Code

느린 순차 실행·tsx
export default async function Page() {
  const user = await getUser();           // 200ms
  const posts = await getPosts();          // 300ms
  const stats = await getStats();          // 250ms
  // 총: ~750ms
  return <Dashboard user={user} posts={posts} stats={stats} />;
}
빠른 병렬 실행·tsx
export default async function Page() {
  const [user, posts, stats] = await Promise.all([
    getUser(),
    getPosts(),
    getStats(),
  ]);
  // 총: ~max(200, 300, 250) = 300ms
  return <Dashboard user={user} posts={posts} stats={stats} />;
}
필요한 의존 순서·tsx
export default async function UserPostsPage({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  const user = await getUser(id);                     // 사용자 정보가 먼저 필요해
  const posts = await getPostsByAuthor(user.id);       // 사용자 정보에 의존해
  return <PostList user={user} posts={posts} />;
}

External links

Exercise

순차 await 세 개가 있는 서버 컴포넌트를 찾아. 독립 요청을 Promise.all로 바꾸고 페이지 로딩 시간이 합계에서 가장 느린 요청 수준으로 줄어드는지 재.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.