repo-scan은(는) 무엇을 하나요?
모든 생태계에는 자체 의존성 관리자가 있지만, C++, Android, iOS, Web을 통틀어 '실제로 당신의 코드는 얼마나 되는지, 무엇이 서드파티인지, 무엇이 데드 웨이트인지'를 알려주는 도구는 없었습니다.
사용 시점
- 대규모 레거시 코드베이스를 인수하고 구조적 개요가 필요할 때
- 주요 리팩토링 전 — 핵심, 중복, 데드 코드 식별
- 패키지 매니저에 선언되지 않고 소스에 직접 임베디드된 서드파티 의존성 감사
- 모노레포 재구성을 위한 아키텍처 결정 기록 준비
설치
# 먼저 클론하여 고정된 커밋을 설치 전에 검토할 수 있도록 함
set -euo pipefail
REPO_SCAN_COMMIT=2742664ebcad1450c208eda0ae45d3c17fad5dd8
REPO_SCAN_INSTALL_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/repo-scan"
REPO_SCAN_INSTALL_PARENT="$(dirname "$REPO_SCAN_INSTALL_DIR")"
mkdir -p "$REPO_SCAN_INSTALL_PARENT"
REPO_SCAN_TMP="$(mktemp -d "$REPO_SCAN_INSTALL_PARENT/.repo-scan-install.XXXXXX")"
REPO_SCAN_TOKEN="${REPO_SCAN_TMP##*.}"
REPO_SCAN_STAGE="$REPO_SCAN_TMP/stage-$REPO_SCAN_TOKEN"
REPO_SCAN_BACKUP="$REPO_SCAN_TMP/backup-$REPO_SCAN_TOKEN"
REPO_SCAN_LOCK="$REPO_SCAN_INSTALL_PARENT/.repo-scan-install.lock"
REPO_SCAN_KEEP_TMP=0
REPO_SCAN_LOCK_HELD=0
REPO_SCAN_MV_HAS_NO_TARGET=0
cleanup_repo_scan_install() {
if [ "$REPO_SCAN_KEEP_TMP" -eq 0 ]; then
rm -rf -- "$REPO_SCAN_TMP"
fi
if [ "$REPO_SCAN_LOCK_HELD" -eq 1 ] && ! rmdir -- "$REPO_SCAN_LOCK"; then
printf '설치 잠금을 해제할 수 없습니다: %s\n' "$REPO_SCAN_LOCK" >&2
fi
}
trap cleanup_repo_scan_install EXIT
mkdir "$REPO_SCAN_TMP/mv-probe-source"
if mv -T -- "$REPO_SCAN_TMP/mv-probe-source" \
"$REPO_SCAN_TMP/mv-probe-destination" 2>/dev/null; then
REPO_SCAN_MV_HAS_NO_TARGET=1
rmdir "$REPO_SCAN_TMP/mv-probe-destination"
else
rmdir "$REPO_SCAN_TMP/mv-probe-source"
fi
move_repo_scan_dir() {
REPO_SCAN_MOVE_SOURCE=$1
REPO_SCAN_MOVE_DESTINATION=$2
REPO_SCAN_MOVE_NAME=${REPO_SCAN_MOVE_SOURCE##*/}
if [ -e "$REPO_SCAN_MOVE_DESTINATION" ] || [ -L "$REPO_SCAN_MOVE_DESTINATION" ]; then
return 1
fi
if [ "$REPO_SCAN_MV_HAS_NO_TARGET" -eq 1 ]; then
mv -T -- "$REPO_SCAN_MOVE_SOURCE" "$REPO_SCAN_MOVE_DESTINATION"
return
fi
if ! mv -- "$REPO_SCAN_MOVE_SOURCE" "$REPO_SCAN_MOVE_DESTINATION"; then
return 1
fi
if [ -e "$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" ] || \
[ -L "$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" ]; then
if ! mv -- "$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" \
"$REPO_SCAN_MOVE_SOURCE"; then
REPO_SCAN_KEEP_TMP=1
printf '이동 충돌 복구 실패; 스테이징 데이터가 %s에 남아 있습니다\n' \
"$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" >&2
fi
return 1
fi
}
git clone --filter=blob:none --no-checkout \
https://github.com/haibindev/repo-scan.git "$REPO_SCAN_TMP/source"
git -C "$REPO_SCAN_TMP/source" checkout --detach "$REPO_SCAN_COMMIT"
mkdir -p "$REPO_SCAN_STAGE"
git -C "$REPO_SCAN_TMP/source" archive "$REPO_SCAN_COMMIT" | \
tar -xf - -C "$REPO_SCAN_STAGE"
# 설치 승인 전에 "$REPO_SCAN_TMP/source"를 검토하세요.
printf '고정된 소스를 검토한 후 %s를 교체하려면 install을 입력하세요: ' \
"$REPO_SCAN_INSTALL_DIR" >&2
read -r REPO_SCAN_CONFIRM
if [ "$REPO_SCAN_CONFIRM" != install ]; then
printf '설치가 취소되었습니다.\n' >&2
exit 1
fi
if ! mkdir -- "$REPO_SCAN_LOCK" 2>/dev/null; then
printf '다른 repo-scan 설치가 %s에서 잠금을 보유하고 있습니다\n' \
"$REPO_SCAN_LOCK" >&2
exit 1
fi
REPO_SCAN_LOCK_HELD=1
if [ -e "$REPO_SCAN_INSTALL_DIR" ] || [ -L "$REPO_SCAN_INSTALL_DIR" ]; then
move_repo_scan_dir "$REPO_SCAN_INSTALL_DIR" "$REPO_SCAN_BACKUP"
fi
if ! move_repo_scan_dir "$REPO_SCAN_STAGE" "$REPO_SCAN_INSTALL_DIR"; then
if [ -e "$REPO_SCAN_BACKUP" ] || [ -L "$REPO_SCAN_BACKUP" ]; then
if [ -e "$REPO_SCAN_INSTALL_DIR" ] || [ -L "$REPO_SCAN_INSTALL_DIR" ]; then
REPO_SCAN_KEEP_TMP=1
printf '교체 실패 및 대상이 재생성됨; 이전 설치가 %s에 보존됨\n' \
"$REPO_SCAN_BACKUP" >&2
elif ! move_repo_scan_dir "$REPO_SCAN_BACKUP" "$REPO_SCAN_INSTALL_DIR"; then
REPO_SCAN_KEEP_TMP=1
printf '교체 및 롤백 실패; 이전 설치가 %s에 보존됨\n' \
"$REPO_SCAN_BACKUP" >&2
fi
fi
exit 1
fi
에이전트 스킬을 설치하기 전에 소스를 검토하세요.
설치는 부트스트랩만 완료합니다. 에이전트 환경을 다시 로드한 후 repo-scan을 다시 호출하세요. 이 ECC 포인터는 외부 스킬을 설치하지만 스캔 자체를 실행하지는 않습니다.
핵심 기능
| 기능 | 설명 |
|---|---|
| 크로스 스택 스캐닝 | C/C++, Java/Android, iOS (OC/Swift), Web (TS/JS/Vue) 단일 패스 |
| 파일 분류 | 모든 파일을 프로젝트 코드, 서드파티, 빌드 아티팩트로 태그 |
| 라이브러리 탐지 | 50개 이상의 알려진 라이브러리(FFmpeg, Boost, OpenSSL…) 버전 추출 포함 |
| 4단계 평가 | 핵심 자산 / 추출 및 병합 / 재구축 / 폐기 |
| HTML 보고서 | 드릴다운 탐색이 포함된 대화형 다크 테마 페이지 |
| 모노레포 지원 | 계층적 스캐닝과 요약 + 하위 프로젝트 보고서 |
분석 깊이 수준
| 수준 | 읽는 파일 수 | 사용 사례 |
|---|---|---|
fast | 모듈당 1-2개 | 대규모 디렉토리의 빠른 인벤토리 |
standard | 모듈당 2-5개 | 전체 의존성 + 아키텍처 검사가 포함된 기본 감사 |
deep | 모듈당 5-10개 | 스레드 안전성, 메모리 관리, API 일관성 추가 |
full | 모든 파일 | 병합 전 종합 검토 |
작동 방식
- 레포 표면 분류: 파일을 열거한 후 각각을 프로젝트 코드, 임베디드 서드파티 코드, 빌드 아티팩트로 태그합니다.
- 임베디드 라이브러리 탐지: 디렉토리 이름, 헤더, 라이선스 파일, 버전 마커를 검사하여 번들된 의존성과 추정 버전을 식별합니다.
- 각 모듈 점수 평가: 파일을 모듈 또는 서브시스템별로 그룹화한 후 소유권, 중복성, 유지보수 비용에 따라 네 가지 평가 중 하나를 할당합니다.
- 구조적 위험 강조: 데드 웨이트 아티팩트, 중복 래퍼, 오래된 벤더 코드, 추출/재구축/폐기해야 할 모듈을 지적합니다.
- 보고서 생성: 간결한 요약과 모듈별 드릴다운이 가능한 대화형 HTML 출력을 반환하여 감사를 비동기적으로 검토할 수 있도록 합니다.
예시
50,000개 파일의 C++ 모노레포에서:
- 2015년형 FFmpeg 2.x가 여전히 프로덕션에 사용 중임 발견
- 동일한 SDK 래퍼가 3번 중복 복제되어 있음 발견
- 636MB의 커밋된 Debug/ipch/obj 빌드 아티팩트 식별
- 분류 결과: 3MB 프로젝트 코드 대 596MB 서드파티 코드
모범 사례
- 첫 감사는
standard깊이로 시작하세요. - 모듈이 100개 이상인 모노레포에서는
fast를 사용하여 빠른 인벤토리를 얻으세요. - 리팩토링 대상으로 표시된 모듈에서 점진적으로
deep을 실행하세요. - 하위 프로젝트 간 중복 탐지를 위해 모듈 간 분석을 검토하세요.