Next.js 13 앱 라우터로 모던 웹 개발하기 - 초보자도 쉽게 따라하는 완벽 가이드
안녕하세요! 오늘은 Next.js 13에서 도입된 앱 라우터(App Router)에 대해 자세히 알아보겠습니다. 기존의 페이지 라우터와는 완전히 다른 접근 방식으로, 처음엔 조금 어려워 보일 수 있지만 한 번 익숙해지면 정말 강력한 도구가 될 거예요.
🚀 앱 라우터가 뭔가요?
Next.js 13부터 도입된 앱 라우터는 React Server Components를 기반으로 한 새로운 라우팅 시스템입니다. 기존의
pages
폴더 대신 app
폴더를 사용하며, 파일 시스템 기반의 라우팅을 더욱 직관적이고 강력하게 만들어줍니다.가장 큰 변화는 서버 컴포넌트가 기본이라는 점이에요. 이제 별도의 설정 없이도 서버에서 렌더링되는 컴포넌트를 만들 수 있고, 필요한 경우에만 클라이언트 컴포넌트로 변환할 수 있습니다.
📁 폴더 구조의 혁신
앱 라우터에서는 폴더와 파일의 역할이 명확하게 구분됩니다:
- page.tsx: 실제 페이지 컴포넌트
- layout.tsx: 공통 레이아웃 (헤더, 네비게이션 등)
- loading.tsx: 로딩 상태 UI
- error.tsx: 에러 상태 UI
- not-found.tsx: 404 페이지
예를 들어,
/blog/post/123
경로를 만들고 싶다면:app/blog/post/[id]/page.tsx
파일을 생성하면 됩니다. 정말 직관적이죠?💡 실제 구현해보기
간단한 블로그 페이지를 만들어볼게요. 먼저 루트 레이아웃부터 시작합니다:
📸 Photo by Timothy Hales Bennett
🔗 Unsplash에서 보기 • ❤️ 1395 likes • 클릭하면 원본 이미지로 이동
typescript<br>// app/layout.tsx<br>export default function RootLayout({<br>children,<br>}: {<br>children: React.ReactNode<br>}) {<br>return (<br><html lang="ko"><br><body><br><nav><br><h1>내 블로그</h1><br></nav><br>{children}<br></body><br></html><br>)<br>}<br>
이제 메인 페이지를 만들어보죠:
typescript<br>// app/page.tsx<br>export default function HomePage() {<br>return (<br><div><br><h2>최근 포스트</h2><br><p>여기에 포스트 목록이 들어갑니다.</p><br></div><br>)<br>}<br>
🔄 데이터 페칭의 새로운 방법
앱 라우터에서는 서버 컴포넌트에서 직접 데이터를 fetch할 수 있습니다. 더 이상
getServerSideProps
나 getStaticProps
가 필요 없어요!typescript<br>// app/posts/page.tsx<br>async function getPosts() {<br>const res = await fetch('https://api.example.com/posts')<br>return res.json()<br>}<br>export default async function PostsPage() {<br>const posts = await getPosts()<br>return (<br><div><br>{posts.map(post => (<br><article key={post.id}><br><h3>{post.title}</h3><br><p>{post.excerpt}</p><br></article><br>))}<br></div><br>)<br>}<br>
정말 깔끔하고 직관적이죠? async/await를 컴포넌트에서 바로 사용할 수 있어서 코드가 훨씬 읽기 쉬워졌습니다.
📸 Photo by Christian Wiediger
🔗 Unsplash에서 보기 • ❤️ 215 likes • 클릭하면 원본 이미지로 이동
⚡ 로딩과 에러 처리
앱 라우터의 가장 멋진 기능 중 하나는 자동 로딩 및 에러 처리입니다. 각 라우트 폴더에
loading.tsx
와 error.tsx
파일을 만들면 자동으로 처리해줍니다:typescript<br>// app/posts/loading.tsx<br>export default function Loading() {<br>return (<br><div><br><p>포스트를 불러오는 중...</p><br><div className="spinner"></div><br></div><br>)<br>}<br>
typescript<br>// app/posts/error.tsx<br>'use client'<br>export default function Error({<br>error,<br>reset,<br>}: {<br>error: Error<br>reset: () => void<br>}) {<br>return (<br><div><br><h2>문제가 발생했습니다!</h2><br><button onClick={() => reset()}>다시 시도</button><br></div><br>)<br>}<br>
🎯 동적 라우팅 마스터하기
동적 라우팅도 더욱 강력해졌습니다. 대괄호 폴더명을 사용해서 매개변수를 받을 수 있어요:
- [id]: 단일 동적 세그먼트
- [...slug]: 모든 하위 경로 캐치
- [[...slug]]: 선택적 모든 하위 경로 캐치
실제 예시를 보면:
typescript<br>// app/blog/[category]/[slug]/page.tsx<br>export default function BlogPost({<br>params<br>}: {<br>params: { category: string; slug: string }<br>}) {<br>return (<br><div><br><h1>카테고리: {params.category}</h1><br><h2>포스트: {params.slug}</h2><br></div><br>)<br>}<br>
🔧 클라이언트 컴포넌트 활용하기
모든 컴포넌트가 서버 컴포넌트로 기본 설정되지만, 상호작용이 필요한 경우 'use client' 지시어를 사용해서 클라이언트 컴포넌트로 만들 수 있습니다:
typescript<br>// app/components/Counter.tsx<br>'use client'<br>import { useState } from 'react'<br>export default function Counter() {<br>const [count, setCount] = useState(0)<br>return (<br><div><br><p>카운트: {count}</p><br><button onClick={() => setCount(count + 1)}><br>증가<br></button><br></div><br>)<br>}<br>
📈 성능 최적화 팁
앱 라우터를 사용할 때 성능을 극대화하는 몇 가지 팁을 공유해드릴게요:
- 서버 컴포넌트 우선 사용: 상호작용이 꼭 필요한 경우가 아니라면 서버 컴포넌트를 사용하세요
- 적절한 캐싱 활용: fetch 요청에 캐시 옵션을 설정해서 성능을 향상시키세요
- Suspense 경계 설정: 로딩 상태를 세밀하게 관리할 수 있습니다
- 스트리밍 활용: 페이지의 일부분을 먼저 보여주고 나머지를 점진적으로 로드할 수 있어요
🚨 주의사항과 마이그레이션
기존 프로젝트에서 앱 라우터로 이전할 때 몇 가지 주의할 점이 있습니다:
점진적 이전이 가능합니다.
pages
와 app
폴더를 동시에 사용할 수 있어서, 천천히 옮겨갈 수 있어요. 하지만 같은 경로에 대해서는 app
라우터가 우선순위를 가집니다.API 라우트도
app/api
폴더로 이동해야 하고, 일부 기능들은 아직 실험적 단계이므로 프로덕션 환경에서는 신중하게 판단하시길 바랍니다.📸 Photo by Scott Rodgerson
🔗 Unsplash에서 보기 • ❤️ 98 likes • 클릭하면 원본 이미지로 이동
앱 라우터는 Next.js의 미래이자 현재입니다. 처음에는 학습 곡선이 있을 수 있지만, 한번 익숙해지면 개발 경험이 훨씬 향상될 거예요. 여러분도 한번 도전해보시길 권합니다!