Skip to content

fix(afternote): 수신자 증빙 업로드 재발 — presigned 요청에 BE 필수 필드 contentLength 누락으로 400 #915

Closed

Description

@OnlyReadOneBook

📜 Overview (Required)

수신자 열람 신청의 증빙 서류 업로드가 다시 원천 불가능하다(2026-08-23 dev 서버 실측). 파일을 선택하면 즉시 "서류 업로드에 실패했습니다" 토스트가 뜬다.

원인 (실측 확정)

  • BE의 POST /receiver-auth/presigned-url 스키마(ReceiverPresignedUrlRequest)가 contentLength(int64, "업로드할 파일 크기(바이트). Presigned PUT 시 Content-Length 와 동일해야 합니다")를 required로 요구한다(dev 서버 /v3/api-docs 실측).
  • FE ReceiverAuthPresignedUrlRequestDto(feature/afternote/data/dto/ReceiverAuthDto.kt)는 extension만 보낸다 → 400 "파일 크기는 필수입니다."
  • curl 대조: {"extension":"png"} → 400 / {"extension":"png","contentLength":<size>} → 200, 발급 URL로 S3 PUT 200, delivery-verification 제출 200(PENDING)까지 정상.

재현

  1. Welcome → 전달 받은 기록 확인하기 → 발신자 등록 → 열람 신청 → 이메일 인증·마스터 키 통과
  2. 증빙 서류 업로드 화면에서 이미지/파일 선택
  3. "서류 업로드에 실패했습니다" 토스트, 슬롯 미첨부 (Pixel_7_Claude_QA·develop 계열 빌드 재현 2회)

기대 동작

  • presigned 요청에 선택 파일의 실제 바이트 크기를 contentLength로 전송하고, S3 PUT의 Content-Length와 일치시킨다.
  • 업로드 성공 시 첨부 상태 전환, 실패 시 재시도 가능(기대 동작은 #740과 동일).

📌 Child Issue(Optional)

No response

📍 Note (Optional)

Activity

  1. OnlyReadOneBook commented on Aug 25, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    재현 재확인 + 계약 변경 시점 특정 (develop 4e0a648eb, 2026-08-25 17:53 KST)

    앱에서 수신자 인증 3단계(증빙 서류 업로드)까지 실제로 진행해 파일을 첨부했더니 동일하게 400입니다.

    POST /api/v1/receiver-auth/presigned-url  --> END POST (19-byte body)
    <-- 400 (1290ms)
    

    body 19바이트 = {"extension":"png"} 만 나갑니다. 이 지점에서 막혀 4단계 인증을 앱으로 완주할 수 없습니다(1·2단계 이메일/마스터키는 정상 통과).

    BE 계약이 언제 바뀌었나

    contentLength 필수화는 BE 커밋 27fa442(2026-08-09, "fix: S3 staging 누수 차단과 업로드 크기 상한") 에서 들어왔습니다.

    + @NotNull(message = "파일 크기는 필수입니다.")
    + @Positive
    + Long contentLength   // ReceiverPresignedUrlRequest 에 추가

    즉 8/9에 서버가 계약을 조였고 FE 가 반영하지 않은 상태입니다. FE 로직 버그가 아니라 계약 동기화 누락입니다. 같은 커밋이 일반 이미지 PresignedUrlRequest 도 함께 바꿨으니, 그쪽 업로드 경로도 같은 증상인지 확인이 필요합니다.

    고칠 때 함께 봐야 할 것 — 응답도 안 받고 있다

    요청 DTO 뿐 아니라 응답 DTO 도 contentLength/maxContentLength 를 버립니다.

    // ReceiverAuthDto.kt:57  ReceiverAuthPresignedUrlDto
    presignedUrl · fileKey · fileUrl · contentType   // contentLength 없음

    BE 응답 스키마(PresignedUrlResponse)는 "PUT 요청 시 필수인 Content-Length 값(바이트). 요청한 contentLength 와 동일" 을 내려줍니다. 따라서 수정은 두 곳입니다.

    1. ReceiverAuthPresignedUrlRequestDto 에 contentLength: Long 추가 + 호출부에서 실제 파일 바이트 크기 전달
    2. ReceiverAuthPresignedUrlDto 에 contentLength 를 받아, S3 PUT 시 Content-Length 헤더를 그 서명값과 일치시키기 (헤더가 어긋나면 presigned 서명 검증에서 다시 실패)

    curl 대조로 확인 — presigned 에 contentLength 를 넣고 S3 PUT 의 Content-Length 를 맞추면 200 → PUT 200 → delivery-verification 200 으로 전 구간이 열립니다(이 경로로 만든 PENDING 건을 admin 으로 승인까지 태워 확인).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions