Skip to content

fix(afternote): 추억 노트 미디어 갤러리 취소가 기존 첨부를 지우지 않게 (closes 1113) [base: feat/369] - #1116

Merged
1hyok merged 8 commits into
developfrom
fix/1113
Aug 26, 2026
Merged

1hyok merged 8 commits into
developfrom
fix/1113

Conversation

@1hyok

@1hyok 1hyok commented Aug 25, 2026 •

Copy link
Copy Markdown
Collaborator

갤러리 런처가 취소 결과(uri == null)를 "선택 없음" 으로 그대로 흘려보내, 폼 갱신 콜백이 이미 붙어 있던 첨부를 null 로 덮어썼다. 같은 파일의 촬영 경로는 진작 성공했을 때만 반영하고 있었으니(captured && uri != null), 어긋난 쪽은 갤러리다.

첨부만 지우는 수단은 화면에 없어 취소로 지워진 값은 되돌릴 길이 없다. 특히 장례식에 남길 영상은 로컬 pick 과 서버 prefill 이 videoUrl 한 칸을 겸해, 수정 모드에서는 취소 한 번이 videoMediaInput(null) → MediaInput.None 으로 이어져 서버에 저장된 영상까지 떨어뜨렸다.

슬롯 취소가 지우던 것 결과
영정사진 pickedPhotoUri 신규는 방금 고른 사진 소실, 수정 모드는 displayPhotoUri() = pickedPhotoUri ?: photoUrl 이라 예전 서버 사진으로 되돌아감
장례식에 남길 영상 videoUrl + thumbnailUrl 수정 모드에서 서버 영상까지 소실, 그대로 저장하면 서버에서도 떨어짐

변경

4줄이다.

  • onPhotoSelected/onVideoSelected 를 (String?) -> Unit → (String) -> Unit 으로 좁힌다. 인자 반공변이라 호출부의 setMemorialPhoto/setMemorialVideo((String?) -> Unit)는 그대로 들어간다.
  • 플랫폼이 주는 Uri?(= PickVisualMedia 의 결과 타입, 취소가 곧 null)는 런처 람다에서 바로 접는다 — uri?.let { onPhotoSelected(it.toString()) }.

이 조합이면 널이 흘러드는 형태를 타입이 막고, ?.let 안에서는 수신자가 Uri 로 좁혀져 uri.toString() 이 "null" 문자열을 흘리는 갈래도 표현 자체가 안 된다.

검증

  • :feature:afternote:presentation:testDebugUnitTest 31건 · :feature:afternote:presentation:ktlintCheck · :app:compileDebugUnitTestKotlin 통과.
  • 시각 검증 skip — 렌더링 코드를 건드리지 않았다(런처 결과 콜백뿐). screenshot baseline 변경 0장.

리뷰어에게

Closes #1113

@github-actions

Copy link
Copy Markdown
Contributor

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

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

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

갤러리 런처가 취소 결과(`uri == null`)를 "선택 없음" 으로 그대로 흘려보내, 폼 갱신
콜백이 이미 붙어 있던 첨부를 null 로 덮어썼다. 같은 파일의 촬영 경로는 진작
성공했을 때만 반영하고 있었으니(`captured && uri != null`), 어긋난 쪽은 갤러리다.

첨부만 지우는 수단은 화면에 없어 취소로 지워진 값은 되돌릴 길이 없다. 장례식에 남길 영상은
로컬 pick 과 서버 prefill 이 `videoUrl` 한 칸을 겸해, 수정 모드에서는 취소 한 번이
`MediaInput.None` 으로 이어져 서버에 저장된 영상까지 떨어뜨렸다.

`onPhotoSelected`/`onVideoSelected` 를 `(String?) -> Unit` → `(String) -> Unit` 으로
좁히고, 플랫폼이 주는 `Uri?` 는 런처 람다에서 바로 접는다. 널이 흘러드는 형태를
타입이 막고, `?.let` 안에서는 수신자가 `Uri` 로 좁혀져 `"null"` 문자열이 새는 갈래도
표현되지 않는다. 인자 반공변이라 호출부의 `setMemorialPhoto`/`setMemorialVideo`
(`(String?) -> Unit`)는 그대로 들어간다.

