Next.js 15 버전에서 동적 라우팅([id]
)과 API 응답 처리 시 여러 타입 에러가 발생했습니다.
// 에러 메시지
Error: Route "/items/[id]" used `params.id`. `params` should be awaited before using its properties.
Type error: Property 'id' does not exist on type 'ApiResponse<Item>'.
1. Next.js 15의 변경된 동적 라우팅 처리
페이지 파라미터가 Promise 타입으로 변경됨
params 객체 처리 방식의 변화
2. API 응답 타입과 실제 데이터 구조의 불일치
interface ApiResponse<T> {
data: T;
statusCode: number;
message: string;
}
// 실제 받은 응답 구조
{
id: number;
tenantId: string;
name: string;
memo?: string;
imageUrl?: string;
isCompleted: boolean;
}
// src/app/items/[id]/page.tsx
interface PageProps {
params: { id: string };
}
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
return {
title: `Item ${params.id}`,
};
}
export default function ItemDetailPage({ params }: PageProps) {
const id = Number(params.id);
if (isNaN(id)) {
return notFound();
}
return <ItemDetail id={id} />;
}
// src/hooks/useItemDetail.ts
export function useItemDetail(id: number) {
const [item, setItem] = useState<Item | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchItem = useCallback(async () => {
if (!id) return;
try {
setLoading(true);
setError(null);
const response = await itemApi.getItemById(id);
if (!response || !response.id) {
throw new Error('유효하지 않은 응답입니다.');
}
console.log('Fetched item:', response);
setItem(response);
} catch (err) {
console.error('Fetch error:', err);
setItem(null);
setError(err instanceof Error ? err.message : '항목을 불러오는데 실패했습니다.');
} finally {
setLoading(false);
}
}, [id]);
useEffect(() => {
fetchItem();
}, [fetchItem]);
// ... 나머지 코드
}
3. API 함수 수정
// src/lib/api.ts
export const itemApi = {
getItemById: async (id: number) => {
const response = await api.get<Item>(`/${TENANT_ID}/items/${id}`);
return response.data;
},
// ... 다른 메서드들
};
// types/item.ts
export interface Item {
id: number;
tenantId: string;
name: string;
memo?: string;
imageUrl?: string;
isCompleted: boolean;
}
API 응답 래퍼 타입을 제거하고 직접 Item 타입 사용
불필요한 중첩 구조 제거
try {
const response = await itemApi.getItemById(id);
if (!response) throw new Error('데이터를 찾을 수 없습니다.');
setItem(response);
} catch (err) {
setError(err instanceof Error ? err.message : '오류가 발생했습니다.');
}
// next.config.js
const nextConfig = {
typescript: {
ignoreBuildErrors: true, // 권장하지 않음
}
}
ㅎㅎㅎ... 버전을 잘봅자..ㅠㅅㅠ 두시간동안 고생하지말고,....