From 251890a748b4e71f735546cdcfed1ddf6b0b3282 Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 26 Oct 2026 12:03:18 +0900 Subject: [PATCH] =?UTF-8?q?docs(gift):=20=EC=88=98=EB=A0=B9=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EA=B0=81=20=EC=A0=95=EB=B0=80=EB=8F=84=20?= =?UTF-8?q?=EA=B3=84=EC=95=BD=EA=B3=BC=20=ED=9A=8C=EA=B7=80=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=EC=9D=84=20=EA=B8=B0=EB=A1=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20260929_크리에이터_선물하기/plan-task.md | 39 +++++++++++++++++-- docs/20260929_크리에이터_선물하기/prd.md | 7 +++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/docs/20260929_크리에이터_선물하기/plan-task.md b/docs/20260929_크리에이터_선물하기/plan-task.md index aeeecc52..c07e9704 100644 --- a/docs/20260929_크리에이터_선물하기/plan-task.md +++ b/docs/20260929_크리에이터_선물하기/plan-task.md @@ -4,12 +4,12 @@ | 문서 항목 | 내용 | |---|---| -| 상태 | Phase 16 서버 구현·검증·리뷰 완료, 운영 반영 전 | +| 상태 | Phase 16 및 P16-R1 시각 정밀도 회귀 수정·검증 완료 | | 작성일 | 2026-09-29 | | 요구사항 기준 | `docs/20260929_크리에이터_선물하기/prd.md` | | API 기준 | `docs/20260929_크리에이터_선물하기/prd.md`의 `8. API 계약` | | 현재 Phase | Phase 16 누락 푸시와 가격 스냅샷 검증 | -| 현재 활성 Goal | 없음. `P16-GATE` 완료, 운영 반영은 별도 | +| 현재 활성 Goal | 없음. `P16-R1` 완료, CI 재실행·배포는 별도 | ## 목표 @@ -43,7 +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 커밋 승인·미배포 | +| 16 | 기존 구현·회귀 수정 완료 | `2/2` Task, `P16-R1` 완료 | 없음 | 최신 전체2403개 통과, CI 재실행·배포 별도 | - 동시에 하나의 미완료 goal만 운용한다. - 구현 중 요구사항이 바뀌면 이 문서의 체크박스와 범위를 먼저 갱신한 뒤 코드를 수정한다. @@ -2046,3 +2046,36 @@ P15-T1 문서 검증 → 별도 구현 승인 → P15-T2 → P15-T3 → P15-T4 - 검증 명령: `./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·배포는 미검증이다. + +### P16-R1: 수령확인 완료 시각 정밀도 회귀 수정 + +**Goal:** OS/JDK의 소수초 정밀도와 무관하게 수령확인 응답 `deliveredAt`과 DB 재조회값을 정확히 일치시킨다. + +- 시작 조건: 배포 중 `AdminGiftControllerTest.kt:581` 실패 보고 및 이전과 같은 수정·재발 방지 문서화 승인. +- 근거: 이전 `82ce6f88`/`P14-T4`는 관리자 취소 시각의 나노초→DB 반올림 차이를 초 단위 정규화로 해결했다. 이번 `confirmDelivery`는 raw `now()`를 그대로 쓰고 `delivered_at` DDL은 소수초 없는 TIMESTAMP다. CI actual/expected 원문은 미제공이므로 고정 입력의 실제 DB roundtrip으로 실패 메커니즘을 재현한다. +- Files: Modify `src/main/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftCommandService.kt`; Test 기존 `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/GiftCommandServiceTest.kt`; Verify 기존 `src/test/kotlin/kr/co/vividnext/sodalive/v2/gift/application/GiftAdminServiceTest.kt`의 P14 회귀; Docs `AGENTS.md`, `docs/agent-guides/코드스타일.md`, `docs/agent-guides/테스트스타일.md`, 기존 PRD/plan. +- Interfaces: 기존 `confirmDelivery`와 UTC ISO 응답 스키마는 유지하고, 저장/응답에 같은 초 단위 단일 값을 사용한다. 푸시 호출/수신자·잠금·상태 전이는 그대로다. +- 범위 밖: 전역 `toUtcIso`/Jackson/timezone 변경, DDL 정밀도 변경, 다른 도메인/상태 메서드의 일괄 절삭, 테스트 허용오차/문자열 잘라 비교/skip, CI 설정·운영 DB·배포·커밋·푸시. +- [x] **RED:** 고정 입력3개 중 나노초0은 통과하고123456789/999999999 두 입력은 DB 재조회와 반환값 불일치로 실패했다. 실제 transaction/flush/clear/재조회로 이전과 같은 반올림 메커니즘을 확인했다. +- [x] **GREEN:** `now().truncatedTo(ChronoUnit.SECONDS)`를 한 번 계산하고 기존 변수로 저장·응답에 사용했다. production 변경은 import와 한 줄이며 원래581행 완전 일치 비교를 유지했다. +- [x] **검증:** 관련137개와 최신 전체2403개 테스트 실패·오류·skip0, lint/build 통과. 실제 JWT HTTP 수령확인과 세 나노초 입력 모두 저장·응답의 완전 일치를 확인했다. +- [x] **재발 방지/리뷰:** AGENTS에 연결 규칙을 추가하고 코드·테스트 가이드에 DDL 선확인/단일값/경계입력/실제 DB 왕복/assertion완화금지를 기록했다. 단일 독립 리뷰 APPROVE. 문서검증·자원 정리 결과는 아래 누적한다. + +#### P16-R1 재현·수정·최종 검증 — 2026-10-26 + +- 이전 근거: `git log -S 'truncatedTo(ChronoUnit.SECONDS)'`와 `git show 82ce6f88`에서 관리자 취소의 동일 수정과 DB roundtrip 테스트를 확인했다. 원 실패581행은 DB `deliveredAt.toUtcIso()`와 HTTP 반환 문자열 비교다. `toUtcIso`는 값을 UTC ISO로 형식화할 뿐 저장 정밀도를 보정하지 않는다. +- RED: `AdminGiftControllerTest.shouldPersistAndReturnSameSecondPrecisionDeliveryTime`을 고정0/123456789/999999999나노초로 실행했다. 3개 중2개 실패: `2026-10-22T23:59:59.123456789`는 DB에서 `.123457`, `.999999999`는 다음날`2026-10-23T00:00`으로 반올림됐고 반환값은 원래 나노초였다. CI actual/expected 원문은 없으므로 CI 원문 비교가 아니라 동일 실패 메커니즘의 로컬 재현이다. +- 수정: 기존 시각 주입 seam과 실제 repository를 쓰는 local service를 transaction 안에서 호출하고 저장·응답·DTO의 초단위 완전일치를 검증했다. 응답만 절삭하거나 assertion tolerance/substring/skip을 추가하지 않았고 기존 실제 HTTP assertion도 유지했다. +- 진행 복구: 담당 세션이 RED와 source 수정 이후 GREEN 실행을 시작하지 않아 프로세스/세션 상태를 확인했다. task 취소 조회는 not found였고 active test worker는 없었다. lead가 직접 검증을 이어받았으며 동시에 Gradle을 중복 실행하지 않았다. +- GREEN: `./gradlew --no-daemon test --tests '*GiftCommandServiceTest' --tests '*AdminGiftControllerTest' --tests '*GiftAdminServiceTest' ktlintCheck` exit0(1분31초),51+58+28=137개 실패·오류·skip0. 세 고정 입력 모두 returned/reloaded=`2026-10-22T23:59:59`, DTO=`2026-10-22T23:59:59Z`. +- 최종 전체: `./gradlew --no-daemon test --rerun ktlintCheck build --info` exit0,`BUILD SUCCESSFUL in 16m 37s`. 최신 JUnit XML322개에서2403개 테스트,실패0·오류0·skip0. 실제 HTTP 수령확인 status200/senderPush1/recipientPush0 및 고정입력3개 통과 로그를 다시 확인했다. +- 리뷰: read-only reviewer가 source/test/DDL/이전수정 및 AGENTS 연결 문서를 확인하고 APPROVE,차단 사항 없음. 결과 수집 도구 오류는 reviewer가 저장한 보고서로 확인했으며 재검토를 중복 실행하지 않았다. +- 한계: LSP 도구 없음으로 Kotlin compile/ktlint 대체. 운영 MySQL/Jenkins 재실행·배포는 하지 않았다. 기존 H2/비관련 scheduler/Gradle 경고는 별도이며 테스트 실패는 없다. 기존 사용자 GradleDaemon PID25133은 이번 작업 소유가 아니어서 보존한다. 커밋·푸시 없음. +- 문서/자원: `./gradlew --no-daemon tasks --all` exit0(13초), `git diff --check` exit0, 기존 HEAD`52e5c974` 및 index 불변. AGENTS→코드/테스트 가이드 링크와 규칙을 확인했다. 작업전용 `gift-p16-timefix.UnkCmG`의 열린 파일/작업 JVM·Redis가 없음을 확인하고 로그·캐시·메모·임시 Tomcat/Redis를 제거했으며 경로 부재를 확인했다. 최신 build/JUnit 산출물과 공유캐시는 유지했다. +- 판정: P16-R1 수정·회귀·재발 방지 문서화 완료. 현재 test 브랜치 미커밋 변경이며 CI 재실행/운영 반영 완료를 의미하지 않는다. + +#### P16-R1 커밋 전 재검증 — 2026-10-26 + +- 검증 명령: `./gradlew --no-daemon test --rerun --tests '*GiftCommandServiceTest' --tests '*AdminGiftControllerTest' --tests '*GiftAdminServiceTest' ktlintCheck`. +- 결과: exit 0, `BUILD SUCCESSFUL in 1m 33s`. 최신 JUnit XML 3개에서 137개 테스트, 실패·오류·skip 0을 확인했다. 테스트는 재실행됐으며 컴파일과 lint는 동일 입력의 UP-TO-DATE 결과다. `git diff --check`도 통과했다. +- 범위: 수령확인 시각 정밀도 수정의 커밋 검증으로 관련 서비스·HTTP·DB 왕복 회귀를 재실행했다. 전체 테스트와 패키징 빌드는 반복하지 않았으며 위 2,403개 결과는 이전 검증 기록이다. 운영 MySQL·Jenkins 재실행·배포는 미검증이다. diff --git a/docs/20260929_크리에이터_선물하기/prd.md b/docs/20260929_크리에이터_선물하기/prd.md index 8fac2042..095929f5 100644 --- a/docs/20260929_크리에이터_선물하기/prd.md +++ b/docs/20260929_크리에이터_선물하기/prd.md @@ -4,7 +4,7 @@ | 항목 | 내용 | |---|---| -| 문서 상태 | Phase 16 누락 푸시 보완·가격 스냅샷 검증 완료, 운영 반영 전 | +| 문서 상태 | Phase 16 및 수령확인 시각 정밀도 회귀 수정·검증 완료 | | 작성일 | 2026-09-29 | | 최종 수정일 | 2026-10-26 | | 대상 제품 | 크리에이터 선물하기 | @@ -636,6 +636,11 @@ Response: ### 8.9 크리에이터 수령확인 +수령확인 완료 시각은 운영 `gift_delivery.delivered_at TIMESTAMP`의 초 단위 정밀도에 맞춰 +`now()`를 한 번 `truncatedTo(ChronoUnit.SECONDS)`로 정규화한 값을 DB 저장과 응답에 공통 사용한다. +전역 날짜 변환/시간대나 다른 상태 변경의 정책은 바꾸지 않는다. 근거는 이전 관리자 취소 정밀도 수정 `82ce6f88`과 동일하다. +고정 나노초 3개 입력의 DB 왕복과 기존 실제 HTTP 비교를 유지한 회귀를 `P16-R1`에서 검증했다. + `POST /api/v2/gifts/{applicationNo}/delivery-complete` Request: 없음