grep 두 번으로 틀린 글을 냈다 — 127일째 아무도 안 부르는 코드

죽은 코드 실측 — analyzer.py는 디스크에 있지만 import 참조 0건, 127일째 아무도 부르지 않았다

grep 두 번으로 틀린 글을 냈다 — 127일째 아무도 안 부르는 코드

죽은 코드는 에러를 내지 않는다. 그냥 거기 있다.

지난주에 발행한 글의 근거가 그런 파일이었다. 그 글은 5월에 쓴 다른 글을 정정 대상으로 지목했는데, 재보니 5월 쪽이 맞았다.

결론부터 적는다. 죽은 코드는 안 도는 데서 끝나지 않았다. 틀린 주장을 발행하게 만들었고, 그 주장은 검토를 전부 통과했다.

누가 읽으면 좋은가

새 저장소를 열면 grep부터 돌리는 사람. 자기가 만든 도구를 글이나 문서로 설명해 본 사람. 조사 결과를 근거 삼아 무언가를 결정해 본 사람.

파일을 찾고 나서 그게 실행 경로에 있는지는 안 본 적이 있다. 오래된 저장소에 안 쓰는 파일이 몇 개인지 세어본 적은 없다. 커밋 메시지가 틀릴 수 있다는 생각은 해본 적이 없다.

두 달 전에 쓴 규칙, 50일 뒤의 위반

6월 15일 발행글에 이렇게 적었다.

설정 파일에 등록돼 있다고 그 기능이 도는 게 아니다.

같은 글에 확인 방법도 적어뒀다. “에이전트라면 실제로 호출되는지 본다.”

50일 뒤인 8월 4일. 수집기의 비용을 조사하면서 저장소를 두 번 뒤졌다.

grep으로 유료 API 키를 참조하는 파일 하나를 찾았다. 이어서 스케줄러 설정을 열어 08:17과 20:17, 하루 두 번 도는 것을 확인했다.

둘을 곱했다. “하루 두 번 유료 호출인데 회당 비용 기록이 0건이다.” 그대로 발행했다.

그 파일이 실제로 호출되는지는 안 봤다. 규칙을 쓴 사람이 그 규칙의 첫 항목을 건너뛴 셈이다.

127일째 아무도 안 부르는 파일

오늘 다시 열어보니 확인은 세 번으로 끝났다.

확인 명령·대상 결과
import 역추적 grep -rn "from trend_scout.analyzer" --include="*.py" . 0건
엔트리포인트 main.py의 내부 import 목록 collectors·compare·models·tool_tracker. 해당 모듈 없음
의존성 선언 pyproject.toml dependencies praw·httpx·bs4·pyyaml·dotenv·click. anthropic 없음

첫 줄에서 이미 끝났어야 할 조사였다. 부르는 곳이 0건이면 나머지 둘은 볼 필요도 없다.

그 파일이 파이프라인에서 빠진 건 2026년 4월 6일이다. 오늘까지 127일. 스케줄러가 등록된 4월 1일부터 제거일까지 실제로 유료 호출이 돈 구간은 닷새뿐이었다.

닷새치 청구액은 지금도 모른다. 기록이 없다.

8월 4일 글이 정정 대상으로 지목한 건 5월에 쓴 다른 글(“한 달에 비용은 0원”)이었다. 제거일에서 그 글 발행일까지가 34일이다.

5월의 서술은 그 시점에 맞는 값이었다. 정정하겠다고 나선 쪽이 틀렸다.

커밋 메시지도 사실과 달랐다

제거 커밋에는 이렇게 적혀 있다.

Benefits:
- $0 API cost per run (was ~$0.10-0.20)

넉 달 동안 저장소에 있던 문장인데 조사할 때 열어보지 않았다.

그런데 같은 메시지의 다른 줄이 더 문제였다.

Removed:
- analyzer.py, reporter.py, image_gen.py, keyword_volume.py (unused by main)

git show --stat으로 보면 그 커밋이 실제로 바꾼 파일은 pyproject.tomlmain.py 두 개다. 116줄 추가, 84줄 삭제.

즉 “Removed”라고 적힌 네 파일은 한 개도 안 지워졌다. 의존성과 호출부만 끊고 파일은 디스크에 남겼다. 그래서 넉 달 뒤에 그중 하나가 살아 있는 코드처럼 읽혔다.

왜 메시지와 실제 변경이 어긋났는지는 모른다. 의도인지 실수인지 판단할 자료가 없다.

오늘 그 파일 하나는 지웠다. 298줄이었다. 지운 뒤 저장소 테스트를 돌려 122건 통과를 확인했다.

나머지 셋에 reporter.py를 더한 네 개는 아직 안 지웠다. 외부 참조는 각각 0건, 0건, 0건, 그리고 자기 테스트 1건이다.

관문을 늘려도 안 걸리는 것

반박이 가능하다. 두 번 뒤진 걸로 근거가 충분하지 않나, 어디까지 파야 하나.

비용을 재보면 답이 나온다. 위 표의 첫 줄은 명령 한 줄이고 몇 초다.

부족했던 건 근거가 아니다. 확인 세 줄 중 두 줄을 건너뛰었는데, 건너뛴 자리가 하필 결론을 뒤집을 수 있는 줄이었다.

