Skip to content

업로드 파이프라인

truloop-media-service의 스트리밍 업로드 흐름, 202 Accepted 패턴, S3 multipart 업로드 구현을 설명합니다.


업로드 흐름 개요


202 Accepted 패턴

업로드 요청 시 파일을 S3에 저장한 직후 즉시 응답합니다. 이미지/비디오 변환은 백그라운드에서 비동기 처리됩니다.

Client → [업로드] → 202 Accepted (즉시 반환)

              [SQS + Redis 큐 발행]

              [MediaWorker: Redis 폴링] → 변환 생성 → SQS → truloop-core 알림

주의

에러 처리: SQS 발행이 실패하면 이미 업로드된 S3 파일을 삭제하고 idempotency key도 정리합니다. Redis 큐 Push 실패는 업로드를 실패시키지 않으며 로그만 기록합니다 (SQS가 primary).

응답 예시

json
{
    "eid": "ABC123XYZ",
    "url": "https://cdn.truloop.app/users/.../uuid.jpg",
    "status": "processing",
    "uploaded_at": "2026-03-10T12:00:00Z",
    "message": "File uploaded successfully as PHOTO"
}

정보

202 Accepted는 "요청은 수락되었지만 처리는 아직 완료되지 않았다"를 의미합니다. 클라이언트는 eid를 사용하여 이후 상태를 추적할 수 있습니다. eid는 TSID로 생성됩니다.


S3 업로드 전략

파일 크기에 따라 최적의 업로드 방식을 자동 선택합니다.

파일 크기업로드 방식설명
< 100MBPutObject (단일 업로드)AWS 권장 방식, 오버헤드 최소화
>= 100MBMultipart Upload청크 분할 후 병렬 업로드

Multipart Upload 처리 과정

Multipart 초기화

CreateMultipartUpload로 업로드 세션을 시작합니다.

동적 청크 분할 및 병렬 업로드

파일 크기에 따라 청크 크기가 자동 결정됩니다. Worker Pool을 통해 병렬 업로드합니다.

ETag 수집

각 청크 업로드 완료 시 반환되는 ETag를 수집합니다.

Multipart 완료

모든 ETag를 포함하여 CompleteMultipartUpload를 호출합니다. 실패 시 AbortMultipartUpload를 호출합니다.

동적 청크 크기

파일 크기청크 크기
< 1GB10MB
1GB ~ 5GB25MB
>= 5GB100MB

Dynamic Worker Pool

  • Worker 수는 CPU 코어 기반으로 자동 결정: numCPU * 3 (I/O bound 최적화)
  • 최소 Worker 수: max(maxWorkers/2, 1)
  • 최대 Worker 수: MAX_S3_UPLOAD_WORKERS (0이면 자동 감지)
  • 부하에 따라 동적으로 Worker 수 조정 (큐 크기 기반)

메모리 최적화

기법설명
Zero-copy Streaming전체 파일을 메모리에 로드하지 않고 청크 단위로 S3에 전송
Buffer Pool재사용 가능한 sync.Pool 기반 버퍼 풀로 GC 부담 감소 (bufpool 패키지)
Size-adaptive Buffers파일 크기에 따라 5MB/10MB/25MB/100MB 풀에서 버퍼 할당

Idempotency (중복 방지)

Redis를 사용하여 중복 업로드를 방지합니다.

항목설명
키 구조{idempotency_key}:loop:{loop_eid} → 상태 + 결과 매핑
범위loop_eid 단위 (같은 룹 내 중복 키 방지)
TTL1년
상태processing (진행 중) → completed (완료)
헤더Idempotency-Key 요청 헤더로 전달
용도네트워크 재시도 중복 방지, 비즈니스 로직 중복 업로드 방지

흐름


파일 검증

업로드 전 다음 항목을 검증합니다:

검증 항목규칙
파일 확장자이미지: .jpg, .jpeg, .png, .gif, .webp, .bmp, .tiff
비디오: .mp4, .mov, .avi, .mkv, .webm, .m4v, .flv
파일 크기최대 2GB (Content-Length 검사)
필수 필드file (multipart), loop_eid
미디어 타입Internal API에서는 type 파라미터 필수 (PHOTO, VIDEO, POSTER, HIGHLIGHT)

제한 사항

서버 과부하를 방지하기 위한 제어:

항목기본값
파일 크기 제한2GB
읽기/쓰기 타임아웃30분
Multipart 메모리 버퍼32MB
MaxHeaderBytes1MB

큐 메시지

업로드 완료 시 (이중 발행)

업로드 직후 SQSRedis Job Queue 양쪽에 메시지를 발행합니다.

용도소비자
SQS (media-upload-queue)서비스 간 이벤트truloop-core
Redis (media:jobs)내부 처리 작업MediaWorker

media-ready-queue (변환 완료 시)

MediaWorker가 변환 처리 완료 후 SQS에 MediaReadyMessage를 발행합니다. truloop-core의 SQS Consumer가 이를 폴링하여 미디어 상태를 업데이트합니다.

정보

비디오의 경우, 썸네일 생성과 트랜스코딩이 병렬로 실행되며 각각 독립적인 media-ready-queue 메시지를 발행합니다 (incremental visibility).


변경 이력

날짜내용
2026-03-10소스 코드 기반 전면 검증: 업로드 흐름 다이어그램 (크기 기반 전략, Redis), 에러 처리 힌트, 응답 예시, 동적 청크 크기, Worker Pool (numCPU*3), Idempotency (composite key, CheckAndReserve), 파일 검증 (확장자 목록), 이중 큐 발행