들어가며
팀 프로젝트에서 중요한 것 중 하나는 일관된 코드 스타일과 품질 관리입니다. 개발자마다 다른 코딩 스타일이나 사소한 실수로 인한 버그는 프로젝트가 커질수록 누적되어 큰 문제가 될 수 있습니다.
제가 진행하고 있는 프로젝트는 현재 모노레포(Monorepo) 구조로 디자인 시스템을 관리하고 있습니다. 여러 패키지가 하나의 저장소에 공존하다 보니, 각기 다른 설정 때문에 관리가 복잡해지는 문제가 발생했습니다.
이번 글에서는 ESLint
, Prettier
, Husky
를 활용해 모노레포 환경에서 안정적인 개발 환경을 구축한 경험을 공유하고, 과정 중 마주했던 문제와 해결 방법을 정리해보겠습니다.
도구 소개
우선 본격적인 설명에 앞서, 각 도구가 해결하는 문제와 역할을 간단히 정리해봤습니다.
ESLint - 코드 품질 검사
ESLint
는 JavaScript/TypeScript 코드를 정적 분석해 잠재적인 오류나 규칙 위반을 찾아내는 도구입니다.
// ESLint가 잡아낼 수 있는 문제들
const unusedVariable = "hello"; // ❌ 사용하지 않는 변수
let name = "john";
name = 123; // ❌ 타입 불일치 (TypeScript)
if ((user.name = "admin")) {
// ❌ 할당(=) vs 비교(===) 실수
// ...
}
Prettier - 코드 포맷팅
Prettier
는 코드 포맷터로, 개발자가 스타일을 고민하지 않아도 일관된 규칙에 따라 코드를 정리해줍니다.
// Before: 들여쓰기, 공백이 제각각
const user = { name: "john", age: 25, city: "seoul" };
// After: 일관된 스타일 적용
const user = {
name: "john",
age: 25,
city: "seoul",
};
Husky + lint-staged - 자동화
Husky
는 Git Hook을 관리하는 도구로, 커밋/푸시 전에 자동으로 검사나 스크립트를 실행할 수 있습니다.
lint-staged
는 Git에 staged된 파일들만 선별적으로 검사하여 성능을 최적화해줍니다.
# 커밋 시도
git commit -m "fix: button component"
# Husky가 자동 실행
→ ESLint 검사 실행...
→ Prettier 검사 실행...
→ 모든 검사 통과 시에만 커밋 완료
실제로 문제가 있는 파일을 커밋하면 아래와 같이 차단되며 오류가 표시됩니다.

왜 도입해야할까?
앞선 도구들을 간략하게 설명드렸습니다. 그렇다면 저는 왜 프로젝트에서 해당 도구들을 도입하게 되었는지 배경을 간략하게 정리해봤습니다.
- 코드 스타일 불일치: 개발자마다 다른 들여쓰기, 따옴표 사용 등으로 인한 가독성 저하
- 잠재적 버그: 타입 에러, 사용하지 않는 변수 등 런타임 에러로 이어질 수 있는 문제들
- 리뷰 시간 낭비: 코드 스타일이나 간단한 실수에 시간을 쓰느라 핵심 로직 리뷰에 집중하지 못함
- 모노레포 복잡성: 여러 패키지에 각각 다른 설정이 있어 관리 부담 증가
따라서 아래와 같이 목표를 설정했습니다.
- Root 중심의 통합 설정으로 모노레포 전체에 일관된 규칙 적용
- 커밋 전 자동 검사로 품질이 낮은 코드의 저장소 유입 방지
- 효율적인 검사로 개발 속도 저하 최소화
- 팀원 간 설정 공유로 개발 환경 통일
해결 과정: 단계별 구현
그렇다면 각 도구를 어떻게 적용했는지를 살펴봅시다.
ESLint 설정 - 코드 품질 검사
TypeScript + React 환경에 맞는 ESLint 설정을 구성했습니다.
// eslint.config.ts
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
},
}
);
핵심 포인트:
- 모듈형 설정: 플러그인별로 명확하게 분리하여 유지보수성 향상
typescript-eslint
로 타입 안전성 확보- React Hooks 및 Fast Refresh 지원
eslint-config-prettier
로 ESLint와 Prettier 간 규칙 충돌 방지
Prettier 설정 - 코드 스타일 통일
코드 스타일 통일을 위한 Prettier 설정을 추가했습니다.
// .prettierrc
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80
}
.prettierignore
를 활용해 빌드 산출물, 로그 파일, lock 파일 등은 검사 대상에서 제외했습니다.
// .prettierignore
# Build output
dist/
build/
storybook-static/
# Dependencies
node_modules/
.pnpm/
# Tooling
.turbo/
coverage/
*.tsbuildinfo
# Logs and temp files
*.log
.DS_Store
# Lock file
pnpm-lock.yaml
# eslint config
eslint.config.js
plopfile.js
plop-templates/
Husky + lint-staged - 커밋 시점 자동화
가장 핵심적인 부분인 Git Hook을 통한 자동화를 구현했습니다.
// package.json 일부
{
"scripts": {
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives",
"format:check": "prettier --check .",
"quality:check": "pnpm lint && pnpm format:check"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --max-warnings 0",
"prettier --check"
],
"*.{js,jsx,json,css,md}": [
"prettier --check"
]
}
}
모노레포 구조와 통합 관리
저희 프로젝트는 다음과 같은 모노레포 구조를 가지고 있습니다:
design-system/
├── eslint.config.js # 전체 프로젝트 ESLint 규칙
├── .prettierrc # 전체 포맷팅 규칙
├── .vscode/settings.json # VSCode 통합 설정
├── package.json # 통합 스크립트 및 Husky 설정
├── packages/
│ ├── design-system/ # 디자인 시스템 패키지
│ ├── playground/ # 테스트 및 데모 환경
│ ├── tokens/ # 디자인 토큰
│ └── themes/ # 테마 설정
└── .husky/ # Git hooks
└── pre-commit
각 패키지별로 따로 설정하지 않고 Root 디렉토리에서 통합 관리하는 방식을 선택했습니다.
마주한 문제점들과 해결책
구현 과정에서 몇 가지 문제점들을 마주했는데, 이를 어떻게 해결했는지 공유하겠습니다.
ESLint와 Prettier 규칙 충돌
초기에는 ESLint의 포맷팅 규칙과 Prettier가 충돌하는 문제가 발생했습니다.
해결책: eslint-config-prettier
패키지를 설치하여 충돌하는 ESLint 규칙을 비활성화했습니다.
pnpm add -D eslint-config-prettier
성능 이슈 - 전체 파일 검사로 인한 느린 커밋
처음에는 커밋 시 프로젝트 전체를 검사하여 커밋 시간이 매우 오래 걸렸습니다.
해결책: lint-staged
를 도입하여 변경된 파일만 검사하도록 최적화했습니다.
마무리
ESLint, Prettier, Husky를 통한 개발 환경 구축은 단순히 코드를 정리하는 수준을 넘어, 팀 전체의 생산성과 협업 효율성을 높이는 기반이 됩니다.
저희 팀에서는 실제로 코드 리뷰 시 스타일 관련 코멘트가 크게 줄어들었으며 협업 효율성도 크게 향상되었습니다.
처음에는 규칙과 설정이 번거롭게 느껴질 수 있습니다. 그러나 한 번 구축해두면 시간이 지날수록 이점이 누적되어, 특히 모노레포처럼 복잡한 구조에서는 필수적인 품질 관리 수단이 됩니다.