sgkstudio.
엔지니어링

git status 정리, 파일 571개를 한 자릿수로 줄인 기록

git status 정리는 무시 규칙을 몇 줄 보태는 일이 아니라 저장소가 무엇을 추적해야 하는지 다시 정하는 일이었습니다. 이미지와 초안을 스크립트가 매일 만들어 떨어뜨리는 저장소에서 git status가 571줄을 뱉었고, 임시 파일과 렌더 출력을 무시하는 규칙을 두 번 넣었는데도 노이즈는 줄지 않았습니다. 2026년 7월 2일 커밋에서 생성 산출물 폴더를 무시하고 cron이 고쳐 쓰는 상태 파일 4개를 추적에서 빼자 571줄이 한 자릿수로 내려갔습니다. 이 글은 왜 앞의 두 조치가 틀렸는지, 두 종류의 노이즈가 어떻게 다른지, 그리고 무엇이 끝내 줄지 않았는지의 기록입니다.

2026-09-03저장소 1개 (전자책 원고 5권 + 마케팅 자산) · 정리 커밋 1건 (2026-07-02)정리 전 git status 571줄 · 정리 후 한 자릿수 · 무시 대상 PNG 450장 · 추적 해제 상태 파일 4개같은 PR의 변경 규모 — 파일 784개 · 추가 28,870줄 · 삭제 24줄 · 바이너리 545개

무엇이 문제였나 — git status가 571줄을 뱉었다

이 저장소는 전자책 원고만 담지 않습니다. 책을 팔기 위한 자산을 전부 스크립트로 만들고, 그 산출물이 같은 폴더 트리 안에 떨어집니다. 블로그 초안 18편, 썸네일 17장, 인스타그램 카드덱 9개(덱마다 10장), 릴스 대본 5종, 랜딩 섹션 이미지 10종, 상세 판매 페이지 풀페이지 PNG까지 전부 파이썬 생성기의 출력물입니다.

생성기 일부는 사람이 돌리지 않습니다. 카드 덱은 cron이 매일 아침 7시 15분에 만들고, 블로그 초안 자동 발행 스크립트는 큐 파일을 읽어 그날 쓸 주제를 고른 뒤 그 파일을 고쳐 씁니다. 발행 목록도 같은 방식으로 매일 갱신합니다. 사람이 아무것도 하지 않아도 저장소 안의 파일이 매일 바뀝니다.

그 결과가 git status 571줄입니다. 571줄이면 방금 내가 고친 파일 두 개를 찾으려고 화면을 여섯 번 넘겨야 합니다. 에이전트는 커밋 전에 git status를 읽고 자기 변경분만 골라 담는데, 571줄 안에서는 그 선별이 실질적으로 불가능합니다. 반대로 전부 담아 버리면 커밋 하나에 이미지 수백 장이 딸려 들어갑니다.

그 두 번째 사고가 실제로 났습니다. 이 글의 정리 커밋을 포함한 PR 하나가 파일 784개를 바꾸고 28,870줄을 추가했는데, 그 가운데 바이너리가 545개였습니다. 인스타그램 카드 PNG 330장, 썸네일 41장, 릴스 영상 5개가 그 안에 있습니다. 노이즈는 읽기 불편한 문제로 끝나지 않고 저장소 이력에 그대로 새겨졌습니다.

정리 전후 네 칸. 정리 전 git status 571줄, 정리 후 한 자릿수, 무시 대상 인스타그램 카드 PNG 450장, 추적 해제한 cron 상태 파일 4개
숫자 하나가 내려간 게 아니라 두 종류의 파일이 각각 다른 방식으로 빠졌습니다

처음 잰 숫자 — 571개는 어디서 왔나

측정 방법은 단순합니다. git status 출력에서 변경 또는 미추적으로 뜬 파일 줄 수를 셉니다. 그 값이 571이었고, 정리 커밋 메시지에 그대로 남아 있습니다. 이 글에서 전후 비교에 쓰는 유일한 지표이며, 그래서 뒤에서 이 지표의 한계도 따로 적습니다.

571줄 가운데 가장 큰 덩어리는 인스타그램 카드 출력 폴더의 PNG 450장입니다. 카드덱 하나가 10장이고, 첫 구축 때 9개 덱을 만들었고, 그 뒤 S04부터 S09까지 6세트를 더 만들었습니다. 여기에 디자인 시스템을 통일하면서 카드 15장과 썸네일 37장을 다시 그렸습니다. 디자인이 바뀌면 카드는 한 장이 아니라 전량이 다시 생깁니다.

