Next.js 15에서 App Router의 params.slug 타입 오류 해결하기

Next.js 15에서 App Router의 동적 라우트(params.slug)에서 발생하는 타입 추론 오류를 해결하는 방법을 정리합니다.

2025.07.22

문제 상황

export default async function Page({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug);
}
  • npm 빌드시 아래와 같은 에러가 발생
Type '{ params: { slug: string; }; }' is not assignable to type 'PageProps'.
  Types of property 'params' are incompatible.
    Type '{ slug: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally...

원인

  • Next.js App Router가 내부적으로 params를 비동기적으로 resolve할 수도 있다는 구조 때문에 발생
  • params가 Promise 타입으로 추론되는 경우 TypeScript가 타입 에러를 냄
  • 특히 Vercel 빌드 환경에서 자주 터짐

해결

1. gpt로 쉽게 해결해보려 했으나 실패

2. 구글링으로 글을 찾기 시작

🔗 https://github.com/vercel/next.js/issues/77609

  • 좋은 댓글 발견
  • 공식 문서도 읽어봤으나.. 아직 그것으로 해결 불가한 역량ㅠㅠ

🔗 참고 | https://nextjs.org/docs/app/api-reference/file-conventions/dynamic-routes


3. 아예 빌드 에러로 검색

🔗 https://github.com/vercel/next.js/discussions/71997

  • 아주 좋은 글 등장

👉 params를 Promise처럼 타입 지정하고 await으로 푸는 방식으로 해결

interface PageProps {
  **params: Promise<{ slug: string }>;**
}

export const generateStaticParams = async (): Promise<{ slug: string }[]> => {
  const slugs = getAllProjectsSlugs();
  return slugs.map((slug) => ({ slug }));
};

export default async function BlogPost({ params }: PageProps) {
  const { slug } = await params;
  const post = await getProjectPost(slug);
  • 공식 문서 기준이 아님
  • 특히 Vercel 환경에서 PageProps의 params를 Promise로 잘못 추론되어 생기는 문제
    • params: { slug: string } - 정상 상태(동기 객체)
    • params: Promise<{ slug: string }> - 버그(비동기 객체)
  • Next는 params를 비동기로 주지 않는데.. 비동기로 잘못 추론되니 그냥 Promise로 타입 지정해서 해결..
  • 버그인 것 같으니 Next 버전 제대로 올라가면 수정되기를 바람

export const getAllBlogSlugs = () => {
  const postDir = path.join(process.cwd(), "posts", "Blog");
  const files = fs.readdirSync(postDir);

  return files
    .filter((file) => file.endsWith(".mdx"))
    .map((file) => file.replace(".mdx", ""));
};
  • 추가적으로 이 함수에서 async를 없앴는데 원래 불필요 하던 것이라 한다.
  • readdirSync → 동기 → async 필요 x
  • fs.promises.readdir → 비동기 → async 필요
  • async 안 없애면 위에 해결한 방법에서 map 속성이 없다는 에러 + await 잊었냐는 에러가 남

Copyright © 2025 NahyunKim

Mag.dev