1. Next.js란 무엇인가요? 왜 배워야 하나요?

Next.js는 React 애플리케이션을 만들기 위한 풀스택 프레임워크입니다. 쉽게 말해, React로 웹사이트를 만들 때 필요한 모든 도구를 한 번에 제공하는 종합 선물세트라고 생각하시면 됩니다.

  1. 서버 사이드 렌더링(SSR): 웹페이지가 검색엔진에 잘 노출되도록 도와줍니다
  2. 정적 사이트 생성(SSG): 미리 페이지를 만들어두어 속도가 매우 빠릅니다
  3. API 라우트: 백엔드 기능도 함께 구현할 수 있습니다
  4. 자동 코드 분할: 필요한 부분만 로드하여 성능을 최적화합니다
  5. 이미지 최적화: 이미지를 자동으로 최적화하여 로딩 속도를 개선합니다

2. Next.js 시작하기: 설치부터 실행까지

Next.js를 시작하는 방법은 정말 간단합니다. 터미널을 열고 다음 명령어를 입력하기만 하면 됩니다.

  1. 새 프로젝트 생성하기
npx create-next-app@latest my-app
# 또는
yarn create next-app my-app
# 또는
pnpm create next-app my-app
  1. 프로젝트 폴더로 이동
cd my-app
  1. 개발 서버 실행
npm run dev
# 또는
yarn dev
# 또는
pnpm dev

브라우저에서 http://localhost:3000을 열면 Next.js 앱이 실행되는 것을 확인할 수 있습니다!

3. Next.js 핵심 명령어 완벽 정리

Next.js를 사용할 때 꼭 알아야 할 명령어들을 모두 정리했습니다.

  1. 개발 관련 명령어
    npm run dev         # 개발 서버 실행 (핫 리로딩 지원)
    npm run build       # 프로덕션용 빌드 생성
    npm run start       # 프로덕션 서버 실행
    npm run lint        # 코드 품질 검사
  2. 추가 유용한 명령어
    npm run export      # 정적 HTML 파일로 내보내기
    npm run analyze     # 번들 크기 분석 (별도 설정 필요)
  3. TypeScript 프로젝트 생성
    npx create-next-app@latest --typescript
  4. 특정 템플릿으로 프로젝트 생성
    npx create-next-app@latest --example [템플릿명]
    # 예시: npx create-next-app@latest --example with-tailwindcss

4. Next.js 폴더 구조와 파일 시스템 라우팅

Next.js의 가장 큰 특징 중 하나는 파일 시스템 기반 라우팅입니다. 폴더와 파일을 만들면 자동으로 URL 경로가 생성됩니다.

  1. 기본 폴더 구조
    my-app/
    ├── app/                # App Router (Next.js 13+)
    │   ├── page.js        # 홈페이지 (/)
    │   ├── layout.js      # 공통 레이아웃
    │   └── globals.css    # 전역 스타일
    ├── public/            # 정적 파일 (이미지, 폰트 등)
    ├── components/        # 재사용 가능한 컴포넌트
    └── package.json       # 프로젝트 설정
  2. 페이지 라우팅 예시
    • app/page.js → / (홈페이지)
    • app/about/page.js → /about
    • app/blog/[id]/page.js → /blog/123 (동적 라우팅)
  3. 특수 파일들
    • layout.js: 페이지의 공통 레이아웃 정의
    • loading.js: 로딩 중 표시할 UI
    • error.js: 에러 발생 시 표시할 UI
    • not-found.js: 404 페이지

5. Next.js 기초 문법: 페이지 만들기

실제로 페이지를 만들어보면서 기초 문법을 익혀봅시다.

  1. 기본 페이지 생성 (app/page.js)
    export default function HomePage() {
      return (
        <div>
          <h1>안녕하세요, Next.js!</h1>
          <p>첫 번째 페이지입니다.</p>
        </div>
      )
    }
  2. 동적 라우팅 (app/posts/[id]/page.js)
    export default function Post({ params }) {
      return (
        <div>
          <h1>포스트 ID: {params.id}</h1>
        </div>
      )
    }
  3. 레이아웃 컴포넌트 (app/layout.js)
    export default function RootLayout({ children }) {
      return (
        <html lang="ko">
          <body>
            <header>공통 헤더</header>
            <main>{children}</main>
            <footer>공통 푸터</footer>
          </body>
        </html>
      )
    }

6. 데이터 페칭: 서버와 클라이언트에서 데이터 가져오기

