얕은 클론이 가져오는 정적 분석의 실패

GitHub Actions를 비롯한 현대적인 CI 파이프라인은 효율성을 위해 저장소 체크아웃 시 기본값으로 얕은 클론(Shallow Clone)을 적용하는 경우가 많다. actions/checkout@v4 액션의 기본 동작은 전체 히스토리를 가져오는 것이 아니라 최근 커밋만 가져오는 것이다. 이는 대용량 저장소의 빌드 시간을 단축하는 데 효과적이지만, 저장소 내의 파일 이력을 추적해야 하는 정적 분석 도구나 주제 생성 스크립트에게는 치명적인 결함이 된다.

이 저장소의 .github/workflows/auto_post.yml 파일을 보면, 코드 리뷰 및 주제 생성 과정에서 전체 히스토리가 필요하다는 전제가 명확히 드러난다. 만약 기본값인 depth: 1을 유지한다면, 과거의 커밋 메시지를 탐색하여 새로운 주제 후보를 추출하는 로직은 단 한 건의 커밋만 보게 되어 기능 자체가 마비된다. 이는 단순한 성능 최적화가 아니라, 파이프라인의 핵심 논리를 차단하는 설정 오류다.

본문에서 다루는 설정은 scripts/auto_post.py 스크립트가 실행될 때 필요한 데이터의 완전성을 보장하기 위한 것이다. 이 스크립트는 과거의 주제 기록(posted_topics.json)과 커밋 이력을 함께 참조하여 중복되지 않는 새로운 주제를 생성한다. 따라서 CI 환경에서 이 설정이 올바르게 작동하려면, 체크아웃 단계의 설정이 스크립트의 요구사항과 일치해야 한다.

워크플로우 파일에서의 명시적 설정

GitHub Actions의 기본 체크아웃 액션은 성능을 위해 depth: 1을 기본값으로 한다. 하지만 이 저장소의 워크플로우 파일인 .github/workflows/auto_post.yml에서는 이를 명시적으로 변경하여 문제를 해결했다. 파일의 1단계(저장소 체크아웃) 설정을 살펴보면 다음과 같은 코드가 적용되어 있다.

      - name: 1. 저장소 체크아웃!
        uses: actions/checkout@v4
        with:
          # 커밋 이력에서 주제를 뽑으므로 얕은 클론이면 후보가 1개뿐이다.
          # 기본값(depth 1)에서는 이 기능이 통째로 죽는다.
          fetch-depth: 200

이 설정은 가장 최근 200개 커밋의 히스토리를 가져오도록 지시한다. fetch-depth: 200을 적용함으로써, 스크립트는 과거의 주제 목록과 최근의 코드 변경 사항을 모두 확보할 수 있다. 만약 이 값을 지정하지 않으면, 스크립트 내부에서 히스토리를 탐색하는 로직은 빈 데이터나 극히 제한된 데이터만 처리하게 되어 실패하거나 잘못된 결과를 산출한다.

이 설정의 핵심은 “필요한 만큼만” 가져오는 균형이다. 200이라는 수치는 이 저장소의 주제 생성 빈도와 중복 검사 주기(Topic Lookback)를 고려하여 결정된 값이다. 너무 작은 값은 데이터 누락을 초래하고, 너무 큰 값은 빌드 시간만 지연시킨다. 워크플로우 파일의 주석이 명시하듯, 기본값을 방치하면 “이 기능이 통째로 죽는다”는 점은 반드시 인지해야 한다.

스크립트 내부의 데이터 의존성 분석

scripts/auto_post.py 파일의 내용을 분석하면, 이 스크립트가 Git 히스토리에 얼마나 깊게 의존하고 있는지 확인할 수 있다. 히스토리에 직접 의존하는 것은 GIT_TOPIC_LOOKBACK 하나다.

POSTED_TOPICS_PATH = "scripts/posted_topics.json"
# ...
GIT_TOPIC_LOOKBACK = 120

GIT_TOPIC_LOOKBACK = 120은 git log -120으로 최근 120개 커밋을 읽어 글감을 뽑는 범위다. 커밋 제목과 그 커밋이 건드린 파일을 짝지어 주제 후보로 쓴다. 따라서 fetch-depth가 120보다 작으면 후보 수가 그만큼 줄고, 기본값인 1이면 후보가 사실상 하나만 남는다.

여기서 구분할 것이 있다. 중복 검사는 이 상수와 무관하다. 중복은 scripts/posted_topics.json에 쌓인 발행 이력과 is_topic_duplicate가 판정하며, 그 파일은 얕은 클론에서도 HEAD 시점 내용이 그대로 들어 있다. fetch-depth가 영향을 주는 것은 “무엇을 쓸까”를 정하는 재료의 양이지, “이미 쓴 것인가”를 판정하는 근거가 아니다.

즉 얕은 클론의 피해는 조용하다. 스크립트는 오류 없이 끝나고, 다만 고를 수 있는 글감이 거의 없어진다. 실패가 아니라 빈곤으로 나타나므로 로그만 보고는 알아채기 어렵다.

워크플로마다 값이 다른 이유

이 저장소의 워크플로 여덟 개는 fetch-depth를 제각각 쓴다. 통일해야 할 것처럼 보이지만, 각자 필요한 이력의 양이 다르기 때문에 그대로 두는 것이 맞다.

