✨ [Feat] 명함 데이터 계층 — 명함첩 저장 · 카운트 조합 · QR · DI 배선 (#1195) - #1199
Merged
Conversation
8 tasks
- ReceivedCardRecord: 전 필드 기본값·unique 금지 (CloudKit 제약) - memberId 기준 수동 upsert — 재교환 시 최신 명함으로 갱신 - 이름·닉네임·파트·학교 검색, 인메모리 컨테이너 테스트 - 빈 스캐폴드 BusinessCardData.swift 제거, Data 테스트 타겟 활성화
- Profile→MyCard 파생 규칙을 MyPage 정본 매핑과 일치(최신 기수 기록 우선·admin 폴백) - 캐시·forceRefresh가 그대로 전파돼 명함 편집 즉시 갱신(MP-F06) 성립 - String intValue/nonEmpty 헬퍼는 파일 로컬 복제 — UMCFoundation에 없음(크로스 피처 금지)
- BusinessCardRouter: 카운트 전용 엔드포인트 복제 + 계약 테스트 - 얇은 카운트 DTO 2종 custom Codable (totalElements / 커서 항목 수) - 스크랩 카운트는 서버 totalElements를 String 그대로 통과 (서버 정수 String 통일) - hasNext는 decodeBoolFlexibleIfPresent로 문자열 Bool 흡수 (Activity 선례) - APIResponse 래핑·raw 양쪽 흡수, 테스트 seam으로 baseURL fatalError 회피
- CIQRCodeGenerator 보정 M·정수 배율 12 — 실기기 스파이크 검증 파라미터 - 빈 페이로드·렌더 실패를 전용 에러로 구분 - CIDetector 역스캔 왕복 테스트로 페이로드 보존 검증
- UseCase 7종을 한 번에 주입하는 Presentation 진입점 (MyPage Provider 패턴) - ReceivedCardRecord를 SwiftData Schema(CloudKit)에 합류 - registerBusinessCardDependencies: Repository 4종+Transport+Provider 등록 - transport는 이슈 #1196 전까지 Mock — DI 캐싱이라 실기기 구현은 세션 상태 리셋 필요 - 빈 스캐폴드 BusinessCardPresentation.swift 제거
GthingkingG
force-pushed
the
feature/1195
branch
from
August 20, 2026 18:21
c9e6893 to
bb2c88b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
✨ PR 유형
✨ Feature — #1194 에서 정의한 Repository 인터페이스의 실제 구현과 앱 배선입니다.
명함첩 SwiftData 저장, 내 명함의 정본 프로필 위임, 마이페이지 카운트 조합, QR 생성,
DI 등록까지. 스택 4개 PR 중 3번째입니다.
Closes #1195
🛠️ 작업내용
명함첩 저장소 (SwiftData)
내 명함 저장소
/member/me→Profile)에 위임 — 명함 전용 서버 API 는없습니다 (서버·Android 레포 전수 조사 결과 신규 API 0개로 진행,
Profile+MyCard매핑)카운트 저장소 · QR
totalElements문자열 그대로 전달DI 배선
BusinessCardUseCaseProvider+DIContainer+BusinessCard등록,앱 실행 시 명함 레코드 포함 SwiftData 컨테이너 초기화
AC 체크
테스트
저장 후 전체 조회하면 같은 명함이 나온다·같은 memberId로 다시 저장하면 중복 없이 최신 명함으로 갱신된다·삭제하면 목록과 카운트에서 빠진다테스트
이름·닉네임·파트·학교로 검색된다 (MP 받은명함_검색)·공백 검색어는 전체 목록테스트
forceRefresh를 정본 저장소에 그대로 전달하고 매핑 결과를 돌려준다테스트
내 스터디 목록은 GET /api/v1/study-groups/managed·스크랩 목록은 GET /api/v1/posts/scrapped — size 1로 totalElements만 취한다테스트
APIResponse 래핑 응답의 totalElements를 String 그대로 통과시킨다테스트
생성한 QR을 역스캔하면 원본 페이로드가 나온다·빈 페이로드는 에러를 던진다DIContainer+BusinessCard배선 + 시뮬레이터 스모크로 확인make test SCHEME=BusinessCardData통과📋 추후 진행 상황
mainContext액터 격리 — 명함첩 저장소는 ✨ Feature: WiFiAwareTransport — Wi-Fi Aware 근거리 명함 교환 #1196 에서MainActor.run으로고정됩니다. 같은 패턴의 Home·Notice Repository 는 이 브랜치 밖이라 별도 이슈로 분리
예정입니다 (간헐 무한 로딩의 유력 원인)
📌 리뷰 포인트
전부 이 두 키로 한 장에 수렴하는 구조가 맞는지
init(from:)규약 —decodeIntFlexibleIfPresent사용,서버가 hasNext 를 문자열로 줘도 흡수 (
서버가 hasNext를 문자열로 줘도 흡수한다)(
챌린저 기록이 없으면 기수 0·admin 폴백으로도 명함이 만들어진다), 서버 마스킹 정책이바뀌면 조용히 잘못된 명함이 저장될 수 있어 계약 테스트로 고정했습니다
✅ Checklist
PR이 다음 요구 사항을 충족하는지 확인해주세요!!!