문제 발생

Server Component waterfall 때문에 상품과 추천 목록을 각각 300ms에 조회하는 페이지 응답이 600ms 이상 걸립니다. 첫 조회를 await한 뒤 두 번째 조회를 시작하면 두 작업이 독립이어도 대기 시간이 더해집니다.

서로 독립인 server data fetch를 부모 결과 뒤에 순차 배치하면 network·DB 대기가 직렬화되므로 dependency가 없는 작업은 일찍 시작해야 합니다.

원인 분석

아래 코드는 getProduct()가 끝난 뒤에야 getRecommendations()를 호출합니다. 두 번째 함수가 첫 번째 결과를 사용하지 않는다면 불필요한 순차 실행입니다. 반대로 추천 조회에 product.categoryId가 필요하다면 실제 의존성이므로 억지로 병렬화하면 안 됩니다.

const product = await getProduct(id);
const recommendations = await getRecommendations(id);

서버 trace나 함수 시작·종료 시각을 같은 요청 ID로 남기면 두 막대가 겹치는지 이어지는지 확인할 수 있습니다.

해결 방안

독립 요청은 Promise를 먼저 만들고 함께 기다립니다. 오류 처리 계약도 기존과 같아야 합니다.

const productPromise = getProduct(id);
const recommendationsPromise = getRecommendations(id);

const [product, recommendations] = await Promise.all([
  productPromise,
  recommendationsPromise,
]);

수정 전후에 반환 데이터와 오류 응답이 같은지 확인하고, trace에서 두 조회가 실제로 겹쳤는지 봅니다. DB connection pool이 작은데 병렬 조회만 늘리면 대기열이 다른 곳으로 옮겨갈 수 있으므로 pool 대기와 p95도 함께 확인합니다.

공식 문서

현재 Next.js version과 실제 데이터 의존 관계에서 다시 확인합니다.