node.js 프로젝트 생성 ->
npx create-next-app@latest 프로젝트이름
TypeScript → Yes
ESLint → Yes
Tailwind → Yes
src/ → No
App Router → Yes
권장 설정을 체크했다.
Need to install the following packages:
create-next-app@16.3.8
Ok to proceed? (y) y
√ Would you like to use the recommended Next.js defaults? » Yes, use recommended defaults
타입 안정성
ESLint ≠ 포매터라는 것.
Prettier
→ 코드 모양을 예쁘게 정리
ESLint
→ 코드가 올바른가?
→ 문제 있는 패턴인가?
- 이 변수 안 쓰고 있는데?
- React에서는 더 중요 -> Hook을 잘못 사용하는 패턴이나 의존성 문제 등을 검사
| 방식 | 특징 | 이번 프로젝트에서 |
|---|---|---|
| 일반 CSS | .css 파일에 스타일 작성 | 가능하지만 파일을 오가야 함 |
| CSS Modules | 컴포넌트별 CSS 파일 + 클래스 이름 충돌 방지 | 깔끔하지만 파일이 늘어남 |
| styled-components | JS/TS 안에서 CSS 작성 | 동적 스타일에 좋지만 별도 라이브러리 |
| Tailwind | className에 유틸리티 조합 | 이번 학습 프로젝트에 적합 |
처음 배우는 프로젝트에서 이것들을 여러 개 섞으면 학습 포인트가 흐려지니까 하나를 골라서 쓰는 게 좋다 -> Tailwind CSS만 사용
프론트엔드 스타일링
│
├─ CSS를 직접 작성하는 계열
│ ├─ CSS / CSS Modules
│ └─ Sass(SCSS)
│
├─ 유틸리티 CSS 계열 ("스타일을 내가 조립한다.")
│ ├─ Tailwind CSS
│ └─ UnoCSS
│
└─ UI 컴포넌트 ("React UI 컴포넌트를 가져다 쓴다.") / CSS 프레임워크 계열 ("미리 만들어진 CSS 스타일을 가져다 쓴다.")
├─ Bootstrap
├─ Chakra UI
├─ MUI
├─ Ant Design
└─ Mantine
작은 학습 프로젝트 → src 없어도 됨
src는 코드를 한 단계 안쪽으로 넣어서 정리하는 폴더일 뿐 -> 왜 src를 쓰나?
큰 프로젝트의 경우 디렉토리 구조
project/
├── app/
├── components/
├── hooks/
├── lib/
├── public/
├── tests/
├── scripts/
├── config/
├── package.json
└── ...
project/
├── src/ ---> 복잡해지니까 실제 애플리케이션 코드를 한단계 안쪽으로 정리
│ ├── app/
│ ├── components/
│ ├── hooks/
│ └── lib/
├── public/
├── tests/
├── package.json
└── ...
| Pages Router | App Router | |
|---|---|---|
| 기준 디렉터리 | pages/ | app/ |
| 등장 시기 | 기존 방식 | 최신 방식 |
| 서버 컴포넌트 | 기본 지원 X | 기본 지원 |
| Layout | 직접 구성하는 경우가 많음 | layout.tsx로 자연스럽게 구성 |
| 데이터 처리 | 기존 Next.js 방식 | Server Component 중심 |
| 현재 신규 프로젝트 | 유지보수에는 많이 존재 | 신규 프로젝트에서 주로 사용 |
2016 ~ 2022
│
│ Pages Router 시대
│ pages/가 사실상 기본
│
├── Next.js 13 (2022.10)
│ app/ 등장
│ → 아직 Beta
│
├── Next.js 13.4 (2023.05)
│ ⭐ App Router Stable
│ → 신규 프로젝트에 App Router 권장
│
2023 ~ 현재
│
│ App Router가 새로운 기본 방향
│ Pages Router도 계속 지원
│
└── 2026 현재
→ 새 프로젝트: App Router 권장
→ 기존 프로젝트: Pages Router도 정상적으로 사용
Pages Router
pages/
├── index.tsx
├── products.tsx
└── products/
└── [id].tsx
/ → index.tsx
/products → products.tsx
/products/1 → [id].tsx
App Router : Pages Router와 URL 구조는 비슷하지만 컴포넌트와 서버 기능을 결합해서 설계하기 편함
app/
├── page.tsx
├── products/
│ ├── page.tsx
│ └── [id]/
│ └── page.tsx
└── layout.tsx
예를 들어 MES가 있다고 하자.
┌─────────────────────────────┐
│ 회사 로고 사용자 정보 │
├─────────┬───────────────────┤
│ 메뉴 │ │
│ 생산관리 │ 화면 내용 │
│ 재고관리 │ │
│ 출고관리 │ │
└─────────┴───────────────────┘
왼쪽 메뉴와 위쪽 헤더는 모든 페이지에서 계속 유지를 원함.
App Router에서는 이걸 아주 자연스럽게 표현:
app/
├── layout.tsx ← 전체 공통
├── page.tsx ← /
│
└── mes/
├── layout.tsx ← MES 공통
├── production/
│ └── page.tsx
└── inventory/
└── page.tsx
layout
│
├── 생산관리 페이지
│
└── 재고관리 페이지
이런 페이지 구조 자체를 폴더 구조로 표현 가능하다.
Pages Router에도 공통 레이아웃을 만들 수 있 지만 구조적으로 App Router만큼 자연스럽지는 않았다.
예를 들어 예전에는 _app.tsx를 사용해서 전체 페이지를 감싸는 구조를 만들었다.
export default function App({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
전체 사이트 공통 Layout 은 만들기 쉬운데,
MES 공통 Layout
├── 생산관리
├── 재고관리
관리자 공통 Layout
├── 사용자 관리
└── 권한 관리
처럼 여러 단계의 레이아웃을 자연스럽게 중첩하는 구조는 불편했다.
Next.js가 App Router를 만든 중요한 이유 중 하나
현재 App Router를 배우는 가장 중요한 이유
App Router에서는 기본적으로 컴포넌트가 Server Component이다.
// app/products/page.tsx
export default async function ProductsPage() {
const products = await getProducts();
return (
<div>
...
</div>
);
}
// 서버에서 데이터를 가져와서 화면을 만들어 보낼 수 있다.
버튼 클릭이나 useState 같은 브라우저에서 동작해야 하는 것은 따로 지정 :
"use client"; // Client Component
import { useState } from "react";
즉 App Router는 단순히 "pages를 app으로 바꾼 것"이 아니라,
React Server Components를 중심으로 Next.js의 구조 자체를 새로 만든 것이다.
cd 프로젝트
npm run dev