[2025년 기준] Next.js 15 프로젝트 셋팅하기 - prettier, eslint, husky

김규리·2025년 2월 15일
5
post-thumbnail

Next.js 프로젝트를 새로 시작하며 셋팅을 맡았다.
그런데 인터넷에서 검색하고 대충 "복사+붙여넣기"를 하니 에러가 펑펑 터졌다.
왜 에러가 나는지 찾아보니 내가 인터넷에서 찾고 붙여넣은 글들은 몇 년 된 글이고, 그 사이 툴들은 빠르게 업데이트 되어 많이 바뀌어있었다.
그래서 이 참에 공식문서를 읽어보고, 최신 버전으로 prettier, eslint, husky를 셋팅하는 방법을 작성해보았다.




prettier

prettier 공식 문서

prettier는 코드 스타일을 일관되게 만들어주는 포맷터다. 들여쓰기, 따옴표 스타일, 콤마 위치, 줄바꿈 등 코드의 형식을 자동으로 정리해준다.

여러 개발자가 함께 프로젝트를 진행할 때 각자 선호하는 코드 스타일이 다르다. 어떤 사람은 '작은따옴표'를, 다른 사람은 "큰따옴표"를 선호하고, 세미콜론 사용 여부나 줄바꿈도 개인마다 다르다. 이렇게 다양한 스타일이 섞여 있으면 코드의 가독성이 떨어진다. prettier는 이런 문제를 해결해주는데, 모든 코드를 동일한 스타일로 자동 변환해준다.

설치 및 설정

우선 VSCode에서 prettier 확장 프로그램을 설치하는 것이 좋다. 확장 프로그램이 없이 CLI로도 prettier를 사용할 수 있지만, 그러면 매번 수동으로 포맷팅을 실행해야 한다. VSCode 확장 프로그램을 사용하면 파일 저장 시 자동으로 포맷팅이 적용된다.

그다음 프로젝트에 prettier 패키지를 설치한다.

npm install -D prettier
yarn add -D prettier
pnpm add -D prettier

프로젝트 최상단에 .prettierrc 파일을 생성하고 원하는 포맷팅 규칙을 설정하면 된다. 일반적으로 다음과 같은 옵션들을 설정한다.

{
  "arrowParens": "always", 
  "bracketSpacing": true, 
  "endOfLine": "lf",
  "htmlWhitespaceSensitivity": "css",
  "singleAttributePerLine": false,
  "bracketSameLine": false,
  "jsxSingleQuote": false,
  "printWidth": 80,
  "proseWrap": "preserve",
  "quoteProps": "as-needed",
  "semi": true,
  "singleQuote": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "useTabs": false,
  "embeddedLanguageFormatting": "auto",
  "experimentalTernaries": false,
}

각 속성이 무엇을 의미하는지 궁금하다면 주석을 읽어보자. (나는 너무 궁금해서 찾아봤다.)
더 자세한 설명은 여기서 볼 수 있다.

{
  // 화살표 함수의 매개변수 괄호 여부 (x) => x
  "arrowParens": "always",
  
  // 객체 리터럴의 중괄호 안쪽 공백 여부 { foo: bar }
  "bracketSpacing": true,
  
  // 줄 끝 문자를 LF(Line Feed)로 통일
  "endOfLine": "lf",
  
  // HTML 공백 처리 방식을 CSS 디스플레이 속성에 따라 결정
  // => inline 요소의 공백은 유지하고, block 요소의 공백은 무시
  "htmlWhitespaceSensitivity": "css",
  
  // JSX/HTML 속성을 한 줄에 하나씩 작성할 것인지
  "singleAttributePerLine": false,
  
  // JSX 태그의 닫는 괄호(>)를 같은 줄에 배치할 것인지
  "bracketSameLine": false,
  
  // JSX 속성에 작은 따옴표를 사용할 것인지
  "jsxSingleQuote": false,
  
  // 한 줄의 최대 길이를 몇 자로 제한할 것인지
  "printWidth": 80,
  
  // 마크다운 등의 prose 텍스트를 printWidth에 맞춰 줄바꿈할 것인지 유지할 것인지
  "proseWrap": "preserve",
  
  // 객체 속성에 따옴표를 필요한 경우에만 사용
  "quoteProps": "as-needed",
  
  // 문장 끝에 세미콜론 추가
  "semi": true,
  
  // '작은따옴표'를 사용할 것인지
  "singleQuote": false,
  
  // 탭 너비
  "tabWidth": 2,
  
  // 가능한 모든 곳에 후행 쉼표 추가
  "trailingComma": "all",
  
  // 들여쓰기에 탭을 사용할 것인지 공백을 사용할 것인지
  "useTabs": false,
  
  // 템플릿 리터럴 내의 코드를 자동으로 포맷팅
  "embeddedLanguageFormatting": "auto",
  
  // 삼항 연산자의 실험적 포맷팅 기능을 활성화 할건지
  "experimentalTernaries": false,
}

.prettierignore

특정 파일이나 디렉토리를 포맷팅에서 제외하고 싶다면 .prettierignore 파일을 생성하고 제외하고 싶은 파일 형식이나 디렉토리 등을 작성하면 된다.

.gitignore

# macOS
.DS_Store

# Windows
Thumbs.db

# 100MB 이상 파일 제외
**/*.{zip,tar,gz}
**/*.{mp4,mov}

**/generated/
**/__generated__/

eslint

