들어가며
필자는 최근 캡스톤 디자인 수업을 듣고 있다. 캡스톤 디자인 프로젝트로 체험단 웹서비스를 개발하기로 결정했고, 개발을 시작하기 위해 언제나 스트레스를 받는 환경 세팅을 진행했다. 이번 프로젝트는 next
최신 버전인 15.2.2
버전을 사용하기로 결정했으며, 이로 인해 기존 세팅과 다른 점들이 있어 애를 먹은 부분이 존재한다. 특히 eslint
버전이 9
버전으로 올라갔고, 설정 방법이 약간 달라져서 이번 경험을 기록하기 위한 포스팅을 작성하게 되었다.
개발자에게 협업이란
개발자에게 있어 협업이란 굉장히 중요한 요소이다. 많은 직무의 동료들과 협업을 하겠지만, 이번 포스팅은 개발자들과의 협업시 필요한 코드의 품질 관리와 일관성이다. 이러한 문제들을 해결하기 위해서는 코드 규칙을 정하고, 이를 자동으로 적용할 수 있는 도구들이 필요하다. 따라서 이번 포스팅에서는 코드 규칙을 정해 오류를 사전에 방지할 수 있는 eslint
와 코드의 포맷을 일관되게 만들어주는 prettier
를 다룰 예정이다.
코드 스타일 유지
일관된 코드 스타일을 유지하는 것은 여러 개발자가 같은 코드를 볼 때 가독성을 높이고, 협업 시 발생할 수 있는 혼란을 줄이는 데 매우 중요하다. 코드가 일관되게 작성되면, 팀원들은 서로의 코드를 쉽게 이해하고 수정할 수 있게 된다. 이는 특히 프로젝트의 크기가 커질수록 필수적이다.
prettier
prettier
는 코드 포캣팅 도구로, 코드의 스타일을 일관되게 자동으로 정리해준다. 예를 들어, 들여쓰기, 줄 바꿈, 세미콜론 사용 여부 등 다양한 규칙을 직접 설정할 수 있다.
자세한 내용은 아래 공식문서를 확인하자.
prettier 설치
필자는 yarn
을 사용하고 있어서 아래의 명령어를 통해 prettier
를 추가했다.
npm install --save-dev --save-exact prettier
yarn add --dev --exact prettier
pnpm add --save-dev --save-exact prettier
--exact
명령어는 패키지 버전을 정확히 설치하기 위한 옵션이다.
// --exact 사용
"prettier": "3.2.5"
// --exact 사용
"prettier": "^3.2.5"
.prettierrc
prettier
를 설치했다면 설정 파일은 루트 디렉토리에 .prettierrc
를 생성하여 설정한다. 필자는 아래와 같이 설정했다. 각 옵션에 대해서는 주석을 참고하자.
{
"printWidth": 100, // 한 줄의 최대 너비
"singleQuote": true, // 단일 인용부호(')로 사용할지 여부
"trailingComma": "all", // 마지막 항목 뒤에 쉼표 사용 여부
"tabWidth": 2, // 탭 너비
"arrowParens": "avoid", // 화살표 함수에서 단일 파라미터에 괄호 사용 여부
"semi": true // 명령문의 끝에 세미콜론 추가 여부
}
vscode 설정
먼저 vscode의 extension에서 prettier를 설치한다.
prettier 익스텐션
설치가 되었다면 ctrl
+ ,
키를 통해 설정 화면으로 이동한다. 이후 위 검색창에 Default Formatter 를 검색하여 Prettier 로 설정한다.
default formatter 설정
다음으로 검색창에 Format on save mode 를 검색 후 사용하도록 체크해준다. 이 옵션은 저장시 코드 포맷터인 prettier 가 작동하여 스타일을 적용해주는 옵션이다.
format on save 설정
마지막으로 setting.json
파일에서 아래 내용을 추가해준다.
{
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 3000,
"editor.formatOnSave": true
}
추가로 vscode 설정에서도 prettier
포맷 설정을 할 수 있는데, 프로젝트에 .prettierrc
파일이 있다면 이 파일이 적용 순위가 더 높기 때문에 설정값이 무시된다.
코드 규칙 설정
코드 규칙 설정은 팀의 코드 품질을 높이고, 협업을 원활하게 하기 위한 중요한 과정이다. 명확한 규칙을 정함으로써 팀원들은 동일한 기준에 따라 코드를 작성할 수 있다. 또한 이러한 코드는 가독성과 일관성을 크게 향상시켜준다.
eslint
prettier
는 코드 스타일 즉 포맷팅을 위한 도구라면, eslint
는 코드의 품질을 검사하고 유지하기 위한 도구이다. Javascript, Typescript 코드에서 문법 오류, 코드 스타일 위반, 그리고 잠재적인 버그를 찾아내는 역할을 한다.
자세한 내용은 아래 공식문서를 확인하자.
eslint 설치
eslint
는 아래 명령어를 통해 설치와 설정 파일을 생성할 수 있다.
npm init @eslint/config@latest
yarn create @eslint/config
pnpm create @eslint/config@latest
bun create @eslint/config@latest
만약 이 글을 읽고 있는 독자가 npx create-next-app@latest
를 이용해서 next
프로젝트를 시작한다면 터미널에서 eslint
사용여부를 선택할 수 있다.
Would you like to use ESLint? No / Yes
.eslintrc.json (ESLint 8 이하)
package.json
에서 본인이 설치한 eslint
버전을 확인해보자. 버전이 8
이하라면 아래와 같이 린트 규칙을 설정할 수 있다.
먼저 루트 디렉토리에 .eslintrc.json
파일을 생성하자. 필자의 프로젝트는 아래와 같이 설정되어있다.
{
// ESLint 규칙 세트를 상속받아서 사용
"extends": ["next/core-web-vitals", "next/typescript", "plugin:prettier/recommended", "plugin:import/recommended"],
// 개별적으로 적용시킬 규칙. 사용하려면 rules에 추가해야함
"plugins": ["prettier", "import"],
// ESLint가 코드에서 검사할 규칙들 정의
"rules": {
"prettier/prettier": "error",
"import/no-named-as-default": "off",
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal", ["parent", "sibling"], "index", "object", "type", "unknown"],
"pathGroups": [
{
"pattern": "react*",
"group": "builtin",
"position": "before"
},
{
"pattern": "next",
"group": "builtin"
},
{
"pattern": "@/assets/**",
"group": "internal",
"position": "after"
},
{
"pattern": "@/store/**",
"group": "internal",
"position": "after"
},
{
"pattern": "@/lib/**",
"group": "internal",
"position": "after"
},
{
"pattern": "@/components/**",
"group": "internal",
"position": "after"
}
],
"pathGroupsExcludedImportTypes": ["react-hook-form"],
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
]
}
}
정확한 각 설정 방식은 공식문서를 확인하자.
eslint.config.js (ESLint 9 이상)
eslint 9
버전부터는 기존의 .eslintrc.json
또는 .eslintrc.yaml
형식이 지원되지 않고, 새로운 Flat Config
형식으로 설정 파일을 작성해야 한다. Flat Config
는 JavaScript 파일(eslint.config.js)로 작성하며, JS Object를 직접 export 하는 방식이다.
기존 문자열 기반 설정에서 벗어나 코드로 직접 설정할 수 있어 가독성과 확장성이 좋아졌다.
현재 필자의 설정 파일은 아래와 같다.
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js';
const compat = new FlatCompat({
baseDirectory: import.meta.dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
const eslintConfig = [
...compat.config({
ignorePatterns: ['node_modules/'],
extends: ['next', 'prettier', 'next/core-web-vitals', 'next/typescript', 'eslint:recommended'],
plugins: ['import'],
rules: {
// 상대 경로 사용 금지
// 'no-restricted-imports': [
// 'error',
// {
// patterns: ['.*'],
// },
// ],
'no-undef': 'off',
// HTML 엔티티 사용 가능
'react/no-unescaped-entities': 'off',
// 페이지 전용 폰트 방지
'@next/next/no-page-custom-font': 'off',
// 선언은 했지만 사용되지 않은 변수
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'warn',
// any 타입 사용 금지
'@typescript-eslint/no-explicit-any': 'error',
// 모듈 정렬
'import/order': [
'error',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'],
pathGroups: [
{
pattern: 'react', // React 관련
group: 'external',
position: 'before',
},
{
pattern: 'next', // Next.js 관련
group: 'external',
position: 'after',
},
{
pattern: 'next/font/google', // Next.js 폰트 관련
group: 'external',
position: 'after',
},
{
pattern: 'configs/**', // configs 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'hooks/**', // hooks 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'libs/**', // libs 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'services/**', // services 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'stores/**', // stores 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'types/**', // types 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'utils/**', // utils 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'constants/**', // public 폴더
group: 'internal',
position: 'after',
},
{
pattern: 'public/**', // public 폴더
group: 'internal',
position: 'after',
},
{
pattern: '@tanstack/**', // @tanstack 관련 라이브러리
group: 'internal',
position: 'after', // 가장 마지막에 배치
},
{
pattern: 'embla-carousel-autoplay', // embla-carousel-autoplay 라이브러리
group: 'internal',
position: 'after', // 가장 마지막에 배치
},
],
pathGroupsExcludedImportTypes: ['@tanstack', 'embla-carousel-autoplay'],
'newlines-between': 'always',
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
},
}),
];
export default eslintConfig;
위와 마찬가지로 각각의 설정은 공식문서를 참고해서 본인이 직접 작성하는 것을 권장한다.
마무리
이번 포스팅에서는 eslint 8
, eslint 9
버전의 설정 방법과, 협업에 필수적인 코드 스타일 관리 도구인 prettier 사용법에 대해 다뤄보았다. 특히 eslint의 Flat Config 도입으로 설정 방식이 크게 바뀌면서 초기 환경 세팅에 다소 어려움이 있을 수 있지만, 이는 더 깔끔하고 유지보수가 쉬운 설정을 가능하게 한다는 점에서 긍정적인 변화라 할 수 있다.
필자는 코드 품질과 일관성을 유지하는 것은 협업의 기본이자 프로젝트 성공의 중요한 부분이라고 생각한다. 따라서 prettier와 eslint를 적절히 활용해 자동화된 코드 스타일 검사 및 포맷팅 환경을 구축하는 것을 적극 추천한다. 앞으로도 최신 도구와 변화에 유연하게 대응하며, 쾌적한 개발 환경을 만들어가길 바란다.