방명록
- [Next.js] 인프런 강의 "Next.js 필수 개발 가이드 3시간 완성!" 정리(섹션 2: 라우팅과 네비게이션)2024년 02월 07일 09시 38분 21초에 업로드 된 글입니다.작성자: DandyNow728x90반응형
섹션 2: 라우팅과 내비게이션
📌 다이내믹 라우트(Dynamic Routes)
- 공식 문서 : https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#convention
- "src/app/users/[id]/photo/[photoId]" 경로를 작성
- 대괄호 [] 안에 매개 변수를 지정할 수 있고, 이 매개 변수에 할당되는 인수가 경로가 된다.
// src/app/users/[id]/photo/[photoId]/page.tsx import React from "react"; interface Props { params: { id: number; photoId: number }; } // props에 params 속성이 존재하고 params에 동적 라우트 속성이 존재한다. // props.params.id 혹은 props.params.photoId로 동적 라우트 path variable의 값에 접근할 수 있다. // props.params.photoId를 destructuring하여 { params: { photoId } }로 표현할 수 있다. const PhotoPage = ({ params: { id, photoId } }: Props) => { // props를 생략해도 동작하지만 id, photoId 속성을 이용할 수 없게 된다. return ( <div> PhotoPage {id} {photoId} </div> ); }; export default PhotoPage;
📌 Catch-all Segments
- 공식 문서 : https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments
- "src/app/profile/[...username]" 경로 작성
- "http://localhost:3000/profile/kim/post1/post1-1/post1-1-1"과 같은 방식으로 접근이 가능하다.
- 단, "http://localhost:3000/profile"로는 접근 불가
// src/app/profile/[...username]/page.tsx import React from "react"; interface Props { params: { username: string[]; }; } const ProfilePage = (props: Props) => { console.log(props); /* 출력 결과 { params: { username: [ 'kim', 'post1', 'post1-1', 'post1-1-1' ] }, searchParams: {} } */ return <div>ProfilePage</div>; }; export default ProfilePage;
📌 Optional Catch-all Segments
- 공식 문서 : https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments
- "src/app/profile/[[...username]]"와 같이 이중 대괄호 사용하여 경로 작성
- "http://localhost:3000/profile/kim/post1/post1-1/post1-1-1" 뿐만 아니라 "http://localhost:3000/profile"로도 접근 가능
📌 QueryString
- "http://localhost:3000/products/computer?sortOrder=name"에서 ?(start of parameters)에서 부터 시작하는 query string을 다룬다.
// src/app/products/[..slug]/page.tsx import React from "react"; interface Props { params: { slug: string }; searchParams: { sortOrder: String }; } const ProductPage = ({ params: { slug }, searchParams: { sortOrder }, }: Props) => { return ( <div> page {slug} {sortOrder} </div> ); }; export default ProductPage;
📌 QueryString 기반 정렬
- fast-sort 설치 : https://npmjs.com/package/fast-sort
npm i fast-sort
- page.tsx에서 searchParams를 자식 컴포넌트(userTable.tsx)의 props로 넘겨 정렬의 키워드로 사용
// src/app/users/page.tsx import React from "react"; import UserTable from "./UserTable"; interface Props { searchParams: { sortOrder: string }; } const UsersPage = async ({ searchParams: { sortOrder } }: Props) => { return ( <div> <h1>This is UESRPAGE</h1> <p>{new Date().toLocaleTimeString()}</p> <UserTable sortOrder={sortOrder} /> // query string을 props로 넘김 </div> ); }; export default UsersPage;
// src/app/users/UserTable.tsx import { sort } from "fast-sort"; import Link from "next/link"; import React from "react"; interface User { id: number; name: string; email: string; } interface Props { sortOrder: string; } const UserTable = async ({ sortOrder }: Props) => { const res = await fetch("https://jsonplaceholder.typicode.com/users"); const users: User[] = await res.json(); // fast-sort를 이용한 정렬 // asc : 오름차순 정렬 const sortedUsers = sort(users).asc( sortOrder === "email" ? (user) => user.email : (user) => user.name ); return ( <> <table> <thead> <tr> {/* Link 컴포넌트를 이용한 네비게이션 처리 */} <th> <Link href="/users?sortOrder=name">Name</Link> </th> <th> <Link href="/users?sortOrder=email">Email</Link> </th> </tr> </thead> <tbody> {/* 정렬된 배열 이용 */} {sortedUsers.map((user) => ( <tr key={user.id}> <td>{user.name}</td> <td>{user.email}</td> </tr> ))} </tbody> </table> </> ); }; export default UserTable;
📌 Layout
- app 폴더에 작성하면 모든 컴포넌트에 공통 적용(Global Layout)
- 각 폴더에 적용하면 해당 폴더 범위만 적용(Local Layout)
- page.tsx는 반드시 있어야 하지만 layout.tsx는 생략 가능
// src/app/admin/layout.tsx // Local layout 예제이다. import React from "react"; interface Props { children: React.ReactNode; // ReactNode = 리엑트 컴포넌트 } // props children에 page.tsx가 들어온다. const AdminLayout = ({ children }: Props) => { return ( <div className="flex"> <aside className="bg-slate-200 p-5 mr-5">Admin Sidebar</aside> <div>{children}</div> </div> ); }; export default AdminLayout;
📌 Programmatic Navigation
// src/app/users/new/page.tsx "use client"; import { useRouter } from "next/navigation"; // 추가 import React from "react"; const NewUser = () => { const router = useRouter(); // 추가 return ( // 서버 컴포넌트는 클릭 이벤트 처리 안됨. CSR로 변경해야 함. // CSR에서의 라우팅 처리를 Programmatic Navigation이라고 한다. <button className="btn btn-primary" onClick={() => router.push("/users")}> // router.push() Create </button> ); }; export default NewUser;
🤔Next.js 공식 문서에서는 찾을 수 없는 용어였음. Vue.js 공식 문서에서 용어 발견하였음. https://v3.router.vuejs.org/guide/essentials/navigation.html
728x90반응형'언어·프레임워크 > Next.js' 카테고리의 다른 글
[Next.js] 인프런 강의 "Next.js 필수 개발 가이드 3시간 완성!" 정리(not-found) (0) 2024.02.11 [Next.js] 인프런 강의 "Next.js 필수 개발 가이드 3시간 완성!" 정리(Loading UI) (0) 2024.02.11 [Next.js] 인프런 강의 "Next.js 필수 개발 가이드 3시간 완성!" 정리(섹션 1: Styling) (0) 2024.02.06 [Next.js] 인프런 강의 "Next.js 필수 개발 가이드 3시간 완성!" 정리(섹션 0: 기초) (0) 2024.02.04 [Next.js] 인프런 강의 "Next + React Query로 SNS 서비스 만들기" 정리 (0) 2024.01.21 다음글이 없습니다.이전글이 없습니다.댓글