Skip to content

feat: 위치 기반 리마인드(NEARBY_PLACE)와 nearby-triggers 엔드포인트 추가 - #120

Draft
sudosubin wants to merge 1 commit into
feat/fcm-top-commentedfrom
feat/fcm-nearby-place
Draft

feat: 위치 기반 리마인드(NEARBY_PLACE)와 nearby-triggers 엔드포인트 추가#120
sudosubin wants to merge 1 commit into
feat/fcm-top-commentedfrom
feat/fcm-nearby-place

Conversation

@sudosubin

@sudosubin sudosubin commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

📌 Related Issue

  • 없음

🚀 Description

POST /api/v1/notifications/nearby-triggers로 클라이언트 지오펜스가 보고한 근처 장소를 기록하고 앱 밖 알림을 보냅니다. Swagger에 이미 문서화돼 있던 계약을 그대로 구현했습니다.

알림함에는 개별 장소가 각각 한 행으로 들어갑니다. 여러 곳이 한꺼번에 잡히면 앱 밖 알림만 대표 한 건으로 묶고, 그 대표 알림은 알림함에 남기지 않습니다. 발송을 묶는 방식일 뿐 알림함의 기록이 아니기 때문입니다. (FR-019, EC-002)

대표 알림은 이동 대상이 달라 타입을 나눴습니다. 단건은 NEARBY_PLACE로 해당 장소 상세로 가고, 대표는 NEARBY_PLACE_SUMMARY로 알림 탭을 엽니다. placeId 유무로 판별하게 두면 클라이언트가 같은 타입 안에서 분기해야 해서 도착지를 타입으로 드러냈습니다.

단건 payload에는 { placeId, pinId }를 싣습니다. 같은 장소가 내 방 여러 곳에 있으면 핀도 여럿이라 가장 최근에 저장된 핀을 고릅니다.

NEARBY_PLACE_SUMMARY는 저장되지 않으므로 NOTIFICATION_TYPES에 넣지 않았습니다. 이 상수는 notifications.type 컬럼과 알림함 응답 enum을 함께 타이핑하는데, 여기에 넣으면 응답에 올 수 있는 값 목록이 사실과 달라집니다. 푸시 전용 타입은 PUSH_ONLY_NOTIFICATION_TYPES로 따로 뒀습니다.

placeIds는 클라이언트가 보내오는 값이라 그대로 믿으면 남의 장소 id를 섞어 보내 장소명을 알아낼 수 있습니다. 활성 멤버인 방의 활성 핀인지 서버가 다시 확인하고, 하나라도 어긋나면 403으로 막습니다.

sequenceDiagram
    participant C as 클라이언트
    participant Ctrl as NotificationController
    participant Svc as NotificationService
    participant Repo as NotificationRepository
    participant Msg as MessagingService

    C->>Ctrl: POST /notifications/nearby-triggers { placeIds }
    Ctrl->>Svc: recordNearbyTriggers(userId, placeIds)
    Svc->>Repo: findAccessiblePlaces
    alt 접근 불가 포함
        Svc-->>C: 403 PLACE_NOT_ACCESSIBLE
    else 전부 접근 가능
        loop 장소마다
            Svc->>Repo: record (key로 중복 제거)
        end
        alt 신규 1건
            Svc->>Msg: data = { type: NEARBY_PLACE, placeId }
        else 신규 N건
            Svc->>Msg: data = { type: NEARBY_PLACE_SUMMARY } (알림함 행 없음)
        end
        Ctrl-->>C: 200 { newPlaceCount }
    end
Loading

