ESLint와 Prettier로 코드 스타일  통일하기

ESLint와 Prettier로 코드 스타일  통일하기

1. 배경 

이전 글에서 모노레포(Monorepo) 기반의 물리적 구조 설계를 다루었다면, 이번에는 그 위에서 코드를 작성하는 개발자 간 코드 작성 규칙을 통일하는 방법을 이야기해 보려 합니다.

프로젝트 규모가 커질수록 동일한 파일을 여러 개발자가 수정하는 일이 많아졌고, 들여쓰기나 따옴표 스타일 차이로 인한 불필요한 Git diff가 지속적으로 발생했습니다. 이러한 스타일 차이는 단순한 코드 형식 문제를 넘어 코드 리뷰 과정에서 반복적인 논의를 유발했고, 결과적으로 리뷰 피로도를 높이는 요인이 되었습니다.

사내 위키(Wiki)에 가이드라인을 정리하는 방식만으로는 이러한 문제를 해결하는 데 한계가 있었고, 코드가 원격 저장소에 반영되기 전에 규칙을 개발자의 실수와 무관하게 강제할 수 있는 자동화된 체계가 필요했습니다.

이 글에서는 Vue 3와 TypeScript 환경을 기준으로 ESLint와 Prettier를 활용해 코드 컨벤션을 정착시킨 과정과 VS Code·IntelliJ 환경에서 동일한 규칙을 적용하기 위한 방법을 공유합니다.

2. ESLint와 Prettier 역할 분리

이러한 문제를 해결하기 위해 먼저 ESLint와 Prettier의 역할을 명확히 구분할 필요가 있었습니다.

ESLint는 코드 품질을 검증하는 도구로, 사용하지 않는 변수, 잠재적인 버그 패턴, 잘못된 코드 구조 등을 검출합니다.
반면 Prettier는 코드 형식을 일관되게 유지하는 도구로, 들여쓰기, 줄바꿈, 따옴표 스타일과 같은 시각적 규칙을 자동으로 정렬합니다.

두 도구를 함께 사용할 때 가장 흔하게 발생하는 문제는 규칙 충돌입니다. ESLint 역시 일부 스타일 규칙을 포함하고 있기 때문에 Prettier와 동일한 영역을 서로 다르게 판단할 수 있습니다.

이를 해결하기 위해 본 프로젝트에서는 plugin:prettier/recommended 를 사용하여 Prettier 결과를 ESLint 실행 과정에서도 확인할 수 있도록 구성했습니다. 이를 통해 ESLint 실행만으로 코드 품질과 포맷팅 문제를 함께 확인할 수 있습니다.

프로젝트에서 적용한 ESLint 설정 예시는 다음과 같습니다.

// .eslintrc
{
  "root": true,
  "env": {
    "node": true,
    "browser": true,
    "es2021": true
  },
  "parser": "vue-eslint-parser",
  "parserOptions": {
    "parser": "@typescript-eslint/parser",
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "plugin:vue/vue3-recommended", // Vue 3 환경에서 권장되는 규칙 적용
    "plugin:prettier/recommended"
  ],
  "rules": {
    "vue/multi-word-component-names": "off", // 단일 단어 컴포넌트명 허용
    "no-console": "warn",
    "@typescript-eslint/no-explicit-any": "off"
  }
}

참고로 본 예제는 .eslintrc 기반 Legacy Config 환경을 기준으로 작성했습니다. 프로젝트에서 사용하는 eslint-plugin-vue 버전에 따라 plugin:vue/vue3-recommended 또는 plugin:vue/recommended를 사용할 수 있습니다.

또한 ESLint 9 이상에서는 Flat Config(eslint.config.js) 사용이 권장되므로, 신규 프로젝트라면 공식 문서를 함께 참고하는 것이 좋습니다.

3. 프로젝트 공통 규칙 구성

프로젝트 내 EditorConfig를 지원하는 에디터가 동일한 기본 규칙을 따르도록 .editorconfig를 추가했습니다.

특히 end_of_line = lf 설정은 Windows와 macOS 간 줄바꿈 방식 차이(CRLF/LF)로 인해 발생하는 불필요한 Git diff를 줄이는 데 도움이 됩니다.

각 설정의 의미는 다음과 같습니다.

  • indent_style = space: 들여쓰기 통일

  • indent_size = 2: Vue/TS 프로젝트 기본 스타일 유지

  • end_of_line = lf: OS 간 줄바꿈 충돌 방지

  • insert_final_newline = true: 파일 끝 개행 보장

  • trim_trailing_whitespace = true: 불필요한 공백 제거

EditorConfig 설정은 다음과 같습니다.

# .editorconfig
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

4. IDE 환경 동기화

규칙을 정의하더라도 IDE에서 동일하게 적용되지 않으면 의미가 줄어듭니다. 실제로는 VS Code와 IntelliJ(WebStorm 포함)를 혼용하는 환경에서 포맷팅 차이로 인해 Git diff가 반복적으로 발생하는 문제가 있었습니다.

4.1 문제 원인

VS Code는 확장 프로그램 기반으로 Prettier를 쉽게 적용할 수 있지만, IntelliJ는 기본적으로 자체 포매터를 사용하며 설정에 따라 Prettier 대신 IDE 포매터가 실행될 수 있습니다. 이로 인해 동일한 코드라도 IDE에 따라 포맷 결과가 달라지는 문제가 발생했습니다.

4.2 해결 방안

4.2.1 VS Code 설정

VS Code에서는 저장 시 자동 포맷팅과 ESLint 자동 수정이 동작하도록 설정했습니다.

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

참고로 VS Code 및 ESLint 확장 버전에 따라 source.fixAll.eslint 설정 방식은 달라질 수 있으며, 최신 환경에서는 "explicit" 사용이 권장되는 경우도 있습니다.

4.2.2 IntelliJ 설정

IntelliJ 환경에서는 다음과 같이 설정을 통일했습니다.

  • Prettier 경로를 프로젝트 node_modules 기준으로 명시

  • 코드 reformat 시 Prettier 사용 강제

  • 저장 시 포맷팅을 IDE 포매터가 아닌 Prettier로 위임

이 설정을 통해 IDE 간 포맷팅 차이를 최소화했습니다.

5. Vue SFC 파싱 오류 원인과 해결

초기 적용 과정에서 Vue 3 Single File Component(SFC, .vue) 내부에서 ESLint 파싱 오류가 발생했습니다. 특히 <script setup lang="ts"> 영역이 정상적으로 해석되지 않아 TypeScript 관련 오류가 비정상적으로 발생하는 문제가 있었습니다. 이는 Vue SFC 구조를 이해하는 vue-eslint-parser 없이 @typescript-eslint/parser만 사용하거나, parser 구성이 올바르게 연결되지 않은 경우 발생할 수 있습니다.

이를 해결하기 위해 Vue 구조와 스크립트 영역 파서를 분리했습니다.

// .eslintrc
{
// ...생략
  "parser": "vue-eslint-parser", // 최상단 파서로 Vue 파일의 기본 구조 해석
  "parserOptions": {
    "parser": "@typescript-eslint/parser", // 스크립트 내부 영역만 TS 파서가 담당
    "ecmaVersion": "latest",
    "sourceType": "module"
},
// ...생략
}

이 설정 이후 .vue 파일에서도 정상적으로 린트가 동작하며 파싱 오류가 해결되었습니다.

6. 운영 경험과 한계

초기 도입 시 기존 코드베이스에서 약 200건 이상의 린트 오류가 발생했습니다. 특히 any 사용, console.log, Vue 컴포넌트 네이밍 규칙 위반이 주요 원인이었습니다. 모든 규칙을 Error로 강제할 경우 개발 속도에 영향을 줄 수 있기 때문에 초기에는 일부 규칙을 warn 또는 off로 설정하여 점진적으로 적용하는 전략을 사용했습니다. 또한 console.log는 디버깅 과정에서 빈번하게 사용되기 때문에 초기에는 no-console을 Warning 수준으로 운영했습니다.

또한 이번 단계에서는 Husky 기반의 커밋 검증은 적용하지 않았습니다. 초기에는 lint-staged와 Husky를 통한 커밋 단계 강제도 고려했지만, 우선순위는 로컬 개발 환경 통일과 팀 내 개발 경험 안정화에 두었습니다. 향후에는 커밋 단계 또는 CI 단계에서 ESLint 검증을 추가하여 개발 환경 차이에 영향을 받지 않도록 코드 품질을 검증하는 구조로 확장하는 것을 고려하고 있습니다.

7. 결론

ESLint와 Prettier를 적용한 이후 가장 크게 체감된 변화는 코드 리뷰 방식이었습니다. 기능과 직접적인 관련이 없는 스타일 수정이 크게 줄어들면서, 개발자들은 코드 형식이 아닌 비즈니스 로직에 더 집중할 수 있는 환경을 만들 수 있었습니다. 결과적으로 코드 리뷰 시간과 불필요한 변경 이력을 줄이는 데 도움이 되었으며, 코드 품질을 일정 수준 이상으로 유지하는 기반을 마련할 수 있었습니다.

자동화된 코드 컨벤션 환경은 대규모 협업에서 일관성을 유지하기 위한 중요한 기반이 될 수 있습니다.

참고 문헌

- ESLint Official Documentation: https://eslint.org/

- Prettier Official Documentation: https://prettier.io/

- EditorConfig Official Documentation: https://editorconfig.org/

- Vue ESLint Plugin Official Documentation: https://eslint.vuejs.org/

Code_Latte

Site footer