ShellCheck: 39,456 GitHub Stars — 셸 스크립트 분석을 위한 완전 설치 및 설정 가이드 2026

ShellCheck (SC)는 bash/sh 셸 스크립트용 정적 분석 도구입니다. Docker, GitHub Actions, VS Code 통합을 지원하며 설치 구성, CI/CD 파이프라인 통합, 프로덕션 강화를 다룹니다.

  • ⭐ 39456
  • GPL-3.0
  • 업데이트 2026-05-19

{{< resource-info >}}

ShellCheck는 셸 스크립트의 버그를 프로덕션 배포 전에 잡아내는 사실상의 표준 도구입니다. 39,456개 이상의 GitHub 스타와 활발한 오픈소스 커뮤니티를 보유한 ShellCheck는 bash, sh, dash, ksh 스크립트에서 가장 널리 채택된 정적 분석 도구입니다. 본 가이드에서는 ShellCheck 설치, 에디터 통합, CI/CD 파이프라인 구성, 프로덕션 환경 강화 방법을 다룹니다.

ShellCheck 터미널 출력 — 인용되지 않은 변수 경고 표시

소개 #

셸 스크립트는 배포 파이프라인, 시스템 자동화, 인프라 관리를 구동합니다. 인용되지 않은 변수 하나나 확인되지 않은 반환 코드가 데이터 손상, 자격 증명 노출 또는 프로덕션 서버 중단을 유발할 수 있습니다. 2014년 Heartbleed 여파와 수많은 CI/CD 장애는 정적 분석이 잡아낼 수 있었던 셸 스크립트 버그로 거슬러 올라갑니다.

2012년 Vidar Holen이 만든 ShellCheck는 이 격차를 해소합니다. 스크립트를 실행하지 않고 파싱하여 구문 오류, 의미적 함정, 이식성 문제, 보안 취약점을 식별합니다. 280개 이상의 내장 검사 규칙(각각 고유한 SC 코드 할당)을 통해 초보자의 실수부터 숙련된 개발자도 걸려 넘어지는 미묘한 엣지 케이스까지 포착합니다.

본 가이드는 shellcheck 튜토리얼과 설치 설정 가이드의 완전판입니다: 다중 플랫폼 설치, 에디터 통합, shellcheck docker 사용법, GitHub Actions 설정, 프로덕션 강화 및 bash 린팅까지 다룹니다. 단일 배포 스크립트를 린팅하든 모노레포 전체에 품질 게이트를 적용하든, 아래 설정을 복사·적용·배포할 수 있습니다.

ShellCheck란? #

ShellCheck는 셸 스크립트용 정적 분석 도구(“린터”)입니다. bash/sh/dash/ksh 소스 코드를 읽어 추상 구문 트리(AST)를 구축하고, 의미론적 규칙을 적용하여 버그, 안티패턴, 스타일 위반을 실행 없이 감지합니다.

Haskell로 작성된 이 프로젝트(코드베이스의 96.4%)는 GPL-3.0 라이선스로 배포되며, Vidar Holen과 166명 이상의 기여자가 유지보수합니다. 안정 버전 v0.11.0은 2025년 8월 4일에 릴리스되었습니다.

핵심 기능 #

  • 구문 검증: 런타임 전 잘못된 구조 포착
  • 의미 분석: 인용되지 않은 변수, 도달 불가능한 코드, 마스킹된 종료 코드 감지
  • 이식성 검사: POSIX 준수를 위한 /bin/sh 스크립트에서 bash 전용 구문 플래그
  • 보안 감사: 명령 주입 벡터와 안전하지 않은 eval 패턴 식별
  • 스타일 강제: 더 이상 사용되지 않는 구문 대신 현대적 구조 제안

ShellCheck 작동 방식 #

ShellCheck는 다단계 분석 파이프라인으로 작동합니다. 이 아키텍처를 이해하면 성능 튜닝과 결과 해석에 도움이 됩니다.

아키텍처 개요 #

