Vercel 배포 및 오류 해결

Odyssey·2025년 1월 15일
0

Next.js_study

목록 보기
17/58
post-thumbnail

2025.1.15 수요일의 공부기록

Next.js 프로젝트를 Vercel을 통해 배포하려고 시도하면서 몇 가지 문제를 직면했고, 이를 해결하는 과정을 정리했다.


첫 번째 문제: export 제한으로 인한 컴파일 오류

문제 설명

Next.js의 app 디렉토리 구조에서는 페이지 파일에서 특정 필드만 export로 내보내는 것이 허용된다.
metadata, generateMetadata, default 등 Next.js가 정의한 필드 외의 임의의 변수를 export로 내보내면 컴파일 오류가 발생한다.
예를 들어, 아래 코드에서 API_URLexport로 내보냈기 때문에 문제가 발생했다.

수정 전 코드

import Movie from "../components/movie";
import styles from "../../styles/home.module.css";

export const metadata = {
  title: "Home",
};
export const API_URL = "https://nomad-movies.nomadcoders.workers.dev/movies"; // 문제 발생

async function getMovies() {
  return fetch(API_URL).then((response) => response.json());
}

export default async function HomePage() {
  const movies = await getMovies();
  return (
    <div className={styles.container}>
      {movies.map((movie) => (
        <Movie
          key={movie.id}
          id={movie.id}
          poster_path={movie.poster_path}
          title={movie.title}
        />
      ))}
    </div>
  );
}

문제 원인

  • Next.js의 페이지 파일에서 허용되지 않는 필드를 export하려고 했기 때문에 발생한 컴파일 오류.

해결 방법: 환경 변수 파일 사용

API_URL과 같은 값을 .env 파일로 관리하고, 이를 코드에서 process.env.NEXT_PUBLIC_* 형식으로 참조하도록 변경했다.

수정 후 코드

import Movie from "../components/movie";
import styles from "../../styles/home.module.css";

export const metadata = {
  title: "Home",
};

async function getMovies() {
  return fetch(process.env.NEXT_PUBLIC_API_URL).then((response) =>
    response.json()
  );
}

export default async function HomePage() {
  const movies = await getMovies();
  return (
    <div className={styles.container}>
      {movies.map((movie) => (
        <Movie
          key={movie.id}
          id={movie.id}
          poster_path={movie.poster_path}
          title={movie.title}
        />
      ))}
    </div>
  );
}

.env 파일 예시

NEXT_PUBLIC_API_URL=https://nomad-movies.nomadcoders.workers.dev/movies

두 번째 문제: 타입 불일치로 인한 오류

문제 설명

Next.js에서 props.params의 타입이 개발자가 정의한 IParams 타입과 일치하지 않는다는 오류가 발생했다.
구체적으로, params는 Next.js 내부적으로 Promise 객체로 처리되는데, 개발자는 이를 일반 객체로 정의했기 때문에 타입 오류가 발생했다.

수정 전 코드

interface IParams {
  params: { id: string };
}

export async function generateMetadata({ params: { id } }: IParams) {
  const movie = await getMovie(id);
  return {
    title: movie.title,
  };
}

export default async function MovieDetail({ params }: IParams) {
  const { id } = await params;

  return (
    <div>
      <Suspense fallback={<h1>Loading movie info</h1>}>
        <MovieInfo id={id} />
      </Suspense>
      <Suspense fallback={<h1>Loading movie videos</h1>}>
        <MovieVideos id={id} />
      </Suspense>
    </div>
  );
}

문제 원인

  • Next.js는 props.paramsPromise 객체로 처리하지만, 개발자는 이를 단순 객체로 정의했다.
  • 타입 선언이 Next.js의 예상 타입(Promise<{ id: string }> 형식)과 불일치하여 오류가 발생했다.

해결 방법: params를 Promise로 처리

props.paramsPromise 객체임을 명확히 하고, 이를 await로 처리하도록 코드를 수정했다.

수정 후 코드

import { Suspense } from "react";
import MovieInfo, { getMovie } from "../../../components/movie-info";
import MovieVideos from "../../../components/movie-videos";

type IParams = Promise<{ id: string }>;

export async function generateMetadata(props: { params: IParams }) {
  const params = await props.params;
  const id = params.id;
  const movie = await getMovie(id);
  return {
    title: movie.title,
  };
}

export default async function MovieDetail(props: { params: IParams }) {
  const params = await props.params;
  const id = params.id;

  return (
    <div>
      <Suspense fallback={<h1>Loading movie info</h1>}>
        <MovieInfo id={id} />
      </Suspense>
      <Suspense fallback={<h1>Loading movie videos</h1>}>
        <MovieVideos id={id} />
      </Suspense>
    </div>
  );
}

최종 배포 성공

수정 결과

  • 첫 번째 문제: .env 파일을 사용하여 export 문제를 해결.
  • 두 번째 문제: params의 타입을 Promise로 정의하고, await로 처리하여 타입 불일치 문제를 해결.

Vercel 배포 완료

  • 수정 후 git push를 통해 Vercel에서 자동 배포를 실행했다.
  • 배포가 성공적으로 완료되었으며, 동적 메타데이터와 컴포넌트 병렬 렌더링도 정상적으로 작동함을 확인했다.

배운 점

  1. Next.js의 app 디렉토리 제한

    • 페이지 파일에서 허용되지 않는 필드를 export하면 오류가 발생한다.
    • 환경 변수를 사용하여 필요한 값을 관리하는 것이 중요하다.
  2. 타입 정의 중요성

    • Next.js에서 params와 같은 기본 제공 값의 타입을 정확히 이해하고 처리해야 한다.
    • Promise 객체와 일반 객체를 구분하여 타입을 정의해야 한다.

배포된 페이지 가기

0개의 댓글