콘텐츠로 이동

푸시알림 시스템 (FCM)

문서 역할

Firebase Cloud Messaging 기반 푸시알림 아키텍처를 정리한 문서이다. 이 문서의 타입 섹션은 대표 타입과 범주를 설명하는 요약본이며, 전체 타입 인벤토리를 1:1로 열거하지 않는다. 기존 알림 흐름과 그룹미팅 77~85의 API·Mobile 연결은 현행이다. 그룹미팅의 운영 반영 기준점은 2.3.0 릴리스 실행 기록에 보존한다. 인연찾기 86~89는 방향별 카드 전달·수락을 1:1 매칭 화면으로 연결한다.

논리 데이터 모델

  • 도메인 ID: notification

먼저 보는 그림

이 그림은 데이터가 어디에 속하고 무엇을 참고하는지 먼저 보여준다. 정확한 이름과 조건은 아래 상세 표를 따른다.

flowchart LR
    entity_group_dash_meeting_dot_event["그룹미팅 행사 · 다른 영역<br/>group-meeting.event"]
    entity_legacy_dash_meeting_dot_meeting["기존 2:2 미팅 · 다른 영역<br/>legacy-meeting.meeting"]
    entity_lounge_dot_post["라운지 게시글 · 다른 영역<br/>lounge.post"]
    entity_matching_dot_match["1:1 매칭 · 다른 영역<br/>matching.match"]
    entity_member_dot_member["회원 계정 · 다른 영역<br/>member.member"]
    entity_notification_dot_delivery["알림 발송 이력<br/>notification.delivery"]
    entity_notification_dot_preference["알림 설정<br/>notification.preference"]
    entity_member_dot_member -->|"같이 관리"| entity_notification_dot_preference
    entity_member_dot_member -->|"같이 관리"| entity_notification_dot_delivery
    entity_notification_dot_delivery -->|"참고"| entity_matching_dot_match
    entity_notification_dot_delivery -->|"참고"| entity_legacy_dash_meeting_dot_meeting
    entity_notification_dot_delivery -->|"참고"| entity_group_dash_meeting_dot_event
    entity_notification_dot_delivery -->|"참고"| entity_lounge_dot_post

꼭 지킬 규칙:

  • 발송과 저장 여부는 같은 회원 설정 판정 결과를 사용한다
  • 알림에 인증정보를 포함하지 않고, 대화 원문은 채팅 미리보기 허용 타입 37·82의 표시 문구에만 포함한다
  • 서버는 알림 종류별 설정을 단일 기준으로 판정한다
정확한 값과 조건 보기

논리 엔티티

논리 ID 표시명 생명주기 역할 엔티티 형태 기록 역할 책임 최고 데이터 분류 생명주기
notification.preference 알림 설정 child entity state 회원의 채팅·매칭·행사 알림 수신 선택 내부 회원 계정과 함께 유지하고 변경 시 현재값 갱신
notification.delivery 알림 발송 이력 child entity history 수신자, 알림 종류, 표시 문구와 이동 대상 민감 활성 회원의 알림함에 보존하고 탈퇴·차단 회원은 상태 변경 30일 뒤 개인정보 자동 정리 때 삭제

관계

출발 논리 ID 관계 역할 관계 유형 도착 논리 ID 카디널리티 소유·삭제 규칙
member.member notification-preference owns notification.preference 1:1 회원 계정 삭제 시 설정도 함께 정리
member.member notification-deliveries owns notification.delivery 1:N 회원 개인정보 자동 정리 시 수신자 연결과 문구를 함께 삭제
notification.delivery match-target references matching.match N:1 이동 대상이 매칭이면 해당 문맥을 참조
notification.delivery meeting-target references legacy-meeting.meeting N:1 이동 대상이 기존 미팅이면 해당 문맥을 참조
notification.delivery group-meeting-target references group-meeting.event N:1 이동 대상이 그룹미팅이면 해당 행사 문맥을 참조
notification.delivery post-target references lounge.post N:1 이동 대상이 라운지면 해당 문맥을 참조

