How Developers Adopt, Use, and Evolve CI/CD Caching: An Empirical Study on GitHub Actions
이 논문은 GitHub Actions 의 CI/CD 캐싱을 도입하고 유지보수하는 개발자들의 실제 행태를 952 개 저장소를 대상으로 실증적으로 분석하여, 캐싱의 활용 패턴, 진화 양상, 그리고 유지보수 동인을 규명하고 이를 개선하기 위한 기회와 도구의 필요성을 제시합니다.
원저자:Kazi Amit Hasan, Yuan Tian, Safwat Hassan, Steven H. H. Ding
캐싱이 없는 상황: 매번 요리를 할 때마다 재료 (의존성) 를 다시 사오고, 칼을 다시 갈고, 냄비를 씻는 과정을 반복합니다. 이렇게 하면 시간이 너무 오래 걸려요.
캐싱이 있는 상황: 요리를 할 때, 이미 다 손질해 둔 재료를 냉장고 (캐시) 에 넣어둡니다. 다음에 같은 요리를 할 때는 냉장고에서 꺼내서 바로 쓰면 되죠. 이렇게 하면 요리 (빌드) 시간이 획기적으로 줄어듭니다.
이 논문은 **"개발자들이 이 '냉장고'를 어떻게 쓰고, 어떻게 관리하는지"**를 952 개의 프로젝트 (약 266 개는 냉장고를 쓰고, 686 개는 안 씀) 를 분석해서 밝혀냈습니다.
🔍 주요 발견 사항 (3 가지 핵심 이야기)
1. 누가 냉장고를 잘 쓸까? (적용 현황)
인기 있는 식당일수록 냉장고를 잘 써요: 연구 결과, 인기 있고 활동이 활발한 프로젝트일수록 냉장고를 더 잘 활용했습니다. (별이 많고, 개발자 수가 많고, 코드가 자주 바뀔수록 필요하기 때문이죠.)
언어마다 선호도가 다릅니다: PHP 나 Java 를 쓰는 식당은 냉장고를 아주 잘 쓰지만, Python 이나 Ruby 를 쓰는 곳은 상대적으로 덜 썼습니다.
어디에 가장 많이 쓰일까? 가장 많이 쓰는 곳은 **'요리 준비 (빌드)'**와 '맛보기 (테스트)' 단계입니다. 재료를 많이 다루는 곳에서 냉장고를 가장 아끼는 거죠.
2. 냉장고는 한 번만 설치하면 끝일까? (진화 과정)
아니요, 계속 수리하고 고쳐야 해요: 많은 사람들은 냉장고를 한 번 설치하면 끝이라고 생각하지만, 실제로는 지속적인 관리가 필요합니다.
자주 바뀌는 것: '요리 준비'나 '맛보기' 단계에서는 매일, 혹은 몇 시간마다 냉장고의 위치나 정리법을 고칩니다. ("아, 이 재료는 여기 넣는 게 더 빠르네?", "이건 버리고 저걸 넣어야겠다" 같은 식으로요.)
안 바뀌는 것: '마무리 (릴리스)' 단계는 한 번 설정하면 오랫동안 그대로 둡니다.
실패하고 다시 시도: 개발자들은 처음 냉장고를 설정했다가 안 되면, 바로 지우고 다시 설정하는 과정을 반복합니다. 마치 "이제 이걸로 해보자, 아니 그건 안 되네, 저걸로 해보자"를 반복하는 것과 같습니다.
3. 누가 냉장고를 고치나? (수정 원인)
사람 (개발자) vs 로봇 (봇):
로봇의 역할: 로봇은 주로 냉장고의 '버전'을 업데이트할 때만 나옵니다. (예: "이 냉장고 모델이 구식이니 새 모델로 바꿔주세요"라고 알림을 줍니다.)
사람의 역할: 하지만 냉장고 안의 내용물을 정리하고, 위치를 바꾸고, 고장 나면 고치는 일은 거의 사람이 합니다.
왜 고치나요? 대부분 "요리가 안 돼서 (에러 발생)" 또는 "더 빨리 하려고 (성능 개선)" 고칩니다. 특히 "이 재료를 어디에 넣어야 더 빨리 꺼낼 수 있을까?"를 고민하며 매우 자주 수정합니다.
💡 이 연구가 우리에게 주는 교훈
냉장고는 '설치'가 아니라 '관리'입니다: 캐싱을 켜기만 하면 끝나는 게 아니라, 프로젝트가 커질수록 계속 손봐야 하는 '살아있는 시스템'입니다.
사람의 노력이 가장 큽니다: 자동화 도구 (봇) 가 버전만 올려줄 뿐, 실제로 냉장고를 효율적으로 만드는 건 개발자의 고된 수고입니다.
미래의 도구: 앞으로는 개발자가 일일이 냉장고 위치를 고칠 필요 없이, "어떤 재료를 어디에 넣으면 가장 빠를지" 자동으로 알려주는 똑똑한 비서가 필요하다는 결론입니다.
📝 한 줄 요약
"개발자들은 소프트웨어를 빨리 만들기 위해 '디지털 냉장고 (캐싱)'를 쓰지만, 이 냉장고는 한 번 설치하고 끝나는 게 아니라, 개발자들이 매일매일 고치고 정리하며 관리해야 하는 귀찮지만 필수적인 작업입니다."
논문 요약: GitHub Actions 에서 개발자가 CI/CD 캐싱을 어떻게 채택, 사용 및 진화시키는지에 대한 실증 연구
이 논문은 GitHub Actions (GHA) 워크플로우에서 CI/CD 캐싱의 채택, 사용 패턴, 그리고 시간에 따른 진화 양상을 분석한 최초의 대규모 실증 연구입니다. 캐싱은 반복적인 계산을 줄이고 CI/CD 효율성을 높이는 핵심 기술이지만, 효과적인 캐싱 유지를 위해서는 지속적인 관리 노력이 필요하다는 점을 강조합니다.
1. 연구 배경 및 문제 정의 (Problem)
배경: 현대 소프트웨어 개발은 CI/CD 파이프라인에 의존하고 있으며, 프로젝트가 커짐에 따라 의존성 재설치 및 중간 결과물 재빌드와 같은 반복 작업으로 인해 빌드 시간이 지연되는 문제가 발생합니다. 이를 해결하기 위해 GitHub Actions 는 캐싱 메커니즘을 제공합니다.
문제: 캐싱은 단순한 성능 최적화 도구가 아니라, 적절한 시점에 적용할지, 어떤 아티팩트를 저장할지, 그리고 캐시 키 (key) 를 어떻게 설계할지 등 복잡한 의사결정이 필요한 유지보수 과제입니다.
부적절한 캐시 키 설계는 캐시 미스 (cache miss) 를 유발하여 오히려 성능 저하를 초래할 수 있습니다.
기존 연구들은 캐싱을 '일회성 설정'이나 단순한 최적화 전략으로만 다루었으며, 실제 개발 환경에서 캐싱 설정이 어떻게 진화하고 유지보수되는지에 대한 심층적인 분석이 부족했습니다.
목표: GHA 워크플로우에서 캐싱 설정이 어떻게 채택되고, 시간이 지남에 따라 어떻게 진화하며, 이러한 변경의 동기는 무엇인지 규명하는 것입니다.
2. 연구 방법론 (Methodology)
연구팀은 GitHub 의 952 개 저장소 (GHA 사용) 를 대상으로 데이터를 수집하고 분석했습니다.
데이터셋:
총 저장소: 952 개 (캐싱 채택 266 개, 비채택 686 개).
분석 범위: 1,556 개의 워크플로우 파일, 10,373 개의 커밋, 17,185 개의 워크플로우 설정 변경 사항 (이 중 2,494 개는 캐싱 관련).
기간: 2025 년 5 월 5 일까지의 커밋 히스토리.
데이터 수집 및 전처리:
Step 1: GitHub GraphQL API 를 통해 저장소 메타데이터 (별점, 포크, 기여자 수 등) 수집.
Step 2:actions/cache, 패키지 매니저 설정 (setup-*), Docker 레이어 캐싱 등 3 가지 방식을 통해 캐싱 채택 여부 판별.
Step 3: Gigawork 도구를 사용하여 워크플로우 히스토리 재구성.
Step 4: 개발자가 정의한 작업 (Job) 이름을 8 가지 CI/CD 유형 (build, test, integration, lint, release, linux, analyze, sync) 으로 정규화.
Step 5: 캐싱 관련 유지보수 활동을 7 가지 범주 (캐싱 활성화, 버전 업데이트, 추가, 제거, 파라미터 업데이트, 추가, 제거) 로 분류.
연구 질문 (RQs):
RQ1: 캐싱을 채택한 저장소의 특성은 무엇인가?
RQ2: 다양한 CI/CD 작업 유형별로 캐싱 설정은 어떻게 진화하는가?
RQ3: 개발자가 GitHub Actions 워크플로우에서 캐싱 관련 수정을 수행하는 이유는 무엇인가?
3. 주요 결과 (Key Results)
RQ1: 캐싱 채택 저장소의 특성
활발한 프로젝트: 캐싱을 채택한 저장소는 비채택 저장소보다 기여자 수, 커밋 수, 별점, 포크 수 등 커뮤니티 활동이 더 활발하고 인기가 높았습니다.
언어별 차이: PHP 와 Java 프로젝트에서 캐싱 채택률이 가장 높았으며 (각각 54.2%, 50.7%), Python 과 Ruby 는 상대적으로 낮았습니다.
작업 유형별 분포: 캐싱은 주로 빌드 (build) 및 테스트 (test) 작업에서 가장 많이 사용되었습니다.
캐싱 전략: **명시적 캐싱 (actions/cache)**이 전체의 70.9% 로 가장 우세했으며, 패키지 매니저 캐싱 (24.5%) 이 그 뒤를 이었습니다.
RQ2: 캐싱 설정의 진화 패턴
반복적인 유지보수: 캐싱 설정은 일회성 설정이 아니라, 지속적인 업데이트, 추가, 제거가 반복되는 진화 과정입니다.
작업 유형별 차이:
빌드 및 테스트 작업: 파라미터 업데이트 (Parameter update) 가 매우 빈번하고 빠르게 발생하며 (중앙값 2~4 일), 이는 초기 설정을 안정화하기 위한 반복적인 튜닝을 의미합니다.
릴리스 및 통합 작업: 변경 주기가 길고 (중앙값 60~87 일), 설정이 일단 안정화되면 오랫동안 수정되지 않습니다.
자기 순환 (Self-loop): 많은 작업 유형에서 파라미터 업데이트 → 파라미터 업데이트와 같은 자기 순환 전이가 우세하여, 개발자가 동일한 상태 내에서 지속적으로 설정을 미세 조정함을 보여줍니다.
제거와 재추가: 캐시를 제거하고 즉시 새로운 캐시를 추가하는 패턴이 관찰되었으며, 이는 기존 설정의 비효율성을 인지하고 전략을 변경했음을 시사합니다.
RQ3: 캐싱 수정의 동기 (Drivers)
인간 vs 봇:
파라미터 업데이트: 주로 **개발자 (Human)**가 주도하며, 캐싱 문제 해결 (cache miss, 빌드 실패) 이나 의존성 업데이트가 주요 동기입니다.
버전 업데이트: 주로 **봇 (Bot, 예: Dependabot)**에 의해 트리거되며, 캐시 액션의 버전 업그레이드와 관련이 있습니다.
주요 동기 분류:
의존성 업데이트 (Update dependencies): 가장 흔한 동기.
캐싱 성능 개선 (Improve cache): 성능 최적화 목적.
봇 경고 (Bot alert): 버전 업데이트 자동화.
캐싱 문제 해결 (Fix caching issues): 빌드 실패 또는 미스 해결.
특이점: 보안 관련 수정은 드물지만 발생 시 다양한 조치 (파라미터 변경, 버전 업데이트 등) 가 취해집니다.
4. 주요 기여 (Contributions)
최초의 대규모 실증 연구: GHA 워크플로우에서 캐싱의 채택, 진화, 동기를 체계적으로 분석한 최초의 연구입니다.
포괄적인 캐싱 메커니즘 분석: 명시적 캐싱뿐만 아니라 패키지 매니저 및 Docker 레이어 캐싱 등 다양한 메커니즘을 포함하여 실제 구현 양상을 다각도로 조명했습니다.
진화 패턴의 정량화: 상태 전이 (State transitions) 모델을 사용하여 다양한 작업 유형별 캐싱 유지보수 활동의 진화 패턴을 정량화했습니다.
동기 분류 체계 구축: 커밋 메시지 및 PR 컨텍스트를 분석하여 캐싱 변경의 원인을 분류한 분류체계를 제시했습니다.
오픈 소스 데이터: 연구에 사용된 데이터셋과 재현 패키지를 GitHub 에 공개하여 후속 연구를 지원했습니다.
5. 의의 및 시사점 (Significance & Implications)
캐싱은 유지보수 대상: 캐싱은 단순한 성능 최적화 옵션이 아니라, 지속적인 관리와 수정이 필요한 '진화하는 CI 구성 요소'로 인식해야 합니다.
자동화 도구의 한계: 현재 봇 생태계는 버전 업데이트에는 효과적이지만, 파라미터 튜닝이나 구조적 수정과 같은 복잡한 유지보수 작업에는 도움이 되지 않습니다.
도구 개발의 필요성: 개발자가 반복적으로 수행하는 파라미터 수정 (키/경로 조정) 을 자동화하거나 지원할 수 있는 지능형 도구 (Agent-based support) 가 필요합니다.
불필요한 캐싱 제거: 캐싱은 항상 긍정적인 것만은 아니며, 워크플로우 변화에 따라 불필요해진 캐싱 설정을 제거하는 것도 중요한 유지보수 활동임을 강조합니다.
향후 연구 방향: 빈번한 캐싱 유지보수 활동이 실제로 빌드 시간 단축으로 이어지는지 정량적으로 평가하는 연구가 필요합니다.
이 연구는 CI/CD 캐싱이 단순한 기술적 설정을 넘어, 개발 팀의 지속적인 노력과 관리가 필요한 핵심 프로세스임을 입증하며, 이를 효율화하기 위한 도구 및 방법론 개발의 중요성을 제기합니다.