Skip to content

refactor(afternote): 응답 DTO 보정형 기본값 정리 — 누락 계약을 빈 값으로 은폐하지 않는다 (#789·#790 애프터노트 판) #957

Closed

Description

@OnlyReadOneBook

📜 Overview (Required)

#789(mindrecord)·#790(timeletter)가 잡은 결함 — 서버가 항상 채우는 응답 키를 보정형 기본값(false·0·""·emptyList())으로 메워 계약 누락을 정상 빈 값으로 은폐 — 이 feature/afternote 에 그대로 남아 있다. PR #933 리뷰 중 전수 조사(develop 6123a68a 기준)에서 응답 DTO 보정형 기본값 13건을 확인했다.

확인된 대상

제외(정당한 기본값): 요청 DTO 의 receivers = emptyList() 2건(AfternoteDto.kt L24·L35) — "미선택 = 빈 배열 전송" 의도라 #933 의 receiverIds 판단과 일관된다.

진행 방식

#789→#933 이 확립한 판단 절차를 그대로 따른다: 문서 required 가 아니라 실서버 응답 실측으로 각 키의 상시 존재를 확인한 뒤 기본값을 걷어내고, 키-하나당-테스트-하나의 계약 테스트로 실패 방향을 고정한다. 값이 조건부인 필드는 nullable 유지(명시적 null 파싱), 값 집합이 열린 enum 성 필드는 값만 관대하게.

📌 Child Issue(Optional)

No response

📍 Note (Optional)

Activity

  1. OnlyReadOneBook commented on Aug 23, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    Note 의 선행 판단 사항("#676·#932 와의 조율")이 #932 쪽에서 해소됐습니다. 이 이슈는 #676 기준 확정만 기다리면 됩니다.

    #932 를 실측 대조한 결과, 그 이슈의 근거 수치가 origin/develop 이 아니라 머지되지 않은 PR #933 브랜치
    (refactor/789-dto-defaults) 기준
    이었습니다. 같은 스크립트를 세 리비전에 돌린 결과입니다.

    기준 위험 필드(non-null·기본값 없음) / Response 총계
    #932 최초 본문 주장 147 / 245 (60%)
    6123a68a (develop) 118 / 245 (48%)
    refactor/789-dto-defaults (PR #933, 미머지) 147 / 245 (60%) — 14개 파일 전부 일치

    즉 #932 는 #933 이 만들어 낸 상태를 근거로 그 PR 을 되돌리자고 말하는 구조였습니다.
    파일별로는 mindrecord 4건만 어긋났고(WeeklyReportDto 14→3, DiaryDto 9→1, MindRecordDto 14→7,
    DailyQuestionDto 10→7), 나머지 10개 파일 수치와 총계 245 · Request 109 는 정확했습니다.

    이에 따라 #932 에서 nullable·기본값 처방(문제 1)을 삭제하고, 계약 근거 주석과 afternote 매퍼 명명 정리만
    남기도록 재작성했습니다. 이제 nullable·기본값 판단은 #676(기준) → #789 · #790 · 이 이슈(적용)로 단일 방향입니다.

    이 이슈에 직접 영향 있는 것 하나 — #932 의 매퍼 항목이 feature/afternote/data/mapper/ 명명·배치 정리로 좁혀졌는데,
    같은 모듈 DTO 를 이 이슈가 건드리므로 한 PR 로 묶는 편이 충돌이 적습니다. #932 작업 순서에도 그렇게 적어 뒀습니다.

  2. OnlyReadOneBook commented on Aug 23, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    #932 에서 주석 3건을 이 이슈로 넘깁니다 — #790 에 timeletter 2건을 넘긴 것과 같은 논리입니다.

    이 이슈가 손대는 세 파일이 곧 계약 근거 주석이 없는 파일입니다.

    이 이슈에서 13건의 기본값을 걷어내려면 필드별로 "서버가 이 키를 항상 보내는가" 를 실서버 응답으로 판정해야 합니다.
    그 판정을 KDoc 으로 같이 남기면 됩니다 — 새로 조사할 일이 아니라 이미 하는 조사를 코드에 적어 두는 것입니다.
    양식은 DiaryDto.kt 를 따릅니다.

    같은 모듈에서 이 이슈가 안 건드리는 2파일(ReceiverAuthDto.kt · LeaveMessageBlockDto.kt)은 #932 에 남겨 뒀습니다.
    보정형 기본값이 0건이라 이 이슈의 대상이 아니고(이미 non-null 로 엄격), 주석만 없는 상태입니다.

    참고로 feature/afternote/data/mapper/ 명명 정리(#932)도 같은 모듈이라 이 이슈 PR 과 묶으면 충돌이 적습니다.

  3. OnlyReadOneBook commented on Aug 23, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    #676 재정의로 afternote 몫 9건이 나왔습니다 (BE 0fb9e0b 실코드 대조).

    FE BE record FE 에만 (유령) BE 에만 (누락)
    AfternoteDetailDto AfternotedetailResponse createdAt isDraft
    ReceivedAfternoteDetailDto ReceivedAfternoteDetailResponse credentials —
    ReceiverEmailAuthVerifyDto ReceiverEmailAuthVerifyResponse — accessCode
    AfternoteListItemDto ⚠ AfternoteResponse — isDraft
    AfternoteSongDto ⚠ SongRequest id —
    AfternoteDetailReceiverDto ⚠ UserPatchReceiverResponse — email
    ReceiverAuthPresignedUrlDto ⚠ PresignedUrlResponse — contentLength maxContentLength

    AfternoteDetailDto.createdAt 이 이 이슈와 직접 맞물립니다. BE 응답에 없는 필드인데 = "" 로 메워 두고,
    AfternoteDetailMapper.kt:39가 formatDateFromServer(createdAt) 로 포맷합니다 — 항상 빈 문자열입니다.
    이 이슈가 잡은 createdAt/updatedAt = "" 7건 중 createdAt 은 기본값을 떼는 게 아니라 필드를 지우는 쪽입니다.

    isDraft 는 BE 가 requiredMode = REQUIRED 로 선언해 항상 보내는데 FE 상세 DTO 에 필드 자체가 없습니다 — #808 이 필요로 하는 값입니다.

    receivers 는 non-null 로 좁히면 됩니다. BE AfternoteService.getDetailAfternote() 가 카테고리 분기 전에
    toList() 로 조립해 세 분기 모두 같은 값을 넣습니다 — null 분기가 없어 수신자가 없으면 빈 배열입니다.

    ⚠ 는 클래스명이 달라 필드 유사도로 매칭한 쌍이라 대응 관계부터 확인해 주세요.
    AfternoteSongDto ↔ SongRequest 처럼 요청 record 에 매칭된 건은 실제 응답 타입을 다시 찾아야 합니다.

  4. OnlyReadOneBook commented on Aug 23, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    앞서 넘긴 "계약 근거 주석" 몫을 철회합니다. 하지 않으셔도 됩니다.

    엔드포인트는 ApiService 와 Swagger 에, nullable 근거는 BE @Schema(description) 에 이미 있습니다.
    FE 가 KDoc 으로 복제하면 정본이 둘로 갈리고, BE 가 바뀔 때 FE 주석만 낡아 거짓이 됩니다.

    실제로 그렇게 됐습니다 — Detail.kt 에 있던 계약 설명 주석(카테고리별 non-null 표,
    ReceiverRequest 는 이 필드 하나뿐(2026-08-02 Swagger 실측), name·relation·phone 은 실리지 않아 빈 문자열)이
    전부 현재 계약과 어긋나 #676 에서 삭제됐습니다. receivers 는 전 카테고리 공통이고, BE #81 이 닫히며
    name·relation 은 이제 옵니다.

    남길 가치가 있는 주석은 명세를 봐도 모르는 FE 판단뿐입니다 — wire 이름과 도메인 이름이 다른 이유,
    실패 폭 때문에 명세와 달리 기본값을 두는 결정 같은 것. 그건 Swagger 어디에도 없으니까요.

    #932 는 afternote 매퍼 명명 정리만 남기고 축소했습니다.

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

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions