Frontend
[유데미 러닝크루] Next.js 스터디 4주차 – 파일 기반 라우팅 완벽 정리! 동적 경로 & 필터링까지
· 5분 읽기
📑 목차
- 1) 4주차 진행 범위 & Udemy 강의 소개
- 2) 4주차 학습 정리 — 파일 기반 라우팅/동적 경로/필터링
- 1️⃣ 프로젝트 시작 & 라우팅 계획
- 2️⃣ 페이지 & 동적 라우팅 구현
- 3️⃣ 연도/월 필터링 & 프로그램 내비게이션
- 4️⃣ 공통 컴포넌트 & 스타일링
- 🔥 최종 점검 체크
- 📌 부록: 무료 아이콘 사이트
1. 4주차 진행 범위
📝 세션 12 ~ 17 강의까지 진행
[Udemy 강의 소개]
이번 스터디에서 수강하는 강의는 【한글자막】 Next.js 15 & React - 완벽 가이드이다. 이 강의에서는 Next.js 15를 기초부터 학습하고, 앱 라우터 & 페이지 라우터를 활용하여 풀스택 앱을 구축하는 방법을 배울 수 있다.
💡 강의 정보
- 강의명: 【한글자막】 Next.js 15 & React - 완벽 가이드
- 강의 시간: 40시간
- 수강생: 5,021명
- 강의 평가: ⭐ 4.7/5 (585명 평가)
- 언어: 한국어 자막 제공
📌 강의 주요 내용
✅ Next.js 15의 앱 라우터 & 페이지 라우터 ✅ 서버/클라이언트 컴포넌트 이해 ✅ 서버 액션 기반 데이터 처리 ✅ SSR·파일 기반 라우팅·인증 기능
2. 4주차 학습 내용 정리 — 파일 기반 라우팅, 동적 경로, 필터링
이번 주는 Pages Router 관점에서 라우트/동적경로/필터링을 구현.
1️⃣ 프로젝트 시작 및 라우팅 계획
- 시작: Starting Project 다운로드 → 프로젝트 폴더에서
npm install - 주요 라우트 (총 4개)
/— 메인(주요 이벤트 목록)/events— 모든 이벤트 목록/events/[eventId]— 개별 이벤트 상세/events/[...slug]— 연/월 필터링
2️⃣ Next.js 페이지 & 동적 라우팅 구현
✔ 홈 (/)
pages/index.js—getFeaturedEvents()로 주요 이벤트만 추려서EventList로 렌더
✔ 모든 이벤트 (/events)
pages/events/index.js—getAllEvents()로 전체 목록,EventList재사용
✔ 동적 상세 (/events/[eventId])
pages/events/[eventId].js—getEventById()로 상세 데이터useRouter()로eventId추출EventSummary,EventLogistics,EventContent구성
// pages/events/[eventId].js
import { useRouter } from "next/router";
import { getEventById } from "../../helpers/api-util";
import EventSummary from "../../components/event-detail/event-summary";
import EventLogistics from "../../components/event-detail/event-logistics";
import EventContent from "../../components/event-detail/event-content";
export default function EventDetailPage(){
const router = useRouter();
const { eventId } = router.query;
const event = getEventById(eventId);
if (!event) return <p>Loading...</p>;
return (
<>
<EventSummary title={event.title} />
<EventLogistics date={event.date} address={event.location} image={event.image} imageAlt={event.title} />
<EventContent><p>{event.description}</p></EventContent>
</>
);
}✔ 다중 동적 경로 (/events/[...slug])
useRouter()로slug에서[year, month]추출getFilteredEvents({ year, month })로 목록 필터- 유효성 검사(숫자 아님/범위 벗어남) → 오류 메시지
// pages/events/[...slug].js
import { useRouter } from "next/router";
import { getFilteredEvents } from "../../helpers/api-util";
import EventList from "../../components/events/event-list";
import ErrorAlert from "../../components/ui/error-alert";
export default function FilteredEventsPage(){
const router = useRouter();
const slug = router.query.slug;
if (!slug) return <p>Loading...</p>;
const year = +slug[0];
const month = +slug[1];
if (isNaN(year) || isNaN(month) || year < 2020 || year > 2030 || month < 1 || month > 12) {
return <ErrorAlert><p>Invalid filter. Please check values!</p></ErrorAlert>;
}
const events = getFilteredEvents({ year, month });
if (!events || events.length === 0) {
return <ErrorAlert><p>No events found!</p></ErrorAlert>;
}
return <EventList items={events} />;
}3️⃣ 필터링 기능 (연/월 선택) & 프로그래밍 내비게이션
✔ 검색 폼 컴포넌트 — components/events/events-search.js
<select>로 연/월 선택,useRef로 값 읽기useRouter().push()로/events/2021/5등으로 이동
// components/events/events-search.js
import { useRef } from "react";
import { useRouter } from "next/router";
export default function EventsSearch(){
const router = useRouter();
const yearRef = useRef();
const monthRef = useRef();
function submitHandler(e){
e.preventDefault();
const y = yearRef.current.value;
const m = monthRef.current.value;
router.push(`/events/${y}/${m}`);
}
return (
<form onSubmit={submitHandler}>
<select ref={yearRef} defaultValue="2023">
<option value="2021">2021</option>
<option value="2022">2022</option>
<option value="2023">2023</option>
</select>
<select ref={monthRef} defaultValue="5">
{Array.from({length:12}).map((_,i)=>(
<option key={i+1} value={i+1}>{i+1}</option>
))}
</select>
<button>찾기</button>
</form>
);
}4️⃣ 공통 컴포넌트 & 스타일링
- 헤더/네비:
components/layout/main-header.js→_app.js에서 전체 래핑 - 버튼 UI:
components/ui/button.js— Link를 감싼 재사용 버튼 구성- Next 13 미만:
<Link href="..."><a>...</a></Link> - Next 13 이상:
<Link>에<a>불필요
- Next 13 미만:
- 에러 표시:
components/ui/error-alert.js로 사용자 친화적 오류 메시지
// components/ui/button.js (예시)
import Link from "next/link";
export default function Button({ link, children }){
if (link) return <Link className="btn" href={link}>{children}</Link>;
return <button className="btn">{children}</button>;
}🔥 최종 정리 — 기능 점검
- ✅ 기본 페이지 동작 확인 (
/,/events) - ✅ 상세 페이지 (
/events/[eventId]) 정상 - ✅ 연/월 필터 (
/events/[...slug]) 정상 - ✅ URL 직접 입력 (
/events/2023/2등) 동작 - ✅ 모든 페이지에서 네비게이션 정상
팁 — 데이터가 비어 있으면 “No events found!” 메시지로 UX 보완.
📌 부록: 무료 아이콘 다운로드 사이트
| 이름 | 특징 |
|---|---|
| Heroicons | Tailwind 팀의 무료 아이콘 · SVG/JSX 복사 |
| Font Awesome | 가장 유명 · 무료/유료 제공 |
| Material Icons | Google Material · SVG/폰트 |
| Iconmonstr | 심플/선명 · SVG/PNG |
| Flaticon | 방대한 컬렉션 · SVG/PNG/EPS (계정 필요) |
| The Noun Project | 디자이너 참여 대형 라이브러리 · 출처 표기 |
| Remix Icon | 간결/일관성 높은 무료 아이콘 · SVG/JSX |
댓글
GitHub 계정으로 댓글을 남길 수 있어요.