첨부를 지우는 수단 자체는 이 범위 밖이다 — 별도 이슈로 분리한다.

검증:
- `:feature:afternote:presentation:testDebugUnitTest` 31건 · `ktlintCheck` ·
  `:app:compileDebugUnitTestKotlin` 통과.
- 렌더링 변경이 없어 screenshot baseline 은 건드리지 않는다.

closes #1113
@1hyok 1hyok changed the title fix(afternote): 추모 미디어 갤러리 취소가 기존 첨부를 지우지 않게 (closes 1113) [base: feat/369] fix(afternote): 추억 노트 미디어 갤러리 취소가 기존 첨부를 지우지 않게 (closes 1113) [base: feat/369] Aug 25, 2026
@github-actions github-actions Bot removed the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 2026
@1hyok
1hyok marked this pull request as draft August 25, 2026 08:25
@1hyok

1hyok commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

🚧 리뷰 적체 가드 — 이 PR 을 닫습니다

리뷰 적체 가드(#1136)를 기존 PR 에 소급 적용했습니다. 이 PR 을 열었을 때 @1hyok 님에게 처리하지 않은 리뷰 요청이 있었습니다.

밀린 PR 리뷰 요청 시각 이 PR 생성 시각
#440 2026-08-25T01:02:07Z 2026-08-25T04:59:18Z
#771 2026-08-25T01:45:32Z

두 리뷰 모두 이 PR 이 열린 뒤인 08:34·08:36 에 처리됐습니다.

되살리는 법

밀린 리뷰는 이미 정리됐으므로 지금 바로 다시 열 수 있습니다. 브랜치와 커밋은 그대로입니다.

gh pr reopen 1116

@1hyok 1hyok closed this Aug 25, 2026
@1hyok

1hyok commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

↩️ 가드 오적용으로 닫혔습니다 — 판정 기준을 "PR 을 올린 시점의 미처리" 로 잡았으나, 실제 기준은 "지금까지도 미처리인가" 입니다. @1hyok 의 현재 미처리 리뷰 요청은 0건이라 이 PR 은 대상이 아닙니다. 되돌립니다.

@1hyok 1hyok reopened this Aug 25, 2026
@github-actions github-actions Bot added the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 2026

@Sadturtleman Sadturtleman 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.

방향과 근거에 이견 없습니다. 「취소가 사실상 유일한 삭제 경로로 쓰이고 있었다」를 별건(#1114)으로 뗀 판단, 그리고 seam 을 만들었다가 그 seam 이 새 구멍(Any?.toString())을 만든다는 이유로 되돌린 것이 특히 정확합니다 — 테스트가 지키던 게 결함 자체였다는 지적이 맞습니다.

막는 것은 하나입니다.

지적

  1. [blocking] base(feat/369)와 충돌합니다.

    $ git merge-tree --write-tree origin/feat/369 origin/fix/1113
    CONFLICT (content): .../memorial/MemorialMediaSourceState.kt
    

    merge-base 이후 base 가 두 커밋 전진했고 둘 다 같은 파일입니다.

    da17d093e refactor(afternote): discardMemorialCapture 파라미터를 non-null 로 좁힌다
    d33c4779a feat(afternote): 촬영 인텐트 발사 실패를 텔레메트리에 남긴다
    

    해소는 어렵지 않아 보입니다 — 이 PR 이 건드리는 줄(런처 람다 2개 + KDoc 2줄)과 base 가 건드린 줄(discardMemorialCapture 시그니처·onCaptureFailed 배선)이 서로 다른 자리입니다. base 를 한 번 물어 주세요.

확인한 것 (문제 없음)

  • 인자 반공변이라 호출부 setMemorialPhoto/setMemorialVideo((String?) -> Unit)가 좁아진 (String) -> Unit 자리에 그대로 들어갑니다 — 호출부 수정 0건이 맞습니다.
  • 촬영 경로는 이미 captured && uri != null 이라 이 PR 뒤에도 두 경로의 규칙이 같아집니다.
  • 수정 모드에서 videoUrl 이 로컬 pick 과 서버 prefill 을 겸한다는 점 때문에 취소 한 번이 서버 영상까지 떨어뜨린다는 설명, 코드에서 확인했습니다(displayPhotoUri() = pickedPhotoUri ?: photoUrl 도 같은 모양).
  • base 인 #1112 는 방금 승인했습니다 — FileProvider authority 가 매니페스트(${applicationId}.afternote.fileprovider)와 코드(context.packageName + ".afternote.fileprovider")에서 같은 값으로 풀리는 것, cache-path 가 CAPTURE_DIR 과 일치하는 것까지 봤습니다.

1hyok added 2 commits August 25, 2026 23:55
충돌은 `rememberMemorialMediaSourceState` 시그니처 한 곳이다. base 가 들여온
`onCaptureFailed` 파라미터와 이 브랜치가 좁힌 non-null 콜백 타입이 같은 줄에
겹쳤다 — 한쪽만 남으면 촬영 실패가 다시 조용해지거나 갤러리 취소가 기존 첨부를
지운다. 파라미터는 셋 다 두고 타입은 좁힌 쪽을 쓴다.
충돌 상태에서 push 된 머지 커밋(6a9d2ed)은 `pull_request` 트리거를 놓쳤다. GitHub 이
그 시점에 `refs/pull/1116/merge` 를 만들지 못해 워크플로가 아예 생성되지 않았고, 충돌이
풀린 뒤에도 그 이벤트는 소급 발사되지 않는다(#1028). 9분간 mergeable 이 unknown 에 머물고
head 에 런 0건인 것을 확인하고 빈 커밋으로 head 를 갱신한다.

검증(6a9d2ed 트리 기준, 이 커밋은 트리 동일):
- :feature:afternote:presentation:testDebugUnitTest · ktlintCheck ·
  :app:compileDebugUnitTestKotlin 통과.
@1hyok

1hyok commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

[blocking] base 충돌 — 반영했습니다 (6a9d2edcc)

말씀하신 대로 feat/369 를 물렸습니다. 실제로 겹친 자리는 한 곳뿐이었습니다 — rememberMemorialMediaSourceState 의 파라미터 목록입니다.

<<<<<<< HEAD                                    ← 이 PR: non-null 로 좁힌 콜백
    onPhotoSelected: (String) -> Unit,
    onVideoSelected: (String) -> Unit,
=======                                         ← base: 텔레메트리 파라미터 추가
    onPhotoSelected: (String?) -> Unit,
    onVideoSelected: (String?) -> Unit,
    onCaptureFailed: (Throwable) -> Unit,
>>>>>>> origin/feat/369

한쪽만 남기면 둘 중 하나가 되돌아갑니다 — base 를 택하면 갤러리 취소가 다시 기존 첨부를 지우고, 이쪽을 택하면 촬영 실패가 다시 조용해집니다. 파라미터는 셋 다 두고 타입은 좁힌 쪽을 썼습니다.

나머지는 예상대로 자동 병합됐습니다. KDoc 은 이 PR 이 고친 @param onPhotoSelected 문구와 base 가 더한 @param onCaptureFailed 문단이 그대로 합쳐졌고, 촬영 런처의 when 블록은 base 판이 살아 있습니다 — 그쪽은 이미 uri == null 을 갈라 두어 좁힌 시그니처와 그대로 맞습니다.

검증

  • :feature:afternote:presentation:compileDebugUnitTestKotlin · :app:compileDebugAndroidTestKotlin — BUILD SUCCESSFUL
  • :feature:afternote:presentation:ktlintCheck — BUILD SUCCESSFUL
  • 호출부 수정 0건. 인자 반공변이라 그대로 들어간다는 확인, 병합 뒤에도 유효합니다.

@1hyok
1hyok requested a review from Sadturtleman August 25, 2026 15:08
@1hyok 1hyok closed this Aug 25, 2026
@1hyok 1hyok reopened this Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚧 리뷰 적체 가드 — 이 PR 을 닫습니다

아무도 리뷰하지 않은 PR 이 1건 남아 있습니다.

PR 열린 날 경과 제목
#1156 2026-08-25 0일 refactor(mindrecord): 생성·수정 응답 DTO 의 기본값을 걷는다 (#789 마무리)

이 저장소는 아무도 응답하지 않은 PR 이 1건이라도 남아 있으면 새 PR 을 열 수 없습니다 (#1136).

각 PR 에 필요한 리뷰는 한 건입니다 — 누구든 먼저 판정을 내면 그 PR 은 모두의 목록에서 빠집니다. 승인 뒤에 올라온 변경을 다시 봐 줄 의무는 없지만, 변경요청은 작성자가 반영한 시점에 다시 리뷰어의 몫이 됩니다.

되살리는 법

위 리뷰를 끝낸 뒤 이 PR 을 다시 여세요. 브랜치는 지워지지 않았고 커밋도 그대로입니다.

gh pr reopen 1116

리뷰보다 이 PR 이 급하면 review-debt-exempt 라벨을 붙이고 다시 열면 통과합니다.

@github-actions github-actions Bot closed this Aug 25, 2026
@1hyok

1hyok commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

CI 트리거 복구 (커밋 3cfc2f60b · 재개방)

머지 커밋 6a9d2edcc 로 충돌은 풀렸는데 검증이 돌아오지 않아 두 가지를 더 했습니다.

3cfc2f60b 은 빈 커밋이라 6a9d2edcc 와 트리가 같습니다 — 리뷰 대상 diff 는 바뀌지 않았습니다. 로컬에서 병합 트리 기준 testDebugUnitTest · ktlintCheck · :app:compileDebugUnitTestKotlin 통과를 확인했습니다.

@github-actions

Copy link
Copy Markdown
Contributor

🚧 리뷰 적체 가드 — 이 PR 을 닫습니다

아무도 리뷰하지 않은 PR 이 1건 남아 있습니다.

PR 열린 날 경과 제목
#1156 2026-08-25 0일 refactor(mindrecord): 생성·수정 응답 DTO 의 기본값을 걷는다 (#789 마무리)

이 저장소는 아무도 응답하지 않은 PR 이 1건이라도 남아 있으면 새 PR 을 열 수 없습니다 (#1136).

각 PR 에 필요한 리뷰는 한 건입니다 — 누구든 먼저 판정을 내면 그 PR 은 모두의 목록에서 빠집니다. 승인 뒤에 올라온 변경을 다시 봐 줄 의무는 없지만, 변경요청은 작성자가 반영한 시점에 다시 리뷰어의 몫이 됩니다.

되살리는 법

위 리뷰를 끝낸 뒤 이 PR 을 다시 여세요. 브랜치는 지워지지 않았고 커밋도 그대로입니다.

gh pr reopen 1116

리뷰보다 이 PR 이 급하면 review-debt-exempt 라벨을 붙이고 다시 열면 통과합니다.

@github-actions github-actions Bot closed this Aug 25, 2026
@1hyok 1hyok reopened this Aug 25, 2026
@1hyok
1hyok marked this pull request as ready for review August 25, 2026 15:44
@github-actions
github-actions Bot requested a review from koongmai August 25, 2026 15:44
Base automatically changed from feat/369 to develop August 25, 2026 15:59
@github-actions github-actions Bot removed the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 2026
@1hyok
1hyok dismissed Sadturtleman’s stale review August 26, 2026 21:21

Dismissed because a later approving review from another current write-capable reviewer is the repository merge decision.

@1hyok
1hyok merged commit 0a09b74 into develop Aug 26, 2026
10 checks passed
@1hyok
1hyok deleted the fix/1113 branch August 26, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants