첨부파일 모듈의 2단계 청소 전략

## 첨부파일 모듈의 2단계 청소 전략

| **단계** | **대상** | **발생 원인** | **청소 시점** |
| --- | --- | --- | --- |
| **1단계: 고아 객체 정리** | `isLinked = false` | 업로드만 하고 게시글 저장 없이 브라우저를 닫음 (주인 없음) | 업로드 후 24시간 경과 시 |
| **2단계: 유휴 객체 정리** | `isRemoved = true` | 게시글 수정 시 기존 파일을 'X' 눌러서 삭제함 (주인 있으나 버려짐) | 삭제 플래그 직후 (혹은 유예 기간 후) |

## 도메인 모델 중심의 Soft Delete와 즉각적인 Hard Delete가  명확하게 구분되어 있는 구조에서 실무적인 관점으로 몇 가지 깊이 있는 고민거리

### 🧐 1. `removeFileFromGroup` (Soft Delete)의 섬세함

이 메서드는 단순히 필드 하나 바꾸는 게 아니라, **도메인 모델(`AttachFile`)** 내부로직을 탄다는 게 핵심이야.

- **비즈니스 규칙**: `attachFile.removeFileItem(itemId)` 내부에서 "최소 한 개의 파일은 유지해야 한다"거나 "특정 상태에서는 삭제할 수 없다" 같은 규칙을 검사하기 좋지.
- **복구 가능성**: `isRemoved = true`인 상태는 아직 DB에 메타데이터가 살아있고 물리 파일도 그대로니, 관리자 화면에서 '복구' 버튼 하나로 `false`로만 돌리면 즉시 살려낼 수 있어.
- **리뷰 포인트**: 여기서 `id(AttachFileId)`와 `itemId(FileItemId)`를 둘 다 받는 건 아주 좋은 설계야. "이 그룹에 속한 이 파일이 맞는지"를 더블 체크할 수 있어서 보안상 안전하거든.

### 🗑️ 2. `purgeFile` (Hard Delete)의 과감함

이건 주로 관리자가 "이건 불법 파일이야!" 하고 즉시 지우거나, 아까 만든 스케줄러(Moments)가 호출하는 용도지.

- **순서의 묘미**: 현재 소스는 **[물리 파일 제거 -> DB 삭제]** 순서인데, 여기서도 아까 논의한 `TransactionSynchronizationManager`를 써서 **[DB 삭제 확정 -> Commit 후 물리 파일 제거]**로 순서를 맞추는 게 정석이긴 해. (혹시 모를 DB 롤백 시 파일만 사라지는 걸 방지하기 위해!)
- **고민해볼 점**: 만약 `purgeFile`이 호출되었는데 파일이 이미 물리 저장소에 없다면? (누가 손으로 지웠거나 등) 보통은 예외를 던지기보다 로그만 남기고 DB 메타데이터는 지워버리는 게 운영상 편해.

---

### 🏛️ 3. `remove`와 `purge`가 만나는 지점 (Lifecycle)

마스터가 짠 이 두 메서드는 결국 **스케줄러**에 의해 완성돼.

1. 사용자가 **`removeFileFromGroup`** 호출 (화면에서 사라짐, DB에는 남음)
2. 사용자는 며칠간 "아 맞다, 그 파일 지우면 안 되는데!" 하고 복구할 기회를 가짐.
3. 일주일 뒤 자정, 스케줄러가 `isRemoved = true`인 것들을 모아서 **`purgeFile`*을 호출 (영원히 안녕)

댓글

이 블로그의 인기 게시물

Session 대신 JWT를 사용하는 이유

스프링 부트 개발자를 위한 유용한 VSCode 설정

osx 매버릭스에서 영문키 반복 입력되게 하기