
새로 시작한 프로젝트에서 Next.js 초기 세팅을 맡게 되었다.
초기 세팅은 매번 비슷하면서도, 막상 시작하면 “이거 했었나?” 하고 다시 찾아보게 되는 작업들이 많은 편이다.
세팅을 하다 보니 다음에 또 프로젝트를 시작할 때 참고하면 좋을 것 같다는 생각이 들어, 기억이 남아 있을 때 기록으로 남겨두려고 한다.
이번 글에서는 Next.js 초기 세팅을 중심으로, 프로젝트 초기에 함께 해두면 좋았던 설정들도 번외로 정리해보려고 한다!
먼저 터미널에서 아래 명령어를 입력해 Next.js 프로젝트를 생성한다.
pnpm create next-app@latest project_name
명령어를 실행하면 아래와 같이 초기 설정을 선택하는 프롬프트가 등장한다. 이 단계에서 프로젝트에 사용할 옵션들을 하나씩 선택해주면 된다.

코드 스타일을 통일하기 위해 Prettier + ESLint 관련 패키지를 추가로 설치했다.
pnpm add -D prettier eslint-config-prettier eslint-plugin-prettier
pnpm add -D prettier-plugin-tailwindcss
pnpm add -D eslint-plugin-simple-import-sort
eslint-config-prettier
→ ESLint와 Prettier가 충돌하지 않도록 ESLint 규칙을 비활성화해주는 설정
eslint-plugin-prettier
→ Prettier 규칙을 ESLint 규칙처럼 사용 가능하게 해줌
prettier-plugin-tailwindcss
→ Tailwind CSS 클래스 순서를 자동으로 정렬해주는 플러그인
eslint-plugin-simple-import-sort
→ import문을 정렬해주는 플러그인
아래는 실제로 사용한 .prettierrc 파일이다.
각 코드에 대한 설명은 주석으로 달아두었다.
{
"arrowParens": "avoid", // 화살표 함수에서 매개변수가 하나일 경우 괄호를 생략
"endOfLine": "auto", // 운영체제에 따른 줄바꿈 차이를 자동으로 맞춰줌
"printWidth": 100, // 한 줄의 최대 길이를 100자로 제한
"semi": true, // 문장 끝에 세미콜론(;)을 항상 붙임
"singleQuote": false, // 문자열에 작은따옴표(') 대신 큰따옴표(")를 사용
"tabWidth": 2, // 들여쓰기 시 스페이스 2칸을 사용
"trailingComma": "all", // 객체, 배열, 함수 파라미터 등에서 마지막 요소 뒤에도 쉼표를 붙임
"useTabs": false, // 탭(tab) 대신 스페이스(space)를 사용
"plugins": ["prettier-plugin-tailwindcss"] // Tailwind CSS 클래스명을 권장 순서대로 자동 정렬해줌
}
Prettier가 포맷을 적용하지 않아도 되는 파일/폴더를 지정하기 위해 .prettierignore 파일도 함께 추가했다.
node_modules
dist
build
.env
아래는 eslint.config.mjs에서 Prettier를 ESLint에 연동한 설정이다.
Next.js에서 제공하는 기본 ESLint 설정 위에 Prettier 관련 플러그인과 룰을 추가하여, 포맷 규칙 위반 또한 ESLint 에러로 감지되도록 구성했다.
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
import prettierConfig from "eslint-config-prettier";
import prettierPlugin from "eslint-plugin-prettier";
import simpleImportSort from "eslint-plugin-simple-import-sort";
const eslintConfig = defineConfig([
...nextVitals,
nextTs,
{
plugins: {
prettier: prettierPlugin,
"simple-import-sort": simpleImportSort,
},
rules: {
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"prettier/prettier": "error",
},
},
prettierConfig,
globalIgnores([".next/**", "out/**", "build/**", "next-env.d.ts"]),
]);
export default eslintConfig;
이 설정을 통해 포맷은 Prettier가 담당하고 코드 품질 검사는 ESLint가 담당하되, 포맷이 맞지 않은 코드도 에러로 관리할 수 있게 된다.
SVG 아이콘을 이미지가 아닌 React 컴포넌트처럼 사용하기 위해 @svgr/webpack을 설치했다.
pnpm add -D @svgr/webpack
@svgr/webpack을 사용하면 SVG 파일을 import 해서 형태의 컴포넌트로 사용할 수 있다.
설치 후, next.config.ts를 아래와 같이 수정해준다.
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
turbopack: {
rules: {
"*.svg": {
loaders: [{ loader: "@svgr/webpack", options: { dimensions: false } }],
as: "*.js",
},
},
},
};
export default nextConfig;
위 설정으로 Turbopack 환경에서 .svg 파일을 React 컴포넌트로 변환할 수 있다.
dimensions: false 옵션을 추가하면 SVG에 내장된 width, height 속성이 제거되어, 사용처에서 직접 크기를 지정할 수 있어 재사용성이 높아진다.
Husky는 Git hook을 쉽게 관리할 수 있게 도와주는 도구다.
Git hook은 commit, push 같은 Git 이벤트가 발생하기 직전/직후에 특정 스크립트를 실행할 수 있게 해준다.
Husky를 사용하면
즉, 잘못된 코드가 커밋되는 걸 미리 막아주는 안전장치 역할을 한다.
아래 명령어로 Husky를 개발 의존성으로 설치한다.
pnpm add -D husky
다음 명령어를 실행해 Husky를 초기화한다.
pnpm dlx husky-init
이 명령어는 다음 작업을 자동으로 수행한다.
.husky/ 디렉토리 생성pre-commit 훅 파일 생성package.json에 prepare 스크립트 추가pnpm install
husky-init 실행 후에는 prepare 스크립트가 정상적으로 동작하도록 의존성 재설치가 필요하다.
이 과정에서 Husky가 Git hook으로 제대로 연결된다.
명령어 실행 후, .husky 폴더와 pre-commit 훅이 자동으로 생성되고,

