인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

ssi02014님의 프로필 이미지

작성한 질문수

손에 익는 Next.js - 공식 문서 훑어보기

서비스 배포하기

안녕하세요! 서비스 배포를 하는데 에러가 생겨서 문의드립니다!

해결된 질문

작성

·

385

·

수정됨

1

안녕하세요! 강의를 쭉 듣고, 배포 단계까지 왔는데 에러가 생겨서 진행이 안되어 문의드립니다!

vercel에서 에러는

image.png

Failed to compile.

src/app/[location]/page.tsx

Type error: Type 'Props' does not satisfy the constraint 'PageProps'.

Types of property 'params' are incompatible.

Type '{ location: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]

Error: Command "npm run build" exited with 1
이며, 그전에도

Route "/[location]" used params.location. params should be awaited before using its properties. Learn more:
위와 같은 에러가 떴고, 이는 경로 및 쿼리 파라미터를 위한 객체에서 런타임 에러가 뜨는걸로 확인했습니다! 강의를 똑같이 따라갔는데, 위와 같은 에러가 나는게 의아하여 한번 문의드립니다!

import HomeButton from "../components/HomeButton";
import { getForecast } from "../utils/getForecast";

type Props = {
  params: {
    location: string;
  };
  searchParams: {
    name: string;
  };
};

export function generateMetadata({ searchParams }: Props) {
  return {
    title: `날씨 앱 - ${searchParams.name}`,
    description: `${searchParams.name} 날씨를 알려드립니다`,
  };
}

export default async function Detail({ params, searchParams }: Props) {
  const name = searchParams.name;

  const res = await getForecast(params.location);

  return (
    <>
      <h1>{name}의 3일 예보</h1>
      <ul>
        {res.forecast.forecastday.map((day) => (
          <li key={day.date}>
            {day.date} / {day.day.avgtemp_c}
          </li>
        ))}
      </ul>
      <HomeButton />
    </>
  );
}


image.png

크리스마스 쉬는날 연락드려, 죄송하며 빠른 답변 부탁드립니다!

답변 1

0

하조은님의 프로필 이미지
하조은
지식공유자

안녕하세요! 메리크리스마스 입니다!

배포 단계까지 오셨다니 고생 많으셨어요. 혹시 설치된 Next.js의 버전을 확인해주실 수 있을까요? 강의에서는 13.4.19 버전을 쓰고 있습니다. 그 이상 버전이 설치된 환경이라면 최신 문서 가이드를 참고하셔서 Props의 params를 Promise로 감싸보시면 해결될 것 같아요!

시도해보시고 다시 답변 남겨주세요.

ssi02014님의 프로필 이미지
ssi02014
질문자

공식문서를 참조해서 바꿨는데, 제 local에선 에러가 안뜨는데, 바꿀때마다 배포에 실패했습니다. 그러다가 params와 searchParams를 전부 Promise 타입으로 감싸고 await로 안전하게 접근하도록 수정했습니다.

import HomeButton from "../components/HomeButton";
import { getForecast } from "../utils/getForecast";

// 수정된 Props 타입
type Props = {
  params: Promise<{ location: string }>; // params를 Promise로 정의
  searchParams: Promise<{ name?: string }>; // searchParams도 Promise로 정의
};

export async function generateMetadata({ searchParams }: Props) {
  const resolvedSearchParams = await searchParams; // 비동기로 처리
  const name = resolvedSearchParams?.name || "Unknown";

  return {
    title: `날씨 앱 - ${name}`,
    description: `${name} 날씨를 알려드립니다`,
  };
}

export default async function Detail({ params, searchParams }: Props) {
  // params와 searchParams를 비동기로 처리
  const resolvedParams = await params;
  const resolvedSearchParams = await searchParams;

  const name = resolvedSearchParams?.name || "Unknown";
  const location = resolvedParams?.location;

  // location이 없는 경우 에러 처리
  if (!location) {
    throw new Error("Location is required!");
  }

  // API 호출
  const res = await getForecast(location);
  return (
    <>
      <h1>{name}의 3일 예보</h1>
      <ul>
        {res.forecast.forecastday.map((day) => (
          <li key={day.date}>
            {day.date} / {day.day.avgtemp_c}
          </li>
        ))}
      </ul>
      <HomeButton />
    </>
  );
}

바뀐 코드는 위와 같습니다! 한 2~3시간 꼼짝없이 매달렸네요.. 제 실력이 너무 부족했던 것 같습니다..! 다른 분들은, 저처럼 실수없이 잘 해결하시길!
일단 배포는 완료했습니다!


하조은님의 프로필 이미지
하조은
지식공유자

감사합니다! 다른 분들에게도 도움이 될 것 같아요. 고생 많으셨어요!

ssi02014님의 프로필 이미지

작성한 질문수

질문하기