Skip to content

refactor(afternote): BE #288 확정 상세 계약과 FE 호환성을 확인한다 #1959

Closed as not planned

Description

@1hyok

작업 유형

refactor — 동작 변경 없는 구조·책임·경계 개선

주 담당 모듈

afternote — 애프터노트

개요

#1958과 분리하여 BE 상세 계약의 확정 결과를 현재 FE와 대조하고 검증한다. 미확정 DTO·매퍼 변경이나 호환성 강화 구현은 예약하지 않는다. 이 이슈는 Afternote/Afternote-BE#288의 결과에 의존한다. #1958은 현재 JSON 계약을 유지하는 FE 내부 정리만 담당하고 이 이슈를 기다리지 않고 완료할 수 있다.

확인된 배경

BE의 종류별 응답은 Draft / Published / PublishedPlaylist로 표현되고, FE develop은 이를 category 및 nullable credentials·memorial을 가진 AfternoteDetailDto로 받는다. BE #288은 종류별 전용 데이터·필수값의 타입·OpenAPI 표현을 일관되게 정리한다. 기존 JSON이 유지될지, 클라이언트 변경이 필요한지는 최종 계약으로 확정해야 하므로 이를 추측해 구현하지 않는다.

선행 의존성과 해제 조건

  • 선행 이슈: [refactor] 애프터노트 상세의 종류별 전용 데이터·필수값 계약을 일관되게 표현한다 Afternote-BE#288. GitHub blocked_by도 이 이슈에 설정한다.
  • 계약 산출물: 종류·임시저장/발행 상태별 JSON 예시, required·nullable 규칙, 기존 클라이언트 호환성·전환 방침.
  • 검증 산출물: 실제 직렬화 결과와 생성 OpenAPI 계약 테스트 또는 대상 환경에서 확인할 수 있는 응답.
  • 위 산출물이 준비되면 차단 관계를 재평가한다. BE 이슈의 열린 상태만으로 준비된 독립 작업을 계속 막지 않는다. 확정 계약과 현재 구현의 차이가 확인될 때만 실제 필요한 구현 범위를 별도로 정한다.

작업 범위

  • 최종 BE 계약과 당시 FE 구현을 대조해 변경 필요 여부와 구체적인 차이를 기록한다. 이 이슈에서 미리 정한 DTO·역직렬화·매퍼 변경은 없다.
  • 임시저장·발행 및 SOCIAL·BUSINESS·GALLERY·PLAYLIST 상세 응답과 에디터 프리필이 확정된 계약에 맞게 동작하는지 검증한다.
  • 발행 계정의 credentials·id·password, 발행 PLAYLIST의 playlist·최소 1곡 보장 및 임시저장의 미작성 허용을 최종 계약·대상 배포 환경과 대조한다. #1762에서 기존 배포 호환을 위해 유지한 발행 계정의 빈 값 처리는 유지한다. 강화 필요 여부는 확정된 계약과 배포 호환성 근거로만 판단한다.
  • BE가 기존 JSON을 유지해 FE 코드 변경이 불필요하면, 계약 대조와 검증 근거를 남기고 변경 불필요로 완료한다. 불필요한 코드 변경을 만들어내지 않는다.

완료 조건

  • BE #288의 최종 계약과 검증 근거를 확인하고 링크한다.
  • 현재 FE와의 계약 차이 또는 변경 불필요함을 근거와 함께 확인한다. 차이가 있다면 확정된 요구사항만 별도 작업으로 정한다.
  • 종류별·상태별 상세 매핑과 에디터 프리필을 검증한다.
  • 호환성·전환 결과를 기록하고 선행 관계의 최종 상태를 확인한다.

참고

