<scshin />

Next.js란? React 개발자가 알아야 할 풀스택 프레임워크

Next.js란? React 개발자가 알아야 할 풀스택 프레임워크

React로 웹 서비스를 만들다 보면 자연스럽게 다음과 같은 고민이 생깁니다.

  • 페이지 라우팅은 어떻게 구성할까?
  • 검색엔진 최적화, 즉 SEO는 어떻게 처리할까?
  • 초기 로딩 속도를 더 빠르게 만들 수 없을까?
  • 프론트엔드 프로젝트 안에서 간단한 API도 같이 만들 수 없을까?
  • 서버 사이드 렌더링과 정적 페이지 생성을 쉽게 적용할 방법은 없을까?

이런 문제를 해결하기 위해 많이 사용하는 프레임워크가 Next.js입니다.

Next.js는 React 기반의 웹 애플리케이션 프레임워크입니다. 단순히 화면을 만드는 React 라이브러리에서 한 단계 더 나아가, 라우팅, 서버 렌더링, 정적 페이지 생성, 이미지 최적화, API 처리, 배포 최적화까지 웹 서비스 개발에 필요한 기능을 함께 제공합니다.


목차

  1. Next.js를 사용하는 이유
  2. Next.js의 핵심 개념
  3. Next.js의 렌더링 방식
  4. Route Handlers로 API 만들기
  5. Metadata API로 SEO 설정하기
  6. Image Optimization
  7. 프로젝트 생성 방법
  8. 기본 폴더 구조 예시
  9. Next.js가 적합한 경우
  10. Next.js 사용 시 주의할 점
  11. 간단한 예제 페이지
  12. 마무리

1. Next.js를 사용하는 이유

React만으로도 웹 화면은 충분히 만들 수 있습니다. 하지만 실제 서비스를 만들다 보면 화면 구성 외에도 처리해야 할 일이 많습니다.

예를 들어 일반적인 React 프로젝트에서는 라우팅을 위해 react-router-dom을 별도로 설정해야 하고, SEO를 위해 메타 태그 관리 방식을 따로 고민해야 하며, 서버에서 데이터를 미리 가져오는 구조도 직접 설계해야 합니다.

Next.js는 이런 부분들을 프레임워크 차원에서 제공합니다.

대표적인 장점은 다음과 같습니다.

구분 설명
파일 기반 라우팅 폴더와 파일 구조만으로 페이지 경로를 만들 수 있습니다.
서버 사이드 렌더링 서버에서 HTML을 생성해 초기 로딩과 SEO에 유리합니다.
정적 페이지 생성 빌드 시점에 HTML을 미리 만들어 빠르게 제공할 수 있습니다.
API 구성 프론트엔드 프로젝트 안에서 간단한 백엔드 API를 만들 수 있습니다.
이미지 최적화 next/image를 통해 이미지 크기, lazy loading, 레이아웃 안정성을 관리할 수 있습니다.
SEO 관리 Metadata API를 통해 페이지별 제목, 설명, OG 이미지를 쉽게 설정할 수 있습니다.
개발 생산성 App Router, Server Components, Turbopack 등을 통해 개발 경험을 개선할 수 있습니다.

2. Next.js의 핵심 개념

2.1 App Router

최근 Next.js 프로젝트에서는 app 디렉터리를 사용하는 App Router 방식이 많이 사용됩니다.

App Router는 파일 시스템 기반 라우팅을 제공합니다. 즉, 폴더 구조가 곧 URL 구조가 됩니다.

예를 들어 다음과 같은 구조가 있다고 가정합니다.

app
├─ page.tsx
├─ layout.tsx
├─ about
│  └─ page.tsx
└─ posts
   ├─ page.tsx
   └─ [id]
      └─ page.tsx

위 구조는 다음 경로로 연결됩니다.

파일 URL
app/page.tsx /
app/about/page.tsx /about
app/posts/page.tsx /posts
app/posts/[id]/page.tsx /posts/1, /posts/2 등 동적 경로

이처럼 Next.js에서는 라우터 설정 파일을 따로 만들지 않아도 폴더 구조만으로 페이지를 구성할 수 있습니다.


2.2 Layout

layout.tsx는 여러 페이지가 공통으로 사용하는 레이아웃을 정의하는 파일입니다.

예를 들어 헤더, 사이드바, 푸터처럼 여러 페이지에서 반복되는 UI를 layout.tsx에 작성할 수 있습니다.

// app/layout.tsx
import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "My Next App",
  description: "Next.js로 만든 웹 서비스입니다.",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body>
        <header>공통 헤더</header>
        <main>{children}</main>
        <footer>공통 푸터</footer>
      </body>
    </html>
  );
}

이 구조를 사용하면 모든 페이지에서 공통 UI를 재사용할 수 있고, 페이지별로 중복 코드를 줄일 수 있습니다.


2.3 Server Components와 Client Components

Next.js의 App Router에서는 기본적으로 컴포넌트가 Server Component로 동작합니다.

Server Component는 서버에서 실행되는 컴포넌트입니다. 데이터베이스 조회, 서버 API 호출, 파일 시스템 접근처럼 브라우저에서 직접 처리하면 안 되는 작업을 서버에서 안전하게 처리할 수 있습니다.

// app/posts/page.tsx
async function getPosts() {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts");
  return res.json();
}

export default async function PostsPage() {
  const posts = await getPosts();

  return (
    <div>
      <h1>게시글 목록</h1>
      <ul>
        {posts.slice(0, 5).map((post: any) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

반대로 브라우저에서 상태 관리, 클릭 이벤트, 입력값 처리 등이 필요한 컴포넌트는 Client Component로 만들어야 합니다.

Client Component를 만들 때는 파일 상단에 "use client"를 작성합니다.

// app/components/Counter.tsx
"use client";

import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      클릭 수: {count}
    </button>
  );
}

정리하면 다음과 같습니다.

구분 Server Component Client Component
실행 위치 서버 브라우저
기본 여부 App Router에서 기본값 "use client" 필요
적합한 작업 데이터 조회, 서버 처리, SEO 이벤트 처리, 상태 관리, 브라우저 API
예시 게시글 목록 조회 버튼 클릭, 모달, 폼 입력

3. Next.js의 렌더링 방식

Next.js를 이해할 때 가장 중요한 개념 중 하나는 렌더링 방식입니다.

Next.js는 페이지 성격에 따라 여러 렌더링 방식을 선택할 수 있습니다.


3.1 SSR: Server Side Rendering

SSR은 사용자가 페이지에 접근할 때마다 서버에서 HTML을 생성하는 방식입니다.

사용자별 데이터가 다르거나, 항상 최신 데이터를 보여줘야 하는 페이지에 적합합니다.

예를 들면 다음과 같은 화면에 사용할 수 있습니다.

  • 관리자 대시보드
  • 로그인 사용자별 마이페이지
  • 실시간 데이터 조회 화면
  • 권한에 따라 내용이 달라지는 페이지

장점은 최신 데이터를 보여주기 좋고 SEO에도 유리하다는 점입니다. 단점은 요청마다 서버에서 HTML을 만들어야 하므로 서버 부하가 생길 수 있다는 점입니다.


3.2 SSG: Static Site Generation

SSG는 빌드 시점에 HTML을 미리 생성해두는 방식입니다.

내용이 자주 바뀌지 않는 페이지에 적합합니다.

예를 들면 다음과 같습니다.

  • 회사 소개 페이지
  • 서비스 소개 페이지
  • 문서 페이지
  • 블로그 글 상세 페이지

이미 만들어진 HTML을 제공하기 때문에 속도가 빠르고 서버 부하가 적습니다. 하지만 데이터가 자주 바뀌는 화면에는 적합하지 않을 수 있습니다.


3.3 ISR: Incremental Static Regeneration

ISR은 정적 페이지의 장점과 데이터 갱신의 장점을 함께 가져가는 방식입니다.

정적 페이지를 제공하되, 일정 시간이 지나면 페이지를 다시 생성할 수 있습니다.

예를 들어 60초마다 데이터를 갱신하고 싶다면 다음처럼 사용할 수 있습니다.

const res = await fetch("https://api.example.com/posts", {
  next: { revalidate: 60 },
});

이 방식은 블로그, 상품 상세, 공지사항처럼 빠른 응답이 필요하지만 데이터가 가끔 바뀌는 페이지에 적합합니다.


4. Route Handlers로 API 만들기

Next.js에서는 app/api 경로 안에 route.ts 파일을 만들면 API를 구성할 수 있습니다.

예를 들어 /api/health API를 만들고 싶다면 다음처럼 작성합니다.

// app/api/health/route.ts
import { NextResponse } from "next/server";

export async function GET() {
  return NextResponse.json({
    status: "ok",
    message: "서버가 정상 동작 중입니다.",
  });
}

이제 브라우저에서 /api/health로 접근하면 JSON 응답을 받을 수 있습니다.

간단한 백엔드 기능, 인증 체크, 외부 API 프록시, 관리자용 내부 API 등을 만들 때 유용합니다.

다만 규모가 큰 백엔드, 복잡한 배치 처리, 대규모 트랜잭션 처리가 필요한 시스템이라면 별도의 백엔드 서버를 분리하는 것이 더 적합할 수 있습니다.


5. Metadata API로 SEO 설정하기

Next.js에서는 metadata 객체나 generateMetadata 함수를 사용해 페이지의 SEO 정보를 설정할 수 있습니다.

// app/blog/[id]/page.tsx
import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "Next.js 입문 가이드",
  description: "Next.js의 핵심 개념과 사용 이유를 정리한 글입니다.",
  openGraph: {
    title: "Next.js 입문 가이드",
    description: "React 기반 풀스택 프레임워크 Next.js 알아보기",
    type: "article",
  },
};

페이지별 제목, 설명, OG 태그를 체계적으로 관리할 수 있기 때문에 블로그, 랜딩 페이지, 서비스 소개 페이지에서 특히 유용합니다.


6. Image Optimization

웹 서비스에서 이미지 최적화는 성능에 큰 영향을 줍니다.

Next.js는 next/image 컴포넌트를 제공합니다.

import Image from "next/image";

export default function Profile() {
  return (
    <Image
      src="/profile.png"
      width={500}
      height={500}
      alt="프로필 이미지"
    />
  );
}

next/image를 사용하면 이미지 크기 최적화, lazy loading, 레이아웃 안정성 개선 등에 도움을 받을 수 있습니다.

일반 <img> 태그보다 설정은 조금 더 필요할 수 있지만, 실제 서비스에서는 성능과 사용자 경험 측면에서 장점이 큽니다.


7. 프로젝트 생성 방법

Next.js 프로젝트는 다음 명령어로 생성할 수 있습니다.

npx create-next-app@latest my-next-app

실행하면 TypeScript 사용 여부, ESLint 사용 여부, Tailwind CSS 사용 여부, App Router 사용 여부 등을 선택할 수 있습니다.

프로젝트 생성 후 실행은 다음과 같습니다.

cd my-next-app
npm run dev

기본 개발 서버는 보통 다음 주소에서 확인할 수 있습니다.

http://localhost:3000

8. 기본 폴더 구조 예시

일반적인 App Router 기반 프로젝트 구조는 다음과 같이 구성할 수 있습니다.

my-next-app
├─ app
│  ├─ api
│  │  └─ health
│  │     └─ route.ts
│  ├─ components
│  │  └─ Counter.tsx
│  ├─ posts
│  │  ├─ page.tsx
│  │  └─ [id]
│  │     └─ page.tsx
│  ├─ layout.tsx
│  └─ page.tsx
├─ public
│  └─ images
├─ styles
├─ next.config.ts
├─ package.json
└─ tsconfig.json

프로젝트 규모가 커지면 components, lib, hooks, types, services 같은 폴더를 추가해서 역할별로 분리하는 것이 좋습니다.

예를 들어 다음과 같이 구성할 수 있습니다.

src
├─ app
├─ components
├─ lib
├─ services
├─ hooks
├─ types
└─ styles

9. Next.js가 적합한 경우

Next.js는 다음과 같은 프로젝트에 잘 어울립니다.

  • SEO가 중요한 서비스
  • 블로그, 문서, 랜딩 페이지
  • 관리자 페이지와 사용자 페이지가 함께 있는 웹 서비스
  • React 기반으로 빠르게 서비스를 만들고 싶은 경우
  • 서버 렌더링과 정적 생성을 함께 사용하고 싶은 경우
  • 프론트엔드 중심이지만 간단한 API도 같이 필요한 경우

특히 페이지별로 렌더링 전략을 다르게 가져갈 수 있다는 점이 큰 장점입니다.

예를 들어 서비스 소개 페이지는 SSG로 만들고, 관리자 대시보드는 SSR로 만들고, 게시글 상세는 ISR로 구성할 수 있습니다.


10. Next.js 사용 시 주의할 점

Next.js가 모든 상황에서 정답은 아닙니다.

다음과 같은 점은 미리 고려하는 것이 좋습니다.

10.1 서버와 클라이언트 경계 이해가 필요합니다

App Router에서는 Server Component와 Client Component의 차이를 이해해야 합니다.

처음에는 왜 useState가 안 되는지, 왜 window 객체를 바로 사용할 수 없는지 헷갈릴 수 있습니다.

서버에서 실행되는 코드와 브라우저에서 실행되는 코드를 구분하는 습관이 필요합니다.


10.2 캐싱 정책을 신중하게 잡아야 합니다

Next.js는 성능을 위해 여러 캐싱 기능을 제공합니다.

하지만 어떤 데이터는 항상 최신이어야 하고, 어떤 데이터는 일정 시간 캐싱해도 됩니다.

서비스 특성에 맞게 캐싱 전략을 정하지 않으면 화면에 오래된 데이터가 보이거나, 반대로 서버 요청이 너무 많아질 수 있습니다.


10.3 백엔드 역할을 어디까지 맡길지 정해야 합니다

Next.js의 Route Handlers로 API를 만들 수 있지만, 모든 백엔드 기능을 Next.js 안에 넣는 것이 항상 좋은 것은 아닙니다.

대규모 서비스에서는 Spring Boot, NestJS, Django, FastAPI 같은 별도 백엔드와 Next.js 프론트엔드를 분리하는 구조도 많이 사용합니다.

예를 들어 화면은 Next.js로 구성하고, 업무 로직과 데이터 처리는 Spring Boot API 서버에서 처리하는 구조를 많이 사용합니다.

사용자 브라우저
    ↓
Next.js 프론트엔드
    ↓
Spring Boot API 서버
    ↓
Database

이 구조를 사용하면 프론트엔드와 백엔드 역할을 명확히 분리할 수 있습니다.


11. 간단한 예제 페이지

다음은 Next.js에서 작성할 수 있는 간단한 메인 페이지 예시입니다.

// app/page.tsx
import Link from "next/link";

export default function HomePage() {
  return (
    <main>
      <h1>Next.js 블로그</h1>
      <p>
        Next.js는 React 기반의 풀스택 웹 프레임워크입니다.
      </p>

      <ul>
        <li>
          <Link href="/posts">게시글 목록 보기</Link>
        </li>
        <li>
          <Link href="/about">서비스 소개</Link>
        </li>
      </ul>
    </main>
  );
}

Link 컴포넌트를 사용하면 페이지 이동을 최적화할 수 있습니다.


12. 마무리

Next.js는 React를 기반으로 실제 서비스 개발에 필요한 기능을 통합해서 제공하는 프레임워크입니다.

React만 사용할 때 직접 구성해야 했던 라우팅, 서버 렌더링, 정적 페이지 생성, 이미지 최적화, SEO 설정, API 구성 등을 Next.js에서는 비교적 체계적으로 처리할 수 있습니다.

처음에는 App Router, Server Component, Client Component, 캐싱 정책이 조금 어렵게 느껴질 수 있습니다. 하지만 이 개념들을 이해하면 단순한 프론트엔드 화면뿐만 아니라 SEO가 필요한 웹 서비스, 블로그, 관리자 페이지, 풀스택 서비스까지 더 효율적으로 만들 수 있습니다.

React를 어느 정도 알고 있고 실제 서비스를 만들고 싶다면 Next.js는 충분히 배워볼 만한 프레임워크입니다.


참고 자료

  • Next.js 공식 문서: https://nextjs.org/docs
  • Next.js App Router 문서: https://nextjs.org/docs/app
  • Next.js Route Handlers 문서: https://nextjs.org/docs/app/getting-started/route-handlers
  • Next.js Metadata 문서: https://nextjs.org/docs/app/getting-started/metadata-and-og-images
  • Next.js Image Optimization 문서: https://nextjs.org/docs/app/getting-started/images
  • Next.js 공식 블로그: https://nextjs.org/blog