🔧 DevOps

Linting

린팅

정적 코드 분석으로 오류/스타일 검사. ESLint, Pylint, Clippy.

📖 상세 설명

Linting(린팅)은 소스 코드를 실행하지 않고 정적으로 분석하여 잠재적인 오류, 버그, 스타일 위반, 의심스러운 코드 패턴을 찾아내는 과정입니다. Linter(린터)라는 도구가 이 분석을 수행하며, 코드 품질과 일관성을 유지하는 데 핵심적인 역할을 합니다.

현대 개발에서 널리 사용되는 린터로는 JavaScript/TypeScript의 ESLint, Python의 Pylint/Ruff/flake8, Rust의 Clippy, Go의 golangci-lint, C/C++의 clang-tidy 등이 있습니다. 각 언어 생태계마다 표준으로 자리잡은 린터가 있어 팀 간 코드 스타일 통일에 기여합니다.

Linting은 크게 세 가지를 검사합니다. 첫째, 구문 오류와 타입 문제 같은 잠재적 버그입니다. 둘째, 들여쓰기, 따옴표 스타일, 세미콜론 사용 같은 코드 스타일입니다. 셋째, 사용하지 않는 변수, 너무 복잡한 함수, 안전하지 않은 코드 패턴 같은 코드 품질 문제입니다.

린팅은 CI/CD 파이프라인에 통합하여 Pull Request 시점에 자동으로 검사하고, 린트 오류가 있으면 병합을 막는 것이 일반적입니다. IDE 확장이나 pre-commit hook과 연동하면 커밋 전에 로컬에서 먼저 검사할 수 있어 개발 사이클이 빨라집니다.

💻 코드 예제

// .eslintrc.js - ESLint 설정 파일
module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
    ecmaVersion: 2022,
    sourceType: 'module'
  },
  plugins: ['@typescript-eslint', 'import', 'prettier'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    'plugin:import/typescript',
    'prettier'  // Prettier와 충돌 규칙 비활성화
  ],
  rules: {
    // 타입 안전성
    '@typescript-eslint/no-explicit-any': 'error',
    '@typescript-eslint/strict-boolean-expressions': 'warn',

    // 코드 품질
    'no-console': ['warn', { allow: ['warn', 'error'] }],
    'no-unused-vars': 'off',
    '@typescript-eslint/no-unused-vars': ['error', {
      argsIgnorePattern: '^_'
    }],

    // import 정리
    'import/order': ['error', {
      groups: ['builtin', 'external', 'internal'],
      'newlines-between': 'always',
      alphabetize: { order: 'asc' }
    }]
  },
  ignorePatterns: ['dist/', 'node_modules/', '*.config.js']
};
# pyproject.toml - Ruff/Pylint 설정 (Python)
[tool.ruff]
target-version = "py311"
line-length = 100
select = [
    "E",   # pycodestyle errors
    "W",   # pycodestyle warnings
    "F",   # Pyflakes
    "I",   # isort
    "B",   # flake8-bugbear
    "C4",  # flake8-comprehensions
    "UP",  # pyupgrade
    "S",   # flake8-bandit (보안)
]
ignore = ["E501"]  # line too long (Formatter가 처리)

[tool.ruff.per-file-ignores]
"tests/*" = ["S101"]  # 테스트에서 assert 허용

[tool.pylint.messages_control]
disable = ["missing-docstring", "too-few-public-methods"]
max-line-length = 100
good-names = ["i", "j", "k", "x", "y", "id"]

# pre-commit 설정 (.pre-commit-config.yaml)
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.1.6
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

🗣️ 실무에서 이렇게 말해요

리드: "ESLint 규칙 중에 팀에서 자주 무시하는 거 있으면 논의해서 조정하자. 의미 없이 eslint-disable 남발하는 건 좋지 않아."

주니어: "no-console 규칙 때문에 디버깅할 때 불편한데, warn 레벨로 낮추면 어떨까요?"

시니어: "좋아요. 그리고 CI에서 린트 에러가 있으면 머지 못 하게 막혀 있으니까, 로컬에서 커밋 전에 한 번 돌려보는 습관 들이면 좋아요."

면접관: "코드 품질을 유지하기 위해 어떤 도구를 사용하셨나요?"

지원자: "ESLint와 Prettier를 함께 사용했습니다. Husky와 lint-staged를 설정해서 커밋 시 변경된 파일만 린팅하게 했고, GitHub Actions에서도 PR마다 전체 린트를 돌렸습니다. 린트 규칙은 eslint-config-airbnb를 베이스로 팀에 맞게 커스터마이징했어요."

리뷰어: "이 함수에 `// eslint-disable-next-line @typescript-eslint/no-explicit-any` 붙어있는데, 왜 any를 써야 했는지 코멘트 달아주세요."

작성자: "서드파티 라이브러리 타입이 없어서 임시로 any 썼습니다. 이슈 만들어서 @types 패키지 찾거나 직접 선언 추가하겠습니다."

⚠️ 주의사항

📚 더 배우기