심화과정이라고 하면 조금 거창하긴 하지만
여러가지 가능성을 두고 연습을 해봐야 실력이 늘기 때문에
심화과정이라고 하겠다.
추가적으로 앞으로의 프로젝트는 모두 타입스크립트로 진행하려고 한다.
타입스크립트만 지원하는 prisma 같은 ORM 도 있고,
정적 타이핑의 장점을 살려서 개발하는 버릇을 들이는 편이 아무래도 좋다는 생각이 든다.
스타일링은 따로 진행하지 않고 tailwind 를 사용해 가볍게
margin, padding, border 정도만 넣어주었다.
tailwind 를 연습하는 것도 정말 재밌는데,
익숙해지면 많이 쓰던 styled-components 이상으로 편할 것 같다.
현재 버전의 Next js 에서 서버 컴포넌트에서 js-in-css 를 사용하기 까다롭다는게
많은 개발자들이 tailwind 를 사용하는 이유라고 하지만
그 이외에도 컴포넌트 작명 같은 아주아주 어려운 작업을 하지 않아도 된다는 점에서
개인적으로 많이 좋아하게 될 것 같은 스타일링 도구다.
디렉토리는 위와같이 진행 했다.
dynamic route 폴더 명에 slug, 혹은 id 라는 키워드를 사용하라고
공식 문서에 나와있지만 개인적으로는 직접 작명하는 것이 조금 더 알기 편한 것 같다.
import React from "react";
export default function ProductsLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<section>
<nav className="flex justify-start items-center px-10 py-5 text-2xl gap-16">
<a href="/products/man">Man</a>
<a href="/products/Woman">Woman</a>
</nav>
{children}
</section>
);
}
products 페이지의 layout 컴포넌트.
products 페이지에서는 남자 혹은 여자라는 링크로 갈 수 있는 navbar 를 만들었다.
Next js 에서는 Link 태그를 사용하는 것이 좋다.
a 태그를 사용하면 링크를 클릭할 때마다 새로운 HTTP 요청을 서버로 하게 되므로
페이지 로딩시간이 늘어난다.
반면에, Link 태그는 클라이언트 사이드 라우팅을 지원해서 필요한 데이터만 가져와
페이지를 즉시로딩 할 수 있다.
React 에서 a 태그대신 react-router-dom 의 Link 태그를 사용하는 것과
비슷한 이유.
type Props = {
params: {
slug: string;
};
};
export default function ItemPage({ params }: Props) {
return <h1>{params.slug}Page</h1>;
}
export function generateStaticParams() {
const gender = ["man", "woman"];
return gender.map((e) => ({ slug: e }));
}
서버 컴포넌트에서 generateStaticParams 함수를 사용하면
미리 페이지를 만들어놓을 수 있다.
// layout.tsx
import Link from "next/link";
import React from "react";
type Props = {
children: React.ReactNode;
params: { slug: string };
};
export default function GenderLayout({ children, params }: Props) {
return (
<section>
<nav className="flex justify-start items-center px-10 py-5 text-1xl gap-16">
<Link href={`/products/${params.slug}/shirt`}>Shirt</Link>
<Link href={`/products/${params.slug}/pants`}>Pants</Link>
<Link href={`/products/${params.slug}/skirt`}>Skirt</Link>
<Link href={`/products/${params.slug}/shoes`}>Shoes</Link>
</nav>
{children}
</section>
);
}
//[category]/page.tsx
"use client";
import React from "react";
type Props = {
params: {
slug: string;
category: string;
};
};
type CategoryData = Record<string, number[]>;
export default function CategoryPage({ params }: Props) {
const data: CategoryData = {
shirt: [1, 2, 3],
pants: [4, 5, 6],
skirt: [7, 8, 9],
shoes: [10, 11, 12],
};
return (
<div className="grid grid-cols-3 gap-4 px-10 py-5">
{data[params.category]?.map((e, i) => (
<div key={i} className="border-2 border-sky-600 h-60">
{e}
</div>
))}
</div>
);
}
layout 컴포넌트로 shirt, pants, skirt, shoes 의 카테고리를
navbar 로 만들어 주었다. 해당 카테고리는 세부 모든 페이지에서 볼 수 있어야 한다.
category 데이터도 api fetch로 받아와서 보여주는 기능도 만들어보면 좋을 것 같지만
일단 편의상 data 라는 임의의 더미 데이터로 바인딩을 해줬다.
데이터는 유동적으로 바뀔 수 있으니까 클라이언트 컴포넌트로 만들어 준 모습.
Next js는 알면 알수록 신기하고 재밌는 기능이 많다.
SSR, CSR, SSG 같은 렌더링 솔루션에 대해서도 조금 더 깊게 알 수 있고,
어떤 경우에 어떤 방식을 사용해야 하는지에 대해서도 고민해볼 수 있는 기회가 되는 것 같다.