두 개의 Python 패키지와 표준 라이브러리 스크립트로 AI 에셋 비용을 거의 제로에 가깝게 유지하는 방법
요약
스톡 에셋 업로드 시 발생하는 플랫폼별 메타데이터 형식 불일치 문제를 Python 스크립트로 해결하는 방법을 제시합니다. 표준 라이브러리만으로 CSV 생성 및 중복 게시 방지 로직을 구현하여, AI 에셋 비용과 시간을 절약할 수 있습니다.
핵심 포인트
- 플랫폼마다 다른 헤더 요구사항(5개/4개/15개 열)이 주요 문제점입니다.
- 표준 라이브러리(`csv`, `pathlib`)만 사용한 스크립트로 메타데이터를 자동 생성합니다.
- 작업 원장(ledger)을 구현하여 중복 게시(Double-posting)를 방지하는 것이 중요합니다.
- Pillow와 reportlab 같은 최소한의 패키지로 시각적 콘텐츠 제작까지 통합했습니다.
지난 봄, 저는 CSV 헤더 하나 때문에 저녁 시간 전체를 날렸습니다. Adobe Stock용으로 40개의 에셋을 준비했고, 메타데이터 파일을 스프레드시트에서 직접 만들었습니다. 업로드 버튼을 눌렀는데, 전체 배치가 즉시 반송되었습니다. 문제는 헤더 행이었습니다. Adobe의 uploader는 특정 5개 열 형식을 요구하는데, 저는 Vecteezy의 형식을 보고 있었기 때문에 4개 열만 가지고 있었습니다. 일주일 뒤 Dreamstime에서도 같은 실수를 저질렀습니다. 여기서는 15개 열을 요구했습니다. 세 개의 플랫폼, 세 가지 다른 헤더 너비, 그리고 거절당할 때마다 실제 검토 대기열에 도달하기도 전에 리뷰 사이클 비용이 발생합니다.
그날 밤 저는 CSV를 손으로 만들기를 그만두고 대신 스크립트를 작성했습니다. 이 글은 가장 저렴한 조합, 즉 두 개의 Python 패키지와 몇 가지 표준 라이브러리 스크립트가 솔로 에셋 파이프라인에 적합한 답이었던 이유에 관한 것입니다.
메타데이터 문제는 콘텐츠 문제가 아니라 형식 문제입니다
스톡 사이트들은 키워드나 제목을 보고 거절하지 않습니다. 파일 구조를 보고 거절합니다. Adobe의 일괄 업로드 CSV는 고정된 5개 열 헤더를 가지고 있고, Vecteezy는 4개를 사용하며, Dreamstime은 15개를 사용합니다. 단 하나의 열만 잘못해도 사람이 작업물을 보기 전에 업로드가 실패합니다.
그래서 make_metadata.py는 한 가지 일만 합니다. 파일 폴더를 순회하면서 각 플랫폼이 요구하는 정확한 헤더를 작성하고, 그 다음 파일 이름과 선택적 제목 JSON에서 행을 채웁니다. 스프레드시트도 없고, 탭 간 복사/붙여넣기도 없습니다. 이 스크립트 자체는 Python 표준 라이브러리인 csv, pathlib, argparse만을 사용하며, 설치할 것이 전혀 없습니다. 이것은 들리는 것보다 더 중요합니다. 왜냐하면 가상 환경이 필요한 메타데이터 도구는 지칠 때 건너뛰게 되는 도구이기 때문입니다.
솔직한 주의사항: 제목 파일이 없으면 스크립트가 파일 이름을 title-case로 변환하여 그것을 제목으로 사용합니다. 이는 첫 번째 시도에는 괜찮지만 최종 결과물에는 좋지 않습니다. 제출하기 전에 교체하세요. 파일 이름의 제목은 파일 이름의 제목처럼 보입니다.
더블 포스팅(Double-posting)은 플래그가 지정되는 가장 빠른 방법입니다
이것은 저에게 시간뿐 아니라 경고를 안겨주었습니다. 부분적인 실패 후 배치 스크립트를 다시 실행했고, 에셋 세트를 두 번 게시했습니다. 검토 큐에 있는 중복물은 마치 상태가 없는 파이프라인처럼 보입니다.
해결책은 놀라울 정도로 간단합니다. upload_tracker.py는 세 가지 명령을 가진 작은 원장(ledger)입니다: pending은 아직 게시되지 않은 것을 보여주고, done은 항목을 표시하며, status는 개요를 제공합니다. 모든 배치 작업은 먼저 이 원장을 확인합니다. 재실행하더라도 스크립트는 원장이 완료되었다고 말하는 것은 처리하기를 거부하기 때문에 더블 포스팅이 불가능해졌습니다.
이것은 텍스트 파일과 일부 파일 잠금 로직(file locking logic)으로, 모두 표준 라이브러리입니다. 저는 데이터베이스를 고려했지만, 이 규모에서는 필요하지 않은 쿼리 파워보다 cat으로 읽을 수 있는 플랫 파일이 더 가치 있다고 판단했습니다.
의도적으로 선택된 두 개의 패키지
파이프라인의 모든 시각적 요소는 두 가지 종속성(dependency)에 달려 있습니다: 커버와 썸네일을 렌더링하기 위한 Pillow, 그리고 Markdown 구조화된 콘텐츠를 스타일이 적용된 PDF로 변환하는 reportlab입니다. 이것이 전체 requirements.txt 내용입니다.
md2pdf.py는 마크다운 파일을 받아 단 하나의 명령으로 실제 제목, 표, 목록 및 링크가 포함된 깔끔한 PDF를 생성합니다. pack_product.py는 제품 폴더를 zip 파일로 묶고 1280×720 크기의 커버와 600×600 크기의 썸네일을 렌더링합니다. 실제 커버가 있는 zip 파일이 판매됩니다. 아무것도 없는 파일은 숙제처럼 보입니다.
나머지 모든 것은 표준 라이브러리(stdlib)입니다. 종속성이 적다는 것은 깨지는 변경(breaking changes)이 적고, 설치 크기가 작으며, pip가 요청하지 않은 충돌을 해결하느라 밤 11시에 디버깅할 것이 없다는 것을 의미합니다.
2 GB 서버 습관
전체 파이프라인은 1 vCPU, 2 GB RAM, GPU 없이 실행됩니다. 이것은 하드웨어 성능(horsepower) 때문이 아니라 규율(discipline) 덕분에 작동하는 것입니다.
- 한 번에 하나의 프로세스만 처리하세요. 단일 코어에서 이미지 작업을 병렬로 분산(fan out)하지 마세요.
- 각 에셋 처리 후
gc.collect()를 호출하여 배치 전체에 걸쳐 메모리가 누적되는 것을 방지하세요. - 평균 사용량 대신
resource.getrusage(RUSAGE_SELF).ru_maxrss로 최대 RSS(Resident Set Size)를 측정하세요. 피크 값이 시스템을 다운시키는 주범입니다. - 무거운 렌더링 단계는 서브프로세스당 파일 하나씩 실행하여 메모리가 실제로 OS에 반환되도록 하세요.
- 300dpi로 렌더링하는 대신 60dpi에서 미리보기를 검사하세요. 최종 출력에는 전체 해상도가 필요할 때만 합니다.
AI 이미지 생성 자체가 시스템의 유일한 실제 비용이며, 의도적으로 생성할 때(deliberately) 프롬프트를 무작위로 뿌리고 기대하는 것보다 적습니다. 그 외 메타데이터, 추적, PDF, 패키징 등 모든 것은 여러분이 소유한 스크립트이기 때문에 비용이 들지 않습니다.
결과적으로 나온 수치들
이 설정은 약 19,000줄의 파이프라인 코드와 플랫폼이 실제로 허용하는 것에 대한 300페이지가 넘는 연구를 바탕으로, 39개의 완성된 제품과 약 856MB의 출력을 패키징했습니다. 이 모든 것은 동일한 사양인 1 vCPU / 2 GB 장비에서 검증되었습니다.
제가 이 스크립트들이 영리하다고 주장하는 것은 아닙니다. 의도적으로 지루하게 만들었습니다. '지루함'이야말로 자정(midnight)에 재실행했을 때 살아남는 것입니다.
저는 네 개의 스크립트, 폴더 레이아웃, 그리고 설치 노트를 하나의 다운로드로 묶었습니다. 다른 제작자들이 설명 대신 정확한 파일 자체를 계속 요청했기 때문입니다. 이것은 코스가 아니라 파이프라인의 패키징 계층이며, Python 3.9 실행을 전제로 합니다. 이 정보가 유용하다면, 여기에서 확인하세요:
디지털 제품 제작 중이신가요? 디지털 제품 판매자를 위한 무료 가이드 및 키트.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기