어떤 기능이 필요한가요?
모바일 앱의 전자 명함 기능을 member 도메인 내부 기능으로 구현해야 합니다.
전자 명함은 회원의 공개 프로필, 링크, 교환 요청, 저장/수집 이력, 오프라인 동기화를 다루므로 별도 최상위 businesscard 도메인으로 빼기보다 member 도메인의 profile 확장 영역으로 두는 것이 자연스럽습니다. 다만 기존 MemberProfile에 단순 필드만 추가하지 말고, 1인 1장 제약과 교환/가시성 정책을 별도 aggregate로 분리합니다.
🔧 TODO
member 도메인 안에 전자 명함 모델을 추가한다.
예시: MemberBusinessCard, MemberBusinessCardFieldVisibility, MemberBusinessCardExchange, MemberBusinessCardCollection
cross-domain 참조는 memberId, scheduleId, activityId 같은 ID만 저장한다.
기존 Member, MemberProfile entity에 @OneToMany 컬렉션을 추가하지 않는다.
1인 1장 정책을 DB와 도메인에서 보장한다.
member_business_card.member_id unique index
최초 생성과 수정 command 분리
삭제 대신 비활성화/숨김이 필요한지 결정
명함 필드와 가시성 정책을 설계한다.
기본 필드: 이름, 닉네임, 학교, 파트, 기수, 프로필 이미지, 한 줄 소개, 링크 목록
확장 필드: 이메일, 전화번호, 소속, 관심사 등 민감도 높은 필드는 별도 동의/노출 정책 필요
visibility enum: PUBLIC, EXCHANGE_ONLY, PRIVATE
서버 응답에서 요청자 관계에 따라 필드를 필터링한다.
명함 CRUD API를 추가한다.
GET /api/v1/members/me/business-card
POST /api/v1/members/me/business-card
PATCH /api/v1/members/me/business-card
GET /api/v1/members/business-cards/{memberId} 또는 username 기반 public path
response DTO는 entity를 직접 노출하지 않는다.
공개 웹 명함 URL 정책을 정한다.
username/publicSlug unique constraint
GET /card/{username}을 서버가 직접 렌더링할지, API만 제공하고 프론트 라우팅으로 처리할지 결정
private field가 public URL에 절대 노출되지 않도록 query/service test 추가
양방향 명함 교환 요청을 구현한다.
POST /api/v1/members/business-cards/exchanges
PATCH /api/v1/members/business-cards/exchanges/{exchangeId} accept/reject/cancel
GET /api/v1/members/business-cards/exchanges?status=
만료 시간, 중복 요청, 차단/거절 후 재요청 정책
활동 참여자 일괄 명함 받기 기능을 구현한다.
schedule/activity 참여자 목록은 schedule/organization/project Query UseCase로 조회한다.
POST /api/v1/members/business-cards/collections/bulk
이미 저장한 명함은 idempotent하게 처리한다.
오프라인 큐잉/동기화 API를 구현한다.
POST /api/v1/members/business-cards/sync/flush
client operation idempotency key 필수
BLE 교환 후 온라인 복귀 시 교환 이력 업로드 가능
같은 상대와 중복 저장/교환되는 케이스를 서버에서 병합
알림과 연결한다.
교환 요청/수락/만료 시 notification 이벤트 발행
FCM payload type 예시: BUSINESS_CARD_EXCHANGE_REQUESTED, BUSINESS_CARD_EXCHANGE_ACCEPTED
보안/개인정보 정책을 반영한다.
본인 명함 전체 조회와 타인 명함 조회 response를 분리
EXCHANGE_ONLY 필드는 교환 완료 관계에서만 노출
block/mute 정책이 도입되면 교환 요청 생성 차단
audit log가 필요한 command 범위 결정
테스트와 문서를 추가한다.
1인 1장 unique 정책
visibility filtering
교환 요청 상태 전이
만료/중복/idempotency
public URL 개인정보 비노출
bulk save/offline flush
RestDocs/OpenAPI
📎 참고 자료
모바일 신기능 계획서: 2기 방학 중 앱 신기능 개발
현재 서버 상태: member에는 MemberProfile이 있지만, 전자 명함/교환/수집 이력 모델은 없습니다.
구현 원칙: 최상위 businesscard 도메인이 아니라 member 도메인 내부에 둡니다.
✅ 제출 전 확인사항
어떤 기능이 필요한가요?
모바일 앱의 전자 명함 기능을
member도메인 내부 기능으로 구현해야 합니다.전자 명함은 회원의 공개 프로필, 링크, 교환 요청, 저장/수집 이력, 오프라인 동기화를 다루므로 별도 최상위
businesscard도메인으로 빼기보다member도메인의 profile 확장 영역으로 두는 것이 자연스럽습니다. 다만 기존MemberProfile에 단순 필드만 추가하지 말고, 1인 1장 제약과 교환/가시성 정책을 별도 aggregate로 분리합니다.🔧 TODO
member도메인 안에 전자 명함 모델을 추가한다.MemberBusinessCard,MemberBusinessCardFieldVisibility,MemberBusinessCardExchange,MemberBusinessCardCollectionmemberId,scheduleId,activityId같은 ID만 저장한다.Member,MemberProfileentity에@OneToMany컬렉션을 추가하지 않는다.member_business_card.member_idunique indexPUBLIC,EXCHANGE_ONLY,PRIVATEGET /api/v1/members/me/business-cardPOST /api/v1/members/me/business-cardPATCH /api/v1/members/me/business-cardGET /api/v1/members/business-cards/{memberId}또는 username 기반 public pathGET /card/{username}을 서버가 직접 렌더링할지, API만 제공하고 프론트 라우팅으로 처리할지 결정POST /api/v1/members/business-cards/exchangesPATCH /api/v1/members/business-cards/exchanges/{exchangeId}accept/reject/cancelGET /api/v1/members/business-cards/exchanges?status=POST /api/v1/members/business-cards/collections/bulkPOST /api/v1/members/business-cards/sync/flushBUSINESS_CARD_EXCHANGE_REQUESTED,BUSINESS_CARD_EXCHANGE_ACCEPTEDEXCHANGE_ONLY필드는 교환 완료 관계에서만 노출📎 참고 자료
2기 방학 중 앱 신기능 개발member에는MemberProfile이 있지만, 전자 명함/교환/수집 이력 모델은 없습니다.businesscard도메인이 아니라member도메인 내부에 둡니다.✅ 제출 전 확인사항