Phantom File
SNS 파일 공유 시 서버 영구 기록 및 만료 누락 문제를 해결하는 휘발성 보안 파일 공유 서비스
$5 미만
월 운영비
671ms
P99 응답 속도
100%
장애 재처리 성공률
0건
요청 유실
이벤트 기반 후처리 파이프라인 - 설계 문서
파일 만료 후 S3 삭제까지의 안정적인 비동기 파이프라인 설계 과정
Problem
→ 만료된 파일이 S3에 잔존하면 스토리지 비용 누수와 서비스 신뢰도 문제가 발생합니다.
파일 만료 후 S3 객체와 DB 레코드가 남아있으면 두 가지 문제가 생깁니다. 첫째, 삭제되지 않은 S3 객체가 누적되어 스토리지 비용이 지속적으로 누수됩니다. 둘째, 만료된 URL이 여전히 살아있는 것처럼 보여 서비스 신뢰도가 훼손됩니다. 처음에는 Lambda가 만료 시간을 주기적으로 체크해서 직접 삭제하는 크론잡 방식을 고려했습니다.
- ▸크론잡이 실행 중 실패하면 해당 배치 전체가 유실되어 삭제되지 않은 파일이 잔존
- ▸Lambda 타임아웃(최대 15분) 내에 처리해야 하는 건수 한계 — 만료 파일이 많으면 처리 불가
- ▸만료 즉시 처리가 아니라 주기적 처리라 삭제까지 지연이 발생
- ▸재처리 로직을 직접 구현해야 하며, 실패 건 추적과 복구가 복잡함
Trade-off
→ 크론잡의 배치 유실·재처리 한계를 해결하기 위해 이벤트 기반 파이프라인을 선택했습니다.
장점
- 구현이 단순하고 직관적
- 추가 AWS 서비스 불필요
단점
- 실행 중 실패 시 해당 배치 전체 유실
- Lambda 타임아웃(최대 15분) 내 처리 건수 한계
- 만료 즉시 처리가 아닌 주기적 처리로 삭제 지연 발생
- 재처리 로직을 직접 구현해야 하며 실패 건 추적이 복잡
장점
- TTL 만료 시 자동으로 이벤트 발생 — 크론 스케줄링 불필요
- SQS가 메시지를 보존하므로 Lambda 실패 시에도 자동 재시도 보장
- 최종 실패 메시지는 DLQ로 격리되어 수동 재처리 가능
- EventBridge Pipes 필터로 TTL 만료 삭제만 골라내어 불필요한 Lambda 호출 제거
- 각 단계별 독립적 모니터링 가능
단점
- 파이프라인 구성 복잡도 증가 (5개 서비스 연동)
- TTL 만료와 Streams 이벤트 발행 사이 최대 수십 분 지연 가능
- 디버깅 시 여러 서비스 로그를 추적해야 함
의사결정
크론잡 방식은 배치 실패 시 전체 유실, 타임아웃 한계, 재처리 구현 부담이 있어 선택하지 않았습니다. 이벤트 기반 파이프라인은 SQS가 메시지를 보존하고 Lambda 실패 시 자동 재시도하며, 최종 실패는 DLQ로 격리하기 때문에 데이터 유실 없이 안정적인 후처리가 보장됩니다.
Trade-off: EventBridge에서 Lambda를 바로 트리거하면 재시도 보장이 약합니다. SQS를 중간에 넣은 이유는 메시지 보존과 자동 재시도, DLQ 격리를 통해 Lambda가 오류를 던져도 메시지가 SQS에 남아있어 데이터 유실이 없기 때문입니다.
Architecture
→ TTL → Streams → Pipes → SQS → Lambda 5단계 파이프라인으로 크론 없이 만료 즉시 후처리를 수행합니다.
각 컴포넌트가 명확한 역할을 담당합니다. DynamoDB TTL이 만료 시각에 레코드 삭제 이벤트를 발생시키고, Streams가 이를 캡처합니다. EventBridge Pipes가 TTL 만료로 인한 삭제만 필터링하여(수동 삭제와 구분) SQS로 전달합니다. SQS는 메시지 보존·재시도 관리·DLQ 연결을 담당하며, 이 단계가 있어야 Lambda 실패 시 재처리가 보장됩니다. 최종적으로 Cleanup Lambda가 실제 S3 삭제 및 후처리를 수행합니다.

구현 흐름
- 1DynamoDB TTL: 만료 시각이 되면 자동으로 레코드 삭제 이벤트 발생
- 2DynamoDB Streams: TTL 삭제 이벤트를 캡처하여 순서대로 기록
- 3EventBridge Pipes: eventName == REMOVE 필터로 TTL 만료 삭제만 골라냄 (수동 삭제와 구분)
- 4SQS Main Queue: 메시지 보존 + 자동 재시도 + DLQ 연결 — Lambda 실패 시에도 이벤트 유실 없음
- 5Cleanup Lambda: S3 DeleteObject 실행으로 실제 파일 삭제 수행
- 6DLQ: 반복 실패 메시지를 격리하여 수동 재처리 가능
Verification
→ Lambda에 의도적 오류를 주입하여 SQS 재시도 → DLQ 격리 → 수동 재처리까지 전 과정을 검증했습니다.
장애 주입 테스트로 파이프라인의 안정성을 검증했습니다. Lambda에 의도적으로 오류를 발생시킨 후, SQS가 자동 재시도하고 최종 실패 시 DLQ에 격리되는 과정을 단계별로 확인했습니다. DLQ에 격리된 메시지를 수동으로 Main Queue에 재투입하여 최종 성공까지 확인했습니다.
100%
장애 주입 재처리 성공률
Lambda 강제 오류 → SQS 재시도 → DLQ 격리 → 수동 재처리까지 전 과정 성공
0건
이벤트 유실
SQS 메시지 보존으로 Lambda 오류 시에도 메시지가 큐에 남아 유실 없음
- Lambda에 의도적 오류 발생 → SQS 자동 재시도(maxReceiveCount 도달) → DLQ 격리 확인
- DLQ에 격리된 메시지를 수동으로 Main Queue에 재투입하여 S3 파일 삭제 최종 성공 확인
- 파이프라인 각 단계(Streams → Pipes → SQS → Lambda → DLQ)의 이벤트 전달 정상 동작 확인
Retrospective
→ TTL-Streams 간 지연과 DLQ 알람 미설정은 향후 개선이 필요한 항목입니다.
한계점
TTL 만료와 Streams 이벤트 발행 사이에 AWS 공식 문서 기준 최대 수십 분의 지연이 발생할 수 있습니다. 즉시성이 필요한 서비스라면 이 아키텍처는 적합하지 않습니다.
보완 방향
현재 서비스 특성상 수십 분 지연은 허용 가능한 수준이지만, 즉시 삭제가 필요한 경우 Lambda에서 만료 시각을 직접 체크하여 Pre-signed URL 발급을 차단하는 방어 로직을 병행할 수 있습니다.
한계점
현재 DLQ에 메시지가 쌓여도 알람이 설정되어 있지 않아, 실제 운영 환경에서는 실패 건을 인지하지 못할 수 있습니다.
보완 방향
CloudWatch 알람으로 DLQ 메시지 수(ApproximateNumberOfMessagesVisible) 증가 시 SNS/Discord 알림을 발송하도록 구성하면 실패 건을 즉시 인지하고 대응할 수 있습니다. 향후 개선 항목으로 기록합니다.