나머지는 블로그 초안 폴더, 썸네일 출력 폴더, 광고 이미지 폴더, 그리고 상태 파일 4개입니다. 상태 파일은 블로그 큐, 인스타그램 발행 목록, 썸네일 목록, 인스타그램 큐이고, 넷 다 cron이 돌 때마다 내용이 바뀝니다.

571줄을 만든 자리를 경로별로 정리한 표. instagram/cards/out 카드 PNG 450장은 cron이 매일 만들어 무시 대상, blog/drafts와 drafts의 초안, thumbnails/out 썸네일, marketing/ads 광고 이미지도 무시 대상, queue.txt·feed.json·thumbnails.json·feed_queue.txt 상태 파일 4개는 cron이 고쳐 써서 추적 해제 대상
같은 status 줄이라도 새 파일과 이미 추적 중인 파일은 다른 조치로 빠집니다

이미지가 왜 이렇게 자주 바뀌는지는 상세 판매 페이지 한 장이 보여 줍니다. 모바일 가독성을 높이려고 글자 크기 계층을 올린 뒤 풀페이지 PNG를 다시 렌더링했더니 파일이 4.2MB에서 1.9MB로 바뀌었습니다. 텍스트 파일이었다면 바뀐 줄만 diff로 남았을 텐데, 이미지는 한 글자를 바꿔도 파일 전체가 새 파일입니다. 세로 19,449픽셀짜리 이미지가 그렇게 통째로 갈립니다.

가설 — 임시 파일만 무시하면 조용해진다

첫 조치는 정리 커밋보다 훨씬 전에 있었습니다. 브라우저 자동화 도구와 에이전트 연동 도구가 남기는 임시 파일을 .gitignore에 넣었습니다. 그때의 진단은 이랬습니다. 노이즈는 도구가 흘리는 부산물이고, 그 부산물만 막으면 status는 사람이 만든 파일만 남긴다.

두 번째 조치는 릴스 양산 엔진을 붙이면서 나왔습니다. 렌더 한 번에 37초가 걸리고 1080×1920 크기에 4Mbps로 나오는 영상 파일이 출력 폴더에 쌓였습니다. 이건 누가 봐도 커밋할 물건이 아니라서 그 폴더를 바로 무시 목록에 넣었습니다. 이때의 진단은 조금 넓어졌습니다. 무거운 렌더 출력만 빼면 된다.

두 가설 모두 각자의 자리에서는 맞았습니다. 임시 파일은 실제로 사라졌고, 영상 폴더도 status에서 빠졌습니다. 문제는 그 두 규칙을 넣은 뒤에도 status가 수백 줄이었다는 사실입니다. 가설이 틀렸다기보다 문제의 크기를 잘못 쟀습니다.

이 단계에서 한 번도 하지 않은 일이 있습니다. 571줄을 경로별로 세어 보는 일입니다. 눈에 띄는 폴더 하나를 막고 status를 다시 열어 '아직 많네'라고 확인한 뒤 다음 작업으로 넘어갔습니다. 세지 않았기 때문에 무엇이 남았는지 몰랐고, 몰랐기 때문에 같은 조치를 두 번 반복했습니다.

왜 무시 규칙을 두 번 넣고도 노이즈가 돌아왔나

첫 번째 이유는 .gitignore의 동작 범위입니다. 무시 규칙은 아직 추적하지 않은 파일에만 듣습니다. 이미 한 번 커밋한 파일은 .gitignore에 경로를 적어도 계속 추적 대상이고, 내용이 바뀌면 여전히 변경으로 뜹니다. 상태 파일 4개가 정확히 이 경우였습니다. 처음 자동화를 구축할 때 큐와 발행 목록을 함께 커밋했고, 그 뒤로 cron이 매일 그 파일을 고쳐 썼습니다.

그래서 상태 파일은 무시 규칙을 아무리 넣어도 매일 아침 다시 status에 올라왔습니다. 카드 PNG처럼 한꺼번에 수백 줄을 만들지는 않지만, 하루도 빠짐없이 나타나는 4줄이었습니다. 그 4줄이 매일 '오늘도 뭔가 바뀌었다'는 신호를 보내니 사람은 status를 믿지 않게 되고, 믿지 않는 status는 읽지 않게 됩니다.

두 번째 이유는 산출물 폴더가 한 곳이 아니었다는 점입니다. 임시 파일 폴더와 영상 출력 폴더를 막는 동안 카드 출력 폴더, 썸네일 출력 폴더, 초안 폴더, 광고 이미지 폴더가 각자 자라고 있었습니다. 생성기를 하나 추가할 때마다 출력 폴더도 하나 늘었는데, 무시 규칙은 생성기를 만들 때가 아니라 노이즈가 눈에 띌 때 뒤따라 넣었습니다.