package.json에는 아래와 같이 prepare 스크립트가 생성된다.

아래는 실제로 사용한 package.json 스크립트 일부이다.
{
"scripts": {
"start": "next start",
"lint": "eslint . --ext .js,.ts,.tsx --fix",
"prepare": "husky install",
"prettier": "prettier --write ."
}
}
prepare
의존성 설치 후 Husky를 자동으로 설치해주는 스크립트
→ 팀원이 새로 레포를 받아도 Husky가 자동으로 적용된다.
lint / prettier
pre-commit 단계에서 실행할 명령어들을 분리해 관리하기 위함
아래 명령어로 lint-staged를 설치한다.
pnpm add -D lint-staged
생성된 .husky/pre-commit 파일을 열어 아래와 같이 수정한다.
#!/bin/sh
pnpm exec lint-staged
커밋을 실행하면 lint-staged가 자동으로 실행되며, staged된 파일에 한해 ESLint 검사와 Prettier 포맷팅을 거친 뒤 커밋이 진행된다.
package.json에 lint-staged 설정을 추가해 대상 파일과 실행할 명령어를 지정한다.

"lint-staged": {
"*.{ts,tsx,js,json,css,md}": [
"eslint --fix",
"prettier --write"
]
}
이미 작성된 파일들에 대해 한 번에 포맷을 적용하고 싶다면 아래 명령어를 실행하면 된다.
pnpm run prettier
초기 세팅 단계에서 한 번 실행해두면 이후에는 pre-commit 훅을 통해 포맷이 자동으로 관리된다.
.vscode 폴더에 settings.json 파일을 생성하고 아래와 같이 설정했다.
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
이 설정을 추가하면 파일을 저장하는 순간 자동으로 포맷과 린트 수정이 수행된다.
editor.formatOnSave: true
-> 파일을 저장할 때마다 자동으로 포맷팅을 실행한다.
수동으로 Prettier를 돌릴 필요 없이, Ctrl + S만 눌러도 코드 스타일이 맞춰진다.
editor.defaultFormatter: "esbenp.prettier-vscode"
-> 저장 시 실행될 기본 포맷터를 Prettier로 지정한다. 이 설정이 없으면 VSCode 기본 포맷터 또는 다른 확장 프로그램이 대신 실행될 수 있어, 팀원마다 포맷 결과가 달라질 수 있다.
editor.codeActionsOnSave.source.fixAll.eslint: "explicit"
-> 저장 시 ESLint가 수정 가능한 규칙들을 자동으로 고쳐준다. "explicit"로 설정한 이유는 의도적으로 ESLint fix를 허용하겠다는 의미로, 예상치 못한 자동 수정으로 인한 혼란을 줄이기 위함이다.
--fix로 처리 가능한 규칙 자동 수정초기 세팅을 하면서 필수는 아니지만, 함께 해두면 협업과 운영 측면에서 훨씬 편해지는 작업들도 정리해본다.
PR 생성, merge등의 이벤트를 Discord로 바로 받아볼 수 있도록 WebHook을 연동했다.
이전에 정리한 글이 있어, 자세한 설정 과정은 해당 글을 참고하면 된다.
이슈, PR을 관리할 때 라벨이 잘 정리되어 있으면 작업 흐름을 한눈에 파악하기 좋다.
이 역시 이전에 정리해둔 글이 있어, 자세한 내용은 해당 글을 참고하면 된다.
.github 폴더에 PULL_REQUEST_TEMPLATE.md 파일을 생성해 팀에서 사용할 PR 템플릿을 정의했다.
.github/
└─ PULL_REQUEST_TEMPLATE.md
이렇게 설정해두면 실제로 PR을 생성할 때, 아래와 같이 미리 정의된 템플릿이 자동으로 노출된다. PR 내용 누락을 방지하고, 리뷰어가 변경 사항을 빠르게 파악하는 데 도움이 된다.