불변조건

규칙 ID 관련 논리 ID 불변조건 기준 문서
NOTIFICATION-INV-001 notification.delivery 발송과 저장 여부는 같은 회원 설정 판정 결과를 사용한다 푸시알림 운영 정책
NOTIFICATION-INV-002 notification.delivery 알림에 인증정보를 포함하지 않고, 대화 원문은 채팅 미리보기 허용 타입 37·82의 표시 문구에만 포함한다 데이터 거버넌스 정책
NOTIFICATION-INV-003 notification.preference 서버는 알림 종류별 설정을 단일 기준으로 판정한다 푸시알림 운영 정책

FCM 알림 타입 요약

회원가입 관련 (1-4)

상수 의미
1 SIGNUP_PROFILE_EDIT 가입심사 정보 수정 필요
2 SIGNUP_PROFILE_EDIT_AGAIN 1차 심사 미승인
3 SIGNUP_OK 가입심사 승인
4 SIGNUP_FAVOR_INFO 추가정보 입력 안내

설정 관련 (5-11, 73-74, 76)

상수 의미
5 SETTING_AUTH_OK 인증 승인
6 SETTING_PROFILE_OK 프로필 승인
7 SETTING_PROFILE_DENY 프로필 반려
8-11 SETTING_RECOMMEND_* 추천 관련
73 SETTING_MEMBER_REVIEW_DENY 준회원/정회원 승급 심사 반려(즉시)
74 SETTING_MEMBER_REVIEW_DENY_AGAIN 준회원/정회원 반려 후 미재제출 리마인드
76 SETTING_AUTH_DENY 설정 인증정보 반려

1:1 매칭 관련 (12-30)

상수 의미
12 MATCH_NEW_MALE_ARRIVE 남성 프로필 전달
13 MATCH_MALE_PROFILE_ACCEPTED 여성이 프로필 수락
14 MATCH_FEMALE_PROFILE_ACCEPTED 남성이 프로필 수락
15 MATCH_FEMALE_CONFIRM 여성 최종승인
16 MATCH_SCHEDULE_SUGGESTED 일정 제안
18-19 MATCH_SCHEDULE_OK_* 일정 확정
20 MATCH_LOCATION_OK 약속 장소 확정
21 MATCH_D_DAY_2 D-2일 도래
22 MATCH_NEW_CHAT 새 채팅 메시지
24 MATCH_CANCEL 만남 취소
25 MATCH_DAY 만남 당일
26 MATCH_4_HOUR_PASSED 만남 4시간 경과
27-30 MATCH_*_CONTRACT/DIRECT 연락처/직진만남

2:2 미팅 관련 (31-37)

상수 의미
31 MEET_ATTEND_REQUEST 참석 요청
32 MEET_ACCEPT_ATTEND 참석 수락
33-34 MEET_MEMBER_OK_* 멤버 확정
35-36 MEET_2_HOUR_PASSED_* 2시간 경과
37 MEET_SEND_CHAT 채팅 전송

라운지 관련 (38-41, 68)

상수 의미
38 LOUNGE_NEW_COMMENT 새 댓글
39 LOUNGE_NEW_CHILD_COMMENT 대댓글
40 LOUNGE_PINNED 고정글 설정
41 LOUNGE_BLAME 신고
68 LOUNGE_LIKE 게시글 좋아요 수 변경

기타 대표 타입 (42-75)

상수 의미
53 MATCH_VOICE_CALL 보이스톡 오픈 알림(모바일 알림 노출 제외)
67 CONCIERGE_CHAT 큐레이터 채팅
66 ADMIN_FREE_KEY 관리자 Key 지급/차감
70 MATCH_CHAT_OPEN 채팅방 오픈
75 SIGNUP_FULL_MEMBER_OK 정회원 가입심사 최종 승인
  • 위 표는 전체 타입 목록이 아니라 대표 타입 예시와 범주 요약이다.

