Skip to content

fix(receiver): 남기지 않은 계정 정보에 마스킹을 그리지 않는다 (closes 619) [base: develop] - #1169

Merged
OnlyReadOneBook merged 4 commits into
developfrom
fix/619
Aug 26, 2026
Merged

OnlyReadOneBook merged 4 commits into
developfrom
fix/619

Conversation

@OnlyReadOneBook

@OnlyReadOneBook OnlyReadOneBook commented Aug 25, 2026 •

Copy link
Copy Markdown
Collaborator

서버는 수신자 상세(GET receiver-auth/after-notes/{id})에 credentials 를 내려주지 않는다. 그런데 presentation 매퍼가 orEmpty() 로 빈 문자열을 채워, 화면이 없는 비밀번호에 •••••••• 마스킹과 「표시」 토글을 그렸다. 수신자는 가려진 값이 있다고 믿고 「표시」 를 눌렀지만 드러나는 건 빈 문자열이었다.

Closes #619

무엇을 바꿨나

부재를 폴백이 아니라 타입으로 옮겼다.

전 후
UI 모델 accountId: String = "" · password: String = "" credentials: ReceivedAccountCredentialsUiModel? (내부 두 필드도 각각 nullable)
매퍼 credentials?.id.orEmpty() 공백뿐인 값은 null 로 접고, 양쪽 다 없으면 모델 자체를 만들지 않는다
화면 항상 마스킹 + 토글 값이 있을 때만 마스킹·토글, 없으면 부재를 명시

ReceivedAccountCredentialsUiModel 이 존재하면 최소 한쪽에는 값이 있다 — 이 불변식을 매퍼가 지킨다. 덕분에 화면에는 "빈 문자열인데 값인 척" 하는 상태가 도달할 수 없다.

