myinfo7091 2024. 12. 17. 15:35
/* eslint-disable @next/next/no-img-element */
// SSG
// 서버 컴포넌트에서는 fetch API를 통해 데이터를 직접 불러올 수 있다.
// build 시점에 데이터를 불러오기 때문에 터미널에 console.log로 데이터를 출력해볼 수 있다.


export default async function HomePage() {
  const response = await fetch("http://localhost:4000/products");
  const data: Product[] = await response.json();
  console.log(data);

  return (
    <div>
      <h1>Hello! Next.js HomePage</h1>
      <div>
        <div className="p-8 m-4">
          {data.map((product) => (
            <div className="flex border p-4 gap-4 rounded-md" key={product.id}>
              <img
                className="rounded-smr"
                width={150}
                height={150}
                src={product.images}
                alt={product.title}
              />
              <div className="flex flex-col justify-between">
                <div>
                  <h2 className="text-xl font-bold">{product.title}</h2>
                  <p className="text-sm">{product.description}</p>
                  <p className="mt-4 text-2xl">{product.price.amount}$</p>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

export interface Product {
  id: string;
  isNew: boolean;
  handle: string;
  availableForSale: boolean;
  title: string;
  description: string;
  descriptionHtml: string;
  options: { name: string; values: string[] }[];
  price: { amount: string; currencyCode: string };
  variants: {
    id: string;
    title: string;
    price: string;
    availableForSale: boolean;
  }[];
  images: string;
  featuredImage: string;
  seo: { title: string; description: string };
  tags: string[];
  updatedAt: string;
}
/* eslint-disable @next/next/no-img-element */
// SSR
// 사용자가 웹사이트에 접속하려고 시도할 때마다 새로 컨텐츠를 불러와서 렌더링한다.
// fetch 옵션에 cache: "no-store"를 추가하면 된다.
// fetch 안에서 캐싱되지 않기 때문에 매번, 새로고침할 때마다 데이터를 새로 불러오게 된다.

export default async function HomePage() {
  const response = await fetch("http://localhost:4000/products", {
    cache: "no-store",
  });
  const data: Product[] = await response.json();
  console.log("렌더링되었습니다.");

  return (
    <div>
      <h1>Hello! Next.js HomePage</h1>
      <div>
        <div className="p-8 m-4">
          {data.map((product) => (
            <div className="flex border p-4 gap-4 rounded-md" key={product.id}>
              <img
                className="rounded-smr"
                width={150}
                height={150}
                src={product.images}
                alt={product.title}
              />
              <div className="flex flex-col justify-between">
                <div>
                  <h2 className="text-xl font-bold">{product.title}</h2>
                  <p className="text-sm">{product.description}</p>
                  <p className="mt-4 text-2xl">{product.price.amount}$</p>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

export interface Product {
  id: string;
  isNew: boolean;
  handle: string;
  availableForSale: boolean;
  title: string;
  description: string;
  descriptionHtml: string;
  options: { name: string; values: string[] }[];
  price: { amount: string; currencyCode: string };
  variants: {
    id: string;
    title: string;
    price: string;
    availableForSale: boolean;
  }[];
  images: string;
  featuredImage: string;
  seo: { title: string; description: string };
  tags: string[];
  updatedAt: string;
}
"use client";

// CSR
// use client 선언 후 useState, useEffect Hook을 사용한다.

/* eslint-disable @next/next/no-img-element */
import React, { useEffect, useState } from "react";
import { Product } from "../page";

const fetchData = async () => {
  const response = await fetch("http://localhost:4000/products");
  const data: Product[] = await response.json();
  return data;
};

const ProductList = () => {
  const [data, setData] = useState<Product[]>([]);

  useEffect(() => {
    console.log("렌더링되었습니다.");
    fetchData().then(setData);
  }, []);

  return (
    <div>
      <h1>ProductList</h1>
      <div>
        <div className="p-8 m-4">
          {data.map((product) => (
            <div className="flex border p-4 gap-4 rounded-md" key={product.id}>
              <img
                className="rounded-smr"
                width={150}
                height={150}
                src={product.images}
                alt={product.title}
              />
              <div className="flex flex-col justify-between">
                <div>
                  <h2 className="text-xl font-bold">{product.title}</h2>
                  <p className="text-sm">{product.description}</p>
                  <p className="mt-4 text-2xl">{product.price.amount}$</p>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

export default ProductList;
/* eslint-disable @next/next/no-img-element */

// ISR
// 정적 증분 생성: 특정 시간마다 재생성
// fetch 옵션에 next: {revalidate: (원하는 시간)}을 적용하면 된다.

export default async function HomePage() {
  const response = await fetch("http://localhost:4000/products", {
    next: {
      revalidate: 3,
    }
  });
  const data: Product[] = await response.json();
  console.log("렌더링되었습니다.");

  return (
    <div>
      <h1>Hello! Next.js HomePage</h1>
      <div>
        <h1>ProductList</h1>
        <div>
          <div className="p-8 m-4">
            {data.map((product) => (
              <div
                className="flex border p-4 gap-4 rounded-md"
                key={product.id}
              >
                <img
                  className="rounded-smr"
                  width={150}
                  height={150}
                  src={product.images}
                  alt={product.title}
                />
                <div className="flex flex-col justify-between">
                  <div>
                    <h2 className="text-xl font-bold">{product.title}</h2>
                    <p className="text-sm">{product.description}</p>
                    <p className="mt-4 text-2xl">{product.price.amount}$</p>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

export interface Product {
  id: string;
  isNew: boolean;
  handle: string;
  availableForSale: boolean;
  title: string;
  description: string;
  descriptionHtml: string;
  options: { name: string; values: string[] }[];
  price: { amount: string; currencyCode: string };
  variants: {
    id: string;
    title: string;
    price: string;
    availableForSale: boolean;
  }[];
  images: string;
  featuredImage: string;
  seo: { title: string; description: string };
  tags: string[];
  updatedAt: string;
}