테마
Story: 영구 삭제 배치 (7일 경과)
메타
| 항목 | 값 |
|---|---|
| Story ID | E-09-S-07 |
| Epic | E-09 미사용 상품 정리 |
| 상태 | ready-for-dev |
| 우선순위 | P1 |
| 규모 | S |
| 담당 개발자 | BE |
사용자 스토리
As a 시스템,
I want 7일 경과한 삭제 상품을 영구 삭제하고 싶다,
So that DB 스토리지를 효율적으로 관리할 수 있다.
수락 기준 (Acceptance Criteria)
AC-01: 배치 실행
| 항목 | 내용 |
|---|---|
| Given | 매일 새벽 3시에 |
| When | 영구 삭제 배치가 실행되면 |
| Then | 7일 경과한 Soft Delete 상품이 Hard Delete 된다 |
AC-02: 배치 처리 방식
| 항목 | 내용 |
|---|---|
| Given | 대량 삭제 시 |
| When | 배치 단위로 처리하면 |
| Then | DB 락 최소화 (1,000건씩 처리) |
AC-03: 실패 처리
| 항목 | 내용 |
|---|---|
| Given | 배치 실행 중 에러 발생 시 |
| When | 3회 재시도 후 실패하면 |
| Then | 알림 발송 + 로그 기록 |
태스크 분해
Task 1: 배치 작업 구현
- [ ] 1.1: 7일 경과 상품 조회sql
SELECT id FROM Product WHERE deleted_at IS NOT NULL AND deleted_at < DATE_SUB(NOW(), INTERVAL 7 DAY) LIMIT 1000; - [ ] 1.2: 배치 단위 Hard Delete (1,000건씩)
- [ ] 1.3: 트랜잭션 처리
Task 2: 스케줄링
- [ ] 2.1: 매일 새벽 3시 실행 (Cron)
- [ ] 2.2: 중복 실행 방지 (Lock)
Task 3: 모니터링
- [ ] 3.1: 배치 실행 로그
- 시작 시간, 종료 시간, 삭제 건수
- [ ] 3.2: 실패 시 Slack/이메일 알림
- [ ] 3.3: 배치 실행 대시보드 (선택)
배치 스펙
실행 조건
| 항목 | 값 |
|---|---|
| 실행 시간 | 매일 03:00 (KST) |
| 대상 | deleted_at < NOW() - 7 DAY |
| 배치 크기 | 1,000건/트랜잭션 |
| 최대 실행 시간 | 30분 |
| 재시도 | 3회 |
배치 로직
typescript
async permanentDeleteBatch() {
const BATCH_SIZE = 1000;
const SEVEN_DAYS_AGO = subDays(new Date(), 7);
let totalDeleted = 0;
while (true) {
// 1. 대상 조회
const products = await this.productRepo.find({
where: {
deletedAt: LessThan(SEVEN_DAYS_AGO)
},
take: BATCH_SIZE
});
if (products.length === 0) break;
// 2. 배치 삭제
const ids = products.map(p => p.id);
await this.productRepo.delete({ id: In(ids) });
totalDeleted += products.length;
// 3. 로그
this.logger.info(`Batch deleted ${products.length} products`);
// 4. 부하 분산
await sleep(100);
}
return { totalDeleted };
}모니터링
배치 로그 형식
json
{
"job": "product_permanent_delete",
"startedAt": "2026-01-20T03:00:00Z",
"completedAt": "2026-01-20T03:05:23Z",
"status": "success",
"totalDeleted": 1532,
"batchCount": 2,
"duration": "5m 23s"
}알림 조건
| 조건 | 알림 |
|---|---|
| 성공 | 없음 (로그만) |
| 실패 (3회 재시도 후) | Slack 알림 |
| 실행 시간 > 30분 | Slack 알림 |
| 삭제 건수 > 10,000 | 정보성 Slack 알림 |
이벤트 로깅
| 이벤트 | 파라미터 |
|---|---|
batch_permanent_delete_started | scheduled_time |
batch_permanent_delete_completed | total_deleted, duration |
batch_permanent_delete_failed | error_message, retry_count |
생성일: 2026-01-20