문구는 afternote 모듈이 아니라 receiver 모듈 strings.xml 에 뒀다 (#1066 리소스 정리 방향).

화면

스크린샷 baseline 을 세 상태로 확장했다. 왼쪽이 이 PR 이 고치는 상태다.

자격증명 부재 (기본 baseline) 아이디만 남김 온전히 남김
계정 정보 부재 아이디만 남김 온전히 남김
「고인이 계정 정보를 남기지 않았습니다.」
마스킹·토글 없음
비밀번호 행만 「남기지 않음」
그 행의 토글만 사라짐
기존 마스킹 + 「표시」 유지
(회귀 없음)

예전 baseline 은 빈 아이디와 •••••••• 를 찍고 있었다. 즉 이 결함이 baseline 으로 고정돼 있었다 — 갱신된 PNG 자체가 수정의 증거다.

세 판은 같은 애프터노트의 자격증명 상태만 다른 것이다. 부재 판도 서비스명을 채웠는데, 제목이 빈 화면은 실재하지 않기 때문이다 — 에디터 검증(TITLE_REQUIRED) · 서버 @NotBlank · DB nullable = false 로 3중 강제된다. 처리방법·남기신 말씀이 빈 것은 서버가 둘 다 선택 항목으로 두므로 실제로 도달하는 상태다.

검증

항목 결과
매퍼 계약 테스트 5건 (신설) PASS — 미제공·양쪽 부재·공백뿐·한쪽만·온전
:feature:receiver:presentation:ktlintCheck BUILD SUCCESSFUL
:app:compileDebugUnitTestKotlin BUILD SUCCESSFUL
:konsist:test · :app:compileDebugAndroidTestKotlin BUILD SUCCESSFUL
baseline 재생성 (docker linux/amd64, CI 동일 컨테이너) updateDebugScreenshotTest BUILD SUCCESSFUL
validateDebugScreenshotTest 42 tests · 0 failures — 스크린샷 CI green 사전 확정

리뷰어에게

서버는 수신자 상세(`GET receiver-auth/after-notes/{id}`)에 credentials 를 내려주지
않는다. 그런데 presentation 매퍼가 `orEmpty()` 로 빈 문자열을 채운 탓에 화면이
«가려진 값이 있다» 는 마스킹을 그렸고, 수신자는 «표시» 를 눌러 빈 값을 확인하고서야
아무것도 전달되지 않았음을 알았다.

부재를 폴백이 아니라 타입으로 옮긴다.

- ReceivedAccountCredentialsUiModel 을 nullable 로 두고, 아이디·비밀번호가 모두
  없으면(공백뿐인 값 포함) 모델 자체를 만들지 않는다. 이 타입이 존재하면 최소 한쪽에는
  값이 있다는 뜻이다.
- 화면은 값이 있을 때만 마스킹과 표시 토글을 붙인다. 자격증명이 통째로 없으면 안내
  문구를, 한쪽만 없으면 그 행에만 부재를 명시한다.
- 문구는 afternote 모듈이 아니라 receiver 모듈 strings.xml 에 둔다 (#1066 방향).

검증 — 매퍼 계약 테스트 5건 신설, 스크린샷 baseline 을 부재·부분 부재·온전 3상태로
확장(docker/amd64 재생성, validate 42 tests 0 failures).
세 baseline 중 자격증명 부재 판만 `ReceivedSocialNetworkDetailContent()` 기본값을 써서
서비스명까지 빈 화면을 찍고 있었다. **제목이 빈 애프터노트는 실재하지 않는다** — 에디터
검증(TITLE_REQUIRED) · 서버 `@NotBlank` · DB `nullable = false` 로 3중 강제된다(BE
Afternote.java·AfternoteCreateRequest.java 실코드 확인). 도달 불가능한 상태를 baseline 으로
고정하면 리뷰어가 현실에 없는 화면을 본다.

서비스명을 채워 세 판을 «같은 애프터노트의 자격증명 상태만 다른» 비교로 맞춘다.

처리방법·남기신 말씀이 빈 것은 그대로 둔다 — 서버가 둘 다 선택 항목으로 정의해 실제로
도달하는 상태다.

검증 — docker/amd64 재생성 후 validate 통과(update·validate 마커 exit 0).
@github-actions github-actions Bot added the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

이 PR 은 develop 와 충돌 상태이고, 그래서 CI 가 돌지 않는다.

pull_request 워크플로는 base 와 head 를 합친 가상 머지 커밋(refs/pull/<N>/merge)에서
실행되는데, 충돌이면 GitHub 이 그 ref 를 만들지 못해 워크플로가 트리거조차 되지 않는다.
체크가 실패하는 것이 아니라 아예 생성되지 않으므로, 새 커밋을 올려도 no checks reported
인 채 최신 커밋이 한 번도 검증되지 않은 상태로 남는다 (#1028).

develop 를 병합해 충돌을 풀면 검증이 다시 돈다. 해소되면 이 라벨은 자동으로 떨어진다.

충돌 1건 — `ReceivedAfternoteDetailSuccessMapper` 의 SOCIAL 매핑에서 develop 의 #1177
(제목 nullable 제거)과 이 브랜치의 #619(자격증명 부재 표현)가 같은 줄을 건드렸다.
둘 다 같은 방향의 «폴백 대신 타입» 이라 양쪽을 그대로 살린다.

    serviceName = title,                          // develop: title 이 non-null 로 좁혀짐
    credentials = credentials.toUiModelOrNull(),  // #619: 부재를 nullable 로 표현

`title.orEmpty()` 는 도메인 모델이 `String` 이 되면서 불필요해졌다.

검증 — 매퍼 계약 테스트 5건 · ktlint · :app:compileDebugUnitTestKotlin ·
:app:compileDebugAndroidTestKotlin · :konsist:test 전부 BUILD SUCCESSFUL.
@OnlyReadOneBook OnlyReadOneBook removed the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 26, 2026
@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

충돌은 e0d1fda2f 에서 해소했습니다 — develop 의 #1177(제목 nullable 제거)과 이 브랜치의 #619(자격증명 부재 표현)가 ReceivedAfternoteDetailSuccessMapper 의 같은 줄을 건드린 건이라, 둘 다 «폴백 대신 타입» 이라는 같은 방향이어서 양쪽을 그대로 살렸습니다.

이후 라벨이 스테일로 남아 오탐이 이어져 직접 뗐습니다. 뗄 때 실측 근거는 이렇습니다.

git merge-tree --write-tree --name-only HEAD origin/develop   # exit 0 (충돌 없음)
gh pr view 1169 --json mergeable                              # MERGEABLE

mergeStateStatus=BLOCKED 는 충돌이 아니라 승인 리뷰 1건이 아직 없어서입니다. 워크플로가 다시 판정해 실제로 충돌이면 라벨은 다시 붙습니다.

🤖 Addressed by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

❌ Screenshot test fail — baseline 과 CI rendered PNG 차이.

📦 Artifact: https://github.com/Afternote/Afternote-FE/actions/runs/32950736093 (페이지 하단 Artifacts → screenshot-test-results)

🔍 확인 위치 (artifact zip 내부):

  • diff PNG: preview/debug/diffs/...
  • rendered PNG: preview/debug/rendered/... (CI 환경에서 새로 그린 결과)
  • baseline PNG: repo <module>/src/screenshotTestDebug/reference/... (:core:ui · :feature:home:presentation · :feature:receiver:presentation · :feature:onboarding:presentation · :feature:afternote:presentation)

📝 조치 가이드:

  • 의도된 시각 변경 → docker build -t afternote-screenshot:latest -f Dockerfile.screenshot . 후 docker run --rm -v "$PWD":/workspace -w /workspace afternote-screenshot:latest ./gradlew :<module>:updateScreenshotTest 로 baseline 갱신 + commit/push
  • diff 가 anti-aliasing/font 차이로 보이면 docker 환경 변경 여부 (Dockerfile.screenshot) 점검

CI ↔ 로컬 환경 차이는 본 워크플로의 container 단계가 root fix 한다 (README 의 "Compose Preview Screenshot Testing (docker baseline)" 섹션 참조).

@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator Author

이 PR 의 변경 때문이 아니라 develop 에서 물려받은 실패입니다. 실패한 3장 중 이 PR 이 새로 넣은 SocialNetworkReceivedDetail baseline 은 없습니다.

onboarding ... onboardingTermsScreenInitialCompactScreenshot          FAILED
receiver   ... deliveryVerificationCompleteScreenLargeFontScreenshot  FAILED
receiver   ... identityVerificationEmailScreenSentLargeFontScreenshot FAILED

원인은 각각 green 이던 두 PR 의 조합입니다 — #1174(lineBreak)가 그 시점 baseline 4장만 갱신했고, #1164(fontScale 1.5 축)의 *LargeFont* baseline 은 그때 develop 에 없어 갱신 대상이 아니었습니다. 확대 축에서는 텍스트가 실제로 줄바꿈되므로 lineBreak 규칙이 픽셀에 드러납니다.

같은 일괄 머지로 :feature:onboarding:presentation:compileDebugUnitTestKotlin 도 깨져 있습니다(Unresolved reference 'terms_agree_all'). 둘 다 이 PR 밖의 건이라 각각 등록했습니다.

이 PR 자체는 로컬 실측에서 전 모듈 유닛 테스트 BUILD SUCCESSFUL 이고, 병합 전 docker 사이클에서 validateDebugScreenshotTest 42 tests · 0 failures 였습니다. #1200 이 머지되면 재검증하겠습니다.

🤖 Addressed by Claude Code

@github-actions github-actions Bot added the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 26, 2026
충돌 1건 — receiver `strings.xml` 끝에 develop 의 #620(수신자 열람 화면에서 발신자용
UI 제거)과 이 브랜치의 #619 가 각각 문자열을 덧붙여 위치가 겹쳤다. 내용이 부딪힌 게
아니므로 양쪽을 모두 남기고 블록 순서만 정리한다.

검증 — :feature:receiver:presentation:testDebugUnitTest · ktlintCheck ·
:app:compileDebugUnitTestKotlin 전부 BUILD SUCCESSFUL. develop 이 이 브랜치의
baseline 3장(SocialNetworkReceivedDetail)은 건드리지 않았다.
@OnlyReadOneBook OnlyReadOneBook removed the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 26, 2026
@OnlyReadOneBook
OnlyReadOneBook merged commit b177bc8 into develop Aug 26, 2026
14 checks passed
@OnlyReadOneBook
OnlyReadOneBook deleted the fix/619 branch August 26, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(afternote): SOCIAL 수신 상세 ACCOUNT 섹션이 서버 미제공 값에 가짜 마스킹 — '표시' 눌러도 빈 값

2 participants