Next.js 프로젝트 보일러플레이트 만들기: 시작 템플릿 구축하기
프로젝트를 시작할 때 매번 환경설정을 처음부터 하는 것은 꽤 귀찮은 일입니다. 특히 Next.js 프로젝트를 여러 번 진행하다 보면, 자주 쓰는 라이브러리와 폴더 구조, ESLint/Prettier 설정 등이 비슷해집니다. 이럴 때 보일러플레이트를 만들어 두면, 새로운 프로젝트를 단 몇 분 만에 시작할 수 있습니다. 이 글에서는 Next.js 15(App Router 기반)로 보일러플레이트 프로젝트를 만드는 방법을 단계별로 설명합니다.

이런 것을 만들 수 있습니다
이 글을 끝까지 따라 하면, 바로 실무에서 활용 가능한 Next.js 보일러플레이트가 준비됩니다. 즉, 프로젝트를 새로 시작할 때 복잡한 초기 설정을 건너뛰고 곧바로 개발에 집중할 수 있습니다.
GitHub에서 완성된 보일러플레이트 확인하기 →
주요 특징
- Next.js 15 (App Router) + TypeScript 환경
- Tailwind CSS + shadcn/ui 기반 컴포넌트 시스템
- ESLint + Prettier 자동 코드 정리
- Husky + lint-staged 커밋 전 검증 자동화
- 확장성과 유지보수에 최적화된 폴더 구조
boilerplate-nextjs-2508/
├── .husky/ # Git hooks 설정
├── public/ # 정적 파일
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── globals.css # 전역 스타일
│ │ ├── layout.tsx # 루트 레이아웃
│ │ └── page.tsx # 홈 페이지
│ ├── components/
│ │ └── ui/ # shadcn/ui 컴포넌트
│ │ └── button.tsx # 버튼 컴포넌트
│ ├── lib/
│ │ └── utils.ts # 유틸리티 함수
│ └── services/
│ ├── local-storage.ts # LocalStorage 래퍼
│ ├── session-storage.ts # SessionStorage 래퍼
│ └── logger.ts # 로거 서비스
├── .gitignore # Git 무시 파일
├── .gitmessage # 커밋 메시지 템플릿
├── commitlint.config.cjs # 커밋 메시지 검증
├── components.json # shadcn/ui 설정
├── eslint.config.mjs # ESLint 설정
├── next.config.ts # Next.js 설정
├── package.json # 의존성 및 스크립트
├── pnpm-lock.yaml # pnpm 락파일
├── postcss.config.mjs # PostCSS 설정
├── prettier.config.js # Prettier 설정
└── tsconfig.json # TypeScript 설정
프로젝트 생성 및 github 연동
Next.js boilerplate 프로젝트의 기초를 만들고 GitHub 저장소와 연결합니다. create-next-app으로 최신 Next.js 프로젝트를 생성하고, 기본 설정을 커스터마이징한 후 버전 관리 시스템을 구축합니다.
1. 프로젝트 생성
create-next-app
을 사용해 Next.js 프로젝트를 생성합니다.
이 도구는 대화형 프롬프트를 통해 프로젝트의 기본 설정을 구성할 수 있게 해줍니다.
npx create-next-app@latest my-boilerplate
각 옵션에 대한 권장 설정과 이유
- TypeScript:
Yes
- 타입 안정성과 개발 생산성 향상 - ESLint:
Yes
- 코드 품질 관리 필수 - Tailwind CSS:
Yes
- 빠른 스타일링과 일관성 src/
directory:Yes
- 프로젝트 구조 명확화- App Router:
Yes
- Next.js 14 이후 주 Router 방법 - Turbopack:
Yes
- Next.js 15부터 안정화되어 빌드 속도 대폭 개선 - Import alias:
No
- custom 없이 기본@/
경로 사용
2. Git 초기화 및 기본 레이아웃 설정
create-next-app으로 생성된 Git 설정을 제거하고 새로 시작합니다. 아래 명령어 실행 후 프로젝트를 엽니다.
rm -rf .git
이제 src/app/layout.tsx
파일을 수정하여 기본 메타데이터와 뷰포트 설정을 적용합니다.
코드 예시는 모바일 환경에서 확대를 제한하는 설정이며, 필요에 따라 maximumScale과 userScalable을 제거하여 접근성을 유지할 수도 있습니다.
import type { Metadata, Viewport } from "next"
import "./globals.css"
export const metadata: Metadata = {
title: "Next.js Boilerplate 2508",
description: "Next.js 프로젝트 보일러플레이트",
}
export const viewport: Viewport = {
width: "device-width",
initialScale: 1,
// maximumScale: 1, // 최대 확대 배율 제한
// userScalable: false, // 확대/축소 불가 설정
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="kr">
<body className="flex flex-col">{children}</body>
</html>
)
}
3. CSS 설정 및 폰트 적용
기본 스타일과 한글 폰트를 설정합니다.
Pretendard는 한글과 영문이 조화롭게 어울리는 오픈소스 폰트입니다. 가독성이 뛰어나고 다양한 굵기를 지원하며 유지보수도 잘 되는 폰트로 추천합니다.
html, body, :root
에 height: 100%
를 적용하면 자식 요소들이 부모의 전체 높이를 참조할 수 있게 됩니다. 이를 통해 풀 스크린 레이아웃이나 sticky footer 같은 레이아웃 패턴을 쉽게 구현할 수 있습니다.
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard-dynamic-subset.min.css");
@import "tailwindcss";
html,
body,
:root {
height: 100%;
}
body {
font-family: "Pretendard Variable", Pretendard, -apple-system,
BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI",
"Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", sans-serif;
}
...
4. 메인 페이지 수정 및 개발 서버 실행
이 프로젝트는 패키지 매니저로 pnpm을 사용하므로,
기존 npm
이 생성한 package-lock.json
파일 삭제 후 pnpm install 명령어를 실행합니다.
rm package-lock.json
pnpm install
기본 페이지를 간단하게 수정하고 개발 서버를 실행하여 지금까지의 설정이 정상적으로 작동하는지 확인합니다.
화면 중앙에 Hello World!
문구가 보인다면 정상 동작입니다.
pnpm run dev
export default function Home() {
return (
<div className="flex items-center justify-center text-5xl flex-1">
Hello World!
</div>
);
}
5. github 프로젝트 생성
작성한 boilerplate를 GitHub에 올려 템플릿으로 활용할 수 있도록 저장소를 생성합니다.
새 저장소 만들기
- GitHub 로그인 후 우측 상단
+
버튼 클릭 New repository
선택- 저장소 정보 입력:
- Repository name:
nextjs-boilerplate-2025
(원하는 이름) - Visibility:
Public
(템플릿 공유) 또는Private
(개인 사용)
제가 선택한 옵션은 이미지를 참조해주세요.
6. 프로젝트 github 연동
로컬 프로젝트를 GitHub 저장소와 연결하고 첫 번째 커밋을 push합니다. develop
브랜치를 기본 작업 브랜치로 설정하였습니다.
Git 초기화 및 브랜치 설정
- Git 저장소 초기화
- develop 브랜치 생성 (개발용)
- GitHub 원격 저장소 연결
- 첫 커밋 및 push
브랜치 전략
- main: 안정된 프로덕션 버전
- develop: 개발 중인 최신 버전
- feature/*: 새 기능 개발용 브랜치
# Git 초기화
git init
# develop 브랜치 생성 및 전환
git checkout -b develop
# GitHub 원격 저장소 연결 (SSH 방식, github 프로젝트 페이지 확인)
git remote add origin git@github.com:YOUR_USERNAME/boilerplate-nextjs-2508.git
# 모든 파일 스테이징 - (staing: 명령어를 통해 github에 추가할 파일들 선택)
git add .
# 첫 커밋
git commit -m "first commit: Next.js boilerplate initial setup"
# develop 브랜치 push
git push -u origin develop
7. github 확인
GitHub 웹사이트에 접속하여 코드가 정상적으로 업로드되었는지 확인합니다.
확인 사항
- 저장소 페이지 접속
- 현재 브랜치가
develop
인지 확인 - 모든 파일이 업로드되었는지 확인
- 커밋 메시지가 올바르게 표시되는지 확인
브랜치 설정
- 현재는
develop
브랜치만 존재 - 추후 안정된 버전을
main
브랜치에 병합 예정 - GitHub Settings에서 기본 브랜치를
develop
으로 변경 가능
1. 프로젝트 생성
create-next-app
을 사용해 Next.js 프로젝트를 생성합니다.
이 도구는 대화형 프롬프트를 통해 프로젝트의 기본 설정을 구성할 수 있게 해줍니다.
npx create-next-app@latest my-boilerplate
각 옵션에 대한 권장 설정과 이유
- TypeScript:
Yes
- 타입 안정성과 개발 생산성 향상 - ESLint:
Yes
- 코드 품질 관리 필수 - Tailwind CSS:
Yes
- 빠른 스타일링과 일관성 src/
directory:Yes
- 프로젝트 구조 명확화- App Router:
Yes
- Next.js 14 이후 주 Router 방법 - Turbopack:
Yes
- Next.js 15부터 안정화되어 빌드 속도 대폭 개선 - Import alias:
No
- custom 없이 기본@/
경로 사용
2. Git 초기화 및 기본 레이아웃 설정
create-next-app으로 생성된 Git 설정을 제거하고 새로 시작합니다. 아래 명령어 실행 후 프로젝트를 엽니다.
rm -rf .git
이제 src/app/layout.tsx
파일을 수정하여 기본 메타데이터와 뷰포트 설정을 적용합니다.
코드 예시는 모바일 환경에서 확대를 제한하는 설정이며, 필요에 따라 maximumScale과 userScalable을 제거하여 접근성을 유지할 수도 있습니다.
3. CSS 설정 및 폰트 적용
기본 스타일과 한글 폰트를 설정합니다.
Pretendard는 한글과 영문이 조화롭게 어울리는 오픈소스 폰트입니다. 가독성이 뛰어나고 다양한 굵기를 지원하며 유지보수도 잘 되는 폰트로 추천합니다.
html, body, :root
에 height: 100%
를 적용하면 자식 요소들이 부모의 전체 높이를 참조할 수 있게 됩니다. 이를 통해 풀 스크린 레이아웃이나 sticky footer 같은 레이아웃 패턴을 쉽게 구현할 수 있습니다.
4. 메인 페이지 수정 및 개발 서버 실행
이 프로젝트는 패키지 매니저로 pnpm을 사용하므로,
기존 npm
이 생성한 package-lock.json
파일 삭제 후 pnpm install 명령어를 실행합니다.
rm package-lock.json
pnpm install
기본 페이지를 간단하게 수정하고 개발 서버를 실행하여 지금까지의 설정이 정상적으로 작동하는지 확인합니다.
화면 중앙에 Hello World!
문구가 보인다면 정상 동작입니다.
pnpm run dev
5. github 프로젝트 생성
작성한 boilerplate를 GitHub에 올려 템플릿으로 활용할 수 있도록 저장소를 생성합니다.
새 저장소 만들기
- GitHub 로그인 후 우측 상단
+
버튼 클릭 New repository
선택- 저장소 정보 입력:
- Repository name:
nextjs-boilerplate-2025
(원하는 이름) - Visibility:
Public
(템플릿 공유) 또는Private
(개인 사용)
제가 선택한 옵션은 이미지를 참조해주세요.
6. 프로젝트 github 연동
로컬 프로젝트를 GitHub 저장소와 연결하고 첫 번째 커밋을 push합니다. develop
브랜치를 기본 작업 브랜치로 설정하였습니다.
Git 초기화 및 브랜치 설정
- Git 저장소 초기화
- develop 브랜치 생성 (개발용)
- GitHub 원격 저장소 연결
- 첫 커밋 및 push
브랜치 전략
- main: 안정된 프로덕션 버전
- develop: 개발 중인 최신 버전
- feature/*: 새 기능 개발용 브랜치
7. github 확인
GitHub 웹사이트에 접속하여 코드가 정상적으로 업로드되었는지 확인합니다.
확인 사항
- 저장소 페이지 접속
- 현재 브랜치가
develop
인지 확인 - 모든 파일이 업로드되었는지 확인
- 커밋 메시지가 올바르게 표시되는지 확인
브랜치 설정
- 현재는
develop
브랜치만 존재 - 추후 안정된 버전을
main
브랜치에 병합 예정 - GitHub Settings에서 기본 브랜치를
develop
으로 변경 가능
코드 품질 자동화: Prettier, ESLint
이번 섹션에서는 코드 스타일과 품질을 자동으로 관리하는 필수 도구들을 설정합니다. Prettier로 일관된 코드 포맷팅을 적용하고, ESLint로 잠재적 문제를 사전에 발견하여 깔끔하고 안정적인 코드베이스를 유지합니다.
function getUserData() {
const name = "John" // ⚠️ 'name' is assigned but never used
var age = 25 // ❌ Unexpected var, use let or const
let userStatus = "active" // ⚠️ 'userStatus' is never reassigned. Use 'const'
console.log("Getting user") // ⚠️ Unexpected console statement
const data = fetchData() // ❌ 'fetchData' is not defined
return data
}
// 미사용 import
import { useState, useEffect } from "react" // ⚠️ 'useEffect' is defined but never used
const Component = () => {
const [count, setCount] = useState(0)
// any 타입 사용
const handleClick = (e: any) => { // ⚠️ Unexpected any. Specify a different type
setCount(count + 1)
}
}
1. Prettier 및 Import 정렬 플러그인 설치
코드 포맷팅을 자동화하고 import 문을 체계적으로 정렬하기 위해 Prettier와 관련 플러그인들을 설치합니다.
pnpm add -D prettier prettier-plugin-tailwindcss @trivago/prettier-plugin-sort-imports
설치할 패키지들
- prettier: 코드 포맷터 핵심 패키지
- prettier-plugin-tailwindcss: Tailwind CSS 클래스 자동 정렬
- @trivago/prettier-plugin-sort-imports: import 문 자동 정렬 및 그룹화
플러그인 기능
- Tailwind 클래스를 권장 순서대로 자동 정렬 (레이아웃 → 스타일 → 효과)
- import 문을 논리적 그룹으로 분류하고 알파벳순 정렬
- 불필요한 import 정리
prettier 설정 파일을 생성하고 아래 내용을 추가합니다.
module.exports = {
// 플러그인 설정
plugins: [
"@trivago/prettier-plugin-sort-imports", // import 문 정렬
"prettier-plugin-tailwindcss", // Tailwind 클래스 정렬
],
// 기본 포맷팅 규칙
bracketSpacing: true, // 객체 중괄호 내 공백 { foo: bar }
semi: false, // 세미콜론 미사용
singleQuote: false, // 큰따옴표 사용
tabWidth: 2, // 들여쓰기 2칸
trailingComma: "es5", // ES5 호환 trailing comma
// Import 정렬 규칙
importOrder: [
"^react$", // 1. React를 최상단에
"<THIRD_PARTY_MODULES>", // 2. 외부 라이브러리
"^[@]+/", // 3. @로 시작하는 alias 경로
"^[.]+/", // 4. 상대 경로 import
],
importOrderSeparation: true, // 그룹 간 빈 줄 추가
importOrderParserPlugins: ["typescript", "jsx", "decorators-legacy"],
}
2. Prettier 정상 동작 테스트 및 현재 파일에 적용
설정이 완료되었으니 Prettier가 제대로 작동하는지 테스트하고, 프로젝트의 모든 파일에 일괄 적용합니다. 이를 통해 코드베이스 전체가 동일한 스타일을 갖게 됩니다.
npx prettier . --write
Import 정렬의 장점
일관된 순서: React → 외부 라이브러리 → 내부 모듈 → 상대 경로 충돌 최소화: 같은 위치에 import가 추가되어 머지 충돌 감소 가독성 향상: 그룹별로 구분되어 필요한 import를 빠르게 찾기
// Before
import "./globals.css"
import { useState } from "react"
import Link from "next/link"
import React from "react"
import { Button } from "@/components/ui/button"
// After (자동 정렬됨)
import React from "react"
import Link from "next/link"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import "./globals.css"
3. Prettier 설정 커밋 및 GitHub Push
Prettier 설정과 포맷팅이 적용된 코드를 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- prettier.config.js 파일 생성됨
- package.json에 prettier 관련 패키지 추가됨
- 모든 소스 파일이 포맷팅됨
import
문이 정렬됨
git add .
git commit
git push origin develop
build: prettier 및 import 정렬 플러그인 설정
Prettier와 관련 플러그인들을 설치하고 설정 파일을 추가했습니다.
- prettier-plugin-tailwindcss: Tailwind 클래스 자동 정렬
- @trivago/prettier-plugin-sort-imports: import 문 그룹화 및 정렬
- 세미콜론 미사용, 큰따옴표 사용 등 코드 스타일 규칙 정의
모든 소스 파일에 포맷팅을 적용하여 일관된 코드 스타일을 확보했습니다.
4. ESLint와 Prettier 호환성 설정
ESLint와 Prettier가 충돌 없이 함께 작동하도록 설정합니다. Next.js는 기본적으로 ESLint가 설치되어 있으므로, Prettier와의 호환성만 추가하면 됩니다.
역할 분담
- ESLint: 코드 품질 검사 (버그 가능성, 미사용 변수 등)
- Prettier: 코드 포맷팅 (들여쓰기, 따옴표 등)
충돌 예시
- ESLint: "세미콜론을 써야 함"
- Prettier: "세미콜론 안 씀" → eslint-config-prettier가 ESLint의 포맷팅 규칙을 끔
pnpm add -D eslint-config-prettier
import { FlatCompat } from "@eslint/eslintrc"
import { dirname } from "path"
import { fileURLToPath } from "url"
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const compat = new FlatCompat({
baseDirectory: __dirname,
})
const eslintConfig = [
...compat.extends(
"next/core-web-vitals", // Next.js 권장 규칙 (이미 eslint-config-next 포함)
"next/typescript", // TypeScript 지원
"prettier" // Prettier 충돌 방지 (마지막에!)
),
// 커스텀 규칙 추가 가능
...compat.config({
rules: {
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_", // _로 시작하는 매개변수는 무시
varsIgnorePattern: "^_", // _로 시작하는 변수는 무시
},
],
},
}),
]
export default eslintConfig
5. ESLint 설정 커밋 및 GitHub Push
ESLint 설정과 Prettier 호환성 설정이 완료된 코드를 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- eslint.config.mjs 파일 수정됨
- eslint-config-prettier 패키지 추가됨
- package.json에 lint 스크립트 추가됨
- ESLint 정상 동작 확인됨
git add .
git commit
git push origin develop
build: ESLint와 Prettier 호환성 설정 추가
ESLint 설정을 확장하여 코드 품질 검사를 강화하고 Prettier와의 충돌을 방지했습니다.
- eslint-config-prettier 패키지 추가로 포맷팅 규칙 충돌 해결
- TypeScript 미사용 변수 규칙 설정 (_prefix 변수 무시)
- console 메서드 제한 규칙 추가 (warn, error, info는 허용)
- prefer-const, no-var 등 코드 품질 규칙 적용
- lint, lint:fix, format, check 스크립트 추가
이제 ESLint는 코드 품질을, Prettier는 코드 포맷팅을 담당하여 역할이 명확히 분리됩니다.
1. Prettier 및 Import 정렬 플러그인 설치
코드 포맷팅을 자동화하고 import 문을 체계적으로 정렬하기 위해 Prettier와 관련 플러그인들을 설치합니다.
pnpm add -D prettier prettier-plugin-tailwindcss @trivago/prettier-plugin-sort-imports
설치할 패키지들
- prettier: 코드 포맷터 핵심 패키지
- prettier-plugin-tailwindcss: Tailwind CSS 클래스 자동 정렬
- @trivago/prettier-plugin-sort-imports: import 문 자동 정렬 및 그룹화
플러그인 기능
- Tailwind 클래스를 권장 순서대로 자동 정렬 (레이아웃 → 스타일 → 효과)
- import 문을 논리적 그룹으로 분류하고 알파벳순 정렬
- 불필요한 import 정리
2. Prettier 정상 동작 테스트 및 현재 파일에 적용
설정이 완료되었으니 Prettier가 제대로 작동하는지 테스트하고, 프로젝트의 모든 파일에 일괄 적용합니다. 이를 통해 코드베이스 전체가 동일한 스타일을 갖게 됩니다.
npx prettier . --write
Import 정렬의 장점
일관된 순서: React → 외부 라이브러리 → 내부 모듈 → 상대 경로 충돌 최소화: 같은 위치에 import가 추가되어 머지 충돌 감소 가독성 향상: 그룹별로 구분되어 필요한 import를 빠르게 찾기
3. Prettier 설정 커밋 및 GitHub Push
Prettier 설정과 포맷팅이 적용된 코드를 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- prettier.config.js 파일 생성됨
- package.json에 prettier 관련 패키지 추가됨
- 모든 소스 파일이 포맷팅됨
import
문이 정렬됨
git add .
git commit
git push origin develop
4. ESLint와 Prettier 호환성 설정
ESLint와 Prettier가 충돌 없이 함께 작동하도록 설정합니다. Next.js는 기본적으로 ESLint가 설치되어 있으므로, Prettier와의 호환성만 추가하면 됩니다.
역할 분담
- ESLint: 코드 품질 검사 (버그 가능성, 미사용 변수 등)
- Prettier: 코드 포맷팅 (들여쓰기, 따옴표 등)
충돌 예시
- ESLint: "세미콜론을 써야 함"
- Prettier: "세미콜론 안 씀" → eslint-config-prettier가 ESLint의 포맷팅 규칙을 끔
pnpm add -D eslint-config-prettier
5. ESLint 설정 커밋 및 GitHub Push
ESLint 설정과 Prettier 호환성 설정이 완료된 코드를 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- eslint.config.mjs 파일 수정됨
- eslint-config-prettier 패키지 추가됨
- package.json에 lint 스크립트 추가됨
- ESLint 정상 동작 확인됨
git add .
git commit
git push origin develop
prettier 설정 파일을 생성하고 아래 내용을 추가합니다.
module.exports = {
// 플러그인 설정
plugins: [
"@trivago/prettier-plugin-sort-imports", // import 문 정렬
"prettier-plugin-tailwindcss", // Tailwind 클래스 정렬
],
// 기본 포맷팅 규칙
bracketSpacing: true, // 객체 중괄호 내 공백 { foo: bar }
semi: false, // 세미콜론 미사용
singleQuote: false, // 큰따옴표 사용
tabWidth: 2, // 들여쓰기 2칸
trailingComma: "es5", // ES5 호환 trailing comma
// Import 정렬 규칙
importOrder: [
"^react$", // 1. React를 최상단에
"<THIRD_PARTY_MODULES>", // 2. 외부 라이브러리
"^[@]+/", // 3. @로 시작하는 alias 경로
"^[.]+/", // 4. 상대 경로 import
],
importOrderSeparation: true, // 그룹 간 빈 줄 추가
importOrderParserPlugins: ["typescript", "jsx", "decorators-legacy"],
}
husky 적용
Husky는 Git commit, push 시 자동으로 스크립트를 실행해 코드 품질과 규칙을 유지하게 해주는 도구입니다.
이 섹션에서는 커밋 전 코드 포맷 검사, 푸시 전 빌드 테스트, 커밋 메시지 규칙 검사를 설정합니다.
commit 메세지 작성
↓
Husky 훅 호출
↓
lint-staged / commitlint 실행
↓
(push 시) 빌드 테스트 실행
↓
문제 없으면 커밋/푸시 진행
↓
1차 검증된 코드가 공유 코드로 이동
1. Husky로 Git Hook 자동화 설정
GitHub은 협업을 위한 핵심 도구이며, 코드 컨벤션을 지키는 것이 중요합니다.
사람의 실수로 인해 코드 스타일이나 커밋 메시지가 규칙을 벗어나지 않도록, local 환경에서 자동으로 검사해주는 도구가 Husky입니다.
이번 단계에서는 명령어를 통해 기본적인 Husky 설정과 Git Hook 구성을 진행합니다.
- pre-commit : 커밋 전에 staged 파일 lint 검사
- pre-push : 푸시 전에 빌드 테스트
- commit-msg : 커밋 메시지 규칙 검사
# 1. 패키지 설치
pnpm i -D husky lint-staged @commitlint/cli
# 2. Husky 초기화
npx husky init
# 3. pre-commit 훅 설정 - commit 실행 전 staged 파일들 lint 검사
echo "pnpm lint-staged" > .husky/pre-commit
# pre-push 훅 추가 - push 실행 전 build 테스트
echo "pnpm build" > .husky/pre-push
# 4. commit-msg 훅 생성 - 커밋 메시지 규칙 검사
echo "pnpm commitlint --edit \$1" > .husky/commit-msg
2. git message template 생성
Git 커밋 메시지를 작성할 때 **일정한 형식(format)**을 유지하도록 가이드하는 템플릿 파일을 생성합니다.
이 파일은 커밋 시점에 에디터에 자동으로 표시되어, 작업자가 팀의 커밋 컨벤션을 따르도록 도와줍니다.
템플릿의 장점
- 일관된 커밋 메시지 형식 유지
- 필요한 정보를 빠짐없이 작성
- 팀원 간 커뮤니케이션 향상
- 커밋 히스토리 가독성 증대
3. Git 메시지 템플릿 자동 등록 및 lint-staged 설정
package.json에 설정을 추가하여 프로젝트 설치 시 자동으로 Git 템플릿이 등록되도록 하고, lint-staged의 동작을 정의합니다.
-
Git commit message 자동 등록
- 프로젝트 루트에 만든
.gitmessage
템플릿을 postinstall 스크립트로 자동 등록 - 프로젝트를 설치하면 Git이 자동으로 커밋 메시지 템플릿을 사용하도록 구성됩니다.
- 프로젝트 루트에 만든
-
lint-staged 설정
- 커밋할 때 staged된 파일만 대상으로 Prettier를 실행
- 불필요한 전체 파일 포맷팅을 방지하고, 커밋 속도를 유지
{
"scripts": {
...
"postinstall": "husky && git config commit.template ./.gitmessage"
},
"devDependencies": {
...
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
}
}
4. Commit Message Rule 적용
Commitlint를 사용하면 커밋 메시지가 팀에서 정한 규칙을 따르도록 강제할 수 있습니다.
이번 단계에서는 commitlint 설정 파일(commitlint.config.cjs
)을 만들어 주요 규칙을 정의합니다.
규칙 설명
- [숫자, 조건] 형식으로 규칙 정의
0
: 비활성화1
: 경고 (warning)2
: 오류 (error) - 커밋 차단
- "never"/"always": 규칙 적용 조건
module.exports = {
rules: {
// 제목(subject) 규칙
"subject-empty": [2, "never"], // 제목은 반드시 존재해야 함
"subject-full-stop": [2, "never", "."], // 제목 끝에 마침표(.) 사용 금지
// 타입(type) 규칙
"type-enum": [ // 허용되는 커밋 타입 목록
2,
"always",
[
"feat", // 새로운 기능
"fix", // 버그 수정
"docs", // 문서 수정
"style", // 코드 스타일 (포맷팅, 세미콜론 등)
"refactor", // 코드 리팩토링
"test", // 테스트 추가/수정
"build", // 빌드 시스템/의존성
"ci", // CI 설정
"perf", // 성능 개선
"chore" // 기타 변경사항
]
],
"type-empty": [2, "never"], // 타입 필수 입력
"type-case": [2, "always", "lower-case"], // 타입은 소문자만
// 본문(body) 규칙
"body-empty": [0, "never"], // 본문은 선택사항 (0 = 비활성)
"body-leading-blank": [2, "always"], // 제목과 본문 사이 빈 줄 필수
// 푸터(footer) 규칙
"footer-leading-blank": [2, "always"], // 본문과 푸터 사이 빈 줄 필수
},
};
5. Husky 테스트 및 GitHub Push
설정한 Git hooks가 정상적으로 작동하는지 테스트하고 GitHub에 push합니다. 각 단계에서 자동화된 검사가 실행되는 것을 확인할 수 있습니다.
테스트 과정
- git add: 변경사항 스테이징
- git commit: pre-commit hook 실행 (lint-staged)
- git push: pre-push hook 실행 (build 테스트)
확인 사항
- 커밋 시 자동 포맷팅 적용
- 커밋 메시지 규칙 검증
- 푸시 전 빌드 성공 확인
git add .
git commit
git push origin develop
git push origin
> boilerplate-nextjs-2508@0.1.0 build /Users/mech2cs/work/mech2cs/boilerplate-nextjs-2508
> next build
▲ Next.js 15.4.6
Creating an optimized production build ...
✓ Compiled successfully in 1000ms
✓ Linting and checking validity of types
✓ Collecting page data
✓ Generating static pages (5/5)
✓ Collecting build traces
✓ Finalizing page optimization
Route (app) Size First Load JS
┌ ○ / 121 B 100 kB
└ ○ /_not-found 991 B 101 kB
+ First Load JS shared by all 99.8 kB
├ chunks/540-d81d811e227e740f.js 43.8 kB
├ chunks/97be0265-f694bf0abffa3d2c.js 54.1 kB
└ other shared chunks (total) 1.89 kB
○ (Static) prerendered as static content
Enumerating objects: 27, done.
Counting objects: 100% (27/27), done.
Delta compression using up to 12 threads
Compressing objects: 100% (15/15), done.
Writing objects: 100% (19/19), 27.42 KiB | 9.14 MiB/s, done.
Total 19 (delta 8), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (8/8), completed with 5 local objects.
To github.com:sijunnoh/boilerplate-nextjs-2508.git
726eab4..4f7ee5d develop -> develop
1. Husky로 Git Hook 자동화 설정
GitHub은 협업을 위한 핵심 도구이며, 코드 컨벤션을 지키는 것이 중요합니다.
사람의 실수로 인해 코드 스타일이나 커밋 메시지가 규칙을 벗어나지 않도록, local 환경에서 자동으로 검사해주는 도구가 Husky입니다.
이번 단계에서는 명령어를 통해 기본적인 Husky 설정과 Git Hook 구성을 진행합니다.
- pre-commit : 커밋 전에 staged 파일 lint 검사
- pre-push : 푸시 전에 빌드 테스트
- commit-msg : 커밋 메시지 규칙 검사
2. git message template 생성
Git 커밋 메시지를 작성할 때 **일정한 형식(format)**을 유지하도록 가이드하는 템플릿 파일을 생성합니다.
이 파일은 커밋 시점에 에디터에 자동으로 표시되어, 작업자가 팀의 커밋 컨벤션을 따르도록 도와줍니다.
템플릿의 장점
- 일관된 커밋 메시지 형식 유지
- 필요한 정보를 빠짐없이 작성
- 팀원 간 커뮤니케이션 향상
- 커밋 히스토리 가독성 증대
3. Git 메시지 템플릿 자동 등록 및 lint-staged 설정
package.json에 설정을 추가하여 프로젝트 설치 시 자동으로 Git 템플릿이 등록되도록 하고, lint-staged의 동작을 정의합니다.
-
Git commit message 자동 등록
- 프로젝트 루트에 만든
.gitmessage
템플릿을 postinstall 스크립트로 자동 등록 - 프로젝트를 설치하면 Git이 자동으로 커밋 메시지 템플릿을 사용하도록 구성됩니다.
- 프로젝트 루트에 만든
-
lint-staged 설정
- 커밋할 때 staged된 파일만 대상으로 Prettier를 실행
- 불필요한 전체 파일 포맷팅을 방지하고, 커밋 속도를 유지
4. Commit Message Rule 적용
Commitlint를 사용하면 커밋 메시지가 팀에서 정한 규칙을 따르도록 강제할 수 있습니다.
이번 단계에서는 commitlint 설정 파일(commitlint.config.cjs
)을 만들어 주요 규칙을 정의합니다.
규칙 설명
- [숫자, 조건] 형식으로 규칙 정의
0
: 비활성화1
: 경고 (warning)2
: 오류 (error) - 커밋 차단
- "never"/"always": 규칙 적용 조건
5. Husky 테스트 및 GitHub Push
설정한 Git hooks가 정상적으로 작동하는지 테스트하고 GitHub에 push합니다. 각 단계에서 자동화된 검사가 실행되는 것을 확인할 수 있습니다.
테스트 과정
- git add: 변경사항 스테이징
- git commit: pre-commit hook 실행 (lint-staged)
- git push: pre-push hook 실행 (build 테스트)
확인 사항
- 커밋 시 자동 포맷팅 적용
- 커밋 메시지 규칙 검증
- 푸시 전 빌드 성공 확인
git add .
git commit
git push origin develop
# 1. 패키지 설치
pnpm i -D husky lint-staged @commitlint/cli
# 2. Husky 초기화
npx husky init
# 3. pre-commit 훅 설정 - commit 실행 전 staged 파일들 lint 검사
echo "pnpm lint-staged" > .husky/pre-commit
# pre-push 훅 추가 - push 실행 전 build 테스트
echo "pnpm build" > .husky/pre-push
# 4. commit-msg 훅 생성 - 커밋 메시지 규칙 검사
echo "pnpm commitlint --edit \$1" > .husky/commit-msg
shadcn/ui - 복사하여 사용하는 컴포넌트 시스템
shadcn/ui는 일반적인 컴포넌트 라이브러리와 다른 독특한 접근 방식을 제공합니다. npm 패키지로 설치하는 대신, 필요한 컴포넌트의 소스 코드를 직접 프로젝트에 복사하여 사용합니다.
shadcn/ui의 해결책:
- 완전한 소유권: 컴포넌트 코드가 내 프로젝트에 직접 존재
- 자유로운 커스터마이징: 소스 코드를 직접 수정 가능
- 선택적 설치: 필요한 컴포넌트만 골라서 추가
- 의존성 최소화: 외부 라이브러리 의존도가 낮음
1. shadcn/ui 컴포넌트 추가하기
아래 명령어를 실행하면 원하는 컴포넌트를 선택적으로 설치할 수 있습니다.
Button으로 커서 이동 후 Space -> Enter로 Button을 프로젝트에 추가합니다.
첫 명령어 실행 직후 옵션도 참고해서 진행하시면 됩니다.
pnpm dlx shadcn@latest add
✔ Which components would you like to add? › button
✔ You need to create a components.json file to add components. Proceed? … yes
✔ Which color would you like to use as the base color? › Neutral
✔ Writing components.json.
✔ Checking registry.
✔ Installing dependencies.
✔ Created 1 file:
- src/components/ui/button.tsx
2. 버튼 컴포넌트 테스트
설치된 shadcn/ui Button 컴포넌트가 제대로 작동하는지 테스트합니다. 다양한 variant와 size 옵션을 적용하여 스타일 변형이 올바르게 적용되는지 확인하고, 클릭 이벤트가 정상 동작하는지 검증합니다.
확인 방법
- 개발 서버 실행 (
pnpm dev
) - 각 버튼의 시각적 스타일 확인
- 클릭 시 alert 동작 확인
"use client"
import { Button } from "@/components/ui/button"
export default function Home() {
return (
<div className="flex flex-1 flex-col items-center justify-center gap-3 text-5xl">
<Button onClick={() => alert("Hello World!")}>Hello World!</Button>
<Button variant="ghost" onClick={() => alert("Hello World!")}>
Hello World!
</Button>
<Button variant="destructive" onClick={() => alert("Hello World!")}>
Hello World!
</Button>
<Button size="lg" onClick={() => alert("Hello World!")}>
Hello World!
</Button>
</div>
)
}
3. css 스타일 수정
Tailwind CSS v3.0 이후 기본 스타일에서 button
의 cursor: pointer
가 제거되었습니다.
이로 인해 버튼에 마우스를 올려도 포인터 커서가 나타나지 않으므로,
아래와 같이 globals.css
에 직접 추가해주는 것이 좋습니다.
...
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
button:not([disabled]),
[role="button"]:not([disabled]) {
cursor: pointer;
}
}
4. shadcn 명령어 스크립트 추가
자주 사용하는 shadcn 명령어를 package.json의 scripts에 추가하여 더 쉽게 컴포넌트를 추가할 수 있도록 설정합니다.
스크립트 추가 이유
npx shadcn@latest add
대신 짧은 명령어 사용- 팀원 간 프로젝트 기능 공유
- 자주 사용하는 명령어 단축
이제 아래 명령어를 통해 컴포넌트를 추가할 수 있습니다.
pnpm ui add
# 특정 컴포넌트 직접 추가
pnpm ui add button card dialog
{
...
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint",
"prepare": "husky",
"ui": "npx shadcn@latest",
"postinstall": "husky && git config commit.template ./.gitmessage"
},
...
}
5. Shadcn Ui 커밋 및 GitHub Push
shadcn/ui 초기 설정과 Button 컴포넌트 추가가 완료된 코드를 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- shadcn/ui 초기화 완료 (components.json)
- Button 컴포넌트 추가 (src/components/ui/button.tsx)
- 유틸리티 함수 생성 (lib/utils.ts)
- 커서 스타일 CSS 추가
- package.json에 ui 스크립트 추가
git add .
git commit
git push origin develop
feat: shadcn/ui 설정 및 Button 컴포넌트 추가
재사용 가능한 UI 컴포넌트 시스템인 shadcn/ui를 프로젝트에 통합했습니다.
- shadcn/ui 초기 설정 (components.json, tailwind.config.ts 업데이트)
- Button 컴포넌트 및 관련 유틸리티 추가
- Radix UI 기반 접근성 보장
- 버튼 커서 포인터 스타일 글로벌 CSS 추가
- package.json에 ui 관련 스크립트 추가 (pnpm ui add)
컴포넌트는 src/components/ui에 소스 코드 형태로 관리되어 자유로운 커스터마이징이 가능합니다.
1. shadcn/ui 컴포넌트 추가하기
아래 명령어를 실행하면 원하는 컴포넌트를 선택적으로 설치할 수 있습니다.
Button으로 커서 이동 후 Space -> Enter로 Button을 프로젝트에 추가합니다.
첫 명령어 실행 직후 옵션도 참고해서 진행하시면 됩니다.
pnpm dlx shadcn@latest add
2. 버튼 컴포넌트 테스트
설치된 shadcn/ui Button 컴포넌트가 제대로 작동하는지 테스트합니다. 다양한 variant와 size 옵션을 적용하여 스타일 변형이 올바르게 적용되는지 확인하고, 클릭 이벤트가 정상 동작하는지 검증합니다.
확인 방법
- 개발 서버 실행 (
pnpm dev
) - 각 버튼의 시각적 스타일 확인
- 클릭 시 alert 동작 확인
3. css 스타일 수정
Tailwind CSS v3.0 이후 기본 스타일에서 button
의 cursor: pointer
가 제거되었습니다.
이로 인해 버튼에 마우스를 올려도 포인터 커서가 나타나지 않으므로,
아래와 같이 globals.css
에 직접 추가해주는 것이 좋습니다.
4. shadcn 명령어 스크립트 추가
자주 사용하는 shadcn 명령어를 package.json의 scripts에 추가하여 더 쉽게 컴포넌트를 추가할 수 있도록 설정합니다.
스크립트 추가 이유
npx shadcn@latest add
대신 짧은 명령어 사용- 팀원 간 프로젝트 기능 공유
- 자주 사용하는 명령어 단축
이제 아래 명령어를 통해 컴포넌트를 추가할 수 있습니다.
pnpm ui add
# 특정 컴포넌트 직접 추가
pnpm ui add button card dialog
5. Shadcn Ui 커밋 및 GitHub Push
shadcn/ui 초기 설정과 Button 컴포넌트 추가가 완료된 코드를 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- shadcn/ui 초기화 완료 (components.json)
- Button 컴포넌트 추가 (src/components/ui/button.tsx)
- 유틸리티 함수 생성 (lib/utils.ts)
- 커서 스타일 CSS 추가
- package.json에 ui 스크립트 추가
git add .
git commit
git push origin develop
✔ Which components would you like to add? › button
✔ You need to create a components.json file to add components. Proceed? … yes
✔ Which color would you like to use as the base color? › Neutral
✔ Writing components.json.
✔ Checking registry.
✔ Installing dependencies.
✔ Created 1 file:
- src/components/ui/button.tsx
Wrapper 클래스 - 안전하고 재사용 가능한 구조
프로젝트에서 특정 라이브러리나 기능을 직접 사용하면,
추후 유지보수가 어렵거나 브라우저 환경에서 발생할 수 있는 에러를 방지하기 어렵습니다.
이런 단점을 보완하기 위해 특정 기능을 중앙화하여 관리하는 것이 좋습니다.
이번 섹션에서는 logger, localStorage, sessionStorage 등을 wrapper 클래스로 구현하고, ESLint와 조합하여 휴먼 에러를 최소화하는 방법을 다룹니다.
Wrapper 클래스의 장점
- 안전성 확보: 브라우저 환경에서만 접근하도록 처리
- 재사용성 향상: 공통 로직을 한 곳에서 관리
- 일관된 인터페이스: localStorage, sessionStorage, logger 모두 동일한 방식으로 사용
- 추후 확장 용이: 예를 들어 Sentry 연동, 로깅 포맷 변경 등을 한 곳에서 적용
1. Logger Wrapper 클래스 구현
logger wrapper 클래스를 만들어 프로젝트 전반에서 통일된 방식으로 로그를 남길 수 있습니다. 현재는 최대한 간단한 구조만 추가했습니다.
- 확장 용이: 추후 콘솔 외 CloudWatch, Sentry 등으로 쉽게 연동 가능
- 환경별 제어: dev/production 환경에서 로깅 방식 선택 가능
- 통합 관리: 로그 포맷과 레벨을 한 곳에서 통제
class Logger {
debug(message: string, ...args: unknown[]): void {
console.log(`[DEBUG]`, message, ...args)
}
info(message: string, ...args: unknown[]): void {
console.log(`[INFO]`, message, ...args)
}
warn(message: string, ...args: unknown[]): void {
console.log(`[WARN]`, message, ...args)
}
error(message: string | Error, ...args: unknown[]): void {
console.log(`[ERROR]`, message, ...args)
}
}
export const logger = new Logger()
2. LocalStorage Wrapper 클래스 구현
브라우저의 LocalStorage를 안전하게 사용하기 위한 Wrapper 클래스를 구현합니다. SSR 환경 호환성, 타입 안전성, 에러 처리 기능을 추가합니다.
추후, LocalStorage가 동작하지 않는 환경에서 대체 Storage를 이곳에서 구현하거나 관리할 수 있습니다.
- 안전성: SSR 환경에서도 에러 발생 방지
- JSON 지원: 객체도 쉽게 저장/불러오기 가능
- 확장 용이: 추후 로깅, Sentry 연동 등 추가 가능
class LocalStorage { private _isAvailable: boolean constructor() { this._isAvailable = this.checkAvailability() } private checkAvailability(): boolean { try { if (typeof window === 'undefined' || !window.localStorage) { return false } const testKey = '__local_storage_test__' window.localStorage.setItem(testKey, 'test') window.localStorage.removeItem(testKey) return true } catch { return false } } setItem(key: string, value: unknown): void { if (this._isAvailable) { window.localStorage.setItem(key, JSON.stringify(value)) } } getItem<T>(key: string): T | null { if (this._isAvailable) { const item = window.localStorage.getItem(key) return item ? JSON.parse(item) : null } return null } removeItem(key: string): void { if (this._isAvailable) { window.localStorage.removeItem(key) } } clear(): void { if (this._isAvailable) { window.localStorage.clear() } } get available(): boolean { return this._isAvailable } } export const localStorage = new LocalStorage()
class LocalStorage {
private _isAvailable: boolean
constructor() {
this._isAvailable = this.checkAvailability()
}
private checkAvailability(): boolean {
...
}
setItem(key: string, value: unknown): void {
...
}
getItem<T>(key: string): T | null {
...
}
removeItem(key: string): void {
...
}
clear(): void {
...
}
get available(): boolean {
return this._isAvailable
}
}
export const localStorage = new LocalStorage()
3. SessionStorage Wrapper 클래스 구현
브라우저의 SessionStorage를 안전하게 사용하기 위한 Wrapper 클래스를 구현합니다. SSR 환경 호환성, 타입 안전성, 에러 처리 기능을 추가합니다.
추후, SessionStorage 동작하지 않는 환경(CookiesDisabled)에서 대체 Storage를 이곳에서 구현하거나 관리할 수 있습니다.
- 안전성: SSR 환경에서도 에러 발생 방지
- JSON 지원: 객체도 쉽게 저장/불러오기 가능
- 확장 용이: 추후 로깅, Sentry 연동 등 추가 가능
class SessionStorage { private _isAvailable: boolean constructor() { this._isAvailable = this.checkAvailability() } private checkAvailability(): boolean { try { if (typeof window === 'undefined' || !window.sessionStorage) { return false } const testKey = '__session_storage_test__' window.sessionStorage.setItem(testKey, 'test') window.sessionStorage.removeItem(testKey) return true } catch { return false } } setItem(key: string, value: unknown): void { if (this._isAvailable) { window.sessionStorage.setItem(key, JSON.stringify(value)) } } getItem<T>(key: string): T | null { if (this._isAvailable) { const item = window.sessionStorage.getItem(key) return item ? JSON.parse(item) : null } return null } removeItem(key: string): void { if (this._isAvailable) { window.sessionStorage.removeItem(key) } } clear(): void { if (this._isAvailable) { window.sessionStorage.clear() } } get available(): boolean { return this._isAvailable } } export const sessionStorage = new SessionStorage()
class SessionStorage {
private _isAvailable: boolean
constructor() {
this._isAvailable = this.checkAvailability()
}
private checkAvailability(): boolean {
...
}
setItem(key: string, value: unknown): void {
...
}
getItem<T>(key: string): T | null {
...
}
removeItem(key: string): void {
...
}
clear(): void {
...
}
get available(): boolean {
return this._isAvailable
}
}
export const sessionStorage = new SessionStorage()
4. Eslint로 휴먼에러 최소화
Wrapper 클래스를 활용해 console, localStorage, sessionStorage에 대한 직접 접근을 금지하고, 프로젝트 전반에서 안전하게 사용하도록 Eslint 규칙을 적용합니다.
적용할 규칙
- no-console:
console
직접 호출 금지 → logger 사용 유도 - no-restricted-globals:
localStorage
/sessionStorage
직접 접근 금지 - 예외 처리:
src/core
폴더는 Wrapper 구현부이므로 규칙 제외
기대 효과
- 프로덕션 코드에
console.log
노출 방지 - SSR 환경에서 storage 에러 방지
- 일관된 로깅 포맷 유지
- 타입 안전성 보장
...
const eslintConfig = [
...
...compat.config({
rules: {
...
// console 직접 호출 금지
"no-console": "error",
// localStorage, sessionStorage 직접 호출 금지
"no-restricted-globals": [
"error",
{
name: "localStorage",
message: "Use localStorageWrapper from '@/services/localStorage' instead of direct localStorage access.",
},
{
name: "sessionStorage",
message: "Use sessionStorageWrapper from '@/services/sessionStorage' instead of direct sessionStorage access.",
},
],
},
}),
// services 폴더 내에서는 예외 허용
{
files: ["src/services/**/*.ts"],
rules: {
"no-console": "off",
"no-restricted-globals": "off",
},
},
]
export default eslintConfig
5. Wrapper Class 관련 커밋 및 GitHub Push
Logger와 Storage Wrapper 구현이 완료되었으니 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- Logger 클래스 구현 (src/core/logger/index.ts)
- LocalStorage Wrapper 구현 (src/core/storage/local-storage.ts)
- SessionStorage Wrapper 구현 (src/core/storage/session-storage.ts)
- ESLint 규칙 추가 (console, storage 직접 사용 금지)
- 테스트 및 동작 확인
git add .
git commit
git push origin develop
feat: Logger 및 Storage Wrapper 클래스 추가
- Logger: 환경별 로그 제어, 컬러 출력, 타임스탬프
- Storage: SSR 안전, 타입 체크, JSON 자동 처리
- ESLint 규칙으로 직접 사용 금지, Wrapper 사용 강제
1. Logger Wrapper 클래스 구현
logger wrapper 클래스를 만들어 프로젝트 전반에서 통일된 방식으로 로그를 남길 수 있습니다. 현재는 최대한 간단한 구조만 추가했습니다.
- 확장 용이: 추후 콘솔 외 CloudWatch, Sentry 등으로 쉽게 연동 가능
- 환경별 제어: dev/production 환경에서 로깅 방식 선택 가능
- 통합 관리: 로그 포맷과 레벨을 한 곳에서 통제
2. LocalStorage Wrapper 클래스 구현
브라우저의 LocalStorage를 안전하게 사용하기 위한 Wrapper 클래스를 구현합니다. SSR 환경 호환성, 타입 안전성, 에러 처리 기능을 추가합니다.
추후, LocalStorage가 동작하지 않는 환경에서 대체 Storage를 이곳에서 구현하거나 관리할 수 있습니다.
- 안전성: SSR 환경에서도 에러 발생 방지
- JSON 지원: 객체도 쉽게 저장/불러오기 가능
- 확장 용이: 추후 로깅, Sentry 연동 등 추가 가능
3. SessionStorage Wrapper 클래스 구현
브라우저의 SessionStorage를 안전하게 사용하기 위한 Wrapper 클래스를 구현합니다. SSR 환경 호환성, 타입 안전성, 에러 처리 기능을 추가합니다.
추후, SessionStorage 동작하지 않는 환경(CookiesDisabled)에서 대체 Storage를 이곳에서 구현하거나 관리할 수 있습니다.
- 안전성: SSR 환경에서도 에러 발생 방지
- JSON 지원: 객체도 쉽게 저장/불러오기 가능
- 확장 용이: 추후 로깅, Sentry 연동 등 추가 가능
4. Eslint로 휴먼에러 최소화
Wrapper 클래스를 활용해 console, localStorage, sessionStorage에 대한 직접 접근을 금지하고, 프로젝트 전반에서 안전하게 사용하도록 Eslint 규칙을 적용합니다.
적용할 규칙
- no-console:
console
직접 호출 금지 → logger 사용 유도 - no-restricted-globals:
localStorage
/sessionStorage
직접 접근 금지 - 예외 처리:
src/core
폴더는 Wrapper 구현부이므로 규칙 제외
기대 효과
- 프로덕션 코드에
console.log
노출 방지 - SSR 환경에서 storage 에러 방지
- 일관된 로깅 포맷 유지
- 타입 안전성 보장
5. Wrapper Class 관련 커밋 및 GitHub Push
Logger와 Storage Wrapper 구현이 완료되었으니 커밋하고 GitHub에 push합니다.
커밋 전 확인사항
- Logger 클래스 구현 (src/core/logger/index.ts)
- LocalStorage Wrapper 구현 (src/core/storage/local-storage.ts)
- SessionStorage Wrapper 구현 (src/core/storage/session-storage.ts)
- ESLint 규칙 추가 (console, storage 직접 사용 금지)
- 테스트 및 동작 확인
git add .
git commit
git push origin develop
class Logger {
debug(message: string, ...args: unknown[]): void {
console.log(`[DEBUG]`, message, ...args)
}
info(message: string, ...args: unknown[]): void {
console.log(`[INFO]`, message, ...args)
}
warn(message: string, ...args: unknown[]): void {
console.log(`[WARN]`, message, ...args)
}
error(message: string | Error, ...args: unknown[]): void {
console.log(`[ERROR]`, message, ...args)
}
}
export const logger = new Logger()
마치며
이번 튜토리얼에서는 Next.js 15를 기반으로 한 완전한 보일러플레이트 프로젝트를 구축하는 과정을 다뤘습니다.
완성된 코드는 GITHUB 저장소를 참조해주세요.
구축한 주요 기능들
- 프로젝트 기초: Next.js 15 + TypeScript + Tailwind CSS
- 코드 품질 자동화: Prettier, ESLint, lint-staged로 일관된 코드 스타일 유지
- Git Hook 자동화: Husky를 통한 커밋 전 검증과 빌드 테스트
- 컴포넌트 시스템: shadcn/ui로 확장 가능한 UI 컴포넌트 기반 구축
- Wrapper 클래스: Logger, Storage를 안전하고 일관되게 사용할 수 있는 추상화 계층
참조자료
공식 문서
- Next.js 공식 문서 - App Router, TypeScript, 최적화 가이드
- Tailwind CSS 문서 - 유틸리티 클래스와 커스터마이징
- TypeScript 핸드북 - TypeScript 기본 문법과 설정
코드 품질 도구
- Prettier 설정 가이드 - 코드 포맷팅 규칙
- ESLint 규칙 레퍼런스 - 린팅 규칙과 커스터마이징
- Husky 문서 - Git Hook 자동화
UI 라이브러리
- shadcn/ui - 복사 가능한 컴포넌트 라이브러리