Remix Framework 한 화면에 Nested Routes 구현하기
Remix Framework, 리믹스 프레임워크, 한 화면에 네스티드 라우츠 구현하기, 한 화면에 Nested Routes 구현하기
한 화면에 Nested Routes 설정하기
이제 리믹스 프레임워크의 가장 강력한 기능인 Nested Routes에 대해 알아보겠습니다.
제목 그대로 한 화면에 Nested Routes를 만들 수 있는데요.
일단 지난 시간에 배웠던 글을 참고해서 이번 글을 쓰도록 하겠습니다.
https://cpro95.tistory.com/680
https://cpro95.tistory.com/681
위의 두 개 글을 잘 읽어 보시면 아래 글을 따라오시는데 어려움이 없을 겁니다.
일단 기존에 다이내믹 라우팅에서 썼던 $movieId.tsx파일을 이용해서 한 화면에 Nested Routes를 구현하도록 하겠습니다.
먼저, $movieId.tsx 파일은 app/routes/child/$movieId.tsx 에 위치하고 있고 내용을 아래와 같이 수정해 줍시다.
import { Link, useParams } from "remix";
export default function GetMovie() {
const { movieId } = useParams();
let movieInfoId = 1;
return (
<>
<h1 className="text-2xl">Movie id : {movieId}</h1>
<div className="flex flex-row space-x-10">
<div className="flex flex-col space-y-5">
{/* <Link
className="hover:underline underline"
to={"movieinfo/" + movieInfoId}
>
Squid Game
</Link> */}
<Link
className="hover:underline underline"
to={"movieinfo/" + "squid_game"}
>
Squid Game
</Link>{" "}
<Link
className="hover:underline underline"
to={"movieinfo/" + "parasite"}
>
Parasite
</Link>
</div>
</div>
</>
);
}
브라우저에서 아래와 같은 주소 들어가 볼까요?
$movieId.tsx 파일 이름처럼 다이내믹 라우팅이라서 테스트하기 위해 위와 같이 주소를 /child/11로 들어갔습니다.
예상데로 Movie id 가 11로 나오고 그 밑에 영화 제목 두 개가 있네요.
그런데 잘 보시면 영화 제목 링크가 to="movieinfo/squid_game"입니다.
원래는 아래 주석 처리되어있는 코드처럼 그 movieinfo/$movieInfoId.tsx 파일처럼 다이내믹으로 만들려고 했는데,
{/* <Link
className="hover:underline underline"
to={"movieinfo/" + movieInfoId}
>
Squid Game
</Link> */}
지금은 테스트라서 위와 같이 하드코드 했습니다.
그래서 결론은 http://localhost:3000/child/11 경로 밑에 다시 http://localhost:3000/child/11/movieinfo/squid_game이라는 폴더 경로가 형성되는데요.
최종적으로 한 화면에 Nested Routes를 구현하기 위해 우리가 필요한 폴더 구조는 먼저, 현재 페이지의 파일 이름인 $movieId.tsx 파일과 같은 폴더를 만드는 겁니다.
폴더명은 당연히 $movieId입니다.
그러면 app/routes/child 폴더 밑에 $movieId.tsx 파일과 $movieId 폴더 두 개가 존재하게 됩니다.
이 방식은 Nested Routes 파헤치기 블로그에서 설명드렸던 Layout Routes입니다.
파일 이름 A와 그 파일 이름과 똑같은 폴더 A-가 있으면 그 A- 폴더 밑의 컴포넌트는 무조건 A 파일을 포함하게 됩니다.
일종의 Layout 컴포넌트가 되는 겁니다.
우리가 원하는 최종 경로는 다음과 같습니다.
http://localhost:3000/child/11/movieinfo/squid_game
http://localhost:3000/child/11/movieinfo/parasite
이 경로로 유추해 볼 때 $movieId 폴더 밑에는 movieinfo 폴더가 있고 그다음에는 $movieName.tsx 파일이 있으면 될 거 같네요.
그런데 Remix Framework에서는 movieinfo 폴더를 만들 필요가 없습니다.
당연히 movieinfo 폴더를 만들고 그 밑에 $movieName.tsx라는 다이내믹 라우팅을 만들어도 됩니다.
좀 더 유연하게 아래와 같은 파일을 만들면 movieinfo 폴더와 $movieName.tsx 파일을 합친 결과를 가져올 수 있습니다.
바로 movieinfo.$movieName.tsx라는 이름으로 파일을 만들면 됩니다.
이제 만들어 볼까요?
import { useParams } from "remix";
export default function movieInfo() {
const { movieName } = useParams();
return <div>{movieName}</div>;
}
단순하게 params를 출력하는 컴포넌트로 만들었습니다.
이제 브라우저에서 해당 링크를 클릭해 볼까요?
위 그림처럼 분명히 링크를 눌러서 브라우저의 경로가 원하는 데로 이동했는데요.
내용은 바뀐 게 없습니다.
왜 그런 걸까요?
바로 Outlet 컴포넌트를 깜빡 한 겁니다.
다시 $movieId.tsx 파일에 돌아가서 Outlet 컴포넌트를 추가해 봅시다.
Outlet 컴포넌트가 바로 하위 컴포넌트를 보여줄 위치를 지정해주는 컴포넌트이기 때문입니다.
import { Link, Outlet, useParams } from "remix";
export default function GetMovie() {
const { movieId } = useParams();
let movieInfoId = 1;
return (
<>
<h1 className="text-2xl">Movie id : {movieId}</h1>
<div className="flex flex-row space-x-10">
<div className="flex flex-col space-y-5">
{/* <Link
className="hover:underline underline"
to={"movieinfo/" + movieInfoId}
>
Squid Game
</Link> */}
<Link
className="hover:underline underline"
to={"movieinfo/" + "squid_game"}
>
Squid Game
</Link>{" "}
<Link
className="hover:underline underline"
to={"movieinfo/" + "parasite"}
>
Parasite
</Link>
</div>
<div className="flex-1">
<Outlet />
</div>
</div>
</>
);
}
Outlet 컴포넌트를 잘 보이기 위해 flex flex-col 디스플레이 방식으로 CSS를 꾸몄습니다.
이제 다시 브라우저를 볼까요?
어떤가요?
한 화면에 Nested Routes를 완벽하게 구현했습니다.
이렇게 구현하면 가장 밑의 컴포넌트가 에러가 난다면 바로 그 자리만 에러 표시를 할 수 있고
또한 라우트 구조 단위로 리믹스가 서버에서 병렬로 자료를 불러오기 때문에 훨씬 더 브라우저 로딩이 빨라집니다.
많이 복잡할 수 있겠지만 한 화면에 Nested Routes를 구현하는 원리만 알면 쉽게 이해할 수 있는데요.
1. 다이내믹 라우팅을 만들고
2. 그 다이내믹 라우팅과 같은 폴더를 만듭니다.
3. 그렇게 되면 다이내믹 라우팅이 레이아웃 라우팅이 되고,
4. 2번에서 만든 라우팅 폴더에 다시 다이내믹 라우팅을 만들고,
5. 1번의 다이내믹 라우팅 안에 적절한 위치에 Outlet 컴포넌트만 위치시키면 됩니다.
끝.