Skip to content

fix(mindrecord): 일기 본문 이미지도 fileKey 로 바꿔 보낸다 (#1016) - #1120

Merged
Sadturtleman merged 3 commits into
developfrom
fix/1016-diary-filekey
Aug 25, 2026
Merged

Sadturtleman merged 3 commits into
developfrom
fix/1016-diary-filekey

Conversation

@Sadturtleman

Copy link
Copy Markdown
Collaborator

Closes #1016

실측으로 전제를 확정했다

같은 일기 생성 API 에 두 형태를 보내 저장 결과와 CDN 응답을 비교했다 (2026-08-25, dev 서버).

보낸 img src 서버가 저장한 값 CDN
전체 URL https://…cloudfront.net/mindrecords/staging/13/bbc4…png https://…cloudfront.net/https://…cloudfront.net/mindrecords/permanent/13/bbc4…png 403
fileKey mindrecords/staging/13/e5de…png https://…cloudfront.net/mindrecords/permanent/13/e5de…png 200

호스트가 두 번 붙는다 — 이슈가 말한 그대로다. promoteReferencedMediaInHtml 이 치환 맵에 키 → 영구 URL 을 먼저 넣고 순서대로 replace 하므로, 본문이 전체 URL 이면 그 뒷부분(키에 해당하는 substring) 만 영구 URL 로 바뀐다.

어제 제가 이슈에 «전제와 어긋나는 실측이 있다» 고 적었는데, 그건 제 오독이었다. 그 관측(diaryId 41541)은 #958 브랜치에서 나온 것이고 그 브랜치의 에디터는 이미 <img src="$fileKey"> 를 넣는다. develop 경로에서는 전체 URL 이 나간다.

무엇을 바꿨나

데일리질문에만 있던 변환(#549)을 일기에도 넣고, 두 화면이 같은 규칙 하나를 쓰도록 HtmlText 로 올렸다.

fun String.toWireContent(uploadedImageUrls: Set<String>): String =
    uploadedImageUrls.fold(this) { content, url -> content.replace(url, url.toUploadedFileKey()) }
  • 이번 작성에서 받은 URL 만 정확히 치환한다. 이미 저장된 영구 URL 은 건드리지 않는다 — 서버가 그대로 통과시키고, 키로 바꾸면 이미 옮겨진 파일을 다시 옮기려다 실패한다.
  • 등록 성공 후 uploadedImageUrls.clear() — 서버가 permanent 로 옮겼으니 더는 치환 대상이 아니다.
  • 데일리질문 VM 에 있던 사본은 지웠다(같은 함수 두 벌이던 자리).

실기동 확인

에뮬레이터에서 일기에 사진을 붙여 등록했다.

요청  {"title":"filekey_emulator_check",
       "content":"<p>body</p><p><img src=\"mindrecords/staging/13/aaa85cc1-….png\" …></p>", …}
저장  <img src="https://…cloudfront.net/mindrecords/permanent/13/aaa85cc1-….png" …>

diaryId 41544 로 남아 있고, 호스트 중복 없이 permanent 로 옮겨졌다.

같은 요청에 width="0.0" height="0.0" 이 보이는데, 이건 이 PR 범위가 아니라 #731(PR #958)이 고치는 자리다 — 리치 에디터가 크기를 안 주면 0 으로 직렬화한다. 그 PR 이 원본 비율로 채운다.

회귀 가드

DiaryWriteImageKeyTest 2건 — 방금 업로드한 이미지의 src 가 fileKey 로 나가는지, 이미 저장된 영구 URL 은 그대로 두는지.

(toWireContent 를 빼면)
DiaryWriteImageKeyTest > 등록 시 방금 업로드한 이미지의 src 는 fileKey 로 나간다  FAILED
(현재)
BUILD SUCCESSFUL

검증

게이트 결과
전 모듈 testDebugUnitTest BUILD SUCCESSFUL
:app:assembleDebug · :app:compileDebugAndroidTestKotlin BUILD SUCCESSFUL
실기동 위 참조 (diaryId 41544)

docs/qa/assumptions.md 의 보류 항목은 이 실측으로 대체했다.

Sadturtleman and others added 3 commits August 25, 2026 08:18
서버는 본문 img src 에서 fileKey 를 받아 staging→permanent 로 옮기고 전체 URL 로
다시 쓴다. 전체 URL 을 그대로 보내면 그 앞에 호스트를 한 번 더 붙여 403 이 된다.
데일리질문에는 이 변환이 있었는데(#549) 일기 경로에만 없었다.

두 화면이 같은 규칙을 쓰도록 치환을 HtmlText 의 toWireContent(uploadedImageUrls)
로 올리고 데일리질문 쪽 사본을 지운다. 이미 저장된 영구 URL 은 건드리지 않는다 —
이번 작성에서 받은 URL 만 정확히 치환한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
서버 복구 후 같은 일기 생성 API 에 두 형태를 보내 비교했다.

  전체 URL → 저장값에 호스트가 두 번 붙고 CDN 403
  fileKey  → permanent URL 로 정상 저장, CDN 200

어긋나 보였던 어제 관측은 #958 브랜치에서 나온 것이었다 — 그 브랜치의 에디터는
이미 fileKey 를 넣는다. assumptions 문서의 보류 항목을 근거로 대체한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1hyok added a commit that referenced this pull request Aug 25, 2026
두 PR 이 DiaryWriteViewModel.uploadImage() 의 onSuccess 를 같이 건드려 충돌했다.
의미가 다투는 게 아니라 같은 줄을 고친 것이라, 양쪽을 그대로 합쳤다.

- #1120 이 넣은 uploadedImageUrls 기억은 유지하되 담는 값을 uploaded.fileUrl 로 맞춘다
- #1120 이 추가한 DiaryWriteImageKeyTest 의 fake 를 UploadedFile 로 적응
  (fileKey 는 역산 결과와 같은 값이라 단언은 그대로 통과)

역산(toUploadedFileKey) 자체를 걷어내는 것은 이 PR 범위가 아니다 — #1125 로 분리했다.

검증: :feature:mindrecord:presentation:testDebugUnitTest,
:app:compileDebugUnitTestKotlin, :app:compileDebugAndroidTestKotlin BUILD SUCCESSFUL

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

승인

일기 본문 이미지의 fileKey 변환 누락을 데일리질문과 같은 규칙 하나로 닫았다. 실측·회귀 가드 모두 충분하고, 공통화 위치(HtmlText.kt)도 맞다.

내가 따로 확인한 것

uploadedImageUrls.clear() 가 안전한지 BE 실코드로 검증했다. 이 줄이 이 PR 에서 제일 위험할 수 있는 자리였다 — 서버가 임시저장에서 승격을 건너뛴다면, 비운 뒤 이어 쓰는 흐름에서 치환이 풀려 전체 URL 이 나간다.

// DiaryService.java:48  createDiary — isDraft 분기 없이 무조건 탄다
mindRecordContentMediaService.prepareContentForSave(userId, request.getContent())
// MindRecordContentMediaService.java:24 → S3Service.promoteReferencedMediaInHtml

임시저장에서도 staging→permanent 승격이 일어난다. 게다가 DiaryWriteScreen.kt:72 의 LaunchedEffect 가 Succeeded 를 보면 곧바로 onSubmitSuccess() 로 화면을 뜨므로, 「임시저장 뒤 화면에 머물다 다시 등록」 흐름이 일기에는 아예 없다. 비우는 게 맞다.

그 밖에:

  • Proxy 로 UserRepository 를 세운 방식은 이 모듈의 선례를 따랐다 (WeeklyReportEmotionAnalysisTest.kt:226 이 같은 모양). 새로 들인 관행이 아니다.
  • 브랜치가 androidTest 게이트(:app:compileDebugAndroidTestKotlin)를 갖고 있다 — 묵은 브랜치의 숨은 부채는 없다.
  • 실서버 재실측은 하지 않았다. 본문의 A/B 실측이 이슈 전제와 BE 실코드 양쪽에 들어맞고, 아래 지적은 어느 쪽도 실측으로 갈리지 않는다.

시안 대조

해당 없음 — 본문 직렬화 규칙만 바뀌고 화면에 보이는 것은 그대로다.

머지 전 주의 — #1121 과 텍스트 충돌한다

두 PR 이 docs/qa/assumptions.md 끝에 각자 새 절을 붙인다. git merge-tree 실측:

CONFLICT (content): Merge conflict in docs/qa/assumptions.md
Auto-merging .../DiaryWriteViewModel.kt        ← 코드는 자동 병합된다

코드는 안 부딪히고 문서만 부딪힌다. 나중에 들어가는 쪽이 해소해야 하고, 충돌 상태로 두면 그 PR 은 CI 가 아예 안 돈다. 먼저 넣을 쪽을 정해 두면 된다.

content = state.content.toWireContent(uploadedImageUrls),
isDraft = isDraft,
todayMood = mood,
imageUrl = state.imageUrl,

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.

본문은 fileKey 로 바뀌는데 이 필드만 전체 URL 그대로 나간다. 같은 요청 안에서 같은 이미지가 두 형태로 실린다.

지금은 서버가 imageUrl 을 버리므로(#1024 실측 — 요청에 실어도 저장 응답이 null) 무해하고, #1124 가 이 줄을 걷어낸다. 그래서 blocking 으로 잡지 않는다.

다만 이 PR 이 #1124 보다 먼저 develop 에 들어가면 그 사이 동안 남는다. 두 건을 붙여 머지하거나, 순서가 벌어질 것 같으면 여기서 함께 걷는 편이 낫다 — 나중에 서버가 이 필드를 받기 시작하면 방금 본문에서 고친 것과 똑같은 호스트 중복이 이 자리에서 재현된다.

@1hyok
1hyok requested a review from koongmai August 25, 2026 11:24
@Sadturtleman
Sadturtleman merged commit fbf6b30 into develop Aug 25, 2026
14 checks passed
@Sadturtleman
Sadturtleman deleted the fix/1016-diary-filekey branch August 25, 2026 13:13
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(mindrecord): 일기 작성의 본문 이미지가 fileKey 로 변환되지 않음 — #953 머지 시 깨진 이미지로 활성화

2 participants