2025-09-22 01:10

  • ESLint는 코드 문법 오류를 잡고, 일관된 스타일을 강제하여 버그를 예방하는 JavaScript 정적 분석 도구.

  • 모든 규칙을 커스터마이징하고 플러그인을 통해 확장할 수 있는 ‘플러그형 아키텍처’가 핵심적인 특징.

  • 코드 파싱(AST 생성), 규칙 적용, 결과 리포트 순서로 동작하며, 현대 프론트엔드 개발의 필수 요소.

ESLint 완벽 핸드북 코드 품질을 지배하는 정적 분석 도구의 모든 것

개발의 세계는 종종 광활한 서부 시대에 비유된다. 특히 JavaScript처럼 유연하고 동적인 언어의 세계에서는 더욱 그렇다. 정해진 규칙 없이 코드를 작성하다 보면, 사소한 오타가 치명적인 버그로 이어지거나, 팀원마다 다른 코드 스타일 때문에 협업이 악몽으로 변하기도 한다. 이러한 혼돈 속에서 코드의 일관성과 품질을 지켜주는 보안관이 바로 ESLint다.

이 핸드북은 ESLint가 왜 만들어졌는지, 어떤 구조로 동작하는지, 그리고 어떻게 우리 프로젝트의 든든한 지원군으로 활용할 수 있는지에 대한 모든 것을 담고 있다. 단순한 문법 검사기를 넘어, 개발팀의 생산성을 극대화하는 ESLint의 세계로 깊이 들어가 보자.


1. ESLint의 탄생 배경 혼돈의 시대에 나타난 새로운 질서

ESLint의 가치를 제대로 이해하려면, 그 이전의 시대를 먼저 돌아볼 필요가 있다.

JSLint와 JSHint의 시대

최초의 JavaScript Linter는 2002년 Douglas Crockford가 만든 JSLint였다. JSLint는 “JavaScript: The Good Parts”의 저자답게, 매우 엄격하고 독선적인(opinionated) 규칙을 강요했다. 개발자가 규칙을 수정할 여지가 거의 없었기에, 그의 스타일에 동의하지 않는 많은 개발자에게는 불편한 도구였다.

이러한 불편함 속에서 2011년, JSLint를 기반으로 더 유연하고 설정 가능한 JSHint가 탄생했다. JSHint는 개발자가 규칙을 켜고 끌 수 있는 .jshintrc 설정 파일을 제공하며 큰 인기를 끌었다. 하지만 JSHint 역시 한계가 있었다. 새로운 규칙을 추가하려면 JSHint의 소스 코드를 직접 수정하고 포크해야만 했다. 즉, 확장성이 부족했다.

ESLint의 등장 ‘플러그인’이라는 혁신

2013년, Nicholas C. Zakas는 JSHint의 한계를 넘어서는 새로운 Linter를 구상했다. 그의 목표는 명확했다.

“모든 규칙이 플러그인 형태로 존재하고, 사용자가 원하면 언제든지 자신만의 규칙을 추가하거나 제거할 수 있는 Linter”

이 아이디어가 바로 ESLint의 핵심 철학인 **‘플러그형 아키텍처(Pluggable Architecture)‘**의 시작이었다. ESLint는 Linter의 코어를 건드리지 않고도, 누구나 쉽게 새로운 검사 규칙을 만들어 추가하고 공유할 수 있는 생태계를 만들었다. 이 혁신 덕분에 ESLint는 빠르게 JavaScript Linter의 표준으로 자리 잡게 되었다.

비유하자면, JSLint는 메뉴 변경이 불가능한 식당, JSHint는 정해진 메뉴에서 몇 가지를 빼달라고 요청할 수 있는 식당이라면, ESLint는 주방 자체를 개방해서 누구나 자신만의 레시피(규칙)로 요리할 수 있게 만든 식당과 같다.


2. ESLint의 작동 원리 코드 해부학

