Skip to content

fix(receiver): 수신자 홈 헤더 액션에 이름을 붙이고 구성을 고정한다 (#613 일부) - #1103

Merged
Sadturtleman merged 7 commits into
developfrom
fix/613-receiver-home-header
Aug 25, 2026
Merged

Sadturtleman merged 7 commits into
developfrom
fix/613-receiver-home-header

Conversation

@Sadturtleman

Copy link
Copy Markdown
Collaborator

#613 의 1번(프로필 아이콘) 과 그 과정에서 드러난 접근성 결함을 닫는다. 2번(설정 목적지)은 시안 근거가 없어 뺐다 — 아래 「남는 것」 참고.

1번은 이미 해소돼 있었다 — 대신 재발 가드를 붙인다

ReceiverHomeScreen 이 showProfileIcon = false 로 넘기고 있어 지금은 프로필 아이콘이 뜨지 않는다. 시안도 같다.

시안 대조 — 수신자 홈 4327:73626(최종 수신자 프로토타입 → 애프터노트 - 상세확인): 헤더에 로고와 톱니 하나뿐이고 프로필 아이콘이 없다.

문제는 이 구성이 기본값 하나로 되돌아간다는 점이다. HomeTopBar(showProfileIcon: Boolean = true) 라 인자를 빠뜨리면 회원 홈과 같은 헤더가 그대로 나온다. 그래서 «수신자 홈에는 프로필 아이콘이 없다» 를 테스트로 고정했다.

(showProfileIcon = true 로 되돌린 상태)
ReceiverHomeHeaderTest > 수신자 홈에는 프로필 아이콘이 없다  FAILED
(현재)
BUILD SUCCESSFUL

함께 드러난 것 — 상단바 액션에 이름이 없다

두 아이콘 모두 contentDescription = null 이었다. 프로필은 장식이라 그래도 됐지만, 설정은 유일하게 눌리는 액션인데도 접근성 트리에 이름이 없어 스크린리더가 무엇인지 읽어 주지 못한다.

Image(
    painter = painterResource(R.drawable.core_ui_settings),
    contentDescription = stringResource(R.string.core_ui_home_top_bar_setting),
    modifier = Modifier.size(18.dp).clickable(role = Role.Button) { onSettingClick() },
)

Role.Button 도 함께 줬다 — 종전에는 «이미지» 로 읽혔다.

남는 것 — 2번(설정 목적지)은 확정이 필요하다

지금 톱니는 회원 설정 그래프(Route.Setting)로 그대로 보낸다. 수신자는 X-Auth-Code 기반이라 로그아웃할 세션이 없고, 프로필 수정·비밀번호 변경·수신자 관리도 해당이 없다.

시안에도 답이 없다. 수신자 섹션 안의 「설정 메인」(4327:75979)은 회원 설정 화면(프로필 수정 · 비밀번호 변경 · 로그아웃)을 그대로 복제한 프레임이라, 수신자 전용 설정 시안은 존재하지 않는다.

선택지는 셋인데 어느 쪽도 코드만 보고 정할 수 없다.

안 근거 걸리는 점
진입점 제거 수신자가 할 수 있는 설정이 없다 시안에는 톱니가 있다
고객지원 항목만 남긴 수신자 설정 FAQ·공지·약관은 수신자에게도 유효 새 화면이라 시안 없음
인증 해제(받은 기록 접근 종료) 수신자 맥락에 맞는 유일한 «끝내기» 도메인 동작·문구 모두 신설

기획·디자인 확정 뒤 후속으로 진행하고, 이 판단 보류를 근거와 함께 docs/qa/assumptions.md 에 남겼다. 그래서 이 PR 은 #613 을 닫지 않는다.

검증

게이트 결과
전 모듈 testDebugUnitTest BUILD SUCCESSFUL
:app:assembleDebug · :app:compileDebugAndroidTestKotlin BUILD SUCCESSFUL
compileDebugScreenshotTestKotlin (core:ui · receiver) BUILD SUCCESSFUL

스크린샷 baseline 재생성 불필요 — contentDescription 과 role 은 시맨틱스만 바꾸고 픽셀을 바꾸지 않는다.

실기동 QA: 못 했다. 수신자 홈은 delivery-verification 이 APPROVED 여야 진입할 수 있고(#618·#614 와 같은 사정), 오늘 dev 서버가 점검 시간대라 응답하지 않는다. 대신 Robolectric 으로 실제 컴포지션을 태워 헤더 구성을 확인했다.

상단바 아이콘 둘 다 contentDescription 이 null 이라, 유일하게 눌리는 설정 아이콘조차
스크린리더가 읽어 주지 못했다. 이름을 붙이고 clickable 에 Role.Button 을 준다.

수신자 홈에 프로필 아이콘이 없다는 것(시안 4327:73626)과 설정 아이콘이 눌린다는 것을
회귀 가드로 고정한다 — 회원 홈 상단바를 그대로 재사용하는 구조라 기본값(true)으로
되돌아가기 쉬운 자리다.

설정 진입의 목적지 정리는 이 PR 범위 밖이다 — 수신자 전용 설정 시안이 없어
docs/qa/assumptions.md 에 근거와 함께 남겼다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@1hyok 1hyok left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설정 아이콘 쪽(contentDescription + Role.Button)은 그대로 좋다. 시안도 대조했고 «수신자 홈에 프로필 아이콘이 없다» 는 판단은 정확하다. docs/qa/assumptions.md 에 톱니 목적지 미확정을 남긴 것도 규약대로다.

다만 프로필 아이콘에 붙인 이름은 되돌려야 한다. 이 PR 이 고치려던 문제를 회원 홈 쪽에 새로 만든다 — 아래 인라인에 근거를 적었다.

검증

  • CI: 필수 체크 11종 전부 green.
  • 시안 대조 완료 — 수신자 홈 4327:73626 을 렌더해 확인했다. 헤더는 좌측 로고 + 우측 톱니 하나뿐이고 프로필 아이콘이 없다. PR 설명·테스트 KDoc 의 주장과 일치한다.
  • 실기동 QA 해당 없음 — 변경이 접근성 트리 semantics 라 Robolectric 테스트가 덮는 범위와 같다. 다만 아래 blocking 은 실기기 TalkBack 에서 재현되는 성질의 것이다.
  • HomeTopBar 사용처 전수: 회원 홈(HomeTabScreen) · 애프터노트 홈 · 타임레터 발신/수신 홈 · 수신자 홈 — 5곳. 이 중 showProfileIcon 을 false 로 넘기는 곳은 수신자 홈뿐이다.

지적

  1. [blocking] 목적지 없는 장식 아이콘에 접근성 이름을 붙였다 → HomeTopBar.kt:51 인라인 코멘트.

Image(
painter = painterResource(R.drawable.core_ui_user),
contentDescription = null,
contentDescription = stringResource(R.string.core_ui_home_top_bar_profile),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocking] 이 Image 에는 clickable 이 없다 — 바로 아래 톱니와 달리 어떤 화면에서도 눌리지 않는다. 이름을 붙이면 TalkBack 이 포커스 가능한 노드로 읽어, 사용자는 액션이 있다고 믿고 탭했다가 아무 반응도 얻지 못한다. 장식 요소에 contentDescription = null 을 두는 것이 Android 접근성 권장이고, 종전 코드가 그 상태였다.

근거가 셋 다 같은 방향을 가리킨다.

테스트가 «프로필 아이콘이 없다» 를 검증하려고 이름이 필요했던 것이라면, 프로덕션 semantics 대신 Modifier.testTag 로 앵커를 잡는 편이 낫다. 아니면 프로필 아이콘 자체를 여기서 걷어내는 쪽이 이슈 본문의 요구에 더 가깝다 — 다만 그건 회원 홈 시안 확정이 필요하니 별도 범위로 두는 것도 합리적이다.

core_ui_home_top_bar_profile 문자열도 함께 정리 대상이 된다.

1hyok and others added 3 commits August 25, 2026 13:43
이름을 붙이면 TalkBack 이 포커스 가능한 노드로 읽어, 사용자가 액션이 있다고 믿고
탭했다가 아무 반응도 얻지 못한다. 이 아이콘은 clickable 이 없는 장식이고, 실제로
그려지는 곳은 이 PR 범위 밖(회원 홈·애프터노트 홈·타임레터 홈)이다.

테스트가 존재 여부를 보려고 필요했던 앵커는 testTag 로 바꿔, 프로덕션 semantics 를
테스트 때문에 넓히지 않는다. 설정 아이콘의 이름·Role 은 그대로 둔다 — 그쪽은 실제로
눌리는 유일한 액션이다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Sadturtleman

Copy link
Copy Markdown
Collaborator Author

지적 반영했습니다 — 되돌리는 쪽이 맞습니다.

프로필 아이콘의 contentDescription 을 null 로 되돌리고 문자열(core_ui_home_top_bar_profile)도 지웠습니다. 근거 셋 다 같은 방향이라는 지적 그대로입니다 — 특히 영향 범위가 이 PR 밖이라는 점이 결정적이었습니다. 수신자 홈은 showProfileIcon = false 라 이 줄을 타지도 않고, 실제로 그려지는 곳은 회원 홈·애프터노트 홈·타임레터 홈입니다. 「눌러도 아무 일 없는 버튼」을 그쪽에 새로 만들 뻔했습니다.

테스트 앵커는 제안대로 testTag 로 바꿨습니다.

// 프로덕션
Image(painter = …, contentDescription = null, modifier = Modifier.size(18.dp).testTag(PROFILE_ICON_TEST_TAG))

// 테스트
composeRule.onNodeWithTag(PROFILE_ICON_TEST_TAG).assertDoesNotExist()

테스트 KDoc 도 «설정은 이름을 두고 프로필은 두지 않는다» 는 이유가 남도록 고쳤습니다.

설정 아이콘의 contentDescription + Role.Button 은 그대로입니다 — 그쪽은 실제로 눌리는 유일한 액션입니다.

프로필 아이콘 자체를 걷어내는 건 말씀대로 회원 홈 시안 확정이 필요해 이 PR 범위 밖으로 두었습니다. docs/qa/assumptions.md 의 항목에 그 사정도 함께 적혀 있습니다.

@1hyok 1hyok left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking 이 닫혔습니다. 승인합니다.

지적 처리

# 지적 처리
1 [blocking] 목적지 없는 장식 아이콘에 접근성 이름을 붙였다 닫힘 — contentDescription = null 복귀 + 문자열 삭제

HomeTopBar.kt:53 이 contentDescription = null 로 돌아왔고, core_ui_home_top_bar_profile 도 지워졌습니다. 회원 홈·애프터노트 홈·타임레터 홈에 「눌러도 아무 일 없는 버튼」이 새로 생기는 일은 없습니다.

되돌리는 데서 그치지 않고 왜 이 아이콘만 이름이 없는지를 세 자리에 남긴 것이 이 수정의 값입니다 — 프로덕션 주석, strings.xml 의 설정 문자열 주석, 테스트 KDoc. 특히 KDoc 이 «설정은 이름을 두고 프로필은 두지 않는다» 를 대비로 적어 두어, 다음 사람이 «누락» 으로 오인해 채워 넣는 경로가 막혔습니다. 종전 KDoc 은 둘을 한 덩어리로 말하고 있어 그 오인이 실제로 가능했습니다.

테스트 앵커도 의도대로 갈렸습니다. onNodeWithTag(PROFILE_ICON_TEST_TAG).assertDoesNotExist() 는 프로덕션 semantics 를 건드리지 않고 «없음» 만 봅니다 — testTag 는 접근성 서비스에 노출되지 않으므로(testTagsAsResourceId 기본 off) TalkBack 이 읽는 트리는 그대로입니다.

검증

  • CI: 필수 체크 전부 green (head 5473d30d).
  • develop 병합 실측: git merge-tree --write-tree origin/develop <head> → 충돌 0건. develop 428022ff 기준.
  • 삭제 자원 잔존 사용처: head 트리 전수 git grep core_ui_home_top_bar_profile → 0건. 문자열만 지우고 참조가 남는 형태가 아닙니다.
  • 시안 대조: 앞 리뷰에서 확인한 수신자 홈 4327:73626 대로 헤더는 로고 + 톱니 하나이고, 이번 수정은 그 판정을 바꾸지 않습니다.
  • 실기동 QA 해당 없음 — 변경이 semantics 라 Robolectric 이 덮는 범위와 같습니다. 이제는 이름 부여가 없어져 TalkBack 재현 대상도 사라졌습니다.

사소한 후속 여지 (이 PR 에서 안 고쳐도 됩니다)

PROFILE_ICON_TEST_TAG 는 core:ui 의 public top-level 상수가 됐습니다. 테스트가 모듈 밖(feature:receiver:presentation)에 있어 internal 이 불가하니 public 자체는 불가피한데, @VisibleForTesting 한 줄이면 «프로덕션에서 참조할 것이 아니다» 라는 의도가 표시됩니다 — #1105 에서 같은 성격의 완화를 그렇게 처리하셨으니 표기만 맞춰 두면 일관됩니다.

@1hyok
1hyok requested a review from koongmai August 25, 2026 11:24
@github-actions github-actions Bot added the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 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 를 병합해 충돌을 풀면 검증이 다시 돈다. 해소되면 이 라벨은 자동으로 떨어진다.

Sadturtleman and others added 2 commits August 25, 2026 22:21
assumptions.md 인접 추가라 양쪽을 모두 살렸다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
assumptions.md 인접 추가라 양쪽을 모두 살렸다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot removed the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 2026
@Sadturtleman
Sadturtleman merged commit e787245 into develop Aug 25, 2026
14 checks passed
@Sadturtleman
Sadturtleman deleted the fix/613-receiver-home-header branch August 25, 2026 14:18
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.

2 participants