지난 3월, 저는 호스팅 업체가 제공하는 백업으로 충분하다고 착각한 나머지 저녁 시간을 날렸습니다. 하지만 그렇지 않았습니다. 제 1 vCPU / 2 GB RAM 박스에서 매일 밤 찍는 스냅샷은 단 7일치만 보관했고, 저는 11일 전의 CSV 파일이 필요했습니다. 그것은 제가 이미 제출했던 40개 에셋 배치에 대한 Adobe용 5열 업로드 파일이었습니다. 이를 재구축하려면 제가 이후 이름을 바꾼 파일 폴더를 대상으로 make_metadata.py 스크립트를 다시 실행해야 했습니다. 결국 되찾았지만, 오직 저에게는 하나의 허술한 습관 덕분이었습니다. 바로 청소하지 않았던 _system 폴더가 있었습니다. 그 순간을 계기로 백업은 더 이상 사후 고려 사항이 아니라 제 파이프라인에 설계된 필수 부분이 되었습니다.
작은 서버 하나에 온 사업이 걸려 있을 때 실제로 작동하는 방식은 다음과 같습니다.
무엇을 백업해야 하는지 알기
제 카탈로그는 39개의 완성된 제품과 856 MB의 압축 출력물로 구성되어 있습니다. 이 수치는 전략을 결정하기 때문에 중요합니다. 856 MB는 버전 관리(version)나 동기화(sync)를 하기에 충분히 작은 크기이지만, 그 뒤에 있는 원자재는 그렇지 않습니다. 상위 프로젝트에는 약 19,000줄의 파이프라인 코드와 300페이지가 넘는 리서치 노트가 담겨 있습니다. 만약 ZIP 파일만 백업한다면, 어떤 것도 재생성하거나 재포장할 수 있는 능력을 잃게 됩니다.
그래서 저는 카탈로그를 세 가지 계층으로 나눴습니다:
- 대체 불가능하고 작은 데이터: 메타데이터 CSV, 업로드 추적 장부(upload tracker ledger), 제목 및 키워드 JSON, 리서치 노트. 몇 킬로바이트에 불과합니다. 이것들은 매일 버전 관리 시스템(version control)과 원격 동기화(remote sync)를 거칩니다.
- 재생성 가능하지만 비용이 많이 드는 데이터: 제품 ZIP 파일, 커버, 썸네일 등 856 MB의 자료. 주간 단위로 서버 외부와 동기화합니다.
- 원자재 에셋(Raw assets): 가장 큰 폴더이며, 만약 제가 해야 한다면 완전히 복제하기보다는 재생성하는 데이터입니다.
제가 이전에 저지른 실수는 모든 것을 똑같이 취급한 후, 아무것도 제대로 백업하지 않은 것이었습니다.
CSV 파일이 진정한 보석입니다
사람들은 예술 작품을 백업하고 메타데이터는 잊어버립니다. 그것은 역행입니다. 예술 작품은 디스크의 파일로 존재합니다. 메타데이터는 의사결정을 인코딩합니다: 어떤 제목, 어떤 키워드, 어떤 순서. 세 채널 모두 잘못된 CSV 헤더를 즉시 거부합니다. Adobe는 5개 열의 헤더를 원하고, Vecteezy는 4개 열을 원하며, Dreamstime은 15개 열을 원합니다. make_metadata.py는 각 플랫폼이 요구하는 정확한 헤더만을 작성하지만, 출력물은 여전히 의사결정 기록입니다. 만약 CSV가 사라지고 소스 파일 이름까지 바뀌었다면, 당신은 단순히 스크립트를 다시 실행하는 것이 아니라 편집 작업을 처음부터 다시 해야 합니다.
upload_tracker.py도 마찬가지입니다. 이 원장(ledger)이 재실행을 안전하게 만드는 것입니다. 스톡 계정을 플래그 지정당하는 가장 빠른 방법은 배치 파일을 중복 게시하는 것이므로, 트래커가 완료된 모든 자산을 기억하도록 해야 합니다. 트래커 파일이 없으면 무엇을 이미 제출했는지 알 수 없습니다. 이렇게 작은 파일은 매 배치 실행 후에 커밋되어야 합니다. 제 것은 그렇습니다.
2GB 박스에서의 백업에는 자체 규칙이 필요합니다
렌더링에 영향을 주는 것과 같은 제약 조건들이 백업에도 적용됩니다. vCPU 하나는 아카이브 작업까지 포함하여 한 번에 하나의 프로세스만 의미합니다. 렌더가 진행 중일 때 tar나 rsync를 실행하면 OOM(Out-of-Memory) 킬이 발생하고 아카이브가 손상될 수 있습니다.
제가 경험한, 고통을 절감한 순서대로의 습관들은 다음과 같습니다:
- 어떤 작업도 예약하기 전에 최대 RSS(Resident Set Size)를 측정하세요.
resource.getrusage(RUSAGE_SELF).ru_maxrss가 실제 한계를 알려줍니다. 제 아카이브 작업들은 제한치보다 훨씬 낮은 수준에서 최고치를 찍지만, cron 슬롯에 신뢰하기 전에 확인해 보는 것이 좋습니다.
- 항목 간 메모리를 확보하세요. 각 에셋 처리 후
gc.collect()를 실행하는 것이 렌더링과 같습니다. 수천 개의 작은 파일을 거치는 긴 백업 루프는 이것 없이는 메모리 누수가 발생합니다.
- 무거운 단계에서는 서브프로세스당 파일 하나만 사용하세요. 메모리가 OS로 반환됩니다. 저는 단일하고 오래 지속되는 Python 프로세스 내에서 배치 압축을 절대 하지 않습니다.
- 필요한 해상도로 렌더링하세요. 이것도 백업 규칙입니다. 300dpi 대신 60dpi로 미리보기를 검사하면, 아카이브를 거치는 검증 과정이 RAM 예산을 초과하는 것을 막아줍니다.
- 백업이 아닌 복원을 검증하세요. 한 달에 한 번은 제품 zip 파일 하나와 CSV 파일 하나를 임시 폴더에 복원하여 열어봅니다. 테스트되지 않은 백업은 희망일 뿐, 진정한 백업이 아닙니다.
폴더 레이아웃이 곧 백업 계획입니다
이 키트가 가정하는 구조는 계층적 백업을 가능하게 하는 요인이기도 합니다:
project/
assets/ 원시 출력물 (에셋당 파일 하나)
output/ 제출 준비 완료된 파일 + metadata.csv
...
각 계층은 폴더에 매핑되므로, 각 폴더는 자체적인 스케줄과 자체적인 보존 기간을 가집니다. research/ 폴더가 가장 강력한 보호를 받습니다. 저는 한때 '정리'하기 위해 리서치 노트를 삭제했다가 미래 제품의 원자료를 잃은 적이 있습니다. 다시는 이런 일이 없도록 합니다. 여러분의 스크랩 로그와 노트는 다음 제품을 위한 입력 자료입니다. 2GB짜리 작은 박스에 디스크 공간을 절약하기 위해 그것들을 삭제하는 것은 전체 리서치 폴더가 단일 제품 zip 파일보다 작기 때문에 잘못된 경제적 판단입니다.
Cron, 보존 기간, 그리고 정직한 한계
저는 세 가지 작업을 실행합니다: 트래커, CSV, 노트의 일일 커밋; packs/와 output/의 주간 동기화; 월별 검증 복원. 서버 자체의 보존 기간은 디스크가 부족하기 때문에 짧지만, 오프서버 사본이 진정한 백업입니다. 서버 사본은 복원을 빠르게 하기 위해서만 존재합니다.
제가 갖지 못한 것은 전체 파이프라인을 실행할 수 있는 DR(재해 복구) 사이트입니다. 만약 장비가 고장 나더라도 모든 제품과 모든 CSV 파일을 복원하여 판매를 계속할 수는 있지만, 1 vCPU 런타임을 재구축하는 데는 오후의 설정 시간이 필요합니다. 39개 제품을 운영하는 개인 작업자에게 있어서 이 교환은 정직하고 받아들일 만합니다. 그렇지 않다고 가장하는 것은 아직 필요하지 않은 인프라에 비용을 지불한다는 의미가 될 것입니다.
출처
이 모든 것은 이론이 아닙니다. 제 키트에 있는 네 개의 스크립트, make_metadata.py, upload_tracker.py, md2pdf.py, 그리고 pack_product.py는 39개 제품 전체를 패키징했고 정확히 이 하드웨어에서 실행되었습니다: 1 vCPU, 2 GB RAM, GPU 없음. 이들이 강제하는 메타데이터 규칙은 각 플랫폼이 실제로 거부하는 것에 대한 300페이지 이상의 연구에서 나왔습니다. 위에 언급된 백업 습관들은 그 스크립트들을 둘러싼 운영 계층이며, 제가 지난 3월 저녁을 그것들이 없어서 날렸기 때문에 문서화한 것입니다.
저는 이 모든 것을 컴플라이언스 메타데이터 키트로 패키징했습니다: 네 개의 독립형 Python 스크립트, 폴더 레이아웃, 그리고 이를 작은 서버에서 모두 실행하는 방법에 대한 메모입니다. 총 두 가지의 타사 패키지, Pillow와 reportlab이 필요합니다. 두 메타데이터 스크립트는 표준 라이브러리 외에는 아무것도 필요하지 않습니다. 만약 당신이 같은 종류의 파이프라인을 구축하고 있다면, 이것은 제가 이 정확한 작업으로 만든 도구입니다.
컴플라이언스 메타데이터 키트 받기
디지털 제품을 제작하시나요? 디지털 제품 판매자를 위한 무료 가이드 및 키트.