Repository navigation
feat(mindrecord): 홈 요약 카드용 주간 기록 수 UseCase 를 만든다 - #994
Conversation
발신자 홈 WeeklySummaryGrid 3개 카드가 모두 목데이터인데, mindrecord 도메인에 UseCase 가 0건이라 홈 쪽 wire-up 이 막혀 있었다. 이번 주 기록 수는 종류별로 세지 않는다. 주간리포트 API 가 일기·데일리질문·깊은 생각 카운트를 한 응답에 담아 주므로 그 합을 쓴다 — 종류별로 목록을 부르면 요청이 셋으로 늘고 화면이 쓰지도 않을 본문까지 받아 온다. 서버가 함께 내려주는데 종전에는 선언하지 않아 버려지던 deepThoughtAmount 를 DTO·도메인에 더한다. 최근 깊은 생각은 목록에서 id 최대값으로 고른다. 목록 순서는 명세에 없어서, 서버가 정렬을 바꾸면 "최근" 이 조용히 바뀐다. 깊은 생각은 앱에 코드가 전혀 없었으므로 API·DTO·매퍼·저장소를 함께 만든다. 두 UseCase 모두 조회 실패를 0·null 로 덮지 않는다 — 실패가 "이번 주에 아무것도 안 썼다" 나 "깊은 생각이 없다" 로 보이면 안 된다. Refs #201 Closes #207
422aa0e to
6d138e6
Compare
발신자 홈 WeeklySummaryGrid 카드가 목데이터인데 mindrecord 도메인에 UseCase 가 0건이라 홈 쪽 wire-up 이 막혀 있었다. 주간리포트 API 가 종류별 카운트를 한 응답에 담아 주므로 그 합을 쓴다 — 종류별로 목록을 부르면 요청이 늘고 화면이 쓰지도 않을 본문까지 받아 온다. 조회 실패를 0 으로 덮지 않는다. 0 으로 내리면 "이번 주에 아무것도 안 썼다" 와 구분되지 않는다. 깊은 생각은 기획에서 제거됐다. 세지 않고, 서버가 deepThoughtAmount 를 계속 내려줘도 DTO 에 선언하지 않아 그대로 무시된다. 최근 깊은생각 카드도 함께 걷어내, 오른쪽에 남은 기록 횟수 카드가 왼쪽 큰 카드와 같은 높이를 채운다. Refs #201 Closes #207
6d138e6 to
aa65bce
Compare
|
❌ Screenshot test fail — baseline 과 CI rendered PNG 차이. 📦 Artifact: https://github.com/Afternote/Afternote-FE/actions/runs/32732718846 (페이지 하단 Artifacts → 🔍 확인 위치 (artifact zip 내부):
📝 조치 가이드:
CI ↔ 로컬 환경 차이는 본 워크플로의 container 단계가 root fix 한다 (README 의 "Compose Preview Screenshot Testing (docker baseline)" 섹션 참조). |
목록에 저장된 기록의 본문을 열어 볼 수단이 없었다 — 상세 라우트가 없고 목록 카드에
클릭 콜백도 없었다. 08-05 시안 4종(3814:18721·18739·18796·18813)에 맞춰 한 화면으로
구현한다. 시안 4종은 두 축의 조합이라 화면을 나누지 않는다 — 첨부 이미지 유무(헤더
배경·글자색이 뒤집힌다)와 기록 종류(일기에만 오늘의 기분 줄).
- `RecordDetailRoute(recordId, isDiary, yearMonth)` 와 상세 화면·ViewModel 신설
- 본문 HTML 을 `img` 태그 경계로 잘라 «문단 → 이미지 → 문단» 순서를 지킨다
- 헤더 이미지는 본문 첫 이미지를 쓴다. 서버가 대표 이미지를 따로 주지 않는다
- `receivers` 를 DTO·도메인까지 실어 시안의 "수신인 OOO" 줄을 채운다
목록 화면의 `onItemClick` 에는 기본값을 두지 않았다. 실제로 이 작업 중 일기 탭 결선을
빠뜨렸는데 기본값 `{}` 때문에 컴파일이 통과해 카드가 눌리지 않는 채로 굴러갔다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
OnlyReadOneBook
left a comment
There was a problem hiding this comment.
총평
종류별로 목록 셋을 부르는 대신 주간리포트 한 응답의 합을 쓰는 선택이 맞습니다 — 바로 아래 단(#736)의 방향과도 같습니다. «조회 실패를 0 으로 덮지 않는다» 를 테스트로 먼저 못 박은 것도 좋습니다. 범위를 도메인까지로 자른 근거(이슈가 wire-up 을 후속으로 분리)도 확인했습니다.
다만 CI red 둘이 이 PR 에서 생겼고, 그중 하나는 실수로 들어간 diff 라 아래 스택 전체(#1006)까지 번지고 있습니다.
지적
- [blocking] 의도 없는 들여쓰기 파손이 ktlint red 를 만들고 스택 아래로 전파된다 →
feature/mindrecord/presentation/src/test/kotlin/com/afternote/feature/mindrecord/presentation/viewmodel/MindRecordRequestCountTest.kt:170인라인. - [blocking] 스크린샷 baseline 미갱신 — CI red. 카드 3장 → 2장은 의도된 시각 변경인데
:feature:home:presentation:validateDebugScreenshotTest가 실패 중이고, 본문에 이 항목이 없습니다. 같은 저자의 #1020·#1021 은 baseline 갱신 필요를 본문에 명시해 두셨는데 여기만 빠졌습니다.:app쪽 스크린샷도 홈을 그리므로 함께 확인이 필요합니다. - [normal] 카드가 실제 기록과 무관하게 항상
0을 표시한다 →feature/home/presentation/src/main/kotlin/com/afternote/feature/home/presentation/WeeklySummaryGrid.kt:38인라인. - [normal] KDoc 이 «세 카운트의 합» 이라고 적었는데 실제로는 둘의 합이다 →
feature/mindrecord/domain/src/main/kotlin/com/afternote/feature/mindrecord/domain/usecase/GetWeeklyRecordCountUseCase.kt:12인라인. - [normal] 테스트 KDoc 이 존재하지 않는 계약을 고정한다고 적었다 —
HomeSummaryUseCaseTest.kt:16의 «최근 깊은 생각은 1건 또는 없음» 은 이 PR 에서 걷어낸 범위라 대응하는 테스트가 없습니다. 깊은 생각 제거 반영 때 함께 정리해 주세요. - [normal]
docs/qa/assumptions.md항목이 실제로는 안 들어갔다 — 본문이 «시안 근거가 없는 판단이라docs/qa/assumptions.md에 적어 둘 항목이다» 라고 했는데 diff 에 그 파일이 없습니다. 같은 저자의 #1052 도 같은 상태라, 이 문서를 실제로 채우는 시점을 한 번 정하는 게 좋겠습니다.
검증
- 시안 대조: 못 했습니다(근거 부재). «깊은 생각 카드 제거» 와 «남은 한 장이 큰 카드 높이를 채운다» 는 본문 서술상 기획 결정 + 저자 판단이고, 대조할 시안 노드가 이슈·PR 어디에도 걸려 있지 않습니다. 미답변 디자인 질의는 FE 재량이라는 팀 합의에 따라 블로커로 세지 않았습니다 — 다만 2번(baseline)을 갱신할 때 렌더 결과는 한 번 눈으로 봐 주세요.
- 실기동 QA: 해당 없음. 본문 설명대로 카드에 값을 꽂는 코드가 아직 없어 화면으로 확인할 것이 없습니다. 실서버 응답 실측은 본문에 있습니다.
- CI: ktlint·스크린샷 red(1·2번), 나머지 green.
| dailyQuestionAmount = 0, | ||
| diaryAmount = 0, | ||
| summaryText = "", | ||
| summaryText = "", |
There was a problem hiding this comment.
[blocking] 이 PR 이 이 파일에서 바꾼 것은 이 한 줄뿐인데, 바뀐 내용이 들여쓰기 파손입니다.
- summaryText = "",
+ summaryText = "",그 결과 ktlint 가 실패합니다.
MindRecordRequestCountTest.kt:170:1 Unexpected indentation (28) (should be 20) (standard:indent)
> Execution failed for task ':feature:mindrecord:presentation:ktlintTestSourceSetCheck'
의도한 변경으로 보이지 않습니다(값도 동작도 그대로). 되돌려 주세요.
이 red 는 이 PR 위에 얹힌 #1006 에도 그대로 실려 있습니다.
| recordedCount: Int = 7, | ||
| recentRecordDate: String = "26.02.01", | ||
| recentRecordTitle: String = "최근 기록 제목최근 기록 제목...", | ||
| recordedCount: Int = 0, |
There was a problem hiding this comment.
[normal] 기본값을 7 → 0 으로 바꿨는데, 호출부가 이 값을 넘기지 않습니다.
# HomeTabScreen.kt:285
WeeklySummaryGrid(onImageClick = …, onCountCardClick = …) ← recordedCount 없음
$ grep -rn "GetWeeklyRecordCountUseCase" --include="*.kt" . # domain 제외
(0건)
즉 이 PR 이 머지되면 이번 주에 실제로 기록이 있어도 카드에 0 이 표시됩니다. wire-up 이 후속이라는 범위 판단에는 동의하지만, 그 사이에 화면에 남는 값이 문제입니다.
7 도 거짓이었지만 명백히 목업으로 읽혔던 반면, 0 은 «이번 주에 아무것도 안 썼다» 라는 그럴듯한 거짓이라 사용자가 그대로 믿습니다. 같은 저자의 #1021·#952 에서 팀이 «조회 전·미상을 결과로 확정하지 않는다» 를 blocking 으로 다루고 있는데, 이 자리만 반대로 갑니다.
기본값을 지우고 필수 파라미터로 만들면(값을 넘기지 않는 호출부가 컴파일 에러가 되므로) 후속 PR 전까지 이 자리가 잊히지 않습니다. 그게 과하면 최소한 미상 표시(대시·시머)로 두는 편이 낫겠습니다.
| /** | ||
| * 이번 주 기록 수 — 홈 `WeeklySummaryGrid` 의 THIS WEEK 카드 (#207). | ||
| * | ||
| * 일기·데일리질문·깊은 생각을 **각각 세지 않는다.** 주간리포트 API 가 세 카운트를 한 |
There was a problem hiding this comment.
[normal] «주간리포트 API 가 세 카운트를 한 응답에 담아 주므로 그 합을 쓴다» 인데, 실제로 더하는 건 둘입니다.
// WeeklyReportModels.kt
val totalRecordAmount: Int get() = dailyQuestionAmount + diaryAmount깊은 생각을 세지 않는다는 건 바로 아래 문단에서 따로 설명하고 있으니, 여기서는 «두 카운트» 로 맞춰 주세요. 지금은 첫 문장만 읽은 사람이 deepThoughtAmount 도 합에 들어간다고 이해합니다.
기본값 0 은 «이번 주에 아무것도 안 썼다» 는 그럴듯한 거짓이라 사용자가 그대로 믿는다. 종전 7 은 명백한 목업이라 오히려 눈에 띄었다. 기본값을 지워 값을 넘기지 않는 호출부가 컴파일에서 걸리게 하고, 값이 아직 없는 동안에는 숫자 대신 대시를 그린다 — 조회 전·미상을 결과로 확정하지 않는다는 #952·#698 과 같은 규칙이다. 실수로 들어간 들여쓰기 파손(ktlint red, 스택 아래 #1006 까지 전파)도 되돌리고, UseCase KDoc 의 «세 카운트» 를 실제와 맞춰 «두 카운트» 로 고친다. 리뷰 지적. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
카드 3장 → 2장, 기록 수 자리가 미상 표기로 바뀐 의도된 시각 변경이다. CI 와 같은 docker 컨테이너에서 생성했다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
지적 4건 반영했습니다. 1. [blocking] 들여쓰기 파손 — 되돌렸습니다. 의도한 변경이 아니었고, 스택 아래 #1006 까지 번지게 한 것도 제 실수입니다. 2. [blocking] 스크린샷 baseline — 본문에서 이 항목이 빠졌던 것도 맞습니다. CI 와 같은 docker 컨테이너에서 갱신했고 3장이 바뀌었습니다(카드 3장→2장 + 기록 수 자리). 3. [normal] 항상 0 을 표시 — 지적하신 대로 «7 은 명백한 목업, 0 은 그럴듯한 거짓» 이 정확합니다. 기본값을 지워 필수 파라미터로 만들었고, 값이 아직 없는 동안에는 숫자 대신 대시를 그립니다. recordedCount: Int?, // 기본값 없음 — 넘기지 않은 호출부가 컴파일에서 걸린다
// null → "–", 0 → "0" (0 은 확정값이라 그대로 그린다)실제로 필수화하자 호출부 2곳이 컴파일 에러로 걸렸습니다. #952·#698 과 같은 규칙이 됐습니다. 4. [normal] KDoc «세 카운트» — «두 카운트» 로 고쳤습니다. 5. [normal] 테스트 KDoc 의 «최근 깊은 생각» — 확인하고 정리하겠습니다. 6. [normal] |
내비게이션이 YearMonth.now() 를 고정으로 넣어, 지난달 기록을 탭하면 상세가 이번 달 목록에서 그 기록을 찾다 실패했다 — 이번 달 기록만 열렸다. 목록은 달을 바꿀 수 있는 화면이라 흔히 밟히는 경로다. 함께 정리한 것: - 날짜를 못 구하면 «이번 달 1일» 을 지어내던 것을 걷고 그 줄을 그리지 않는다. 상세에서 날짜는 부수 정보가 아니라 기록을 식별하는 값이라, 지어내면 사용자가 그 날짜를 믿는다 - «없는 기록» 을 통신 실패와 구분해 NotFound 상태로 둔다. 사용자가 할 일이 다르다 — 통신 실패는 다시 시도, 없는 기록은 목록으로. 종전에는 재시도를 눌러도 같은 화면이었다 - 목록 전체를 받는 이유(단건 조회 API 부재)를 KDoc 에 남긴다 리뷰 지적. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
OnlyReadOneBook
left a comment
There was a problem hiding this comment.
총평
blocking 2건 해소, CI 전부 green 입니다. 3번을 «기본값을 없애 호출부가 반드시 값을 넘기게» 로 처리하신 게 특히 좋습니다 — 자리표시자가 화면에 도달하던 통로 자체가 닫혔습니다. 승인합니다.
반영 확인
- [blocking] 해소. 들여쓰기 파손이 정리돼
Check Code Quality (Ktlint)green. - [blocking] 해소. baseline 3종(
homeTabScreenLoading·homeTabScreenSuccess·weeklySummaryGrid) 갱신,Validate Compose Preview Screenshotsgreen. 스크린샷 프리뷰를 필수 파라미터에 맞춘 커밋(3b63be01)을 따로 두신 것도 좋습니다. - [normal] 해소 — 제안보다 강하게.
recordedCount: Int?를 기본값 없는 필수 파라미터로 두고 호출부에 «값을 붙이는 것은 후속(#562)이다» 를 적어 두셨습니다. 기본값이 남아 있으면 다음 사람이 또 안 넘길 자리인데 그 통로를 닫았습니다. - [normal] 해소. UseCase KDoc 이 «두 카운트를 한 응답에 담아 주므로 그 합» 으로 정정됐습니다.
- [normal] 미반영 — 다시 남깁니다 →
feature/mindrecord/domain/src/test/kotlin/com/afternote/feature/mindrecord/domain/usecase/HomeSummaryUseCaseTest.kt:16인라인. 4번과 같은 성격인데 이 파일만 남았습니다. - [normal] 해소.
docs/qa/assumptions.md가 diff 에 들어왔습니다.
검증
- CI: head
6a1c7852기준 11 SUCCESS · 2 SKIPPED, 실패 0건.mergeable=MERGEABLE. - 스택 관계: base 인 #992 를 포함해 아래 세 단(#961·#966·#992)이 아직 정리 중이므로, 이 PR 이 develop 에 도달하는 것은 그 뒤입니다. 이 브랜치의
unit-test.yml에는 아직 androidTest 컴파일 게이트가 없어 지금 green 은 그 게이트를 통과한 green 이 아닙니다 — 루트 #961 에서 픽스처를 고치면 전파되므로 여기서 따로 하실 일은 없고, 전파 후 CI 를 한 번 더 받아 보시면 됩니다. - 관련 PR: 이 브랜치를 base 로 삼은 #1055(#562)가 같은
WeeklySummaryGrid를 손대다 충돌했습니다. 그쪽 리뷰에 base(이 PR)의 필수 파라미터를 취하고 배선만 남기는 방향으로 정리해 두었으니, 이 PR 은 그대로 두시면 됩니다. - 시안 대조: 지난번과 같음 — 근거 부재로 미수행, 블로커 아님. «깊은 생각 카드 제거»·«남은 한 장이 큰 카드 높이를 채운다» 의 시안 노드가 여전히 걸려 있지 않습니다. 다만 이번에 baseline 이 갱신됐으니 렌더 결과는 그 이미지로 확인 가능한 상태가 됐습니다.
- 실기동 QA: 해당 없음(지난번과 동일). 카드에 값을 꽂는 코드는 후속(#562)이라 화면으로 확인할 것이 아직 없습니다.
| * 발신자 홈 `WeeklySummaryGrid` 데이터 소스 (#207). | ||
| * | ||
| * 세 카드가 모두 목데이터였고 mindrecord 도메인에 UseCase 가 0건이었다. 여기서 고정하는 | ||
| * 계약은 두 가지다 — **주간 기록 수는 세 종류의 합**, **최근 깊은 생각은 1건 또는 없음**. |
There was a problem hiding this comment.
[normal] 4번과 같은 자리인데 이 파일만 남았습니다. 이 KDoc 이 고정한다고 적은 계약 두 문장이 모두 지금 코드와 다릅니다.
계약은 두 가지다 — **주간 기록 수는 세 종류의 합**, **최근 깊은 생각은 1건 또는 없음**.
- «세 종류의 합» → 바로 아래 테스트 이름이
이번 주 기록 수는 일기와 데일리질문의 합이다입니다. 둘입니다. - «최근 깊은 생각은 1건 또는 없음» → 깊은 생각은 이 PR 에서 걷어낸 범위라 대응하는 테스트가 없습니다. 고정한다고 적어 놓고 고정하지 않는 계약이라, 다음 사람이 «어딘가에 그 테스트가 있겠지» 로 읽습니다.
테스트 파일의 KDoc 은 «여기서 무엇을 보장하는가» 를 읽는 자리라 특히 정확해야 합니다. 두 문장을 실제 테스트에 맞춰 주세요.
feat(mindrecord): 데일리 질문·일기 항목 상세 화면 구현 (#759)
- DTO 2종: 상세 화면용 receivers(#759)를 들이되 isDraft 는 기본값 없이 둔다 — 키가 빠지면 false 로 접혀 임시저장이 목록에 샌다 (#789). - WeeklyReport: emotionAnalysis nullable(#725) + totalRecordAmount(#207) 둘 다. - HtmlText: 상세 본문 블록 유틸(#759)을 들이면서 중복 선언된 정규식을 정리한다. - RecordDetailViewModel: toUi 가 날짜 해석 실패에 null 을 주므로 날짜 줄만 비운다 — 오늘 날짜로 메우지 않는다 (#751). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closes #207 · Refs #201
범위
이슈가 나눠 둔 대로 mindrecord 도메인까지만 합니다.
HomeTabUiState·HomeTabViewModelwire-up 은 이슈가 «후속 … 별도 작업» 으로 적어 둔 부분이라 건드리지 않았습니다. 다만 3번째 카드 제거는 기획 결정이라 여기서 함께 처리했습니다.이번 주 기록 수 —
GetWeeklyRecordCountUseCase종류별로 세지 않는다. 주간리포트 API 가 카운트를 한 응답에 담아 준다.
종류별로 목록을 부르면 요청이 늘고, 화면이 쓰지도 않을 본문까지 받아 온다 — #736(첫 진입 요청 수 줄이기)과도 방향이 같다.
조회 기준일은 그 주 월요일이다 — 일요일에 열어도 같은 주를 봐야 한다.
깊은 생각 처리
기획에서 제거된 기능이라 세지 않는다. 서버는
deepThoughtAmount를 계속 내려주지만, DTO 에 선언하지 않으므로ignoreUnknownKeys가 그대로 무시한다 — 서버가 언제 필드를 빼든 앱은 영향받지 않는다.홈 카드 3장 → 2장
WeeklySummaryGrid의 «최근 깊은생각» 카드(우측 하단)를 제거했다.recentRecordDate·recentRecordTitle·onRecentRecordClick파라미터와HomeTabActions.onWeeklyRecentRecordClick도 함께 걷어냈다.남은 한 장이 왼쪽 큰 카드와 같은 높이를 채운다 — 한 장만 남기고 아래를 비우면 그리드가 어긋나기 때문이다. 시안 근거가 없는 판단이라
docs/qa/assumptions.md에 적어 둘 항목이다.recordedCount의 목데이터 기본값7은0으로 바꿨다. 값을 꽂는 후속 PR 에서 기본값 자체를 걷어내는 게 맞다(#562 도 이 자리표시자를 지적하고 있다).실서버 실측 (2026-08-24)
UseCase 가 계산할 값을 서버 응답으로 확인했다.
테스트
HomeSummaryUseCaseTest(신규 3개,:feature:mindrecord:domain)2026-08-24요청)mindrecord 3개 모듈 +
:app통과.화면 시연이 없는 이유
이 PR 은 도메인 계층 + 카드 제거까지다 — 이슈가 홈 wire-up 을 후속으로 분리했으므로 카드에 값을 꽂는 코드가 아직 없다. UseCase 가 계산할 입력은 실서버로 찍었고, 계산 규칙은 단위 테스트로 고정했다.
후속 (이슈에 적힌 대로)