그룹미팅 타입 (77-85)

아래 값은 그룹미팅 시스템의 API 발송 계약에 반영됐다. Mobile 연결 계약은 신청·승인· 확정 취소·행사 취소 77~79·81과 신청 완료 84를 행사 상세, 새 메시지·후기·채팅 개방 82·83·85를 채팅 이력으로 연결한다. 모집 마감 알림 80은 과거 알림 재진입 호환용으로 소비하되 신규 모집 마감에서는 발송하지 않는다. 모든 target은 그룹미팅 행사 ID다.

상수 의미 Mobile 이동
77 GROUP_MEETING_APPLICATION_RECEIVED 신규 신청 행사 상세
78 GROUP_MEETING_APPLICATION_APPROVED 신청 승인 행사 상세
79 GROUP_MEETING_APPLICATION_CANCELED Admin 확정 취소(외부 환불 필요) 행사 상세
80 GROUP_MEETING_EVENT_CONFIRMED 과거 모집 마감 알림 호환 개방 시 채팅, 미개방 시 행사 상세
81 GROUP_MEETING_EVENT_CANCELED 행사 취소 행사 상세
82 GROUP_MEETING_CHAT_MESSAGE 새 채팅 메시지 채팅 이력
83 GROUP_MEETING_REVIEW_AVAILABLE 후기 작성 가능 채팅 이력
84 GROUP_MEETING_APPLICATION_SUBMITTED 신청자 참여 신청 완료 행사 상세
85 GROUP_MEETING_CHAT_OPENED 행사 전날 KST 13시 채팅 접근 개방 채팅 이력

그룹미팅 알림 본문은 실제 행사 제목을 포함한다. 82는 실제 메시지 내용을 함께 포함하고 발신자를 제외한 현재 채팅 구성원 중 전역 alarm_chat과 해당 방 message_notification_enabled가 모두 켜진 회원에게 발송·저장한다. 방 설정은 메시지·WebSocket·unread와 77~81·83~85에는 영향을 주지 않는다. 85는 호스트와 현재 APPROVED 참가자를 대상으로 같은 개방 경계에 한 번만 발송하며, 행사 일시가 변경되어 경계가 달라지면 새 경계를 기준으로 다시 계산한다. 수신자 준비나 내구성 있는 알림 저장이 실패하면 선점한 채팅 구성원별 개방 경계를 복구해 다음 실행에서 재시도한다. 채팅 개방 뒤 Admin이 참가자를 새로 승인하면 78과 85를 해당 참가자에게 함께 발송하고, 승인 transaction에서 그 구성원의 현재 개방 경계를 처리값으로 기록해 다음 cron의 중복 대상에서 제외한다. 행사 단위 marker는 cron batch 요약으로만 사용한다. 83은 행사 시작 +24시간 뒤 현재 APPROVED이면서 후기가 없는 참가자에게만 발송하므로 LEFT·CANCELED는 제외한다.

82의 FCM 수신자는 발신자를 제외하지만, 활성 화면 상태 동기화용 group_meeting:message WebSocket 이벤트는 발신자의 다른 기기까지 포함한 현재 채팅 구성원에게 전달한다. foreground 표시와 WebSocket 연결 여부에 따른 FCM 상태 갱신 보조 경로는 푸시알림 운영 정책, 메시지 원본과 HTTP 복구는 채팅 시스템의 N:N 그룹미팅 채팅 절을 따른다.

인연찾기 타입 (86-89)

모든 target은 1:1 매칭 ID다. 설정·저장 기준과 정확한 발송 조건은 푸시알림 운영 정책을 따른다.

상수 수신자 Mobile 이동
86 MATCH_FINDING_NEW_MALE_ARRIVE 여성 → 남성 카드 수신 남성 For You
87 MATCH_FINDING_MALE_PROFILE_ACCEPTED 남성 수락을 받는 여성 On:Going
88 MATCH_FINDING_MALE_TO_FEMALE_CARD_RECEIVED 남성 → 여성 카드 수신 여성 For You
89 MATCH_FINDING_MALE_TO_FEMALE_ACCEPTED 여성 수락을 받는 남성 For You