관문을 늘려서 막을 수 있는 사고도 아니었다. 8월 4일 글은 사실 정리 파일을 따로 만들고 구조 리뷰를 받고 채점 루프를 돌았다.

그 관문들이 검사한 건 본문의 수치가 정리 파일과 한 자씩 맞는지였다. 정리 파일의 수치가 어디서 왔는지는 검사 항목에 없었다.

그 파일 하나가 정리 파일 첫 줄에 들어간 순간 뒤는 다 늦었다. 입력이 오염되면 관문 수는 의미가 없다. 많을수록 틀린 값이 더 매끄럽게 다듬어져 나갈 뿐이다.

정적 분석 도구가 이걸 잡았을지는 써본 적이 없어서 모른다. 도구를 붙이면 해결된다는 얘기를 하려는 게 아니다.

그래서 관문을 하나 더 만드는 대신 입력에 조건을 걸기로 했다. 코드를 근거로 삼는 문장은 위 표의 세 줄을 확인한 뒤에만 쓴다. 첫 줄이 0건이면 그 문장은 안 쓴다.

커밋 메시지도 같은 조건 아래 둔다. 방향은 참고하되 범위는 따로 확인한다.

이번 메시지는 “LLM 호출을 뺐다”는 방향이 맞았고 “파일 네 개를 지웠다”는 범위가 틀렸다. 한 문단 안에서 갈렸다.

검색으로 코드베이스를 파악하는 방식은 사람만 쓰지 않는다. 조사를 에이전트에게 맡길 때도 같은 조건이 붙어야 한다고 본다. 다만 이건 재본 게 아니라 추정이다.

6월에 쓴 문장은 그대로 맞다. 틀린 건 그 문장을 쓴 사람이 50일 뒤에 안 지켰다는 쪽이다. 규칙을 발행하는 일과 규칙을 적용하는 일은 서로 다른 작업이었다.

지난주 글은 오늘 정정했다. 본문 네 문장과 구조화 데이터를 고치고 상단에 정정 고지를 달았다.

5월 글에는 아무것도 달지 않았다. 그 글이 맞았다.

읽는 쪽에서 해볼 수 있는 건 파일 찾기가 아니다. 최근에 쓴 기술 문서나 회고에서 코드를 근거로 든 문장 하나를 골라, 그 근거가 어디서 왔는지 되짚어 보면 된다. 검색 결과 한 줄에서 왔다면 그 문장은 아직 근거가 없다.

Q&A

Q. grep으로 파일을 찾았으면 근거로 충분하지 않나.
A. 파일이 있다는 것과 그 코드가 실행된다는 것은 다른 정보다. 이번 경우 import 역추적 한 줄로 0건이 나왔고, 그 한 줄이 조사 전체를 뒤집었다. 비용은 몇 초였다. 부족했던 건 근거의 양이 아니라 확인 순서였다.

Q. 죽은 코드가 남아 있으면 실제로 뭐가 문제인가.
A. 안 불리니까 실행 결과는 안 바뀐다. 문제는 그 파일을 읽는 사람에게 생긴다. 이번엔 저장소를 조사하던 사람이 그 파일을 현재 동작의 증거로 읽었고, 그 판단이 글로 발행됐다. 도구가 아니라 서술이 오염됐다.

Q. 커밋 메시지를 어디까지 믿어야 하나.
A. 방향은 믿되 범위는 확인하는 편이 낫다. 이번 커밋은 “LLM 호출을 파이프라인에서 뺐다”는 방향은 맞았고, “파일 네 개를 지웠다”는 범위는 틀렸다. git show --stat 한 번이면 실제 변경 파일 목록이 나온다.

Q. 그래서 관문 대신 뭘 바꿨나.
A. 검사 순서를 바꿨다. 예전에는 본문을 다 쓴 뒤 근거와 대조했다. 지금은 근거를 정리하는 단계에서 코드 관련 항목마다 호출처 확인을 먼저 넣는다. 다만 6월에도 비슷한 규칙을 만들었고 50일 뒤에 안 지켰다. 이번 것이 다음번에 지켜질지는 아직 모른다.

관련 글

한계

한 저장소에서 하루 동안 확인한 기록이다. 다른 환경에서도 같은 비율로 고아가 남는지는 모른다. 남은 네 파일을 지웠을 때 생길 부작용도 아직 확인 못 했다. 저장소 전체 테스트는 122건 통과에 2건 실패인데, 그 2건은 이번 변경 전부터 있던 것이고 여기서 다룬 내용과 무관하다.


저자 — Jason 황재승
cd4761.blogspot.com에서 개발 자동화와 AI 도구 운영 기록을 쓴다. 8년 차 프론트엔드. 측정 환경은 macOS, 대상은 개인 저장소 한 곳으로 한정했다. 갱신일 2026-08-11.

태그: #죽은코드 #코드감사 #개발자동화 #하네스 #리팩터링 #깃 #오픈소스운영

댓글

이 블로그의 인기 게시물

맥 스튜디오 M4 Max 128GB 로컬 LLM 4개 속도 비교 — gemma4·llama3.3·qwen3 실측

Opus 5는 더 잘 쓰고, 더 AI답게 쓴다 — 세 모델 첫날 실측

Claude Opus 4.7 출시 총정리 — 뭐가 달라졌고 지금 써야 하나