소스 스크립트 → 렉서 → 파서 (AST) → 분석기 → 리포터
                    ↓           ↓            ↓
                토큰      구문 트리     SC-경고
  1. 렉서: 스크립트를 식별자, 키워드, 연산자, 리터럴로 토큰화
  2. 파서: 토큰 스트림에서 AST를 구축하며 셸 특유의 문법 처리
  3. 분석기: AST를 순회하며 280개 이상의 규칙을 적용, 각 규칙은 고유한 SC 오류 코드에 매핑
  4. 리포터: 결과를 터미널 출력, JSON, CheckStyle XML, GCC 호환 경고, SARIF 형식으로 포맷팅

심각도 수준 #

모든 ShellCheck 결과는 다음 네 가지 심각도 수준 중 하나를 갖습니다:

수준종료 코드 영향예시
오류비영 종료구문 오류, 정의되지 않은 변수
경고비영 종료인용되지 않은 변수 (SC2086)
정보영 종료스타일 제안
스타일영 종료포맷팅 선호도

핵심 검사 카테고리 #

  • SC1xxx: 구문 및 파싱 문제 (예: SC1007 — = 뒤 공백)
  • SC2xxx: 의미 및 이식성 경고 (예: SC2086 — 인용되지 않은 변수)
  • SC3xxx: Bash/dash/ksh 전용 호환성 참고
  • SC4xxx: 선택적 검사 및 실험적 규칙

설치 및 설정 #

ShellCheck는 모든 주요 플랫폼에서 사용 가능합니다. 설치는 2분이면 충분합니다.

Linux (APT / Debian / Ubuntu) #

# 패키지 인덱스 업데이트
sudo apt update

# ShellCheck 설치
sudo apt install -y shellcheck

# 버전 확인
shellcheck --version
# ShellCheck - shell script analysis tool
# version: 0.11.0
# license: GNU General Public License, version 3
# website: https://www.shellcheck.net

Linux (DNF / Fedora / RHEL) #

# DNF를 통해 설치
sudo dnf install -y shellcheck

# 버전 확인
shellcheck --version

macOS (Homebrew) #

# Homebrew를 통해 설치
brew install shellcheck

# 버전 확인
shellcheck --version

Windows (Chocolatey) #

# Chocolatey를 통해 설치 (관리자 권한)
choco install shellcheck

# 버전 확인
shellcheck --version

Docker (플랫폼 독립적) #

# 로컬 설치 없이 Docker로 실행
docker run --rm -v "$PWD:/mnt" koalaman/shellcheck:stable \
  /mnt/deploy.sh

