AI가 생성한 저장소 1,332개를 열어보니, 종속성(dependency) 중 5개는 존재하지 않았고 누구나 등록할 수 있었습니다.
요약
본 기사는 AI 도구로 생성된 GitHub 저장소의 종속성(dependency)을 분석했습니다. 그 결과, AI가 구축한 코드 중 상당수가 실제로 존재하지 않는 패키지에 의존하고 있음을 발견했습니다. 이는 단순한 설치 오류를 넘어, 해당 이름이 먼저 등록되는 사람이 시스템 동작을 결정할 수 있다는 의미를 시사합니다.
핵심 포인트
- AI 생성 코드는 실제로는 존재하지 않는 종속성에 크게 의존함.
- 이는 단순히 오류가 아니라, 패키지 이름을 선점하여 기능을 정의하는 행위로 해석됨.
- GitHub 신규 코드의 절반이 이미 AI 도구의 영향을 받고 있음.
- 실제 존재하는 종속성은 매우 적은 비율을 차지함.
슬롭스쿼팅(slopsquatting)에 관한 글들은 주로 모델을 측정합니다. 즉, 코드 생성을 요청하여 존재하지 않는 패키지 이름을 얼마나 자주 언급하는지를 세어보는 방식입니다. 저희가 알고 싶었던 것은 파이프라인의 다른 끝단이었습니다. AI 도구를 사용해 실제로 구축하고 게시된 코드 중, 여전히 존재하지 않는 패키지에 의존하는 것이 얼마나 되는가 하는 점입니다.
존재하지 않는 종속성은 단순히 설치 오류를 의미하는 것 이상입니다. 그 이름은 자유롭기 때문에, 가장 먼저 등록한 사람이 이후 해당 설치가 무엇을 실행할지 결정하게 됩니다.
우리가 살펴본 내용
두 가지 샘플 모두 2026-10-03에 수집되었으며, 모두 대조군(control group)이 포함되어 있습니다.
인기 프로젝트. 2025년 1월 이후 Show HN 게시물에서 링크된, 20포인트 이상의 GitHub 저장소: 총 673개의 도달 가능한 저장소입니다.
최근의 비인기 프로젝트. 2025년 1월 이후에 생성되었고 별점이 최대 50개 이하인 저장소들로, AI 도구가 남긴 파일(Lovable 빌드 마커, Bolt의 프로젝트 프롬프트, CLAUDE.md, .cursorrules 파일 등)을 통해 찾았습니다. 대조군은 같은 기간에 생성되었으나 그러한 흔적이 없는 저장소입니다.
저장소가 AI가 구축된 것으로 간주되려면 다음 중 하나를 포함해야 합니다: 에이전트 지침 파일(CLAUDE.md, AGENTS.md, .cursorrules 및 관련 파일), AI 도구가 서명한 커밋(Co-Authored-By: Claude, Co-authored-by: Copilot 등), Lovable 또는 Bolt 마커, 또는 Show HN 게시물에서 작성자가 직접 언급하는 경우입니다.
| AI가 구축된 | 대조군 | |
|---|---|---|
| 인기 프로젝트 (Show HN) | 412개 저장소, 37,158개의 종속성 항목 | 261개 저장소, 7,655개 항목 |
| 최근, ≤ 50 별점 | 920개 저장소, 플랫폼 템플릿 외 추가된 22,966개 종속성 | 303개 저장소, 6,494개 항목 |
모든 package.json, requirements.txt, pyproject.toml, Cargo.toml 및 go.mod에 있는 종속성은 npm, PyPI, crates.io, Go 모듈 프록시에서 실시간으로 조회되었습니다. 첫 번째 샘플에서는 8,240개의 고유 이름이, 두 번째 샘플에서는 6,565개의 고유 이름이 확인되었습니다.
통제 그룹에 대한 부가 설명: 동일 기간에서 추출한 600개의 일반 레포지토리 중, 297개(49.5%)는 이미 AI 도구의 흔적을 가지고 있어 제외해야 했습니다. 현재 GitHub의 신규 코드 절반이 이러한 도구들의 영향을 받고 있습니다.
발견한 내용
레지스트리에서 누락된 이름은 보통 허상이 아닙니다. 대부분은 동일한 레포지토리 내에 존재하는 패키지, 회사 스코프 아래의 비공개 패키지, 다른 레지스트리(Deno의 JSR, Unity의 등)의 패키지, 또는 예제 속 자리 표시자 이름이었습니다. 저희는 이들을 수동으로 제거했습니다. 남은 것은 다음과 같습니다:
| AI가 구축한 (AI-built) | 통제 그룹 (Control) | |
|---|---|---|
| 인기 있는 (Popular) | 1개 레포지토리, 1개 이름 | 1개 레포지토리, 1개 이름 |
| ... |
레포지토리가 포함되지 않은 다섯 가지 사례는 다음과 같습니다:
- Bolt로 구축된 앱의 npm 패키지 세 개: 각각
"name": "^1.0.0"형식으로 작성되었습니다. 이 중 어느 것도 npm에 존재한 적이 없으며, 앱 코드는 그중 하나를 가져옵니다(import). 레포지토리의 lockfile에는 이들이 포함되어 있지 않습니다. 즉, 실패했을 설치 과정 자체가 실행되지 않았기 때문에 아무것도 감지하지 못한 것입니다. - Lovable로 구축된 앱 백엔드의 Python 패키지:
==5.3.0으로 고정되어 있습니다. 이 패키지는 존재한 적이 없으므로 버전 5.3.0도 존재할 수 없습니다. 코드는 하드웨어 라이브러리를 모듈 이름으로 가져오며, 만들어진 패키지 이름은 실제 패키지에 대한 그럴듯한 추측입니다. - 인기 프로젝트 예제의
requirements.txt에 나열된 Python 패키지: 예제에서 이 패키지를 가져오는(import) 코드는 아무것도 없습니다. 이 패키지는 해당 예제가 다루는 애플리케이션의 이름을 가지고 있습니다.
통제 그룹의 사례는 마지막 경우와 형태가 같습니다: 시스템 패키지 관리자로 설치되며, PyPI를 통해 설치된 적이 없고, requirements.txt에 정확한 버전으로 나열된 ROS(Robot Operating System) 패키지입니다.
추가로 두 가지 더 만들어졌지만 사용할 수 없는 유형이 있습니다: @types/ 패키지 (해당 스코프 아래는 DefinitelyTyped 유지 관리자만이 게시할 수 있음)와 표준 라이브러리 모듈 (PyPI에서 해당 이름은 거부됨).
숫자가 말하는 것과 그렇지 않은 것
사람들은 출판된 코드에서는 유령 종속성(phantom dependencies)이 드물다고 말합니다. 즉, 400개의 AI가 만든 저장소 중 약 1개 정도에서 발견된다는 것이죠. 그리고 사람들이 온라인에 올리는 코드에는 버전 번호가 붙은 채로 그것들이 존재한다고 합니다.
AI가 만든 코드가 다른 코드보다 나쁘다고 말하는 사람은 없습니다. 인기가 없는 샘플에서는 2개의 저장소 대비 0개, 인기 있는 샘플에서는 1개 대비 1개라는 수치는 비교하기에는 너무 작습니다. 이 샘플들은 무작위 추출이 아니라 검색 순위에서 가져온 것입니다.
저장소가 프로세스의 끝인 이유
출판된 저장소는 완성된 결과물입니다. 그 과정 중에 빌드를 깨뜨렸던 모든 유령 패키지들은 누군가 푸시하기 전에 발견되어 제거되었을 가능성이 가장 높습니다. 즉, 작성자가 앱을 실행해 보고 설치에 실패했거나 이름을 변경한 것이죠. 우리가 발견한 것은 살아남은 것들이고, 우리가 찾은 모든 사례는 같은 이유로 살아남았습니다. 아무도 설치를 실행하지 않은 곳에 놓여 있었기 때문입니다. 예시 폴더. 배포되지 않은 백엔드. 설치가 완료된 적이 없는 것을 보여주는 락파일을 가진 앱.
따라서 이 수치들은 비율(rate)이 아니라 최저선(floor)입니다. 우리는 커밋(commit) 전에 무슨 일이 일어났는지를 측정하지 않았지만, 두 가지 요소가 같은 방향을 가리킵니다. 우리가 일반적인 코딩 작업을 Claude, GPT, Gemini에 맡겼을 때, 이 모델들은 존재하지 않는 87개 패키지 이름을 추천했습니다. 생성 시점에 동일한 것을 측정한 학술 연구(Spracklen et al., 2024)는 생성된 코드의 상당 부분에서 가상의 패키지 이름을 발견했으며, 상업용 모델보다 오픈 모델에서 더 많이 나타났습니다. 모델이 작성하는 것과 실제로 푸시되는 것 사이에는 누군가가 나머지를 잡아야 합니다. 보통은 설치를 실행해 보고 실패하는 것을 지켜보는 방식으로요.
그렇기 때문에 위험한 순간은 실패 직전의 순간입니다. 설치가 실패하는 이유는 아직 아무도 그 이름을 등록하지 않았기 때문입니다. 어느 날 누군가 등록하면, 동일한 명령이 조용히 성공하며 그들의 코드를 실행하게 됩니다. 출판된 저장소 속 유령 이름은 서 있는 초대장과 같습니다. Bolt 앱에 있는 세 가지는 2025년 3월부터 그렇게 되어 왔습니다.
추가 시점에서의 확인
유령 패키지(phantom package)를 막을 수 있는 지점은 에이전트가 이를 추가할 때입니다. 오늘 실패하고 이름이 사용되는 순간 성공하는 설치 이전에 말이죠. 위에 언급된 다섯 가지 이름 모두 VDB의 패키지 게이트로 전송되었고, REFUSE 응답을 받았습니다:
POST /v1/ai/check-packages
{"packages": ["pkg:pypi/<다섯 개 중 하나>"]}
...
게이트는 키 없이 최대 다섯 개의 패키지를 처리할 수 있습니다. 에이전트 앞에 배치하려면 Connect를 참조하세요.
진행 과정
- 후보군(Candidates): Hacker News 검색 API를 통해 Show HN을 확인하고, 각 도구가 남기는 파일들을 이용해 GitHub 검색을 통해 최근 저장소를 찾았습니다.
- AI 추적(AI traces): 각 저장소의 얕은 복제본(shallow clone)에서 읽어왔습니다. 즉, 파일 트리와 마지막 200개 커밋 메시지입니다. 코드는 실행되지 않았습니다.
- 종속성(Dependencies): 매니페스트에서 파싱했으며, 워크스페이스(workspace), 파일(file), git 및 URL 지정자, 별칭(aliases) (실제 이름으로 해결됨), 저장소 자체의 패키지, 그리고 스코프가 사설 레지스트리로 보내는
.npmrc를 제외했습니다. Lovable과 Bolt의 경우, 해당 플랫폼 저장소 중 최소 절반에 존재하는 종속성이 템플릿으로 간주되어 제외되었습니다. - 조회(Lookups): VDB 게이트가 사용하는 프로브로 각 레지스트리에서 실시간 조회했습니다.
- 표시된 모든 이름은 잠금 파일(lockfile)과 이를 가져올 코드까지 포함하여 수동으로 확인했습니다.
이 게시물 이전에 2026년 10월 3일에 관련된 네 개의 저장소 유지 관리자들에게 알렸으며, 여기에는 언급되지 않은 내용입니다. 저희가 직접 어떤 이름도 등록하지 않았습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기