Activity

  1. added
    refactor동작 변경 없이 코드 구조·책임·경계를 개선하는 작업
    area:afternote애프터노트 기능 영역
    on Sep 8, 2026
  2. changed the title [-]refactor(afternote): BE #288 상세 계약을 FE에 반영하고 통합 검증한다[/-] [+]refactor(afternote): BE #288 확정 상세 계약과 FE 호환성을 확인한다[/+] on Sep 12, 2026
  3. 1hyok commented on Sep 13, 2026

    @1hyok
    CollaboratorAuthor

    착수 상태 (2026-09-13 실측)

    착수 불가다. 이 이슈의 유일한 선행인 Afternote/Afternote-BE#288 이 열린 채 09-08 이후 아무 산출물도 내지 않았다. 다음 사람이 다시 조사하지 않도록 오늘 잰 값과, 계약이 확정되면 차이만 보면 되도록 만든 대조표를 남긴다.

    BE#288 실측

    항목 값
    상태 open, Hwanggyuun 어사인
    생성 2026-09-08 03:47:24Z
    마지막 갱신 2026-09-08 03:57:42Z (assigned)
    코멘트 0건
    타임라인 cross-referenced 2건, blocking_added, assigned 넷뿐. 커밋·브랜치·PR 참조 없음
    관련 브랜치 0건
    관련 PR 0건 (BE 열린 PR 자체가 0건)

    응답 파일도 안 움직였다. AfternotedetailResponse.java 의 최신 커밋은 2161078(2026-08-29, BE#255·#256분)이고, BE#288 이 확인 기준으로 인용한 fcca1ff 이후 한 줄도 바뀌지 않았다. AfternotePublishedPlaylistResponse.java 도 72fee63(08-29)이 마지막이다. 09-08 이후 BE main 커밋 3건(87fdbf1 카카오 수신자, d34353e #272·#277, 3593aa3 #287·#286·#282)은 전부 다른 이슈이고 상세 응답 계약과 무관하다.

    대기 중인 답변

    물은 창구는 BE#288 본문 자체다. 09-08 03:47 에 열었고, 03:53 에 이 이슈의 blocked_by 로 걸었으며(오늘 dependencies/blocked_by 로 재확인, 지금도 BE#288 하나뿐이다), 03:57 에 Hwanggyuun 에게 어사인됐다. 오늘까지 5일 동안 코멘트·커밋·브랜치·PR 어느 쪽으로도 회신이 없다. 슬랙 afternote 워크스페이스에서 09-07 이후 "288" 검색도 0건이라 이슈 밖에서 오간 답도 확인되지 않는다(내가 볼 수 있는 채널 범위).

    받아야 할 산출물은 이 이슈 본문이 해제 조건으로 못 박은 넷이고 전부 미존재다.

    • 종류·임시저장/발행 상태별 JSON 예시
    • required·nullable 규칙
    • 기존 클라이언트 호환성·전환 방침
    • 실제 직렬화 결과 또는 생성 OpenAPI(/v3/api-docs) 기준 계약 테스트

    본문의 해제 조건에 비춘 "지금 확인 가능한 범위"

    본문은 "BE 이슈의 열린 상태만으로 준비된 독립 작업을 계속 막지 않는다" 고 적었다. 그 기준으로 갈라 보면 이렇다.

    지금 못 하는 것. 완료 조건 1·2·4(확정 계약 링크, 차이 판정, 호환성·전환 결과 기록)는 대조 대상이 없어 성립하지 않는다. research 로 낮추는 것도 안 된다. 조사 대상인 최종 계약이 존재하지 않아 무엇을 확인해 기록할지가 정해지지 않는다.

    지금 되는 것. BE#288 이 스스로 "되돌리지 않는다"·"유지한다" 고 적은 항목(발행 PLAYLIST 의 playlist·최소 1곡 보장, 임시저장의 미작성 허용, 참조형 필드 nullable)은 결과와 무관하게 오늘 대조할 수 있다. 아래 표와 차이 3건이 그 범위다. 계약이 확정되면 표의 BE 열만 갈아 끼우고 달라진 칸만 보면 된다.

    대조표: FE AfternoteDetailDto 대 BE 응답 3종

    기준은 FE origin/develop 7d87aa3, BE main 3593aa3(오늘 gh api .../contents 로 읽음).

    와이어 키 FE AfternoteDetailDto BE Draft BE Published BE PublishedPlaylist
    afternoteId Long 필수 REQUIRED REQUIRED REQUIRED
    category String 필수 REQUIRED REQUIRED REQUIRED, PLAYLIST 고정
    title String 필수 REQUIRED REQUIRED REQUIRED
    isDraft Boolean 필수, 도메인으로 안 올림 REQUIRED, true 고정 REQUIRED, false 고정 REQUIRED, false 고정
    updatedAt String 필수 REQUIRED REQUIRED REQUIRED
    receivers List 필수, 원소 3필드는 방어적 nullable REQUIRED REQUIRED REQUIRED
    actions List<String>? 기본 null NOT_REQUIRED nullable NOT_REQUIRED nullable 선언은 nullable, 생성 분기가 항상 null 로 채움
    leaveMessage List? 기본 null NOT_REQUIRED nullable NOT_REQUIRED nullable NOT_REQUIRED nullable
    credentials AfternoteCredentialsDto? 기본 null NOT_REQUIRED nullable 선언은 nullable, 생성에서 SOCIAL·BUSINESS 는 id·password 검사 선언은 nullable, 생성 분기가 항상 null 로 채움
    playlist AfternotePlaylistDto? 기본 null, songs 만 필수 NOT_REQUIRED nullable, 타입 PlaylistRequest NOT_REQUIRED nullable, 타입 PlaylistRequest REQUIRED non-null, 타입 AfternotePublishedPlaylistResponse, songs minItems 1

    BE 근거: AfternotedetailResponse.java, AfternotePublishedPlaylistResponse.java.

    오늘 기준으로 이미 어긋나는 3건

    BE#288 결과와 무관하게 성립한다. 확정 계약이 도착하면 이 셋부터 다시 본다.

    1. isDraft 를 읽고 버린다. AfternoteDetailDto.isDraft(AfternoteDto.kt:56)는 non-null 로 파싱되지만 AfternoteDetailMapper.toDomain 이 도메인으로 올리지 않는다. 도메인 Detail 에도 프레젠테이션에도 임시저장 축이 없다. afternote 모듈 main 소스에서 isDraft 는 응답 DTO 두 줄(AfternoteDetailDto, AfternoteListItemDto)이 전부다. 즉 BE 가 타입으로 가른 Draft/Published 구분이 FE 에서는 category 단일 분기로 접힌다. BE#288 이 종류별 전용 타입을 스키마에 드러내도 FE 가 그것을 구별할 자리는 지금 없다. 1차 대조 지점이다.

    2. 임시저장 PLAYLIST 의 playlist 미작성에서 상세가 통째로 실패한다. BE Draft 의 스키마 설명은 "임시저장 PLAYLIST는 미작성 시 null" 이고 BE#288 도 그 정책을 유지한다고 적었다. 반면 FE AfternoteDetailMapper.kt:62 는 requireNotNull(playlist) 로 던지고, 그 예외를 AfternoteRepositoryImpl.getDetail 의 runCatchingCancellable 이 Result.failure 로 옮긴다. 상세 화면도, 같은 getDetail 을 쓰는 에디터 프리필(AfternoteEditorViewModel.loadExistingAfternoteForEdit)도 실패로 끝난다. 지금 안 터지는 이유는 FE 가 임시저장을 만들지 않기 때문이다. 생성 요청 DTO 셋 어디에도 isDraft 필드가 없다. 서버나 다른 클라이언트가 임시저장 PLAYLIST 를 만들면 그때 드러난다. AfternoteDetailMapperTest 16케이스도 전부 isDraft = false 라 이 경로를 덮지 않는다.

    3. memorialAudioUrl 이 FE DTO 에 없다. BE AfternotePublishedPlaylistResponse 와 AfternoteCreateRequest.PlaylistRequest 둘 다 이 필드를 든다. FE AfternotePlaylistDto(AfternoteDto.kt:66)에는 없고, NetworkModule 의 ignoreUnknownKeys = true 때문에 깨지지 않고 조용히 버려진다. 의도된 보류이고 추억 노트 미디어 음성 녹음 첨부 — #369 에서 서버 계약 부재로 빠진 갈래 #1118 이 추적한다(AfternotePlaylistRequestDto KDoc). 계약 확정에서 요구가 올라오면 여기가 대상이다.

    나머지 키는 오늘 기준 어긋나지 않는다. receivers 는 양쪽 필수이고 원소 필드도 receiverId·name·relation 로 같다. FE 는 셋 다 nullable 로 받아 receiverId 없는 항목을 도메인으로 안 올린다. credentials 는 AfternoteDetailMapper.kt:73-74 가 orEmpty() 로 낮춘다. #1762 의 배포 호환 처리이고 본문이 유지한다고 못 박은 부분이라, BE 가 발행 계정의 필수성을 스키마로 올려도 임의로 require 로 바꾸지 않는다.

    본문에서 고칠 곳

    "확인된 배경" 의 "FE develop은 이를 category 및 nullable credentials·memorial을 가진 AfternoteDetailDto로 받는다" 는 낡았다. #1958(7215d44, PR #1960 머지 1d16dcd, 09-11 종료)이 상세 DTO 프로퍼티를 memorial 에서 playlist 로 바꿨다. 지금 필드는 playlist: AfternotePlaylistDto? 다. 남은 memorial 이름은 쓰기 바디인 AfternoteCreatePlaylistRequestDto.memorial 과 AfternoteUpdateRequestDto.memorial 둘뿐이고 둘 다 @SerialName("playlist") 라, 상세 응답 계약인 이 이슈 범위가 아니다. 단일 DTO 로 받는다는 서술 자체는 그대로 유효하다. BE 3타입 대 FE 1DTO 비대칭은 남아 있다.

    재개할 때 열 파일

    • feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/dto/AfternoteDto.kt (AfternoteDetailDto:52, AfternotePlaylistDto:66)
    • feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/mapper/AfternoteDetailMapper.kt (62 행 requireNotNull(playlist), 73-74 행 orEmpty())
    • feature/afternote/data/src/test/java/com/afternote/feature/afternote/data/mapper/AfternoteDetailMapperTest.kt (16케이스), .../dto/AfternoteResponseDtoContractTest.kt (키 누락 회귀 10케이스)
    • 완료 조건 3의 에디터 프리필: feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/editor/model/EditorFormPrefill.kt, 같은 경로 editor/AfternoteEditorFormMapper.kt, 테스트 feature/afternote/presentation/src/test/kotlin/.../editor/AfternoteEditorFormPrefillTest.kt

    에디터 프리필의 시안 대조는 이번에 못 했다. Figma MCP 가 이 세션에서 미인증이라 시안을 열 수 없다. 계약 확정 뒤 착수할 때 다시 연다.

  4. 1hyok commented on Sep 20, 2026

    @1hyok
    CollaboratorAuthor

    2026-09-20 계약 대조를 갱신합니다.

    BE#288은 OPEN이며 최종 종류별 JSON 예시·required/nullable 규칙·호환성 방침의 새 산출물은 아직 없습니다. BE main은 7c961ec3e2eb6fe3d0d87d4ba4e2dea312fdcf7f이고 AfternotedetailResponse.java의 마지막 변경은 21610783입니다.

    이번에는 실제 배포 GET /v3/api-docs도 HTTP 200으로 확인했습니다. AfternotedetailResponse.oneOf에 Draft/Published/PublishedPlaylist 세 응답이 있으며, PublishedPlaylist의 playlist는 required·non-null, songs는 required·minItems=1입니다. 반면 SOCIAL/BUSINESS credentials는 공통 Published 스키마에서 여전히 nullable이며 required 목록에 없습니다. 따라서 예전 FE KDoc의 배포 응답이 아직 평면이라는 설명은 현재 배포 문서와 맞지 않습니다. 이 사실만으로 credentials 호환 처리를 강화하지는 않습니다. #288의 최종 계약과 전환 방침 확인이 남았습니다.

    FE origin/develop f69332d995a2e9890605b3c8075c427b2dd0cc8c에는 이미 toDraftDomain()과 종류별 sealed DraftContent가 있습니다. 앞선 대조표의 isDraft가 도메인에 반영되지 않는다는 설명은 현재 구현의 임시저장 분기까지 설명하지 못합니다. 실제 에디터 이어쓰기 소비는 #808 / PR #1768과 별도로 구분합니다.

    현재 PR #2021 HEAD b13a7026e312c037edfd223b089b50817faee640에서 AfternoteDetailMapperTest 16건과 AfternoteDraftDetailMapperTest 5건을 실행해 모두 통과했습니다. 기존 발행 계정 빈 값 호환과 임시저장 미작성 허용은 유지됩니다. 이 결과는 현재 계약의 매핑 회귀 검증이며, 아직 없는 #288 최종 계약이나 #1768 에디터 통합을 검증했다는 뜻은 아닙니다. 새 DTO·호환 계층을 추측해 추가할 독립 범위는 없습니다.

  5. 1hyok commented on Sep 26, 2026

    @1hyok
    CollaboratorAuthor

    보류로 닫는다. 대조할 계약이 아직 없다.

    Afternote/Afternote-BE#288 은 FE 쪽에서 연 요청이고, 종류별 전용 데이터를 응답 타입으로 나눌지 동등한 스키마로 표현할지를 BE 가 정하지 않았다. 담당자 답, 커밋, PR 이 없다. BE origin/main 7c961ec 의 애프터노트 상세 응답은 2026-08-29(2161078) 이후 그대로다. 이 이슈 본문의 판정 완료 표현은 FE 가 쓴 것이라 BE 결정의 근거가 아니다.

    BE 가 형태를 정하고 FE 와의 차이가 확인되면, 확정된 요구만 담아 새 이슈를 연다.

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

Metadata

Metadata

Assignees

Labels

area:afternote애프터노트 기능 영역refactor동작 변경 없이 코드 구조·책임·경계를 개선하는 작업

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions