Next.js 13 버전을 이용해서 프로젝트 진행 중 dynamic route를 사용할 일이 있었다.
리스트에서 사진을 클릭 시 사진 디테일 페이지로 넘어가게 해야했다.
파일 구조는 아래와 같이 설계했다.
// layout.tsx
'use client';
export default async function PhotoDetailPageLayout() {
console.log('detail page!');
return (
<div>photo layout</div>
)
}
// page.tsx
import PhotoDetailPageLayout from "./layout";
export default function PostDetailPage() {
console.log("post detail page");
return (
<div>
<PhotoDetailPageLayout />
</div>
);
}
일단 확인을 위해 콘솔을 찍어봤다.
확인해보니, 터미널에 콘솔은 찍히지만, 브라우저에서 콘솔은 안찍혔다.
서버컴포넌트인 page.tsx는 잘 작동되지만,
클라이언트 컴포넌트인 레이아웃파일은 콘솔도 안찍히고,
html도 바뀌지 않는걸로 보아 build가 안된거 같았다.
그래서 yarn build로 빌드 트리를 확인해보니 아래와 같았다.
구글링 해보니 다들 O표시로 나오는데 나는 html이 생성이 안되었다고 판단했다.
원래는 레이아웃 페이지를 client component로 설정하고, useMutation을 이용해서 사진 디테일 api요청을 하려고 했다.
근데, 아예 html이 안생기는걸 보아
서버 컴포넌트에서 fetch 해서 사용해야겠다고 판단하고 아래와 같이 코드를 변경했다.
import { PhotoDetailProps } from "@/apis/axios/photos/getPhotoDetail";
import { GetPhotosProps } from "@/apis/axios/photos/getPhotos";
import PhotoDetail from "./(components)/PhotoDetail";
import axiosInstance from "@/apis/axios/instance";
export async function generateStaticParams() {
const response = axiosInstance.get<{
photo_sections: GetPhotosProps[];
}>("/photo-sections");
if (!response) return [];
return (await response).data.photo_sections.map(photo =>
photo.photo_cards.map(photo_card => {
id: photo_card.id.toString();
})
);
}
export default async function PhotoDetailPageLayout({ params }: any) {
const { id } = params;
console.log("params", params);
const res = await axiosInstance.get<PhotoDetailProps>(`/photos/${id}`);
const data: PhotoDetailProps = res.data;
console.log("data", data);
return (
<div className="w-full h-full flex flex-col justify-center items-center gap-1">
<PhotoDetail data={data} />
</div>
);
}
이렇게 변경 후 빌드 트리를 다시 확인해봤더니, O표시로 잘바뀌었다.
근데,, 아직도 각 id 별 html은 없는거 같다.
터미널을 확인하니, 아래와 같이 콘솔이 잘찍힌다.
바꾸기 전과 동일하게 브라우저에서는 url만 변경될 뿐, 디테일 페이지가 아예 렌더링되지 않았다.
stackoverflow 를 열심히 찾아본 결과
layout.tsx가 app/photo/layout.tsx 와 app/photo/[id]/layout.tsx 총 두 곳에 위치해서 그랬던 거였다....!
원인을 찾는데 일주일 이상 걸렸다....
폴더 구조를 아래처럼
app/photo/layout.tsx > app/photo/(components)/PhotoPageLayout.tsx
으로 변경해 상위 layout의 위치를 변경해주었다.
이 문제로 꽤나 오랜 기간 고민했는데 드디어 해결..
스택오버플로우 최고.......🥹
코딩하면서 항상 느끼는 것 : 안될때는 정말 너무 안되는데 항상 알고보면 가까운데에 원인이 있었다.
📝 너무 오랫동안 닫혀있어서 벽인줄 알았는데, 알고보니 문이었다.