세 번째 이유가 가장 뼈아픕니다. 산출물을 자산으로 여겨 커밋해 온 관행입니다. 이 PR의 변경 내역에는 인스타그램 카드 PNG가 330장, 썸네일이 41장 새로 추가로 들어 있습니다. 무시 규칙을 넣은 바로 그 작업 묶음이 동시에 산출물 수백 장을 이력에 새긴 셈입니다. 무시 규칙은 그 뒤에 생길 450장을 막았을 뿐, 이미 들어간 330장은 건드리지 못했습니다.

git status noise: 571 → single-digit

진짜 원인 — 산출물과 상태 파일은 다른 종류의 노이즈였다

세 가지 이유를 늘어놓고 보니 노이즈가 두 종류로 갈렸습니다. 하나는 생성 산출물입니다. 카드 PNG, 썸네일, 초안, 광고 이미지, 렌더 영상처럼 스크립트가 입력을 받아 만들어 내는 파일입니다. 원고와 설정과 생성기 코드만 있으면 언제든 같은 파일을 다시 만들 수 있으니 저장소가 기억할 필요가 없습니다.

다른 하나는 실행 상태입니다. 큐 파일과 발행 목록은 스크립트의 출력이 아니라 스크립트가 다음에 무엇을 할지 기억해 두는 장부입니다. 어제 어떤 주제를 썼는지, 오늘 어떤 카드 차례인지가 여기 적혀 있습니다. 코드도 아니고 산출물도 아닌 세 번째 종류이고, 매일 바뀌는 게 정상입니다.

상태 파일이 왜 처음부터 추적 대상이었는지도 기록에 남아 있습니다. 인스타그램 채널을 처음 세운 커밋은 전략 문서, 발행 큐 24편, 카드 생성기, 발행 목록, 일일 실행 셸 스크립트를 한꺼번에 넣었고, 같은 커밋에서 cron을 아침 7시 15분에 등록하고 덱 9개를 만들어 그중 두 덱을 실제로 게시했습니다. 코드와 큐와 첫 산출물이 한 커밋에 섞여 들어갔고, 그 순간 큐 파일은 무시 규칙이 닿지 않는 자리로 넘어갔습니다. 자동화를 세운 날의 커밋이 그 뒤 매일 4줄의 노이즈를 만든 출발점이었습니다.

두 종류는 원인이 다르니 조치도 달라야 했습니다. 생성 산출물은 대부분 아직 추적하지 않은 새 파일이라 .gitignore로 막힙니다. 실행 상태는 이미 추적 중이라 무시 규칙이 통하지 않고, 추적 자체를 풀어야 합니다. 앞의 두 조치가 실패한 이유는 이 구분 없이 둘 다 무시 규칙 하나로 다루려 했기 때문입니다.

이 구분을 한 줄로 적으면 이렇습니다. 스크립트가 다시 만들 수 있으면 무시하고, 스크립트가 고쳐 쓰면 추적을 풀고, 사람이 쓰면 추적한다. 원고 파일과 생성기 코드는 세 번째에 해당합니다. 카드 생성기 274줄, 썸네일 생성기 264줄, 자동 발행 셸 스크립트 100줄은 그대로 추적합니다. 원고와 생성기 코드가 산출물을 다시 만들 수 있는 유일한 원천이기 때문입니다.

생성 파이프라인 흐름도. 원고·설정·생성기 코드는 추적, cron이 돌리는 생성기의 출력 폴더는 무시, cron이 고쳐 쓰는 큐·발행 목록 4개는 추적 해제
같은 cron이 만드는 파일인데 출력물과 상태 장부는 다른 칸으로 갑니다

조치 — .gitignore 26줄과 상태 파일 4개 추적 해제

2026년 7월 2일 커밋 하나로 두 조치를 같이 넣었습니다. 첫째, .gitignore에 26줄을 추가해 생성 산출물 폴더를 통째로 무시했습니다. 대상은 인스타그램 카드 출력 폴더, 초안 폴더 두 곳, 썸네일 출력 폴더, 광고 이미지 폴더입니다. 파일 단위가 아니라 폴더 단위로 잡아 생성기가 새 파일을 몇 장 만들든 규칙을 다시 손대지 않게 했습니다.

둘째, cron이 고쳐 쓰는 상태 파일 4개를 추적에서 뺐습니다. 파일은 디스크에 그대로 두고 git의 색인에서만 제거하는 방식입니다. 그래서 cron은 다음 날 아침에도 같은 큐 파일을 읽고 같은 발행 목록을 갱신하며, 달라진 것은 그 갱신이 더 이상 status에 뜨지 않는다는 점뿐입니다. 자동화는 한 줄도 바꾸지 않았습니다.

  • 무시(새 파일 차단) — instagram/cards/out · drafts · blog/drafts · thumbnails/out · marketing/ads
  • 추적 해제(이미 추적 중이던 파일) — queue.txt · feed.json · thumbnails.json · feed_queue.txt
  • 계속 추적 — 원고(qmd) · 생성기 코드(make_cards.py 274줄 · make_thumbnail.py 264줄 · daily_post.sh 100줄) · 설정 · 디자인 토큰

조치를 정하면서 기각한 안이 하나 있습니다. 산출물을 계속 커밋하되 별도 브랜치나 별도 저장소로 빼는 안입니다. 발행한 카드가 어떤 모습이었는지 git으로 되짚을 수 있다는 장점이 있지만, 디자인을 바꿀 때마다 수백 장이 다시 생기는 구조에서는 그 저장소도 같은 속도로 부풀어 오릅니다. 되짚을 필요가 있으면 발행 시점의 이미지를 발행 채널이 이미 갖고 있으니, 저장소가 두 번째 사본을 들고 있을 이유가 없다고 봤습니다.

같은 원리로 렌더 영상도 계속 무시합니다. 릴스 한 편은 32.86초짜리 파일이고, 화자 음성만 바꿔도 새 파일이 생깁니다. 이 PR에도 최종본 1개와 음성 수정본 2개가 함께 들어가 있습니다. 대본과 합성 스크립트가 있으면 다시 만들 수 있는 파일이라, 이력에 세 번 남을 이유가 없었습니다.

재측정 — 571에서 한 자릿수로, 그런데 무엇이 안 줄었나

같은 방법으로 다시 쟀습니다. git status 줄 수는 571에서 한 자릿수로 내려갔습니다. 정확한 숫자를 적지 못하는 이유는 정리 커밋 메시지에 'single-digit'으로만 남아 있고, 그 시점의 status 출력을 따로 저장하지 않았기 때문입니다. 전후 비교의 사후 값이 정수가 아니라 자릿수라는 점은 이 글의 약점이고, 뒤 절에서 다시 적습니다.

그 다음 날부터의 변화는 숫자보다 행동에서 보였습니다. cron이 아침에 카드를 만들고 큐를 고쳐 써도 status는 그대로였습니다. 에이전트가 커밋 전에 읽는 status에 자기 변경분만 남으니 선별 커밋이 다시 가능해졌고, 사람이 status를 열었을 때 화면 한 장 안에 전부 들어왔습니다.

두 번째 재측정은 하루 뒤였습니다. cron이 아침 7시 15분에 카드 덱을 만들고 큐와 발행 목록을 고쳐 쓴 다음 status를 열었을 때 그 네 파일이 뜨지 않으면 추적 해제가 제대로 된 것이고, 새 카드 PNG가 뜨지 않으면 폴더 무시가 제대로 된 것입니다. 둘 다 뜨지 않았습니다. 한 번 재고 끝내지 않은 이유는 앞의 두 조치가 바로 그 하루 뒤에 실패를 드러냈기 때문입니다.

줄지 않은 것도 분명합니다. 저장소 이력입니다. 정리 커밋을 포함한 PR 하나가 파일 784개를 바꾸고 28,870줄을 추가하며 24줄을 지웠는데, 그 안에 바이너리 545개가 들어 있습니다. 카드 PNG 330장, 썸네일 41장, 릴스 영상 5개, 목업과 가이드 이미지가 그 목록입니다. 무시 규칙은 앞으로 생길 파일을 막지만 이미 이력에 들어간 파일은 한 장도 빼내지 못합니다.

정리 커밋이 들어간 PR의 규모 네 칸. 변경 파일 784개, 추가 28,870줄, 삭제 24줄, 바이너리 545개
status는 한 자릿수가 됐지만 같은 PR이 이력에 남긴 바이너리는 545개입니다

그래서 이 정리의 효과는 두 층으로 나눠 읽어야 합니다. 작업 화면의 노이즈는 571에서 한 자릿수로 내려갔고, 이건 매일 체감하는 층입니다. 저장소 크기와 이력의 무게는 그대로이고, 이건 저장소를 새로 받는 사람이 체감하는 층입니다. 두 번째 층을 줄이려면 이력을 다시 쓰는 파괴적인 작업이 필요한데, 그건 하지 않기로 했습니다.

남는 한계 — 이미 커밋된 PNG는 이력에 남는다

첫 번째 한계는 방금 적은 이력입니다. 바이너리 545개는 저장소를 복제하는 모든 사람이 내려받습니다. 이력에서 지우려면 과거 커밋을 다시 써야 하고, 그 작업은 이미 받아 간 사본과 충돌합니다. 혼자 쓰는 저장소라도 되돌릴 수 없는 작업이라 승인 없이 하지 않는 항목으로 두었습니다. 지금은 앞으로 늘지 않게 막는 데서 멈춰 있습니다.

두 번째 한계는 측정 자체입니다. 정리 전 값은 571이라는 정수인데 정리 후 값은 '한 자릿수'라는 범위입니다. 개선기의 전후 비교로는 반쪽입니다. 정리 직후 status를 저장해 두었다면 정확한 값이 남았을 텐데, 그때는 줄었다는 사실에 만족하고 숫자를 적지 않았습니다. 다음에 같은 종류의 정리를 하면 전후 출력을 파일로 남기는 게 먼저입니다.

세 번째 한계는 추적 해제의 대가입니다. 큐와 발행 목록을 git에서 빼면 다른 PC에서 저장소를 받았을 때 그 파일이 없습니다. cron은 큐가 있어야 다음 주제를 고르니, 새 환경에서는 큐를 처음부터 다시 만들거나 옮겨 와야 합니다. 상태 파일의 원본이 한 대의 PC에만 있다는 뜻이고, 그 PC가 사라지면 발행 순서도 함께 사라집니다.

네 번째 한계는 발행 이력입니다. 어느 날 어떤 카드를 올렸는지는 git이 아니라 발행 목록 파일이 알고 있었는데, 그 파일도 이제 추적하지 않습니다. 이력이 필요하면 별도 기록이 있어야 합니다. 여러 프로세스가 같은 기록 파일을 고쳐 쓰다 내용을 잃은 경험은 Claude Code 병렬 세션의 기록 유실을 0건으로 만든 기록에 따로 적었고, 상태 파일을 어디에 둘지는 그 글의 문제와 같은 뿌리입니다.

생성 파이프라인이 있는 저장소에서 무엇을 추적해야 하나

이번 정리에서 남은 판단 기준은 세 줄입니다. 스크립트가 다시 만들 수 있는 파일은 무시한다. 스크립트가 고쳐 쓰는 파일은 추적을 푼다. 사람이 쓰는 파일과 그것을 산출물로 바꾸는 코드는 추적한다. 이 기준을 생성기를 만드는 순간에 적용하면 무시 규칙을 노이즈가 보인 뒤에 뒤따라 넣는 일이 사라집니다.

특히 조심할 자리는 자동화가 처음 돌아가는 날입니다. 그날은 큐도 발행 목록도 새 파일이라 무심코 함께 커밋하기 쉽습니다. 한 번 커밋하면 그 파일은 무시 규칙이 닿지 않는 자리로 넘어가고, 매일 바뀌는 4줄이 status에 눌러앉습니다. 이번 저장소에서 두 번의 무시 규칙이 통하지 않은 이유가 정확히 그 첫날의 커밋이었습니다.

이 저장소는 전자책 하나를 알리려고 초안 18편, 카드 수백 장, 릴스 대본 5종을 스크립트로 찍어 냈습니다. 같은 구조는 블로그와 SNS 콘텐츠를 자동으로 만드는 모든 저장소에 그대로 나타납니다. 콘텐츠 생성 파이프라인을 세우고 있고 저장소가 산출물로 부풀기 시작했다면 상담에서 이 정리의 기준표부터 같이 볼 수 있습니다.

마지막으로 이번 글이 감춘 게 없도록 하나만 더 적습니다. 무시 규칙 두 번은 틀린 조치가 아니라 부족한 조치였습니다. 세지 않고 고친 게 문제였고, 세고 나니 노이즈가 두 종류라는 사실이 바로 보였습니다. 571이라는 숫자를 경로별로 쪼개는 데 걸리는 시간은 몇 분이고, 그 몇 분을 아끼려다 같은 일을 세 번 했습니다.

같은 방식으로 우리 업무를 재보고 싶다면

이 글에 쓴 계측·판정·자동화는 저희가 실제로 매일 돌리는 방식 그대로입니다. 어떤 작업을 자동화할 수 있고 어디를 사람이 잡아야 하는지, 현재 업무 흐름을 놓고 같이 짚어 드립니다.

새 글이 올라오면 알려 드립니다

이런 계측 기록을 새로 쓰면 메일로 한 통 보냅니다. 광고나 판촉은 보내지 않습니다.