기록
Next.js에서 npm run build 시 생겼던 에러
als982001
2023. 9. 3. 20:17
저번에 글을 작성했었던 프로젝트를 배포하기 위해 npm run build를 했다. 그런데 갑자기 이런 에러가 발생했다.
처음 보는 에러라 뭐가 문제인지 몰랐다. 그래서 2일 정도 구글링도 해보고 파일의 코드도 다시 읽어보았지만 뭐가 문제인지 알 수 없었다. 위의 이미지에는 없지만, 로그의 마지막에 아래처럼 적혀 있었다.
> Export encountered errors on following paths:
/bookmarks/page: /bookmarks
/join/page: /join
/maintenance/page: /maintenance
/page: /
그래서 bookmarks, join, maintenance, app 폴더의 page.tsx에 문제가 있다고 생각해 몇 시간 동안 이 파일만 쳐다보기도 했다. 하지만 문제는 다른 곳에 있었다.
컴포넌트들을 모아둔 폴더에 팔로우 추천 목록을 보여주는 컴포넌트가 이렇게 있었다.
// Components/RightSidebar/RecommendFollows.tsx
import styles from "./Recommend.module.css";
import RecommendFollow from "./RecommendFollow";
interface IRecommendFollows {
id: string;
nickname: string;
icon: string;
}
export default async function RecommendFollows() {
const response = await fetch("http://localhost:3000/api/recommend-follows", {
method: "GET",
});
const recommends: IRecommendFollows[] = await response.json();
return (
<section className={styles.sidebar__container}>
<h3 id={styles.sidebar__recommend__title}>팔로우 추천</h3>
{recommends.map((recommend) => (
<RecommendFollow recommend={recommend} />
))}
<h4 id={styles.sidebar__recommend__more}>더 보기</h4>
</section>
);
}
이미지의 에러를 보면 fetch failed라고 되어 있었기에 혹시 저 부분이 문제일 수도 있겠다고 생각해 아래처럼 분리하였다.
// Components/RightSidebar/RecommendFollows.tsx
import { getRecommendFollows } from "@/utils/otherDataFunctions";
import styles from "./Recommend.module.css";
import RecommendFollow from "./RecommendFollow";
export default async function RecommendFollows() {
const recommends = await getRecommendFollows();
return (
<section className={styles.sidebar__container}>
<h3 id={styles.sidebar__recommend__title}>팔로우 추천</h3>
{recommends.map((recommend) => (
<RecommendFollow recommend={recommend} />
))}
<h4 id={styles.sidebar__recommend__more}>더 보기</h4>
</section>
);
}
// utils/otherDataFunctions.ts 중 getRecommendFollows
interface IRecommendFollows {
id: string;
nickname: string;
icon: string;
}
export const getRecommendFollows = async () => {
try {
const response = await fetch(
"http://localhost:3000/api/recommend-follows",
{
method: "GET",
}
);
const recommends: IRecommendFollows[] = await response.json();
return recommends;
} catch (error) {
return [];
}
};
데이터를 받아오는 부분을 분리한 후, npm run build를 실행했더니 아래처럼 정상적으로 동작하였다.
아직 코드 정리가 제대로 되지 않아 죄다 다이나믹 렌더링이긴 하지만, 일단 성공하였다. 그리고 왜 이런 에러가 발생했는지 너무나 궁금했다. 하지만 앞에서 언급했듯 구글링을 해도 이 현상을 찾을 수 없어서 chatGPT에게 물어보았다.
Next.js에서의 페이지 렌더링과 데이터 페칭은 서로 다른 동작 방식을 갖습니다. 여기에서 발생한 문제의 주된 원인은 SSR(Server Side Rendering) 또는 SSG(Static Site Generation) 시에 데이터를 가져오는 방법을 제대로 활용하지 않았기 때문일 수 있습니다.
1. Component 내부에서의 비동기 작업:
- React Component (또는 Next.js 페이지 컴포넌트) 내에서 직접 비동기 함수를 사용하면, 해당 컴포넌트가 완전히 마운트되기 전에 데이터가 필요하다면 문제가 발생할 수 있습니다.
- React 컴포넌트 자체는 비동기 작업을 지원하지 않으므로, 데이터 페칭 작업은 useEffect 내에서 이루어져야 합니다.
2. SSR / SSG에서의 데이터 페칭:
- Next.js에서는 SSR 또는 SSG 시에 데이터를 페칭하기 위해 getServerSideProps 또는 getStaticProps를 사용합니다. 이 함수들은 페이지를 렌더링하기 전에 필요한 데이터를 가져오도록 디자인되었습니다.
본질적으로, 원래의 코드는 SSR 또는 SSG 단계에서는 동작하지 않는 직접적인 비동기 페칭 방식을 사용했기 때문에, 빌드 과정에서 문제가 발생했을 수 있습니다. 코드를 리팩토링하여 getRecommendFollows 유틸리티 함수에 데이터 페칭 로직을 분리한 것은 좋은 습관입니다. 하지만, 이 코드에서 최적의 동작을 원한다면, 페이지의 데이터 요구사항을 처리하기 위해 Next.js의 getServerSideProps 또는 getStaticProps를 사용하는 것을 고려해보세요.
이렇게 하면, 서버 사이드에서 데이터를 미리 가져올 수 있어 페이지가 렌더링될 때 이미 필요한 데이터가 준비되어 있을 것입니다.
앞으로 이런 현상을 예방하기 위해서 데이터 페칭을 따로 분리하는 습관을 들여야 할 것이다.