이슈 관리도 동일하게 템플릿을 적용했다.
.github/ISSUE_TEMPLATE 폴더에 issue-template.md 파일을 생성해 원하는 형식으로 작성한다.
.github/
└─ ISSUE_TEMPLATE/
└─ issue-template.md
이후 실제 이슈를 생성하면, 아래와 같이 설정한 이슈 템플릿이 자동으로 적용된다.
협업 중 실수로 잘못된 코드가 main 브랜치에 들어가는 것을 방지하기 위해, Branch 보호 규칙(Branch protection rule)도 함께 설정했다.
설정 경로는 아래와 같다.
Repository → Settings → Branches → Branch protection rules → Add rule
여기서 보호할 브랜치 이름(예: main)을 지정한 뒤, merge 조건을 하나씩 설정해주면 된다.
난 아래와 같은 조건을 활성화했다.
Require a pull request before merging
→ PR을 거치지 않으면 main 브랜치에 직접 merge할 수 없도록 설정
Require approvals
→ 최소 1명 이상의 리뷰 승인 후 merge 가능
또한 Repository → Settings → General 경로에서 Automatically delete head branches 옵션을 활성화해두면, PR이 merge되는 순간 해당 feature 브랜치가 원격에서 자동으로 삭제된다. 
매번 프로젝트를 시작할 때마다 “이거 했었나…?” “초기 세팅할 게 또 뭐 있었지…?” 같은 고민을 반복했던 것 같다.
그래서 이번에는 초기 세팅 과정을 한 번 제대로 정리해서 글로 남겨두기로 했다.
앞으로는 새 프로젝트를 시작할 때 이 글을 보면서 차근차근 따라가면 될 것 같고, 적어도 뭔가 빼먹은 건 없는지 계속 고민하지 않아도 될 것 같다.
나처럼 매번 초기 세팅 단계에서 무엇을 했는지, 무엇을 더 해야 하는지 헷갈렸던 사람이 있다면 이 글이 작은 참고 자료나 체크리스트처럼 도움이 되었으면 좋겠다.