docs(gift): Phase 16 푸시와 가격 스냅샷 검증 결과를 기록한다

This commit is contained in:
2026-10-26 10:26:24 +09:00
parent cd865da6e0
commit 52e5c97423
2 changed files with 99 additions and 7 deletions
@@ -4,12 +4,12 @@
| 문서 항목 | 내용 |
|---|---|
| 상태 | Phase 15 서버 구현·검증·리뷰 완료, 운영 반영 전 |
| 상태 | Phase 16 서버 구현·검증·리뷰 완료, 운영 반영 전 |
| 작성일 | 2026-09-29 |
| 요구사항 기준 | `docs/20260929_크리에이터_선물하기/prd.md` |
| API 기준 | `docs/20260929_크리에이터_선물하기/prd.md`의 `8. API 계약` |
| 현재 Phase | Phase 15 전달 완료 배송 개인정보 정리 |
| 현재 활성 Goal | 없음. `P15-GATE` 완료, 운영 반영은 별도 승인 |
| 현재 Phase | Phase 16 누락 푸시와 가격 스냅샷 검증 |
| 현재 활성 Goal | 없음. `P16-GATE` 완료, 운영 반영은 별도 |
## 목표
@@ -43,6 +43,7 @@
| 10 | 완료 | `3/3` | 완료 | 관리자 선물함 목록/상세 API 추가 |
| 14 | 완료 | `4/4` | 완료 | 전체 테스트 제외, 운영 MySQL/배포/별도 프론트엔드 검증 범위 밖 |
| 15 | 서버 구현·Gate 완료 | `4/4` Task, `P15-R1` 완료 | 없음 | 운영 schema/reader 배포 확인은 별도 |
| 16 | 완료 | `2/2` Task, Gate 완료 | 없음 | 현재 test 브랜치, Phase16 커밋 승인·미배포 |
- 동시에 하나의 미완료 goal만 운용한다.
- 구현 중 요구사항이 바뀌면 이 문서의 체크박스와 범위를 먼저 갱신한 뒤 코드를 수정한다.
@@ -1967,3 +1968,81 @@ P15-T1 문서 검증 → 별도 구현 승인 → P15-T2 → P15-T3 → P15-T4
- 검증 명령: `./gradlew --no-daemon test --rerun --tests '*GiftEntityMappingTest' --tests '*GiftSchedulerTest' --tests '*GiftQueryServiceTest' --tests '*GiftAdminQueryServiceTest' --tests '*GiftCommandServiceTest' --tests '*GiftAdminServiceTest' --tests '*GiftControllerTest' --tests '*AdminGiftControllerTest' ktlintCheck`.
- 결과: exit 0, `BUILD SUCCESSFUL in 1m 18s`. 8개 클래스 229개 테스트 실패·오류·skip 0. 테스트는 재실행됐으며 컴파일과 lint는 동일 입력의 UP-TO-DATE 결과다. 실제 JWT HTTP 삭제 전후 계약, 개인정보 12개 null 저장·재실행 0건, 경합 및 자동취소 batch lock 회귀를 포함한다.
- 범위: 기존 구현의 커밋 검증이므로 전체 테스트와 패키징 빌드는 반복하지 않았다. 2026-10-23 전체 2,396개 결과와 이번 focused 결과를 구분한다. 운영 MySQL DDL·배포·실제 Redis 다중 인스턴스 검증 및 push는 수행하지 않는다.
### Phase 16: 누락 발신자 푸시와 가격 스냅샷 검증
**Goal:** 수령확인·배송지 기한 초과 시 발신자 알림을 PRD대로 발행하고, 설정 변경이 기존 선물 신청과 결제를 바꾸지 않음을 실제 흐름으로 증명한다.
- 승인: 2026-10-26 사용자 후속 작업 진행 요청. 기존 확정 정책을 보완하며 재인터뷰하지 않는다. `test` 브랜치에서 worktree 없이 수행하고 커밋·푸시·운영 DB·실제 FCM 발송은 하지 않는다.
- 기준: PRD `9.3`, `DEC-022`; 기존 완료 Task/검증 이력은 보존한다. 두 호출자의 누락이 원인이며 GiftPushService/FCM 기반을 새로 만들지 않는다.
- 의존성: `P16-T1` → `P16-T2` → `P16-GATE`. 공유 controller test 때문에 한 구현 담당이 순서대로 실행하고, 변경 전체의 독립 리뷰는 Gate에서 수행한다.
#### Task 16.1 누락 발신자 푸시 보완
**Goal ID: `P16-T1`**
- 시작 조건: 승인된 기존 푸시 문구·대상·딥링크와 현재 누락 호출자 확인.
- Files: `src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftCommandService.kt`, `src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/scheduler/GiftScheduler.kt`.
- Test: `src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/GiftCommandServiceTest.kt`, `src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/adapter/out/scheduler/GiftSchedulerTest.kt`, `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/admin/gift/adapter/in/web/AdminGiftControllerTest.kt`; 기존 `src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftPushServiceTest.kt` 재사용.
- Interfaces: 기존 `confirmDelivery(...)` 및 `markExpiredRecipientAddressGiftsUndeliverable(now)` 성공 분기에 기존 send 메서드 호출만 추가한다. API·cron·잠금·상태/환불 정책 불변.
- 범위 밖: 새 푸시 문구/알림종류, 직접 취소/관리자 취소 알림, 기한 계산이나 완료 허용 조건 변경.
- 완료 증거: 발신자에게 정확한 applicationNo로 1회 호출, 수취인 추가 알림0, 거부/재실행의 추가 호출0, 기존 경합 및 rollback 회귀와 이벤트 계약 통과.
- [x] **RED:** 수령확인의 stale 무푸시 기대를 정확한 발신자1회·추가0회로 교체하고 반복/거절·만료3상태/비대상/재실행 검증을 보강했다. 승인된 새 발행에 관련된 경합 기대값만 변경했다.
- [x] **RED 확인:** `./gradlew --no-daemon test --tests '*GiftCommandServiceTest' --tests '*GiftSchedulerTest'` baseline102개 통과 후 production 수정 전103개 중5개가 실제 누락 호출 `WantedButNotInvoked`로 실패했다.
- [x] **GREEN:** 상태 전이 성공 분기에 기존 `sendDeliveredToSender`, `sendUndeliverableToSender` 호출 두 줄만 추가했다. 공통 푸시/금융/잠금/cron/DTO는 불변이다.
- [x] **GREEN 확인:** 관련4클래스168개 통과, 실제 JWT 수령확인 성공·권한 거부·반복 및 actual transaction scheduler 만료의 발신자1회·수취인0회·추가0을 확인했다. 기존 payload 테스트로 문구/딥링크를 대조했다.
- [x] **REFACTOR:** 기존 취소·rollback·erasure no-push 검증과18개 경합을 유지했다. 최종 관련216개와 lint 통과, 독립 리뷰 승인. 아래 Progress에 실제 한계를 기록했다.
#### Task 16.2 기존 신청 스냅샷 보존 통합 테스트
**Goal ID: `P16-T2`**
- 시작 조건: `P16-T1` 통과. 가격/카테고리 production 동작은 이미 구현되어 있으므로 테스트를 위해 임의로 깨뜨리지 않는다.
- Test: 기존 실제 command/admin/query/결제를 주입하는 `src/test/kotlin/kr/co/vividnext/sodalive/v2/api/admin/gift/adapter/in/web/AdminGiftControllerTest.kt`의 fixture/TransactionTemplate/JWT HTTP 헬퍼를 재사용한다.
- Interfaces: `registerGift`, `updateSizePrice`, `deleteCategory`, 기존 목록/상세 GET. 신규 endpoint/helper production 코드 없음.
- 범위 밖: 가격/카테고리 정책 재설계, 새 dependency, 전체 fixture framework, 새 snapshot 필드.
- 검증: 최초 판매가80으로 신청A→판매가120으로 변경→신청B. A의 저장·조회·결제80과 B의120을 flush/clear/reload 및 HTTP로 비교한다. 카테고리 비활성화 뒤 기존A/B와 결제는 유지, 옵션에서 제외, 신규 신청은 거부되며 추가 차감/행 생성이 없다.
- [x] **검증 추가:** 실제 registerGift로 만든 A80/B120, 실제 가격 변경/카테고리 비활성화, DB reload와 JWT HTTP 목록/상세/옵션을 연결했다. 최초 기존가격 fixture 격리를 위해 클래스 초기화의 sizePrice 삭제 한 줄만 보강했다.
- [x] **실행:** 단독 테스트와 관련 클래스 통과. 기존 가격 동작의 검증 보강이므로 임의 production RED는 만들지 않았다. 최초 테스트 끝의 Mockito matcher NPE는 fixture 검증 코드 오류로 구분하고 수정 후 같은 검증을 재실행했다. 가격 production은 변경하지 않았다.
- [x] **정리:** 실제 UseCan80/120·원 결제 연결·정산·잔액100을 보존하고 비활성화 후 추가 Gift/차감0을 확인했다. 운영 데이터·실제 FCM·공유 설정은 건드리지 않았다.
#### Phase 16 Gate
**Goal ID: `P16-GATE`**
- 시작 조건: 두 Task의 실제 증거 확보. 완료 기준: 누락 알림과 가격/카테고리 시나리오 PASS, 관련/전체 회귀·lint/build·독립 리뷰 및 임시자원 정리.
- [x] 관련6클래스216개 테스트/lint를 통과했고 최종 전체 실행에서도 해당 테스트를 포함해 통과했다. 아래 실제 명령을 기록했으며 별도 미실행 명령을 실행했다고 표시하지 않는다.
- [x] 최초 전체 실행15분 timeout을 성공으로 계산하지 않았다. 상세 로그를 남긴20분 제한 재실행은18분22초에 exit0, 전체2400개·lint·build 통과했다.
- [x] 실제 localhost HTTP로 가격/기존 신청 보존, 수령확인 푸시 경계와 만료 transaction을 검증했다. 실제 transport/기기 실수신은 미검증이다.
- [x] 독립 reviewer APPROVE, 차단 사항 없음. PRD 가격/푸시 성공 기준2개만 새 증거로 완료 표시하고 과거 나머지 항목은 유지했다.
- [x] `tasks --all`·diff 검사를 통과했고 전용 임시자원 삭제/부재를 확인했다. 기존 사용자 GradleDaemon과 공유캐시를 보존했으며 커밋·푸시는 하지 않았다.
#### Phase 16 Progress
- 2026-10-26: 기존 PRD에 따른 후속 작업을 승인받아 위 계획을 기록했다. P16-T1/T2/Gate는 아직 구현 검증 전이며 Phase15 기록은 보존했다.
#### P16-T1/T2 실행 결과 — 2026-10-26
- Baseline: `./gradlew --no-daemon test --tests '*GiftCommandServiceTest' --tests '*GiftSchedulerTest'` exit0(31초),102개 통과. 동일 명령 RED는103개 중5개 누락 호출 실패(52초), production 두 줄 수정 후 관련4클래스168개 통과(1분16초).
- Snapshot: 실제 creator/member/Charge300 및 활성카테고리를 준비해 A80결제(잔액220)→가격120→B120결제(잔액100)→카테고리 비활성화를 검증했다. 실제 등록·결제·DB flush/clear/reload 및 TestRestTemplate JWT GET이다. 기존 신청 이름/가격/UseCan ID·정산 보존, 옵션 제외, 이후 신청 거부/추가차감0을 확인했다.
- 단독 명령: `./gradlew --no-daemon test --tests '*AdminGiftControllerTest.shouldPreserveExistingGiftSnapshotsAfterPriceChangeAndCategoryDeactivation'` exit0(51초). 최초 테스트 matcher NPE는 업무결함 RED가 아니며 정확한80/120 호출 검증과 총2회 확인으로 수정했다.
- 관련 최종 명령: `./gradlew --no-daemon test --tests '*GiftCommandServiceTest' --tests '*GiftSchedulerTest' --tests '*GiftPushServiceTest' --tests '*AdminGiftControllerTest' --tests '*GiftAdminServiceTest' --tests '*GiftQueryServiceTest' ktlintCheck` exit0(1분26초),51+52+11+55+28+19=216개,실패·오류·skip0. 최초 들여쓰기 lint2건은 수정 후 재실행했다.
- 실표면: `P16_CONFIRM_HTTP status=200 success=true rejected=true repeated=false senderPush=1 recipientPush=0`, `P16_EXPIRY_DB transitioned=1 repeated=0 senderPush=1 recipientPush=0`. JWT 미인증401·발신자 수령확인 거부·재요청 거부, 원 결제/시각 보존을 함께 검증했다.
- 이벤트 범위: 실제 HTTP/transaction 호출자에서 mock GiftPushService 경계의 정확한 호출을 확인하고 기존 GiftPushServiceTest에서 실제 FcmEvent payload를 검증했다. 실제 FCM 전송/기기 수신이나 외부 provider 성공을 증명한 것은 아니다.
#### P16-GATE 최종 검증 — 2026-10-26
- 전체1차: `./gradlew --no-daemon test --rerun ktlintCheck build`는900초 도구 제한으로 종료됐다. 로그는 `:test`에서 끝났고 실패 메시지는 없었으나 성공으로 계산하지 않았다. 해당 실행의 JVM 잔류 없음 확인 후 재실행했다.
- 전체2차: `./gradlew --no-daemon test --rerun ktlintCheck build --info`를1200초 제한으로 실행해 exit0, `BUILD SUCCESSFUL in 18m 22s`. 최신 JUnit XML322개에서 테스트2400개,실패0·오류0·skip0 확인. lint/build도 성공했다.
- 최신 실제 HTTP 증거: AdminGiftControllerTest55개 성공 XML에서 수령확인·만료 senderPush1/recipientPush0 및 `P16_SNAPSHOT_DB deactivated=false/true A=80 B=120 usageIdsPreserved=true actualUseCan=80,120 memberBalance=100 chargeBalance=100 gifts=2 usesDelta=2 chargesDelta=0 listCount=2`를 확인했다.
- 리뷰: 최초 reviewer 결과 수집이 세션 소실로 실패해 승인 근거로 쓰지 않았다. 별도 read-only reviewer가 현재 diff/소스/테스트/보존로그를 대조해 범위 한정 APPROVE,차단 사항 없음으로 판정했고 보고서를 파일로 보존했다. reviewer가 통과를 확인한216개와 lead의 이후 전체2400개를 구분한다.
- 검증 한계: LSP 도구가 없어 Kotlin 컴파일·ktlint로 대체했다. 기존 H2/비선물 SKIP LOCKED·duplicate JSON·Netty·Gradle 경고는 수정 범위 밖이며 새 테스트 실패는 없다. 운영 MySQL/실제 FCM/배포는 미실행이다. 기존 DataGrip·작업 전부터 있던 GradleDaemon은 사용자 자원으로 보존한다.
- 최종 문서/자원: `./gradlew --no-daemon tasks --all` exit0(6초), `git diff --check` exit0, index 변경 없음, HEAD는 시작 시점의 `d052dd50` 유지. `build/libs/sodalive-0.0.1-SNAPSHOT.jar`와 최신 JUnit/HTML 산출물을 확인했다. 작업 root `gift-p16.xKuBMZ`의 열린 파일과 이번 JVM/Redis 잔류가 없음을 확인한 뒤 내부 캐시·임시 Tomcat·Redis·로그·메모를 제거하고 경로 부재를 확인했다. 작업 전08:44 시작한 기존 GradleDaemon PID25133과 공유 Gradle cache/build 산출물은 보존했다.
- 최종 판정: `P16-T1`, `P16-T2`, `P16-GATE` 완료. 이번 production 수정은 호출 두 줄이며 가격/카테고리 코드는 불변이다. 변경은 현재 test 브랜치의 미커밋 상태로 남긴다.
#### Phase 16 커밋 전 재검증 — 2026-10-26
- 사용자 `/commit-with-validation` 요청으로 기존 Phase 16 변경의 커밋을 승인받았다. 위 미커밋 기록은 당시 실행 결과로 보존한다.
- 검증 명령: `./gradlew --no-daemon test --rerun --tests '*GiftCommandServiceTest' --tests '*GiftSchedulerTest' --tests '*GiftPushServiceTest' --tests '*AdminGiftControllerTest' --tests '*GiftAdminServiceTest' --tests '*GiftQueryServiceTest' ktlintCheck`.
- 결과: exit 0, `BUILD SUCCESSFUL in 1m 19s`. 최신 JUnit XML 6개에서 테스트 216개, 실패·오류·skip 0을 확인했다. 테스트는 재실행됐으며 컴파일과 lint는 동일 입력의 UP-TO-DATE 결과다.
- 범위: 기존 변경의 커밋 검증이므로 관련 회귀를 재실행하고 전체 테스트·패키징 빌드는 반복하지 않았다. 위 전체 2,400개 결과는 이전 Gate 기록이며 이번 재실행 결과와 구분한다. 운영 MySQL·실제 FCM·배포는 미검증이다.
@@ -4,9 +4,9 @@
| 항목 | 내용 |
|---|---|
| 문서 상태 | Phase 15 서버 구현·전체 테스트·실소켓 QA·리뷰 완료, 운영 반영 전 |
| 문서 상태 | Phase 16 누락 푸시 보완·가격 스냅샷 검증 완료, 운영 반영 전 |
| 작성일 | 2026-09-29 |
| 최종 수정일 | 2026-10-23 |
| 최종 수정일 | 2026-10-26 |
| 대상 제품 | 크리에이터 선물하기 |
| 작성자·결정권자 | 사용자 |
| 관련 API Contract | 별도 문서 없음. 이 문서의 `8. API 계약`을 기준으로 사용 |
@@ -17,6 +17,8 @@
> Phase 15 서버 구현과 검증을 완료했다. 최종 2,396개 테스트·lint·build와 실제 JWT HTTP 삭제 전후 QA 및 리뷰를 통과했다. `gift-schema.sql` 하단의 nullable ALTER는 기록만 했으며 운영 DB 실행·배포·커밋·푸시는 하지 않았다.
> Phase 16은 수령확인·배송지 만료의 발신자 알림 두 곳과 기존 신청 가격 보존 검증을 완료했다. 최신 전체 2,400개 테스트·lint·build 및 독립 리뷰를 통과했다. 실제 FCM/기기 수신과 운영 배포는 미검증이며, 후속 커밋 승인에 따른 관련 216개 테스트 재검증 결과는 `plan-task.md`에 기록했다.
## 1. Overview
팬이 내부 재화인 캔을 사용해 크리에이터에게 실물 선물을 보낼 수 있는 API를 제공한다.
@@ -964,6 +966,14 @@ Response `data`는 기존 `AdminGiftOperationStatusResponse`를 사용한다.
크리에이터가 직접 수령확인 API를 호출해 `DELIVERED`가 된 경우에는 크리에이터 대상 `배송 완료` 푸시를 보내지 않는다.
### 9.3 Phase 16 호출 누락 보완
- 수취인 직접 수령확인 성공 시 기존 `sendDeliveredToSender(applicationNo, senderMemberId)`를 호출한다. 수취인에게는 추가 발송하지 않으며 실패·반복 요청으로 중복 발행하지 않는다.
- 배송지 입력 기한 초과로 실제 `UNDELIVERABLE` 전환한 선물만 기존 `sendUndeliverableToSender(applicationNo, senderMemberId)`를 호출한다. 비대상·기한 동일·주소 입력 완료·재실행은 추가 발행하지 않는다.
- 기존 GiftPushService의 제목·본문·수신자 지정·`GIFT_DETAIL`/신청번호 딥링크와 transaction 이벤트 경계를 재사용한다. 새 문구·수신자·알림 종류·스케줄·테이블은 추가하지 않는다.
- 가격·카테고리 검증은 실제 신청→관리자 가격 변경→재신청→카테고리 비활성화 흐름으로 수행한다. 이전 신청의 `salePriceCan`, `categoryNameSnapshot`, 결제 연결/금액은 유지하고, 새 신청에는 최신 가격을 적용하며 비활성화 이후 신규 신청은 거부한다.
- 이번 검증은 서버 이벤트 발행·DB/HTTP 계약까지이며 운영 FCM 및 실제 기기 수신 성공을 의미하지 않는다.
## 10. 데이터 모델 요구사항
### 10.1 Gift
@@ -1102,8 +1112,8 @@ Response `data`는 기존 `AdminGiftOperationStatusResponse`를 사용한다.
- [ ] 크리에이터는 배송지와 수령 약관 2개를 등록할 수 있다.
- [ ] 운영자는 상태별 전용 API로 상태를 전이하고, 잘못된 상태 전이는 실패한다.
- [ ] 팬은 `DELIVERED` 이후 리뷰를 1회 작성할 수 있다.
- [ ] 관리자 카테고리 논리삭제와 사이즈별 가격 변경이 새 신청에만 반영된다.
- [ ] 팬/크리에이터 푸시가 지정된 문구, 수신자, 딥링크로 발송된다.
- [x] 관리자 카테고리 논리삭제와 사이즈별 가격 변경이 새 신청에만 반영된다. 실제 신청A80→가격120→신청B120→비활성화 후 기존 DB/HTTP/결제 보존과 신규 신청 거부를 검증했다. (`P16-T2`)
- [x] 팬/크리에이터 푸시가 지정된 문구, 수신자, 딥링크로 발행된다. 누락된 두 호출과 발신자1회·수취인추가0회·거부/반복추가0, 기존 payload 계약을 서버 경계에서 검증했다. 실제 FCM·기기 수신은 별도다. (`P16-T1`)
- [ ] 선물 사용자/관리자 API의 날짜/시간 응답을 클라이언트가 UTC ISO 문자열로 해석할 수 있다.
- [ ] 카테고리 추가 필드와 새 신청번호 정책이 관리자 API, 사용자 폼 옵션, 선물 신청에 반영된다.
- [x] 관리자 취소는 `RECEIVED`에서만 전액 환불과 함께 성공하고, 목록/상세의 `CANCEL` 액션은 상태에 맞게 제공된다.
@@ -1162,7 +1172,10 @@ Phase 15 서버 구현 완료 판정에는 `P15-T2`~`P15-T4` focused test와 격
| 2026-10-23 | `DEC-019` | 확정 | 네 sender DB column 변경은 30줄 미만이므로 신규 SQL 파일 대신 기존 `gift-schema.sql` 말미에 작성한다. 기존 CREATE block은 두고 추가 ALTER로 fresh install 최종 schema도 nullable로 만든다. 실제 운영 SQL 실행은 별도 승인 rollout gate이며 아직 실행하지 않았다 | 사용자의 latest SQL placement decision; 기존 파일에 추가된 5줄 ALTER | `GIFT-019`, `P15-T1`, `P15-T2`, `P15-GATE` |
| 2026-10-23 | `DEC-020` | 확정 | sender 다섯 Kotlin property 중 `senderAddressDetail` 포함 다섯 모두 nullable, DB상 현재 NOT NULL인 sender 열 네 개만 변경한다 | entity 필드와 DDL nullable 경계의 구별 | `GIFT-019`, `P15-T2` |
| 2026-10-23 | `DEC-021` | 확정 | 신규 시간별 scheduler wrapper는 기존 만료/안내 업무 메서드에 위임하며, 기존 예약은 자동취소 `:00`뿐이다. 신규 등록은 `:10`, `:20`, `:40`이다 | 현재 scheduler 코드와 승인 일정 | `GIFT-021`, `P15-T3`~`P15-T4` |
| 2026-10-26 | `DEC-022` | 확정 | 기존 PRD의 수령확인·배송지 만료 발신자 알림 호출 누락 두 곳을 보완하고 관리자 가격 변경/카테고리 비활성화 후 기존 신청 스냅샷 보존 통합 테스트를 추가한다 | 사용자 후속 작업 승인 | `GIFT-008`, `GIFT-011`, `GIFT-013`, `P16-T1`~`P16-GATE` |
## 문서 상태 안내
Phase 14의 당시 전체 테스트 제외 및 검증 이력은 `plan-task.md`의 P14-GATE 기록을 보존한다. Phase 15는 후속 실행 승인에 따라 서버 구현과 최종 전체 테스트 2,396개·lint·build·실소켓 QA·리뷰를 완료했다. 운영 MySQL DDL 실행 및 배포는 별도 승인/조건이며 이번 완료 범위에 포함하지 않는다.
Phase 16은 2026-10-26 후속 승인 범위의 서버 구현·검증을 완료했다. 최종 전체 테스트 2,400개·lint·build 통과 및 실제 localhost HTTP/DB 시나리오와 독립 리뷰 승인을 확인했다. Phase15의 과거 기록과 달리 이번 두 성공 기준은 새 검증 근거로 완료 표시했으며, 나머지 과거 성공 기준은 일괄 체크하지 않았다.