ESLint가 어떻게 코드 속의 문제점을 귀신같이 찾아낼 수 있을까? 그 비밀은 코드를 분석하는 체계적인 과정에 있다. ESLint는 크게 세 단계로 동작한다.

  1. 파싱 (Parsing): 코드를 조각내어 컴퓨터가 이해할 수 있는 구조로 변환한다.

  2. 규칙 적용 (Linting): 변환된 구조를 순회하며 설정된 규칙을 위반하는지 검사한다.

  3. 결과 보고 (Reporting): 검사 결과를 개발자에게 알려준다.

1단계 파싱과 추상 구문 트리(AST)

ESLint의 심장은 **파서(Parser)**에 있다. 우리가 작성한 JavaScript 코드는 그저 긴 문자열에 불과하다. ESLint는 이 문자열을 의미 있는 구조로 분석하기 위해 파서를 사용해 **추상 구문 트리(Abstract Syntax Tree, AST)**라는 것을 만든다.

AST란 코드의 구조를 나무 형태로 표현한 것이다. 각 노드(Node)는 변수 선언, 함수 호출, 제어문 등 코드의 구성 요소를 나타낸다.

예를 들어, const a = 1; 이라는 간단한 코드는 다음과 같은 AST로 변환될 수 있다.

JSON

{
  "type": "Program",
  "body": [
    {
      "type": "VariableDeclaration",
      "declarations": [
        {
          "type": "VariableDeclarator",
          "id": {
            "type": "Identifier",
            "name": "a"
          },
          "init": {
            "type": "Literal",
            "value": 1,
            "raw": "1"
          }
        }
      ],
      "kind": "const"
    }
  ]
}

복잡해 보이지만, 코드를 ‘변수 선언문’이라는 큰 가지와 그 아래에 ‘변수 이름(a)’, ‘값(1)‘이라는 작은 가지들로 체계적으로 정리한 것이라고 생각하면 쉽다. ESLint는 기본적으로 Espree라는 파서를 사용하며, TypeScript나 최신 문법을 사용하기 위해 @typescript-eslint/parser@babel/eslint-parser 같은 다른 파서를 지정할 수도 있다.

2단계 규칙 적용 (Traversing & Linting)

AST가 만들어지면, ESLint는 이 트리를 위에서부터 아래로 순회(Traversing)하며 각 노드를 방문한다. 그리고 설정 파일(.eslintrc.*)에 정의된 **규칙(Rules)**들을 각 노드에 적용한다.

예를 들어, no-console 규칙이 활성화되어 있다면, ESLint는 AST를 순회하다가 console.log()에 해당하는 CallExpression 노드를 발견했을 때, 이 노드가 console 객체의 log 메서드를 호출하는지 확인하고 경고를 발생시킨다.

각 규칙은 특정 코드 패턴을 찾아내도록 설계된 작은 프로그램과 같다.

3단계 결과 보고

모든 규칙 적용이 끝나면, ESLint는 위반 사항들을 모아 개발자가 알아보기 쉬운 형태로 출력한다. 여기에는 오류가 발생한 파일 경로, 줄 번호, 컬럼 번호, 위반한 규칙의 이름, 그리고 오류 메시지가 포함된다. 이 리포트를 통해 개발자는 신속하게 문제를 파악하고 코드를 수정할 수 있다.


3. ESLint 사용법 실전 가이드

이론은 충분하다. 이제 우리 프로젝트에 ESLint를 직접 설치하고 설정해보자.

1단계 설치 및 초기 설정

