2025.1.15 수요일의 공부기록
Next.js 프로젝트를 Vercel을 통해 배포하려고 시도하면서 몇 가지 문제를 직면했고, 이를 해결하는 과정을 정리했다.
export
제한으로 인한 컴파일 오류Next.js의 app
디렉토리 구조에서는 페이지 파일에서 특정 필드만 export
로 내보내는 것이 허용된다.
metadata
, generateMetadata
, default
등 Next.js가 정의한 필드 외의 임의의 변수를 export
로 내보내면 컴파일 오류가 발생한다.
예를 들어, 아래 코드에서 API_URL
을 export
로 내보냈기 때문에 문제가 발생했다.
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>
);
}
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>
);
}
props.params
를 Promise 객체로 처리하지만, 개발자는 이를 단순 객체로 정의했다.Promise<{ id: string }>
형식)과 불일치하여 오류가 발생했다.params
를 Promise로 처리props.params
가 Promise 객체임을 명확히 하고, 이를 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
로 처리하여 타입 불일치 문제를 해결.git push
를 통해 Vercel에서 자동 배포를 실행했다.Next.js의 app
디렉토리 제한
export
하면 오류가 발생한다.타입 정의 중요성
params
와 같은 기본 제공 값의 타입을 정확히 이해하고 처리해야 한다.