워크플로값그 값인 이유
auto_post.yml200최근 120개 커밋을 읽어 글감을 뽑는다. 여유를 둔 값
ci.yaml0 (전체)커밋 이력을 쓰는 테스트가 있어 얕으면 건너뛴다
build-preview.yaml0 (전체)빌드 산출물 비교에 이전 상태가 필요하다
docker-build-push.yaml1현재 트리만 이미지에 넣는다. 이력이 필요 없다
나머지 4개미지정기본값 1. 이력을 읽지 않으므로 문제가 없다

정하는 기준은 하나다. 그 잡이 git log나 git diff로 과거를 읽는가. 읽지 않으면 기본값 1이 가장 빠르고, 읽는다면 필요한 범위보다 넉넉하게 잡는다. 전부 0으로 맞추면 안전하지만 큰 저장소에서는 체크아웃만으로 시간을 버린다.

  • 이력을 읽지 않는 잡: 지정하지 않는다
  • 정해진 개수를 읽는 잡: 그 수보다 크게 잡는다
  • git describe나 태그 기반 버전을 쓰는 잡: 전체(0)가 필요하다
  • 값을 정한 자리에는 이유를 주석으로 남긴다 — 숫자만 있으면 다음 사람이 줄여도 되는지 알 수 없다

재현 가능한 측정 순서

설정이 제대로 적용되었는지 확인하기 위해서는 CI 실행 로그와 로컬 환경에서의 테스트를 통해 데이터의 완전성을 검증해야 한다. 다음 절차는 워크플로우 실행 시 실제 가져온 커밋 수와 스크립트의 동작 범위를 측정하는 방법이다.

시점실행할 명령결과가 나쁘면 할 일
워크플로우 실행 직후`git log —onelinewc -l`
스크립트 실행 전ls scripts/posted_topics.json파일이 없으면 초기화 로직 확인
스크립트 실행 중로그에서 GIT_TOPIC_LOOKBACK 값 확인값이 120이 아니면 상수 수정
  1. 워크플로우 실행 직후 확인: GitHub Actions의 체크아웃 단계가 끝난 후, 터미널에서 git log --oneline | wc -l 명령을 실행한다. 출력값이 200에 가깝다면 fetch-depth: 200 설정이 정상적으로 작동한 것이다. 만약 1이 나온다면 기본값이 적용되어 실패한 것이다.
  2. 스크립트 실행 전 파일 확인: scripts/posted_topics.json 파일이 존재하는지 확인한다. 얕은 클론 시 이 파일의 이전 버전이 로드되었을 수 있으므로, 최신 상태인지 확인해야 한다.
  3. 스크립트 내 상수 확인: scripts/auto_post.py 파일에서 GIT_TOPIC_LOOKBACK 값이 120으로 설정되어 있는지 확인한다. 이 값이 워크플로우의 fetch-depth보다 크면 데이터 누락이 발생하므로, 두 값의 균형을 맞춰야 한다.

이 방법이 통하지 않는 경우

fetch-depth 설정은 전체 히스토리가 필요한 경우에 효과적이지만, 모든 상황에 만능은 아니다. 저장소의 크기가 매우 크거나, 히스토리가 수천 개에 달하는 경우, 200이라는 고정된 값으로는 부족할 수 있다. 또한, 특정 브랜치만 추적해야 하는 경우에는 다른 접근 방식이 필요할 수 있다.

  1. 초대형 저장소: 저장소의 크기가 수 GB 이상이고 커밋 수가 수만 개에 달하는 경우, fetch-depth: 200으로도 충분한 데이터를 확보하지 못할 수 있다. 이 경우 fetch-depth: 0을 사용하여 전체 히스토리를 가져오거나, shallow-since 옵션을 사용하여 특정 시점 이후의 히스토리만 가져오는 방식을 고려해야 한다.
  2. 다중 브랜치 분석: 여러 브랜치의 히스토리를 동시에 분석해야 하는 경우, 기본 체크아웃 설정으로는 모든 브랜치의 히스토리를 확보하기 어려울 수 있다. 이 경우 fetch-depth 설정과 함께 ref 옵션을 사용하여 특정 브랜치를 지정하거나, submodules 설정을 추가로 조정해야 할 수 있다.
  3. 실시간 데이터 요구: CI 환경에서 실시간으로 변경되는 파일의 이력을 추적해야 하는 경우, 얕은 클론 설정이 오히려 데이터를 누락시킬 수 있다. 이 경우 스크립트 내에서 Git 명령어를 호출할 때 --follow 옵션을 사용하여 파일의 이동 이력까지 추적해야 한다.

본 설정은 이 저장소의 특정 구조(주제 생성 및 중복 검사 로직)에 최적화된 것이다. 다른 프로젝트에 적용할 때는 해당 프로젝트의 데이터 요구사항과 히스토리 구조를 먼저 분석한 후, 적절한 fetch-depth 값을 결정해야 한다.

공식 문서에서는 Git의 얕은 클론 기능과 GitHub Actions의 체크아웃 액션에 대한 자세한 설정 옵션을 제공하고 있다. 관련 내용은 아래 링크에서 확인할 수 있다.

📦추천 상품🔒 개인정보 수집 없음

쿠팡 로켓배송 특가 & 가성비 추천 제품 확인

이 글에서 소개하거나 추천하는 IT 기기, 가공식품, 가성비 필수 꿀템을 쿠팡 로켓배송 최저가로 빠르게 만나보세요.

쿠팡 최저가 확인하기 →