Node.js와 npm(또는 yarn, pnpm)이 설치된 환경을 가정한다.

  1. ESLint 설치:

    프로젝트의 개발 의존성(devDependency)으로 ESLint를 설치한다.

    Bash

    npm install eslint --save-dev
    
  2. 설정 파일 생성:

    가장 쉬운 방법은 초기화 명령어를 사용하는 것이다. 이 명령어는 몇 가지 질문을 통해 프로젝트에 맞는 기본 설정을 자동으로 생성해준다.

    Bash

    npm init @eslint/config
    

    이 명령어를 실행하면 다음과 같은 질문들을 받게 된다.

    • How would you like to use ESLint? (ESLint 사용 목적): 보통 To check syntax, find problems, and enforce code style를 선택.

    • What type of modules does your project use? (모듈 시스템): JavaScript modules (import/export) 또는 CommonJS (require/exports) 등 프로젝트에 맞게 선택.

    • Which framework does your project use? (프레임워크): React, Vue.js, None of these 중 선택.

    • Does your project use TypeScript? (TypeScript 사용 여부): Yes/No.

    • Where does your code run? (코드 실행 환경): Browser, Node 중 선택.

    • How would you like to define a style for your project? (스타일 가이드): Use a popular style guide를 선택하여 Airbnb, Standard, Google 등의 유명 스타일 가이드를 따르거나, Answer questions about your style을 선택하여 직접 규칙을 정할 수 있다.

    • What format do you want your config file to be in? (설정 파일 형식): JavaScript, YAML, JSON 중 선호하는 형식을 선택. (일반적으로 JavaScript 형식이 주석이나 동적 로직 추가에 용이하여 선호된다)

    모든 질문에 답하면, 선택에 따라 필요한 패키지(플러그인, 설정 등)를 설치할지 묻고, .eslintrc.js (또는 선택한 형식의) 설정 파일이 생성된다.

2단계 설정 파일(.eslintrc.js) 분석

초기화 명령어로 생성된 .eslintrc.js 파일은 대략 아래와 같은 구조를 가진다.

JavaScript