prettier와 eslint는 서로 다른 목적을 가진 도구다. prettier는 코드의 형식을 일관되게 만들어주고, eslint는 코드의 품질을 검사하고 잠재적인 버그를 찾아낸다. 사용하지 않는 변수, 잘못된 import 구문, 잘못된 함수 사용 등을 감지하고 경고해준다.

next에서 eslint 설치

Next.js 프로젝트를 처음 생성할 때 eslint 옵션을 선택하면 기본적인 eslint 설정이 자동으로 구성된다.

이 때, eslint를 사용한다고 하자.

그러면 프로젝트 루트에 eslint.config.mjs 파일이 생성되며, 기본 설정은 다음과 같다.

// eslint.config.mjs
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";

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/typescript"),
];

export default eslintConfig;

eslint 설정 파일 변경사항

eslint v9.0.0부터는 .eslintrc 파일 형식이 deprecated되었다. 이제는 eslint.config.mjs 파일을 사용해 eslint 설정을 진행해야 한다. 인터넷에 "eslint 설정하기"라고 검색하면 대부분 .eslintrc 형식을 다루고 있으므로 조심하자!

(역시 공식문서를 잘 읽자)


eslint-config-next

위에서 Next.js 프로젝트를 시작할 때, eslint를 사용한다고 하면 eslint-config-next 라이브러리를 자동으로 설치한다.

이 라이브러리는, 기존에 사용자가 직접 추가해야하는 ESLint 플러그인들의 권장 규칙이 모두 포함되어 있다...

  • eslint-plugin-react
  • eslint-plugin-react-hooks
  • eslint-plugin-next

따라서 괜히 인터넷에서 이거 설치하고, 이거 설치하고,, 하는 글을 읽고 막 설치하지 말자.
오히려 플러그인들이 중복 설치 되어 설정 충돌이 일어날 수 있다.

eslint + prettier

eslint와 prettier를 함께 사용할 때는 규칙 충돌을 방지하기 위해 eslint-config-prettier를 설치해야 한다.

npm install -D eslint-config-prettier
yarn add -D eslint-config-prettier
pnpm add -D eslint-config-prettier

그리고 eslint.config.mjs에 다음과 같이 설정을 추가한다.

import eslintConfigPrettier from "eslint-config-prettier";

...

const eslintConfig = [
  ...compat.extends("next/core-web-vitals", "next/typescript"),
  eslintConfigPrettier,
];

export default eslintConfig;

husky

husky는 git hooks를 쉽게 관리할 수 있게 해주는 도구다. git commit, push 등의 이벤트가 발생하기 전에 지정한 스크립트를 자동으로 실행할 수 있다.

먼저 husky를 설치한다.

npm install -D husky
yarn add -D husky
pnpm add -D husky

그 다음, husky를 초기화한다.

npx husky init
pnpm exec husky init

초기화를 실행하면 .husky 디렉토리가 생성되고 package.jsonprepare 스크립트가 자동으로 추가된다.

참고로 prepare은 패키지 설치 전 자동으로 실행되는 특별한 라이프사이클 스크립트다.
이를 통해 다른 팀원이 pnpm install을 할 때 자동으로 git hooks 설정이 완료된다.

lint-staged

커밋 시에는 변경된 파일만 검사하는 것이 효율적이다.
이를 위해 stage에 올라간 파일만 검사를 수행하는 lint-staged를 사용한다.
lint-staged는 git의 staged 상태인 파일들만 린트 검사를 수행한다.

lint-staged를 설치한다.

npm install -D lint-staged
yarn add -D lint-staged
pnpm add -D lint-staged

설치 후, package.json에서 lint-staged 설정을 추가한다.

// package.json
{
	...
    "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "next lint --fix",
      "prettier --write"
    ],
    "*.{css,md,json,yaml}": "prettier --write"
  }
}

나는 pnpm exec lint-staged 실행 시 lint 검사 후 prettier를 수정하도록 설정했다.

pre-commit.sh

.husky/pre-commit 파일에 커밋 전 실행할 명령어를 작성한다.

// pre-commit.sh
pnpm exec lint-staged

(참고) 인터넷에서 husky 설정 관련 글을 검색하면

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

해당 내용이 적힌 경우가 꽤 있다.
하지만 직접 husky.sh 파일을 열어보면?

echo "husky - DEPRECATED

Please remove the following two lines from $0:

#!/usr/bin/env sh
. \"\$(dirname -- \"\$0\")/_/husky.sh\"

They WILL FAIL in v10.0.0
"

그렇다... 이제 저 위의 2줄은 적지 말라는 글이다.
v.10.0.0 부터는 husky에서 지원하지 않으니 굳이 작성하지 말자.

pre-push.sh

.husky/pre-push 파일에 푸시 전 실행할 명령어를 작성한다.

// pre-push.sh
# 테스트 실행
echo "🛠️  테스트를 실행합니다..."
pnpm test

# 빌드 검증
echo "📦 프로젝트 빌드를 확인합니다..."
pnpm build

# 보안 취약점 검사
echo "🔒 의존성 보안 점검 중..."
pnpm audit

# 커버리지 검증 (예: 80% 이상 유지)
echo "📊 코드 커버리지를 확인합니다..."
pnpm test:coverage

echo "🍊 pushing... (˶• ﻌ •˶) ( • ᴗ - ) ✧"




언젠간 이 글도 deprecated 되겠만.. 많은 사람들에게 유용하게 사용되면 좋겠다.

profile
먹바눕

1개의 댓글

comment-user-thumbnail
2025년 5월 14일

덕분에 너무 쉽게 세팅 마쳤습니다. 감사합니다!

답글 달기