Next.js에서는 다양한 방법으로 데이터를 가져올 수 있습니다.

  1. 서버 컴포넌트에서 데이터 가져오기 (기본값)
    async function getData() {
      const res = await fetch('<https://api.example.com/data>')
      return res.json()
    }
    
    export default async function Page() {
      const data = await getData()
    
      return <div>{data.title}</div>
    }
  2. 클라이언트 컴포넌트 사용하기
    'use client'
    
    import { useState, useEffect } from 'react'
    
    export default function ClientComponent() {
      const [data, setData] = useState(null)
    
      useEffect(() => {
        fetch('/api/data')
          .then(res => res.json())
          .then(setData)
      }, [])
    
      return <div>{data?.title}</div>
    }
  3. 정적 생성과 재검증
    export const revalidate = 60 // 60초마다 재검증
    
    async function getData() {
      const res = await fetch('<https://api.example.com/data>')
      return res.json()
    }

7. API 라우트 만들기: 백엔드 기능 구현

Next.js에서는 API 엔드포인트도 쉽게 만들 수 있습니다.

  1. 기본 API 라우트 (app/api/hello/route.js)
    export async function GET(request) {
      return Response.json({ message: '안녕하세요!' })
    }
    
    export async function POST(request) {
      const data = await request.json()
      return Response.json({ received: data })
    }
  2. 동적 API 라우트 (app/api/users/[id]/route.js)
    export async function GET(request, { params }) {
      const { id } = params
      return Response.json({ userId: id })
    }

8. 스타일링: CSS 모듈부터 Tailwind까지

Next.js는 다양한 스타일링 방법을 지원합니다.

  1. CSS 모듈 사용하기
    /* styles/Home.module.css */
    .container {
      padding: 2rem;
      background: #f0f0f0;
    }
    import styles from './Home.module.css'
    
    export default function Home() {
      return <div className={styles.container}>홈페이지</div>
    }
  2. 전역 CSS
    /* app/globals.css */
    body {
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    }
  3. Tailwind CSS 설정
    npm install -D tailwindcss postcss autoprefixer
    npx tailwindcss init -p

9. 이미지와 폰트 최적화

Next.js는 자동으로 이미지와 폰트를 최적화합니다.

  1. Image 컴포넌트 사용
    import Image from 'next/image'
    
    export default function Profile() {
      return (
        <Image
          src="/profile.jpg"
          alt="프로필 사진"
          width={500}
          height={300}
          priority
        />
      )
    }
  2. 폰트 최적화
    import { Inter } from 'next/font/google'
    
    const inter = Inter({ subsets: ['latin'] })
    
    export default function Layout({ children }) {
      return (
        <html className={inter.className}>
          <body>{children}</body>
        </html>
      )
    }

10. 환경 변수와 설정 파일

프로젝트 설정을 관리하는 방법을 알아봅시다.

  1. 환경 변수 설정 (.env.local)
    NEXT_PUBLIC_API_URL=https://api.example.com
    DATABASE_URL=postgresql://localhost:5432/mydb
  2. next.config.js 설정
    /** @type {import('next').NextConfig} */
    const nextConfig = {
      images: {
        domains: ['example.com'],
      },
      redirects: async () => {
        return [
          {
            source: '/old-page',
            destination: '/new-page',
            permanent: true,
          },
        ]
      },
    }
    
    module.exports = nextConfig

11. 배포하기: Vercel부터 다른 플랫폼까지

Next.js 앱을 배포하는 방법은 여러 가지가 있습니다.

  1. Vercel 배포 (가장 쉬운 방법)
    npm i -g vercel
    vercel
  2. 빌드 후 Node.js 서버에서 실행
    npm run build
    npm run start
  3. 정적 사이트로 내보내기
    npm run build
    npm run export

12. 성능 최적화 팁

Next.js 앱의 성능을 더욱 향상시키는 방법들입니다.

  1. 동적 임포트 사용
    import dynamic from 'next/dynamic'
    
    const DynamicComponent = dynamic(() => import('../components/heavy'), {
      loading: () => <p>로딩 중...</p>,
    })
  2. 이미지 최적화
    • WebP 형식 자동 변환
    • 지연 로딩 기본 적용
    • 반응형 이미지 자동 생성
  3. 번들 크기 줄이기
    • 사용하지 않는 의존성 제거
    • Tree shaking 활용
    • 코드 분할 최적화