1. 서버 액션에서 한꺼번에 처리

이 방법은 데이터 페칭을 하의 서버 액션에서 처리하고, 이를 페이지 컴포넌트로 전달하는 경우.

장점:

  1. 성능 최적화:
  2. 코드 간결성:
  3. 일관된 에러 처리:
  4. 단일 트랜잭션 관리:

단점:

  1. 복잡성 증가:
  2. 유연성 저하:
  3. 초기 로딩 시간 증가 가능성:

코드 예시:

//actions.ts
export async function getNutrientAllFunctionalities(params: {
  mid: string;
  functionalityId: number | null;
}): Promise<
  ActionResponse<{
    functionalityResponse: z.infer<typeof NutrientFunctionalities.findOneV1.outputRs>;
    functionalityMappingsResponse: z.infer<typeof NutrientFunctionalityMappings.findOneV1.outputRs>[];
    nutrients: z.infer<typeof NutrientMinimalOutput>[];
    existMappingsData: z.infer<typeof NutrientCategoryMappingMinimalOutput>[];
    nonMappingData: z.infer<typeof NutrientCategoryMappingMinimalOutput>[];
    categoryQuestionsResponse: z.infer<typeof NutrientCategoryQuestions.findAllV1.outputRs>[];
  }>
> {
  const session = await getSession();

  try {
    // 기능성 데이터 가져오기
    const functionalityResponse = await NutrientFunctionalitiesRepository.findOneV1({
      ...validatedFields,
      pFunctionalityId: params.functionalityId,
    });

    // 기능성 매핑 데이터 가져오기
    const functionalityMappingsResponse = await NutrientFunctionalityMappingsRepository.findOneV1({
      ...validatedFields,
      pFunctionalityId: params.functionalityId,
    });

    // 하위 성분 데이터 가져오기
    const existMappingsData = await NutrientCategoryMappingsRepository.findOneV1({
      ...validatedFields,
      pFunctionalityId: params.functionalityId,
    });

    // 모든 영양소 데이터 가져오기
    const nutrients = await NutrientsRepository.findAllV2({
      pInvokerOperatorId: session?.user.operator_id,
      pThisOperatorMenuIdentifier: params.mid,
      pCallDate: spCallDate(),
    });

    // 연결되지 않은 영양소 데이터 필터링
    const existMappingIds = existMappingsData.map((item) => item.nutrient_id);
    const nonMappingData = nutrients.filter((item) => !existMappingIds.includes(item.nutrient_id));

    // 문진 질문 데이터 가져오기
    const categoryQuestionsResponse = await NutrientCategoryQuestionsRepository.findAllV1({
      ...validatedFields,
      pFunctionalityId: params.functionalityId,
    });

    return {
      status: 'SUCCESS',
      message: '모든 데이터를 성공적으로 불러왔습니다.',
      data: {
        functionalityResponse: functionalityResponse[0],
        functionalityMappingsResponse,
        nutrients,
        existMappingsData,
        nonMappingData: nonMappingData.map((item) => ({
          ...item,
          recommend_weight: 0,
          recommend_memo: '',
        })),
        categoryQuestionsResponse,
      },
    };
  } catch (error) {
    return errorHandler(error);
  }
}

//page.tsx
export default async function Page({ params: { id }, searchParams: { mid } }: PageProps) {
  const { status, data } = await getNutrientAllFunctionalities({ mid, functionalityId: Number(id) });

  if (status !== 'SUCCESS') {
    return <div>데이터를 불러오는 중 오류가 발생했습니다.</div>;
  }

  return (
    <HeaderLayout title="중분류 카테고리 수정" description="중분류 카테고리를 수정할 수 있습니다." backBtn={<BackButton />}>
      <div className="flex flex-col gap-2">
        <CategoryDetailInfo data={data.functionalityResponse} id={id} />
        <TopCategoryView id={Number(id)} mid={mid} data={data.functionalityMappingsResponse} />
        <SubCategoryIngredients id={Number(id)} mid={mid} data={data} />
        <SubCategoryQuestionTable id={Number(id)} mid={mid} data={data.categoryQuestionsResponse} />
      </div>
    </HeaderLayout>
  );
}

2. 각 컴포넌트에서 개별적으로 호출

이 방법은 각 컴포넌트가 자신에게 필요한 데이터를 독립적으로 페칭하는 경우.

장점:

  1. 유연성: