S3 Media Bucket Settings
이 문서는 surfai-vivid의 이미지/비디오 업로드, 생성 결과, 후처리 결과를 저장하는 S3 media bucket 기준을 정리합니다.
현재 기준은 환경별 media bucket 1개 + prefix 분리입니다. 코드에는 아직 S3_TEMP_BUCKET_*, S3_PERMANENT_BUCKET_* 환경 변수가 남아 있으므로, local의 단일 bucket 구성에서는 두 값을 같은 bucket 이름으로 지정할 수 있습니다.
현재 상태
| 환경 | 리전 | 상태 | 버킷 전략 |
|---|---|---|---|
| local | ap-northeast-2 | 생성 완료 | local media bucket 1개, prefix로 raw/final/temp 분리 |
| dev | ap-northeast-2 | 추후 생성 | dev media bucket 1개, local과 같은 prefix 구조 복제 |
| prod | ap-northeast-2 | 추후 생성 | prod media bucket 1개, local과 같은 prefix 구조 복제 |
버킷 기본 설정
| 설정 | 값 |
|---|---|
| Region | ap-northeast-2 |
| Block Public Access | 4개 항목 모두 ON |
| Object Ownership | Bucket owner enforced |
| ACL | 사용하지 않음 |
| Default encryption | SSE-S3부터 시작, 필요 시 prod에서 SSE-KMS 검토 |
| Versioning | local/dev는 OFF, prod는 삭제 복구 정책이 필요해질 때 ON 검토 |
| Public serving | S3 public 공개 금지. backend presigned URL 또는 CloudFront + OAC 사용 |
S3 bucket은 웹 정적 호스팅 bucket이 아니라 사용자 업로드와 생성 결과물을 담는 비공개 저장소입니다. 따라서 public ACL, public bucket policy, anonymous read는 허용하지 않습니다.
Prefix 구조
raw/
temp/
uploads/original/
generation/source/
generation/work-input/
creations/
post-processing/failed/
exports/user-downloads/
| Prefix | 역할 | 보존 정책 |
|---|---|---|
raw/ | ai-node-agent가 ComfyUI/API node 결과를 후처리 전에 올리는 임시 raw output | 짧게 보관 |
temp/ | 워커 공통 임시 파일 | 짧게 보관 |
uploads/original/ | 사용자가 직접 업로드한 원본 파일 | 장기 보관 |
generation/source/ | 결과 히스토리에 보여줘야 하는 생성 입력 원본/참조 이미지 | 최종 결과와 동일하게 보관 |
generation/work-input/ | workflow 실행을 위해 정규화/변환한 작업용 입력 | 제한 보관 |
creations/ | 최종 생성 결과 세트. 원본, 정적 썸네일, 동적 preview를 함께 저장 | 장기 보관 |
post-processing/failed/ | 실패 디버깅용 산출물 또는 로그성 파일 | 제한 보관 |
exports/user-downloads/ | 사용자 다운로드용 export/archive | 제한 보관 |
uploads/resized-preview/는 필수 prefix가 아닙니다. 사용자가 업로드한 원본에 대한 별도 미리보기 파일을 저장해야 할 때만 추가합니다. 최종 생성 결과의 썸네일/preview는 현재 코드 기준으로 creations/ 아래에 원본과 함께 저장합니다.
temp/ai-node-agent/, temp/post-processing-worker/ 같은 하위 prefix도 필수는 아닙니다. worker별 디버깅이나 권한 분리가 필요해질 때 temp/ 아래에 자연스럽게 추가합니다.
현재 코드와의 매핑
현재 코드의 데이터 흐름은 아래와 같습니다.
ai-node-agent
-> S3_TEMP_BUCKET_{ENV}_NAME/raw/{userId}/{creationId}/{filename}
-> SQS post-processing queue
-> post-processing-worker
-> S3_PERMANENT_BUCKET_{ENV}_NAME/creations/{userId}/{creationId}/...
-> backend creation_results
이미지 결과는 creations/{userId}/{creationId}/ 아래에 원본과 thumbnail_{originalFileName}을 저장합니다.
비디오 결과는 같은 prefix 아래에 원본, 정적 썸네일 WEBP, 웹 preview용 MP4를 저장합니다.
백엔드는 creation_results에 다음 경로를 저장합니다.
| 필드 | 의미 |
|---|---|
s3Path | 최종 원본 이미지/비디오 |
staticThumbnailPath | 정적 썸네일 |
dynamicThumbnailPath | 비디오 preview 등 동적 썸네일 |
thumbnailS3Path | 화면 표시용 canonical thumbnail |
local에서 media bucket을 1개만 쓰는 경우 아래처럼 설정합니다.
AWS_REGION=ap-northeast-2
S3_TEMP_BUCKET_LOCAL_NAME=<local-media-bucket-name>
S3_PERMANENT_BUCKET_LOCAL_NAME=<local-media-bucket-name>
이렇게 하면 기존 코드의 temp/permanent 변수명은 유지하면서도 S3 내부에서는 raw/와 creations/ prefix로 역할이 분리됩니다.
Lifecycle 규칙
초기에는 Glacier 전환보다 삭제 가능한 중간 산출물 삭제에 집중합니다. 최종 결과와 사용자에게 보여줄 입력 원본은 자동 삭제하지 않습니다.
| Rule name | Prefix | local 권장 | dev/prod 권장 |
|---|---|---|---|
delete-raw-objects | raw/ | 1-7일 후 삭제 | 1-7일 후 삭제 |
delete-temp-objects | temp/ | 1-7일 후 삭제 | 3-7일 후 삭제 |
delete-work-input-objects | generation/work-input/ | 7일 후 삭제 | 14-30일 후 삭제 |
delete-post-processing-failed | post-processing/failed/ | 14일 후 삭제 | 30-60일 후 삭제 |
delete-export-downloads | exports/user-downloads/ | 3-7일 후 삭제 | 7-14일 후 삭제 |
abort-incomplete-multipart-uploads | 전체 bucket | 7일 후 abort | 7일 후 abort |
다음 prefix에는 기본적으로 lifecycle 삭제 규칙을 걸지 않습니다.
creations/
generation/source/
uploads/original/
raw/는 post-processing-worker가 성공 시 삭제하지만, 실패나 중단 상황에 대비해 lifecycle을 안전망으로 둡니다.
접근 방식
초기 local 개발은 backend가 발급하는 presigned URL로 S3 객체를 서빙합니다. 트래픽, 캐싱, 다운로드 성능, 도메인 정책이 중요해지는 시점에 CloudFront + OAC를 붙입니다.
권한은 환경별로 분리합니다.
- local credential은 local bucket과 local SQS queue에만 접근합니다.
- dev credential은 dev bucket과 dev SQS queue에만 접근합니다.
- prod는 장기 access key 대신 IRSA 또는 동급의 workload identity를 사용합니다.
- local/dev credential은 prod bucket에 접근하지 못해야 합니다.