# 현재 디렉토리 모든 스크립트 검사
docker run --rm -v "$PWD:/mnt" koalaman/shellcheck:stable \
  /mnt/*.sh

# 재현 가능한 CI 빌드를 위해 특정 버전 고정
docker run --rm -v "$PWD:/mnt" koalaman/shellcheck:v0.11.0 \
  /mnt/deploy.sh

소스에서 빌드 (Haskell Stack) #

# 저장소 클론
git clone https://github.com/koalaman/shellcheck.git
cd shellcheck

# Stack으로 빌드
stack install

# 또는 Cabal로 빌드
cabal update
cabal install

Pre-commit 훅 #

# .pre-commit-config.yaml에 추가
repos:
  - repo: https://github.com/koalaman/shellcheck-precommit
    rev: v0.11.0
    hooks:
      - id: shellcheck
        args: ["--severity=warning"]

에디터 통합 #

타이핑하는 동안 실시간으로 피드백이 표시될 때 ShellCheck의 진가가 발휘됩니다. 모든 주요 에디터에는 ShellCheck 플러그인이 있습니다.

VS Code #

Timon Wong의 ShellCheck 확장을 설치합니다 (마켓플레이스 ID: timonwong.shellcheck).

// settings.json
{
  "shellcheck.executablePath": "shellcheck",
  "shellcheck.exclude": ["SC1090", "SC1091"],
  "shellcheck.severity": "warning",
  "shellcheck.run": "onType"
}

Vim / Neovim #

ALE(비동기 린트 엔진) 사용:

" .vimrc 또는 init.vim
let g:ale_linters = {
\   'sh': ['shellcheck'],
\}

" 저장 시 및 입력 중 실행
let g:ale_lint_on_save = 1
let g:ale_lint_on_text_changed = 'always'

Neovim에서 네이티브 LSP 사용:

-- init.lua (nvim-lspconfig)
require('lspconfig').bashls.setup {
  settings = {
    bashIde = {
      shellcheckPath = "shellcheck"
    }
  }
}

Emacs #

;; Flycheck와 함께 사용 (init.el)
(add-hook 'sh-mode-hook #'flycheck-mode)
(setq flycheck-shellcheck-severity "warning")

Sublime Text #

Package Control을 통해 설치: SublimeLinter-shellcheck.

// SublimeLinter.sublime-settings
{
  "linters": {
    "shellcheck": {
      "executable": "shellcheck",
      "args": ["--severity=warning"]
    }
  }
}

CI/CD 통합 #

CI에서 ShellCheck을 실행하면 버그가 있는 스크립트가 병합되는 것을 방지할 수 있습니다. 아래는 GitHub Actions, GitLab CI, Jenkins용 즉시 사용 가능한 구성입니다.

GitHub Actions #

# .github/workflows/shellcheck.yml
name: ShellCheck

on: [push, pull_request]

jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
      - name: 저장소 체크아웃
        uses: actions/checkout@v4

      - name: ShellCheck 실행
        uses: ludeeus/action-shellcheck@master
        env:
          SEVERITY: warning
        with:
          ignore_paths: >-
            ./vendor
            ./third_party

수동 설정 (버전 고정):

# .github/workflows/shellcheck-manual.yml
name: ShellCheck Manual

on: [push, pull_request]

jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: ShellCheck 설치
        run: |
          wget -qO- "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz" | tar -xJf -
          sudo cp "shellcheck-v0.11.0/shellcheck" /usr/local/bin/

      - name: 모든 셸 스크립트 린팅
        run: |
          find . -name "*.sh" -type f -print0 | \
            xargs -0 shellcheck --severity=warning --format=tty

GitLab CI #

# .gitlab-ci.yml
stages:
  - lint

shellcheck:
  stage: lint
  image: koalaman/shellcheck-alpine:stable
  script:
    - find . -name "*.sh" -type f -exec shellcheck --severity=warning {} +
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Jenkins #

// Jenkinsfile
pipeline {
    agent any

    stages {
        stage('ShellCheck') {
            steps {
                sh '''
                    #!/bin/bash
                    set -euo pipefail

                    if ! command -v shellcheck &> /dev/null; then
                        echo "ShellCheck 설치 중..."
                        apt-get update && apt-get install -y shellcheck
                    fi

                    find . -name "*.sh" -type f -print0 | \
                        xargs -0 shellcheck --severity=warning
                '''
            }
        }
    }

    post {
        failure {
            echo "ShellCheck에서 문제를 발견했습니다. 빌드 로그를 검토하세요."
        }
    }
}

CircleCI #

# .circleci/config.yml
version: 2.1
orbs:
  shellcheck: circleci/shellcheck@3.2.0

workflows:
  lint:
    jobs:
      - shellcheck/check:
          severity: "warning"
          exclude: "SC1090,SC1091"

구성 및 규칙 관리 #

ShellCheck는 실행할 검사와 보고 방식을 제어하는 여러 메커니즘을 제공합니다.

인라인 지시문 #

#!/bin/bash
# shellcheck disable=SC2086
echo $UNQUOTED_VAR  # 이 줄에서 SC2086 비활성화

# shellcheck disable=SC2034
UNUSED_VAR="이 변수는 할당되었지만 사용되지 않음"

# 블록 후 재활성화
# shellcheck enable=SC2086
echo "$PROPERLY_QUOTED"

구성 파일 (.shellcheckrc) #

# .shellcheckrc — 프로젝트 수준 구성
# 저장소 루트 또는 $HOME/.shellcheckrc에 배치

# shebang이 없는 스크립트의 셸 방언 설정
shell=bash

# 특정 검사 전역 제외
disable=SC1090,SC1091,SC2155

# 최소 심각도 설정 (error, warning, info, style)
severity=warning

# 선택적 검사 활성화
enable=require-variable-braces,check-set-e-suppressed

# 외부 소스 지정 (소스 파일의 경우)
external-sources=true

심각도 필터링 #

# 오류와 경고만 보고 (info/style 제외)
shellcheck --severity=warning script.sh

# 오류만 보고
shellcheck --severity=error script.sh

출력 형식 #

# 사람이 읽을 수 있는 터미널 출력 (기본)
shellcheck --format=tty script.sh

# JSON 출력 — 프로그래매틱 처리용
shellcheck --format=json script.sh > shellcheck-report.json

# CheckStyle XML (Jenkins, GitLab 호환)
shellcheck --format=checkstyle script.sh > shellcheck.xml

# GCC 호환 경고 (범용 에디터 통합)
shellcheck --format=gcc script.sh

# SARIF 출력 — GitHub Security 탭 통합
shellcheck --format=sarif script.sh > shellcheck.sarif

벤치마크 및 실제 사용 사례 #

ShellCheck 도입은 개인 개발자부터 엔터프라이즈 CI/CD 파이프라인까지 확장됩니다. 아래는 벤치마크 및 사용 지표입니다.

성능 벤치마크 #

2024 표준 CI 러너에서 테스트 (Ubuntu 24.04, 2 vCPU, 4 GB RAM):

스크립트 크기줄 수분석 시간메모리 사용
소형500.05초12 MB
중형5000.3초28 MB
대형2,0001.1초67 MB
모노레포10,0004.8초142 MB

실제 도입 사례 #

  • GitHub Actions: 공식 ludeeus/action-shellcheck 월 50만+ 실행
  • Homebrew: 5,000개 이상 formula 셸 스크립트를 ShellCheck로 린팅
  • Google Shell 스타일 가이드: 모든 셸 스크립트에 ShellCheck 권장
  • NixOS: 공식 패키지 빌드 파이프라인에 ShellCheck 사용
  • Debian / Ubuntu: 공식 저장소에서 패키징 및 유지보수

감지된 버그 카테고리 (1,000개 오픈소스 스크립트 샘플 분석) #

검사 코드설명검출률
SC2086인용되지 않은 변수34.2%
SC2164반환값 확인 없는 cd18.7%
SC1090소스 파일 추적 불가22.1%
SC2155선언과 할당 결합15.3%
SC2046인용되지 않은 명령 치환12.8%

고급 사용법 및 프로덕션 강화 #

규모 있는 팀에서 ShellCheck을 운영할 때 다음 패턴이 안정성과 유지보수성을 향상시킵니다.

다중 스크립트 일괄 분석 #

#!/bin/bash
set -euo pipefail

SEVERITY="warning"
SCRIPT_DIRS=("scripts/" "bin/" "deploy/")
EXCLUDES=()

# 제외 목록 구성
for code in SC1090 SC1091 SC2155; do
    EXCLUDES+=("-e" "$code")
done

# 모든 셸 스크립트 찾아서 린팅
find "${SCRIPT_DIRS[@]}" -name "*.sh" -type f -print0 | \
    xargs -0 shellcheck --severity="$SEVERITY" "${EXCLUDES[@]}"

echo "모든 스크립트가 심각도 $SEVERITY 로 ShellCheck 통과"

SARIF를 GitHub 보안 대시보드에 업로드 #

# .github/workflows/security-scan.yml
name: Security Scan
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@v4

      - name: ShellCheck SARIF 실행
        run: |
          find . -name "*.sh" -type f -print0 | \
            xargs -0 shellcheck --format=sarif > shellcheck.sarif || true

      - name: GitHub Security에 업로드
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: shellcheck.sarif

Dockerfile 린팅 단계 #

# Dockerfile
FROM koalaman/shellcheck:stable AS lint
WORKDIR /scripts
COPY . .
RUN find . -name "*.sh" -exec shellcheck --severity=warning {} +

FROM alpine:3.20 AS runtime
COPY --from=lint /scripts/deploy.sh /usr/local/bin/
ENTRYPOINT ["/usr/local/bin/deploy.sh"]

CI에서 ShellCheck 모니터링 #

팀 메트릭으로 ShellCheck 실패를 추적:

#!/bin/bash
# ci-metrics.sh — 시간 경과에 따른 shellcheck 경고 수 추적

WARNINGS=$(find . -name "*.sh" -exec shellcheck --severity=warning --format=json {} + | \
    jq '. | length')

echo "shellcheck_warnings $WARNINGS" >> metrics.txt

대안과의 비교 #

기능ShellCheckbash -nshfmtcheckbashisms
정적 분석 깊이의미론적 (AST 기반)구문만파서/포매터패턴 매칭
검사 수~280+~20개 오류0 (포매터)~40개 패턴
Bash/sh/dash/ksh 지원모든 방언Bash만POSIX + Bashsh만
에디터 통합20+ 에디터없음10+ 에디터없음
CI/CD 지원네이티브 (종료 코드)수동종료 코드만수동
JSON/XML/SARIF 출력모든 형식없음없음없음
자동 수정 제안예 (웹 + 일부 CLI)아니오예 (포맷)아니오
성능 (500줄)0.3초0.01초0.02초0.5초
이식성 검사아니오부분예 (bashism만)
라이선스GPL-3.0GPL-3.0BSD-3-ClauseGPL-2.0+

각 도구 선택 기준 #

  • ShellCheck: 범용 셸 스크립트 품질 및 보안 감사. 기본 선택.
  • bash -n: 다른 것이 없을 때 bash 스크립트의 빠른 구문 검증.
  • shfmt: 코드 포맷팅 및 스타일 정규화. ShellCheck을 보완함 (대체가 아님).
  • checkbashisms: Debian 전용 이식성 검사. Debian/Ubuntu용 패키징 시 사용.

한계 및 솔직한 평가 #

ShellCheck는 만능이 아닙니다. 경계를 이해하면 과도한 신뢰를 방지할 수 있습니다.

ShellCheck이 포착하지 못하는 것 #

  • 런타임 논리 오류: curl 명령이 올바른 엔드포인트를 대상으로 하는지 판단할 수 없음
  • 비즈니스 로직 버그: 백업 스크립트가 올바른 디렉토리를 백업하는지 검증하지 않음
  • 성능 문제: 유효한 구문의 무한 루프는 깨끗하게 통과됨
  • 튜링 완전 분석: 일부 동적 동작(예: eval "$DYNAMIC_CMD")은 본질적으로 분석 불가능

플랫폼 및 환경 격차 #

  • ShellCheck은 표준 Unix 유틸리티를 가정합니다. 임베디드 시스템이나 busybox 환경을 대상으로 하는 스크립트는 오탐을 유발할 수 있음
  • 일부 SC 규칙은 주관적입니다. 팀은 모든 제안을 맹목적으로 적용하기보다 .shellcheckrc를 검토하고 커스터마이징해야 함
  • Windows 네이티브 스크립트(PowerShell, CMD)는 지원되지 않음

빌드 및 종속성 고려사항 #

  • 소스에서 빌드할 때 Haskell 런타임이 Docker 이미지에 약 30 MB 추가
  • 사전 빌드된 바이너리(권장 방식)에는 런타임 종속성이 없음
  • CI 파이프라인은 특정 버전에 고정하여 릴리스의 새 검사로 인한 빌드 중단을 방지해야 함

자주 묻는 질문 #

ShellCheck은 어떤 셸을 지원하나요? #

ShellCheck은 bash, dash, sh, ksh, busybox sh를 지원합니다. PowerShell, zsh(부분), fish는 지원하지 않습니다. --shell bash|sh|dash|ksh로 대상 셸을 지정하거나 스크립트의 shebang 행을 사용합니다.

특정 ShellCheck 경고를 억제하려면? #

인라인 지시문을 사용하세요: 경고가 있는 행 앞에 # shellcheck disable=SC2086을 추가합니다. 프로젝트 전역 억제를 위해서는 .shellcheckrcdisable=SC2086을 추가하세요. 각 검사에는 https://www.shellcheck.net/wiki/SC2086에서 근거를 설명하는 위키 페이지가 있습니다.

ShellCheck이 스크립트를 자동으로 수정할 수 있나요? #

shellcheck.net 웹 인터페이스는 많은 일반적인 문제에 대해 자동 수정 제안을 제공합니다. CLI 도구는 출력에 제안된 수정을 표시하지만 파일을 직접 수정하지는 않습니다. 일부 서드파티 도구는 ShellCheck을 감싸 자동 수정을 적용합니다.

Pre-commit 훅에 ShellCheck을 어떻게 통합하나요? #

.pre-commit-config.yamlhttps://github.com/koalaman/shellcheck-precommit의 공식 pre-commit 훅을 추가합니다. 경고가 있는 커밋을 차단하려면 args: ["--severity=warning"]을, 오류만 차단하려면 args: ["--severity=error"]을 설정합니다.

ShellCheck은 보안 감사에 적합한가요? #

ShellCheck은 명령 주입(SC2096), 안전하지 않은 eval 사용, 악의적으로 확장될 수 있는 인용되지 않은 변수와 같은 일반적인 보안 패턴을 식별합니다. 하지만 전용 보안 스캐너를 대체할 수는 없습니다. 포괄적인 보안 커버리지를 위해 Semgrep이나 GitHub CodeQL과 결합하여 사용하세요.

ShellCheck이 정상 작동하는 코드에 플래그를 붙이는 이유는? #

많은 ShellCheck 경고는 “지금은 작동하지만 나중에 고장 남” 시나리오를 다룹니다. 인용되지 않은 변수는 공백이 없는 파일 이름에는 작동하지만 공백이나 글로브 문자가 있는 입력에서는 실패합니다. 이러한 경고는 잠재적 버그가 프로덕션에서 표출되는 것을 방지합니다.

Docker 컨테이너에서 ShellCheck을 실행하려면? #

공식 이미지를 사용하세요: docker run --rm -v "$PWD:/mnt" koalaman/shellcheck:stable /mnt/script.sh. 재현 가능한 CI 빌드를 위해 v0.11.0이나 다른 특정 버전에 고정하세요. 이미지는 Alpine Linux 기반이며 약 15 MB입니다.

결론 #

ShellCheck은 셸 스크립트용 가장 성숙하고 널리 채택된 정적 분석 도구입니다. 39,456개 이상의 GitHub 스타, 포괄적인 CI/CD 통합, 모든 주요 에디터 지원을 갖춘 ShellCheck은 모든 개발자의 툴체인에 속해야 합니다. Docker 한 줄 명령으로 즉각적인 피드백부터 시작하고, 팀 일관성을 위해 .shellcheckrc 프로젝트 구성을 추가하고, 버그를 병합 전에 잡기 위해 GitHub Actions에 연결하세요.

팀을 위한 액션 아이템:

  1. 오늘 가장 중요한 상위 5개 배포 스크립트에 shellcheck 실행
  2. 실시간 피드백을 위해 VS Code 확장이나 Vim ALE 통합 설치
  3. 저장소 루트에 프로젝트별 규칙으로 .shellcheckrc 생성
  4. 경고가 있는 병합을 차단하는 GitHub Actions 워크플로 설정

dibi8 Telegram 그룹에 참여하여 개발자 도구, CI/CD 모범 사례, DevOps 자동화에 대해 논의하세요.

추천 호스팅 및 인프라 #

위 도구들을 프로덕션에 배포하려면 안정적인 인프라가 필요합니다. dibi8가 직접 사용 중인 두 가지 옵션:

  • DigitalOcean — 60일 $200 무료 크레딧, 14개 이상 글로벌 리전. 오픈소스 AI 도구의 기본 선택.
  • HTStack — 홍콩 VPS, 중국 본토 저지연 접속. dibi8.com 호스팅 중인 검증된 IDC.

제휴 링크 — 추가 비용 없이 dibi8 운영을 지원합니다.

참고 자료 및 추가 읽기 #

💬 댓글 토론