테마
Story: 기존 쿼리 Soft Delete 대응
메타
| 항목 | 값 |
|---|---|
| Story ID | E-09-S-08 |
| Epic | E-09 미사용 상품 정리 |
| 상태 | ready-for-dev |
| 우선순위 | P0 |
| 규모 | M |
| 담당 개발자 | BE |
사용자 스토리
As a 시스템,
I want 기존 쿼리에서 삭제된 상품을 제외하고 싶다,
So that 삭제된 상품이 화면에 노출되지 않는다.
수락 기준 (Acceptance Criteria)
AC-01: 상품 목록 조회
| 항목 | 내용 |
|---|---|
| Given | 원가입력, 상품관리 등에서 |
| When | 상품 목록을 조회하면 |
| Then | deleted_at IS NULL 조건이 자동 적용된다 |
AC-02: 정산 연동
| 항목 | 내용 |
|---|---|
| Given | 정산 데이터 조회 시 |
| When | 상품 정보를 JOIN하면 |
| Then | 삭제된 상품 참조는 유지되지만 신규 연결 불가 |
AC-03: 진단 API
| 항목 | 내용 |
|---|---|
| Given | 광고 진단 API에서 |
| When | 상품별 분석을 수행하면 |
| Then | 삭제된 상품은 분석 대상에서 제외 |
태스크 분해
Task 1: 영향 범위 분석
- [ ] 1.1: Product 테이블 참조 쿼리 목록 작성
- [ ] 1.2: 수정 필요 쿼리 식별
- [ ] 1.3: 우선순위 결정
Task 2: Repository 레이어 수정
- [ ] 2.1: ProductRepository 기본 조회에 deleted_at IS NULL 추가
- [ ] 2.2: 삭제 상품 포함 조회 옵션 (includeDeleted)
- [ ] 2.3: 단위 테스트
Task 3: 주요 API 수정
- [ ] 3.1: 원가입력 API
- [ ] 3.2: 상품관리 API
- [ ] 3.3: 진단 API (상품별 분석)
- [ ] 3.4: 정산 조회 API (상품 참조)
Task 4: 통합 테스트
- [ ] 4.1: 삭제 상품 미노출 테스트
- [ ] 4.2: 과거 정산 데이터 정합성 테스트
- [ ] 4.3: 성능 테스트 (인덱스 활용)
수정 대상 쿼리 목록
| API/기능 | 쿼리 위치 | 수정 내용 |
|---|---|---|
| 원가입력 목록 | ProductRepository.findBySeller | WHERE deleted_at IS NULL 추가 |
| 상품 상세 | ProductRepository.findById | WHERE deleted_at IS NULL 추가 |
| 진단 - 상품별 | DiagnosisService.byProduct | WHERE p.deleted_at IS NULL 추가 |
| 정산 조회 | SettlementRepository.find | Product JOIN 시 삭제 상품 참조 유지 |
| 마진룸 설정 | MarginRoomRepository.find | 삭제 상품 제외 |
개발 노트
Repository 수정 예시
typescript
// ProductRepository
@Entity()
export class Product {
// ... 기존 필드
@Column({ type: 'datetime', nullable: true })
deletedAt: Date | null;
@Column({ length: 50, nullable: true })
deletedBy: string | null;
}
// 기본 조회 (삭제 상품 제외)
async findBySeller(sellerId: string, options?: FindOptions) {
return this.find({
where: {
sellerId,
deletedAt: IsNull(),
...options?.where
},
...options
});
}
// 삭제 상품 포함 조회 (필요 시)
async findBySellerIncludeDeleted(sellerId: string) {
return this.find({
where: { sellerId }
});
}정산 데이터 처리
[정산 데이터와 삭제 상품]
기존 정산 데이터 (삭제 전):
• Settlement.productId = 'prod_001'
• Product.id = 'prod_001' (삭제됨)
처리 방식:
• 정산 데이터의 상품 참조는 유지
• 과거 정산 조회 시 상품명 표시 (LEFT JOIN)
• 신규 정산 수집 시 삭제 상품은 새 상품으로 생성이벤트 로깅
| 이벤트 | 파라미터 |
|---|---|
soft_delete_migration_completed | affected_queries_count |
생성일: 2026-01-20