module.exports = {
    "env": { // 코드가 실행될 환경 설정
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [ // 확장할 기본 설정 (추천 규칙 세트)
        "eslint:recommended",
        "plugin:react/recommended"
    ],
    "parserOptions": { // 파서 관련 옵션
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [ // 사용할 플러그인
        "react"
    ],
    "rules": { // 개별 규칙 설정 (extends 규칙을 덮어씀)
        "indent": ["error", 4], // 들여쓰기는 4칸, 어길 시 에러
        "quotes": ["warn", "single"], // 따옴표는 홑따옴표, 어길 시 경고
        "no-console": "off" // console.log 사용 허용
    }
};

각 속성의 의미는 다음과 같다.

속성설명
env코드가 실행되는 환경을 명시. 각 환경은 특정 전역 변수(e.g., browserdocument, nodeprocess)를 인식하도록 해줌.
extends다른 ESLint 설정 파일의 모든 규칙을 가져와 적용. eslint:recommended는 ESLint가 추천하는 핵심 규칙 세트. 플러그인의 추천 규칙 세트를 가져올 수도 있음 (plugin:react/recommended).
parser코드를 AST로 변환할 파서를 지정. 기본은 Espree. TypeScript의 경우 @typescript-eslint/parser를 명시해야 함.
parserOptions파서에 전달할 옵션. ecmaVersion으로 사용할 ECMAScript 버전을, sourceType으로 모듈 시스템을 지정.
pluginsextends만으로는 부족한 특정 라이브러리(React, Vue 등)나 프레임워크에 맞는 규칙들을 추가. 플러그인은 규칙의 ‘집합’일 뿐, 규칙을 활성화하려면 rulesextends에 추가해야 함.
rules개별 규칙을 직접 설정. extends로 가져온 규칙을 덮어쓰거나(override) 수정할 수 있음. 규칙의 값은 off(0), warn(1), error(2) 중 하나로 설정하여 심각도를 조절.

3단계 실행 및 자동 수정

설정이 완료되었다면, 이제 ESLint를 실행하여 코드를 검사할 수 있다.

  • 특정 파일 검사:

    Bash

    npx eslint your-file.js
    
  • 특정 디렉토리의 모든 파일 검사:

    Bash

    npx eslint "src/**/*.js"
    
  • 자동 수정:

    ESLint의 가장 강력한 기능 중 하나는 —fix 옵션이다. 들여쓰기, 세미콜론, 따옴표 등 스타일과 관련된 많은 문제들을 자동으로 수정해준다.

    Bash

    npx eslint "src/**/*.js" --fix
    

4단계 에디터 연동 (VS Code 예시)

매번 명령어를 입력하는 것은 번거롭다. 코드를 작성하는 순간 바로 피드백을 받을 수 있도록 에디터에 ESLint 확장 프로그램을 설치하는 것이 좋다.

  1. Visual Studio Code의 Extensions 탭에서 ESLint를 검색하여 공식 확장 프로그램을 설치.

  2. VS Code 설정(JSON)에 다음 코드를 추가하여 파일을 저장할 때마다 자동으로 ESLint가 코드를 수정하도록 설정.

    JSON

    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    }
    

이제 코드를 저장할 때마다 ESLint가 마법처럼 코드를 정리해주는 것을 경험할 수 있다.


4. ESLint 심화 탐구

기본적인 사용법을 넘어 ESLint를 120% 활용하기 위한 몇 가지 심화 주제를 알아보자.

공유 가능한 설정 (Sharable Configs)

팀 프로젝트에서 모든 팀원이 동일한 ESLint 규칙을 사용하도록 강제하는 것은 매우 중요하다. 이때 **공유 가능한 설정(Sharable Config)**을 만들어 npm 패키지로 배포할 수 있다. eslint-config-airbnb, eslint-config-google 등이 바로 이런 패키지다.

만약 회사나 팀만의 고유한 코드 스타일 가이드가 있다면, eslint-config-my-company와 같은 패키지를 만들어 extends"my-company" 한 줄만 추가하여 모든 프로젝트에 일관된 규칙을 적용할 수 있다.

사용자 정의 규칙 (Custom Rules)

ESLint의 기존 규칙만으로 만족할 수 없다면, 직접 규칙을 만들 수도 있다. 예를 들어, 우리 회사 서비스에서만 사용하는 특정 함수(sendAnalyticsEvent)를 반드시 호출해야 하는 비즈니스 로직이 있다고 가정해보자.

이 경우, 특정 파일 패턴에서 해당 함수 호출이 누락되었을 때 에러를 발생시키는 사용자 정의 규칙을 만들 수 있다. 규칙은 AST 노드를 방문하고 특정 조건을 검사하는 로직을 담은 JavaScript 모듈이다. 이는 ESLint의 확장성을 극단적으로 보여주는 예시다.

프로세서 (Processors)

ESLint는 기본적으로 JavaScript 파일(.js, .jsx, .ts 등)을 대상으로 동작한다. 하지만 Markdown 파일 내의 코드 블록이나 HTML 파일의 <script> 태그 안의 JavaScript 코드도 검사하고 싶을 때가 있다.

이때 사용하는 것이 프로세서다. 예를 들어 eslint-plugin-markdown 플러그인은 Markdown 파일에서 JavaScript 코드 블록만 추출하여 ESLint가 검사할 수 있도록 전처리(preprocess)하고, 검사 결과를 다시 원래 Markdown 파일의 위치에 맞게 후처리(postprocess)하는 역할을 수행한다.

새로운 설정 시스템 Flat Config (eslint.config.js)

최근 ESLint는 기존의 .eslintrc.* 시스템의 복잡성을 개선하기 위해 eslint.config.js라는 새로운 설정 파일 형식을 도입했다. Flat Config라고 불리는 이 시스템은 더 명시적이고 간결하며, extendsoverrides의 복잡한 상속 구조 대신 배열 기반의 직관적인 설정을 제공한다.

아직은 전환기이지만, 앞으로 ESLint의 표준이 될 것이므로 새로운 프로젝트를 시작한다면 Flat Config 사용을 고려해보는 것이 좋다.


결론 코드의 품질은 곧 제품의 품질

ESLint는 단순한 코드 검사 도구가 아니다. 이것은 개발 문화다. 일관된 코드 스타일은 가독성을 높여 유지보수 비용을 줄이고, 잠재적인 버그를 사전에 차단하여 코드의 안정성을 높인다. 또한, 코드 스타일에 대한 불필요한 논쟁을 줄여 팀이 더 중요한 비즈니스 로직에 집중할 수 있게 해준다.

자동화된 린팅과 포맷팅은 개발자의 실수를 보완해주고, 더 나은 코드를 작성하도록 이끄는 훌륭한 가이드가 된다. 오늘 당장 당신의 프로젝트에 ESLint를 도입하여, 혼돈의 서부 같던 코드 베이스에 새로운 질서를 부여해보는 것은 어떨까? 깨끗하고 예측 가능한 코드는 결국 더 나은 제품과 서비스로 이어질 것이다.