발송 흐름

sequenceDiagram
    participant M as GroupMeeting model
    participant C as Controller
    participant Common as common.js
    participant FCM as fcm.js
    participant Firebase as Firebase
    participant DB as t_alarm

    opt type 82
        M->>M: 방별 새 메시지 알림 수신자만 선별
    end
    M-->>C: push command와 수신자
    C->>Common: sendFCMPush(user_data, type, data)
    Common->>Common: 전역 알림 설정 체크 (alarm_chat, alarm_match, alarm_event)
    alt 알림 허용
        opt token 있음 AND sendPush AND not OFFLINE_MODE
            Common->>FCM: send(token, type, title, content, data)
            FCM->>Firebase: firebase.messaging().send()
            Firebase-->>FCM: 전송 결과
        end
        opt 표시 문구 있음
            Common->>DB: insertBatch(alarm_data)
        end
    else 알림 설정 거부 또는 숨김 타입
        Common-->>C: FCM·t_alarm 모두 생략
    end

발송 조건

타입별 사용자 설정 매핑, FCM·t_alarm 생략 조건, foreground 처리와 상태 갱신 보조 경로 판정은 푸시알림 운영 정책이 소유한다. 이 문서는 발송 구성요소와 데이터 흐름만 설명한다. 큐레이터·N:N 그룹미팅 채팅의 활성 상태 동기화 구조는 채팅 시스템의 WebSocket 절과 N:N 그룹미팅 채팅 절을 따른다.

메시지 구조

{
  notification: {
    title: '커플러',
    body: '새로운 남성 프로필이 도착했습니다.'
  },
  android: {
    notification: { sound: 'default' }
  },
  apns: {
    payload: { aps: { sound: 'default' } }
  },
  data: {
    type: '12',
    custom_data: '{"target": 123}',
    title: '커플러',
    message: '새로운 남성 프로필이 도착했습니다.'
  },
  token: 'device_fcm_token'
}

라운지 foreground 동기화는 FCM custom_data를 모바일 진입점에서 한 번 검증한 뒤 typed domain event로 전달한다. 화면은 FCM 원본 JSON을 직접 파싱하거나 숫자 변환 fallback을 수행하지 않는다. 타입별 필드 계약은 푸시알림 운영 정책라운지 custom_data 계약을 따른다.

알림 저장

사용자 설정과 저장 조건을 통과한 알림은 FCM 토큰 유무·외부 전송 여부와 독립적으로 notification.delivery에 저장한다. 수신자, 알림 종류, 사용자에게 표시한 문구와 이동 대상만 보존하며, FCM 토큰이나 원천 도메인의 민감 본문을 별도로 복제하지 않는다. 채팅 미리보기 허용 타입은 기존 2:2 채팅 37과 N:N 그룹미팅 채팅 82이며, 두 타입만 실제로 표시한 메시지 문구를 알림 이력에 함께 보존한다. 보관·삭제 기준은 데이터 거버넌스 정책을 따른다.

운영 집계 호환 규칙:

  • 반려 알림 전체 지표는 type IN (7,73,74,76) 기준으로 조회한다.
  • type = 7 단독 필터는 신규 반려 알림(73/74/76)을 누락한다.

주요 발송 지점

영역 기능 주요 알림
Admin cron 스케줄 작업 D-DAY, 만남 당일, 카드 만료
Match 도메인 매칭 액션 프로필 수락, 채팅, 일정
Admin member 회원 관리 심사 승인, 관리자 Key 지급/차감
Lounge 도메인 라운지 댓글, 고정글

다국어 지원

// locales/ko.json
{
  "push": {
    "title": "커플러",
    "signup_profile_edit": "가입심사 단계에서 이용자의 기입정보 수정이 필요합니다.",
    "match_new_male_arrive": "새로운 남성 프로필이 도착했습니다."
  }
}