Next.js 프로젝트를 처음 열면, 왠지 책상 위에 부품이 한가득 놓인 조립 키트를 보는 기분이 듭니다. 그런데 막상 차근차근 보면 생각보다 무섭지 않습니다. 오히려 Next.js는 굉장히 친절한 편입니다. 왜냐하면 파일 이름 자체가 역할을 말해 주기 때문입니다.
이번 챕터의 목표는 딱 하나입니다. 프로젝트를 열었을 때 "이 파일은 뭐 하는 애지?" 하고 얼어붙지 않는 것.
특히 App Router 방식의 Next.js에서는 app 폴더를 중심으로 폴더와 파일 이름이 라우팅과 화면 구조를 결정합니다. 폴더는 URL 구간이 되고, page.tsx가 있으면 공개 페이지가 되며, layout.tsx는 여러 페이지를 감싸는 공통 틀이 됩니다.1
한마디로 말하면 이렇습니다.
Next.js는 규칙을 기억하면 길을 잃지 않는 프레임워크입니다.
먼저, 프로젝트를 전체 지도로 보기
최신 Next.js 프로젝트를 만들면 대체로 아래와 비슷한 구조를 만나게 됩니다.
my-app/
├─ app/
│ ├─ favicon.ico
│ ├─ globals.css
│ ├─ layout.tsx
│ └─ page.tsx
├─ public/
├─ package.json
├─ next.config.ts
├─ tsconfig.json
├─ eslint.config.mjs
├─ .gitignore
└─ node_modules/프로젝트를 만들 때 src 사용 옵션을 켰다면 app 폴더가 루트가 아니라 src/app 안에 들어갈 수도 있습니다. 이건 틀린 구조가 아니라, 소스 코드와 설정 파일을 깔끔하게 분리하는 선택지입니다.1
여기서 초보자가 가장 먼저 친해져야 할 주인공은 다음입니다.
apppubliclayout.tsxpage.tsxglobals.csspackage.json
이 여섯 가지만 이해해도 프로젝트가 갑자기 낯선 외계어 뭉치에서, "아, 이건 이렇게 읽는구나" 하는 상태로 바뀝니다.
app 폴더는 사이트의 지도입니다
app 폴더는 App Router의 중심입니다. 여기서는 폴더 구조가 곧 URL 구조가 됩니다.1
예를 들어 이런 구조가 있다고 해봅시다.
app/
├─ page.tsx
├─ about/
│ └─ page.tsx
└─ notes/
└─ page.tsx이 구조는 이렇게 읽으면 됩니다.
app/page.tsx→/app/about/page.tsx→/aboutapp/notes/page.tsx→/notes
이게 Next.js의 아주 큰 장점입니다. 예전처럼 라우터 설정 파일을 열고 주소를 직접 하나하나 연결하는 대신, 폴더를 만들고 그 안에 page.tsx를 두면 주소가 만들어집니다.
여기서 꼭 기억할 중요한 점이 있습니다. 폴더만 있다고 해서 무조건 페이지가 되는 건 아닙니다. 해당 폴더에 page.tsx나 route.ts 같은 특별한 파일이 있어야 비로소 공개 경로가 됩니다. 그래서 app 안에 보조 파일을 같이 두어도 의도치 않게 페이지가 열리는 일이 없습니다.1
이 규칙 덕분에 Next.js 프로젝트는 "URL → 폴더 → 화면" 순서로 자연스럽게 읽힙니다. 마치 지도에서 구역 이름을 따라 걷는 느낌입니다.
layout.tsx는 공통 틀입니다
layout.tsx는 여러 페이지를 감싸는 공통 껍데기입니다. 헤더, 푸터, 공통 메뉴, 전체 글꼴, 전체 배경 같은 것들이 여기 들어오기 좋습니다.2
가장 위의 app/layout.tsx는 루트 레이아웃이라고 부릅니다. 이 파일은 앱 전체를 감싸며, App Router에서는 루트 레이아웃이 필요합니다. 그리고 루트 레이아웃은 <html>과 <body>를 포함해야 합니다.2
아주 기본적인 형태는 보통 이렇게 생깁니다.
import './globals.css'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ko">
<body>{children}</body>
</html>
)
}여기서 가장 중요한 단어는 children입니다. 이건 "이 레이아웃 안에 들어갈 실제 페이지 내용"이라고 생각하면 됩니다.
비유하면 이렇습니다.
layout.tsx는 액자page.tsx는 액자 안에 들어갈 그림children은 그림이 끼워지는 자리
그래서 layout.tsx에 헤더와 푸터를 넣으면, 그 레이아웃 아래에 있는 모든 페이지가 같은 틀을 공유하게 됩니다.
import './globals.css'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ko">
<body>
<header>작은 기록 상점</header>
<main>{children}</main>
<footer>© 작은 기록 상점</footer>
</body>
</html>
)
}이렇게 하면 앞으로 우리가 만들 페이지들이 전부 같은 머리글과 바닥글을 공유하게 됩니다. 한 번 만들어 두면 계속 재사용되니 정말 효율적입니다.
또 하나 좋은 점은, 레이아웃은 페이지 이동 때 계속 유지되는 공통 UI를 만들기에 좋다는 것입니다. 그래서 메뉴, 사이드바, 상단 바 같은 요소를 넣기 딱 좋습니다.2
page.tsx는 실제 화면의 주인공입니다
page.tsx는 특정 경로에서 실제로 보여줄 내용을 담당합니다.1
예를 들어 app/page.tsx는 홈 화면입니다.
export default function HomePage() {
return (
<main>
<h1>작은 기록 상점에 오신 것을 환영합니다</h1>
<p>오늘의 기록을 차곡차곡 모아 보세요.</p>
</main>
)
}이 파일은 / 주소에 접속했을 때 보이는 첫 화면이 됩니다.
그렇다면 /about 페이지를 만들고 싶다면 어떻게 할까요? 정답은 간단합니다.
app/
├─ page.tsx
└─ about/
└─ page.tsx그리고 app/about/page.tsx에 내용을 적으면 됩니다.
export default function AboutPage() {
return <h1>소개 페이지</h1>
}정말로 이게 끝입니다. 그래서 Next.js를 배우다 보면 어느 순간 이런 생각이 듭니다.
"어? 라우팅 설정 파일이 어디 갔지?"
없습니다. 폴더 구조가 이미 설정 파일 역할을 하고 있기 때문입니다.
layout.tsx와 page.tsx를 함께 읽는 법
처음엔 이 둘이 자꾸 헷갈립니다. 그럴 때는 아래처럼 구분하면 거의 안 틀립니다.
layout.tsx는 여러 페이지가 함께 쓰는 공통 틀page.tsx는 해당 주소에서만 보이는 실제 내용같은 폴더 아래에 있으면
layout.tsx가page.tsx를 감싼다
예를 들어 이런 구조를 보겠습니다.
app/
├─ layout.tsx
├─ page.tsx
└─ shop/
├─ layout.tsx
├─ page.tsx
└─ new/
└─ page.tsx이걸 읽는 순서는 이렇습니다.
/shop으로 들어가면:
app/layout.tsx가 전체를 감쌉니다.app/shop/layout.tsx가 그 안에서 한 번 더 감쌉니다.마지막으로
app/shop/page.tsx가 실제 내용을 보여줍니다.
즉, 아래로 갈수록 더 구체적인 화면이 붙는 구조입니다.1
이 개념은 나중에 대시보드, 관리자 화면, 쇼핑 화면처럼 구역별로 다른 레이아웃을 만들 때 엄청 편합니다.
globals.css는 프로젝트 전체의 분위기 담당입니다
globals.css는 이름 그대로 전역 스타일 파일입니다. 사이트 전체에 적용될 기본 스타일을 넣는 곳이라고 생각하면 됩니다.
보통은 app/layout.tsx에서 import해서 사용합니다.1
import './globals.css'이 한 줄이 의미하는 것은 이렇습니다.
"이 앱 전체에 공통 스타일 규칙을 적용하겠습니다."
예를 들면 이런 것들이 들어갑니다.
기본 글꼴
배경색
링크 색상
여백 초기화
박스 크기 계산 방식
예시를 한 번 볼까요?
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: sans-serif;
background: #faf8f4;
color: #222;
}
a {
color: inherit;
text-decoration: none;
}이런 코드를 넣으면 사이트 전체가 같은 기본 규칙을 공유합니다. 옷가게로 치면 매장 전체 인테리어 톤을 정하는 일과 비슷합니다.
중요한 점은, 전역 스타일은 영향 범위가 넓기 때문에 보통 루트 레이아웃에서 관리한다는 것입니다.1
만약 여러분이 create-next-app으로 Tailwind CSS까지 함께 설치했다면 globals.css 안에 Tailwind 관련 기본 코드가 들어 있을 수 있습니다. 그건 다음 챕터에서 더 자세히 다루겠지만, 지금은 "전역 스타일의 출발점" 정도로 이해하면 충분합니다.
public 폴더는 그대로 꺼내 쓰는 창고입니다
public 폴더는 정적 파일을 보관하는 곳입니다. 쉽게 말해, 브라우저가 바로 가져갈 수 있는 파일 창고입니다.1
예를 들어 public/logo.png 파일이 있으면, 브라우저에서는 이렇게 접근할 수 있습니다.
/logo.png여기서 중요한 포인트가 있습니다.
주소에 public이 들어가지 않습니다.
즉,
실제 파일 위치:
public/logo.png브라우저 접근 경로:
/logo.png
이 폴더에는 보통 이런 것들을 넣습니다.
로고 이미지
아이콘
고정 배너 이미지
robots.txt
sitemap.xml
앞으로 우리가 만들 작은 기록 상점 프로젝트에서도 public 폴더는 꽤 자주 쓰게 됩니다. 예를 들어 가게 로고, 기본 썸네일, 안내 아이콘 같은 파일을 넣어 두면 편합니다.
다만 기억할 점도 있습니다. 모든 이미지를 무조건 public에 넣어야 하는 것은 아닙니다. 하지만 "직접 URL로 접근 가능한 정적 파일"이 필요할 때는 public이 아주 잘 어울립니다.1
package.json은 프로젝트의 신분증이자 리모컨입니다
package.json은 처음 보면 JSON 글자 덩어리라 조금 딱딱해 보입니다. 하지만 역할은 의외로 단순합니다.
이 파일은 크게 두 가지를 관리합니다.
이 프로젝트가 어떤 패키지에 의존하는지
어떤 명령어로 실행하고 빌드하는지
Next.js 프로젝트의 package.json에는 대체로 이런 내용이 들어 있습니다.1
{
"name": "my-app",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint"
},
"dependencies": {
"next": "...",
"react": "...",
"react-dom": "..."
}
}여기서 초보자가 가장 먼저 익혀야 할 곳은 scripts입니다.
npm run dev: 개발 서버 실행npm run build: 배포용 빌드 생성npm run start: 빌드한 결과 실행npm run lint: 린터 실행
즉, package.json은 "이 프로젝트를 어떻게 움직일지 정리한 메뉴판"이라고 생각하면 됩니다.
예전 글에서는 next lint를 많이 볼 수 있지만, 최신 Next.js 기준으로는 ESLint나 Biome 같은 도구를 직접 스크립트에 연결하는 흐름으로 보는 편이 더 자연스럽습니다.1
dependencies는 프로젝트가 실제로 사용하는 라이브러리 목록입니다. 예를 들어 next, react, react-dom이 여기에 들어 있습니다. 이 항목을 보면 "이 프로젝트가 어떤 도구 위에서 돌아가는지"를 알 수 있습니다.
next.config.ts, tsconfig.json도 겁먹지 말기
이번 챕터의 주인공은 아니지만, 프로젝트 루트에서 자주 보게 되는 파일도 간단히 알아두면 좋습니다.
next.config.ts는 Next.js의 동작을 조정하는 설정 파일입니다. 예를 들어 이미지 설정이나 실험 기능, 기타 프레임워크 옵션을 건드릴 때 사용합니다.1
tsconfig.json은 TypeScript 설정 파일입니다. TypeScript가 코드를 어떤 규칙으로 해석할지 정해 줍니다.1
처음에는 이 파일들을 적극적으로 수정할 일이 많지 않습니다. 보인다고 해서 바로 건드릴 필요는 없습니다. 처음 여행 왔는데 공항 관제탑을 바로 조정할 필요는 없는 것과 비슷합니다.
node_modules와 .next는 구경만 하고 손대지 않기
프로젝트를 열면 node_modules와 .next도 보게 됩니다.
node_modules는 설치된 패키지들의 실제 파일이 들어 있는 폴더입니다. npm install을 하면 여기에 잔뜩 생깁니다.
.next는 개발 서버를 돌리거나 빌드할 때 생성되는 결과물과 캐시가 들어가는 폴더입니다.
이 두 폴더는 초보자 입장에서 이렇게 기억하면 충분합니다.
node_modules: 프로젝트가 먹고 사는 재료 창고.next: Next.js가 만들어 놓은 작업 결과물 보관함
직접 수정하는 곳은 아닙니다. 특히 node_modules 안에서 문제를 해결하려고 들어가면, 보통 더 큰 모험이 시작됩니다.
지금 당장 폴더를 읽는 순서
프로젝트를 처음 열었을 때 어디부터 봐야 할지 막막하다면, 아래 순서로 읽어 보세요.
먼저
package.json에서 실행 스크립트를 확인합니다.다음으로
app/layout.tsx를 열어 전체 공통 틀을 봅니다.그다음
app/page.tsx를 열어 홈 화면 내용을 봅니다.이어서
app/globals.css를 확인해 전체 스타일 분위기를 봅니다.마지막으로
public폴더를 열어 이미지와 정적 파일을 확인합니다.
이 순서로 보면 프로젝트가 한 번에 입체적으로 보입니다. 즉, "어떻게 실행되는지 → 어떤 틀인지 → 첫 화면이 뭔지 → 스타일이 뭔지 → 재료가 어디 있는지" 순서로 이해하게 됩니다.
우리 프로젝트로 연결해 보기
이제 앞으로 만들 작은 기록 상점 프로젝트를 떠올려 보겠습니다.
우리는 이 책 뒤쪽에서 여러 페이지를 만들게 됩니다. 아직 다 만들지는 않았지만, 머릿속에 이런 식으로 그려 보면 좋습니다.
app/
├─ layout.tsx
├─ page.tsx
├─ records/
│ ├─ page.tsx
│ └─ [id]/
│ └─ page.tsx
└─ about/
└─ page.tsx
public/
├─ logo.png
└─ default-cover.png이 구조를 읽으면 벌써 대충 감이 옵니다.
layout.tsx는 상단 헤더와 하단 푸터를 맡겠구나page.tsx는 메인 홈 화면이겠구나records/page.tsx는 기록 목록이겠구나records/[id]/page.tsx는 기록 상세 화면이겠구나public에는 로고와 기본 이미지를 넣겠구나
바로 이 감각이 중요합니다. 폴더를 보는 순간 기능이 읽히기 시작하면, Next.js가 훨씬 편해집니다.
초보자가 자주 헷갈리는 포인트
처음 배울 때 특히 많이 헷갈리는 지점을 정리해 보겠습니다.
app 폴더 안의 모든 파일이 페이지는 아닙니다
많은 분이 app 안에 파일을 넣으면 전부 라우팅될 거라고 생각합니다. 그렇지 않습니다. page.tsx나 route.ts 같은 특별한 파일이 있어야 공개 경로가 됩니다.1
그래서 app/shop/_components/ProductCard.tsx 같은 보조 파일을 함께 둬도 괜찮습니다.
layout.tsx는 페이지 내용이 아니라 틀입니다
layout.tsx 안에 너무 많은 페이지 전용 내용을 넣으면 구조가 금방 헷갈립니다. 공통되는 것만 넣는 습관이 좋습니다.
예를 들어 모든 페이지에서 보일 헤더는 layout.tsx에, 홈에서만 보일 소개 문구는 page.tsx에 두는 식입니다.
public 경로를 쓸 때는 public을 쓰지 않습니다
public/logo.png를 쓸 때는 /public/logo.png가 아니라 /logo.png입니다.1
이건 정말 자주 틀립니다. 한 번은 꼭 틀리고, 두 번부터는 잘 안 틀립니다.
globals.css는 전체에 영향을 줍니다
전역 스타일은 편리하지만, 너무 많은 규칙을 넣으면 예상치 못한 곳까지 영향을 줄 수 있습니다. 그래서 기본 규칙과 공통 스타일 중심으로 관리하는 것이 좋습니다.
이번 챕터의 핵심만 다시 잡기
이번 챕터에서 꼭 가져가야 할 것은 어렵지 않습니다.
app 폴더는 사이트의 지도입니다. 폴더가 URL 구조를 만들고, page.tsx가 실제 화면을 만듭니다.1
layout.tsx는 공통 틀입니다. 특히 루트 레이아웃은 앱 전체를 감싸며 <html>과 <body>를 포함합니다.2
globals.css는 전체 분위기를 정하는 전역 스타일 파일입니다. 보통 루트 레이아웃에서 import합니다.1
public은 정적 파일 창고입니다. 파일은 URL로 바로 접근할 수 있습니다.1
package.json은 프로젝트의 실행 명령어와 라이브러리 정보를 담는 중요한 파일입니다.1
이제부터 Next.js 프로젝트를 열면, 더 이상 파일들이 낯선 이름표로만 보이지 않을 것입니다. 이름을 읽고 역할을 떠올릴 수 있게 되었으니까요.
다음 챕터에서는 이 폴더 구조 위에 실제로 만들 앱, 작은 기록 상점의 설계를 얹어 보겠습니다. 이제 지도는 펼쳤고, 다음은 어디에 무엇을 지을지 정할 차례입니다.
참고
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.