📢 Notes

  • 대표 알림 푸시에는 placeId를 싣지 않습니다. 가리킬 장소가 하나로 정해지지 않아서, 클라이언트는 id가 없으면 알림 탭을 열면 됩니다. 스펙상 대표 알림은 6종 유형이 아니라 별도 enum을 만들지 않았습니다.
  • 양쪽 클라이언트 모두 지오펜스가 아직 없어서 당분간 호출자가 없는 엔드포인트입니다. iOS에 CLCircularRegion, Android에 GeofencingClient가 없고 백그라운드 위치 권한 선언도 없습니다.
  • 클라이언트가 어느 장소에 펜스를 걸지 정하려면 서버가 후보를 내려줘야 합니다. 미방문 판정은 pin_accesses 기반이라 서버만 가능하고, 지오펜스 상한을 넘는 핀 중 무엇을 고를지 기준도 필요합니다. 후보 조회 API는 이번 범위에서 제외했습니다.
  • docs/prd.md는 트리거 방식(클라이언트 지오펜스 대 서버 폴링)을 여전히 미결로 두고 있습니다. 이 PR은 이미 문서화된 지오펜스 계약을 구현한 것이라, 방식이 뒤집히면 재검토가 필요합니다.
  • 상한 100은 Android 지오펜스 한도입니다. iOS는 기기당 20개로 더 낮습니다.

@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 06b43fb to f4868cc Compare August 30, 2026 15:30
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch 2 times, most recently from 9f6c697 to fd85c0c Compare August 30, 2026 15:42
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from f4868cc to 00f39ec Compare August 30, 2026 15:42
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from fd85c0c to 771eae8 Compare August 30, 2026 15:46
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 00f39ec to 3b070a2 Compare August 30, 2026 15:46
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from 771eae8 to f915681 Compare August 30, 2026 15:52
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch 2 times, most recently from b3977fb to d8727ce Compare August 30, 2026 16:00
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from f915681 to a788964 Compare August 30, 2026 16:00
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from d8727ce to 129531d Compare August 30, 2026 16:04
@sudosubin sudosubin self-assigned this Aug 30, 2026
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 129531d to 5d8b2b3 Compare August 30, 2026 16:14
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from a788964 to 040f94f Compare August 30, 2026 16:14
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 5d8b2b3 to ea7ae40 Compare August 30, 2026 16:24
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from 633a77e to 822337d Compare August 31, 2026 11:49
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from ea7ae40 to 1f883ff Compare August 31, 2026 11:49
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from 822337d to c5c77f4 Compare August 31, 2026 13:28
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch 3 times, most recently from ffda33f to b8e54bf Compare August 31, 2026 14:17
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from 2162eb4 to affc8a0 Compare August 31, 2026 14:17
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from b8e54bf to e8e77cb Compare August 31, 2026 14:27
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from affc8a0 to 4778b2d Compare August 31, 2026 14:27
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from e8e77cb to a89f213 Compare August 31, 2026 14:48
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch 2 times, most recently from a5ed930 to ca79bbc Compare August 31, 2026 15:04
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from a89f213 to 0561d1b Compare August 31, 2026 15:04
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from ca79bbc to a29a0e8 Compare August 31, 2026 15:31
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch 2 times, most recently from 789918d to 500a0c9 Compare September 1, 2026 00:10
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from a29a0e8 to 717c119 Compare September 1, 2026 01:24
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 500a0c9 to 29d8f46 Compare September 1, 2026 01:24
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from 717c119 to 18587a3 Compare September 1, 2026 01:32
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 29d8f46 to 8918714 Compare September 1, 2026 01:32
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from 18587a3 to e23005a Compare September 1, 2026 01:38
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 8918714 to 1c88b7b Compare September 1, 2026 01:38
클라이언트 지오펜스가 진입을 보고하면 후보 placeId를 받아 기록하고 앱 밖 알림을 보낸다.
클라이언트가 보내오는 값이라 활성 멤버인 방의 활성 핀인지 서버가 다시 확인하고,
접근할 수 없는 장소가 섞이면 403으로 막는다 — 남의 장소명을 캐낼 수 없게.

알림함에는 개별 장소가 각각 한 행으로 들어가고, 여러 곳이 한꺼번에 잡히면 앱 밖
알림만 대표 한 건으로 묶는다. 대표 알림은 발송을 묶는 방식일 뿐이라 알림함에
남기지 않는다(FR-019 · EC-002). 이미 알린 장소는 key 충돌로 걸러진다.
@sudosubin
sudosubin force-pushed the feat/fcm-top-commented branch from e23005a to 9ef387d Compare September 2, 2026 03:20
@sudosubin
sudosubin force-pushed the feat/fcm-nearby-place branch from 1c88b7b to 8da238b Compare September 2, 2026 03:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant