지난 3월, 저는 헤더 행 때문에 주말 전체를 날렸습니다. Adobe Stock에 올릴 60장의 JPG 파일과 스프레드시트에서 직접 만든 CSV 파일을 준비하고 제출 버튼을 눌렀죠. 그리고 1분도 안 되어 거절 통보가 왔습니다. 검토 단계의 거절도, 품질 문제도 아니었습니다. 파일이 그 단계까지 가지 못했어요. 파서(parser)가 제 헤더 행 때문에 막히면서 전체 배치가 실패한 겁니다. 헤더를 고치고 재제출했지만, 이번에는 다른 컬럼 때문에 또다시 거절당했습니다. 그때 저는 추측을 멈추고, 이 헤더들을 코드로 한 번에 기록하기 시작했습니다.
이 과정은 가장 화려하지 않고 가장 비용이 많이 드는 파이프라인의 일부이기 때문에, 제가 왜 이런 일이 발생하는지 배운 내용을 공유합니다.
파서는 사람이 검토하기 전에 먼저 읽는다
모든 스톡 플랫폼은 CSV 파일을 기계적으로 점검합니다. Adobe Stock, Vecteezy, Dreamstime 모두 이 과정을 거칩니다. 이 점검은 단일 에셋을 검증하기 전에 컬럼 개수와 컬럼 순서를 확인합니다. 이것을 잘못하면 콘텐츠 검토가 아니라 메타데이터 오류를 받게 됩니다. 기다리는 시간도 없고, 배울 것도 거의 없으며, 스프레드시트를 디버깅하는 동안 파일들은 제출되지 못한 채 머물러 있습니다.
컬럼 개수는 고정되어 있으며 플랫폼마다 다릅니다:
- Adobe Stock: 5개 컬럼. Filename, title, keywords, category, releases.
- Vecteezy: 4개 컬럼. Filename, title, keywords, category.
- Dreamstime: 15개 컬럼. 세 플랫폼 중 가장 넓은데, 빈 컬럼 하나가 뒤의 모든 것을 이동시키기 때문에 수동으로 만든 CSV에서 가장 자주 문제가 발생하는 부분입니다.
함정은 이들이 충분히 비슷해 보여서 우리의 뇌가 빈 부분을 채우게 된다는 것입니다. Adobe의 5개 컬럼 헤더는 Vecteezy에서 작동하지 않습니다. Dreamstime의 15개 컬럼도 5개 컬럼 행을 허용하지 않을 겁니다. 저는 세 가지 조합 모두를 시도했기 때문에 이 사실을 압니다.
제가 수동으로 CSV를 편집하는 것을 멈춘 이유
스프레드시트는 40번 반복해서 사용해 보기 전까지는 안전하다고 느껴집니다. 실패 모드는 모두 지루합니다: 가짜 16번째 열을 만드는 후행 쉼표, 플랫폼이 원하는 구분자 대신 쉼표를 붙여넣은 키워드 필드, 존재하지 않는 파일을 가리키는 잘못된 확장자를 가진 파일 이름 등입니다. 이 모든 것이 배치(batch) 처리를 실패시키고, 일부 플랫폼은 사람이 작업물을 보기 전에 반복적으로 실패한 제출 건수를 누적하여 감점합니다.
그래서 저는 make_metadata.py를 작성했습니다. 이 스크립트는 폴더의 파일들과 플랫폼 플래그를 받아서, 해당 플랫폼이 요구하는 정확한 헤더만 그리고 그 외에는 아무것도 쓰지 않습니다:
python make_metadata.py ./my-assets --platform adobe --out metadata.csv --ext .jpg
python make_metadata.py ./my-assets --platform vecteezy --out vecteezy.csv --ext .jpg
python make_metadata.py ./my-assets --platform dreamstime --out dreamstime.csv --ext .jpg
이 스크립트는 파이썬 표준 라이브러리만 사용하므로 설치할 것이 없습니다. 제목은 기본적으로 파일 이름의 Title Case(제목 대문자)로 설정되는데, 이는 첫 번째 시도에는 괜찮지만 제출하기 전에 실제 제목과 키워드로 교체해야 합니다. 이를 위해 --titles titles.json 플래그가 있습니다.
자동화가 당신을 공격하는 두 번째 방법: 중복 업로드
CSV 파일이 올바르게 준비되었다면, 다음 기계적 거부 위험은 바로 '당신'입니다. 같은 배치를 두 번 실행하는 경우죠. 저도 초기에 이런 실수를 했습니다. 업로드 스크립트를 재실행하자 동일한 파일 이름들이 다시 올라갔고, 중복 제출은 계정이 플래그(flagged)를 받기 가장 빠른 방법 중 하나입니다. 어떤 플랫폼도 같은 기여자로부터 같은 에셋을 두 번 올리는 것을 원하지 않습니다.
해결책은 간단하지만 효과적입니다: 원장(ledger). upload_tracker.py는 이미 업로드한 내용을 평문으로 기록합니다.
python upload_tracker.py pending items.txt # 아직 완료되지 않은 항목을 보여줌
python upload_tracker.py done
배치 실행 전에 `pending`을 확인하세요. 파일이 원장(ledger)에 없으면 업로드됩니다. 있으면 그렇지 않습니다. 이것은 표준 라이브러리만 사용합니다. 두 개의 스크립트, 제로 의존성으로, 제가 가장 많은 시간을 낭비하게 했던 두 가지 실패 모드를 제거했습니다.
## 이것이 중요한 지루한 수학적 이유
예술적인 부분이 아마 작업의 3분의 1 정도일 것입니다. 39개의 완성된 제품을 만들고 약 856 MB의 출력을 생성했던 상위 프로젝트에서, 메타데이터 처리, 추적 및 패키징을 담당하는 파이프라인 코드는 대략 19,000줄입니다. 그 비율은 우연이 아닙니다. 창의적인 부분은 프롬프트 하나만 떨어져 있으면 됩니다. 거절당하게 만드는 부분은 헤더 행이며, 검토자가 파일을 열기 전에 조용히 거절시킵니다.
말할 가치가 있는 또 다른 점은 이것입니다. 이 모든 것이 큰 기계를 필요로 하지 않는다는 것입니다. 이미지 생성과 패키징을 포함한 전체 파이프라인은 GPU 없이 1 vCPU와 2 GB RAM으로 실행되었습니다. 그것이 작동하게 만든 습관들은 화려하지 않습니다. 한 번에 하나의 프로세스, 각 에셋 후에 `gc.collect()`를 사용하고, 평균 대신 `resource.getrusage`로 최대 RSS(Resident Set Size)를 측정하는 것입니다. 만약 메타데이터 단계가 2 GB보다 더 많은 메모리를 필요로 한다면, 과도하게 엔지니어링한 것입니다. 5개 열짜리 CSV 파일을 만드는 것은 거의 아무것도 사용하지 않아야 합니다.
## 과거의 나에게 전하고 싶은 말
플랫폼별로 헤더를 코드에 한 번만 작성하세요. 제출용 CSV는 절대 수동으로 편집하지 마세요. 재실행이 이중 게시(double-post)하는 것을 막기 위해 모든 업로드를 원장에 기록하세요. 연구 노트는 영원히 보관하세요. 저는 한때
이 모든 것이 이제 스크립트로 패키징되었습니다. 반복해서 작성하는 것에 지쳤기 때문입니다. 메타데이터 빌더, 업로드 추적기, Markdown-to-PDF 변환기, 그리고 제품을 zip으로 압축하고 1280×720 커버와 600×600 썸네일을 렌더링하는 패키징 스크립트가 한곳에 모여 있습니다. 이들은 앞서 39개 제품을 패키징할 때 사용했던 것들과 동일합니다. 저는 워크플로우, 플랫폼 규칙, 그리고 소규모 서버 운영 습관들을 'ai sticker factory playbook'라는 곳에 정리했습니다. 이것이 바로 이 게시물의 솔직한 버전입니다: 무엇이 망가졌는지, 실제 규칙은 무엇인지, 그리고 제가 그것들이 다시 망가지지 않도록 사용하는 도구들입니다.
첫 번째 배치를 제출할 예정이라면, 헤더부터 수정하세요. 다른 모든 것은 하루 정도 기다려도 됩니다.
[Get ai sticker factory playbook](https://revanzart-shop.revanzart.workers.dev/go/ai-sticker-factory-playbook?src=devto)
_디지털 제품을 제작하고 계신가요? [디지털 제품 판매자를 위한 무료 가이드 및 키트](https://revanzart-shop.revanzart.workers.dev/guides)._
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23