약속 장소를 투표로 정하고, 실시간으로 함께 조율합니다.
"후보지는 함께 올리고, 장소는 투표로 결정한다."
- OAuth2 소셜 로그인
- 로그인 성공 시 JWT 발급
- 이후 인증이 필요한 HTTP 요청은
Authorization: Bearer <token>헤더 사용 - WebSocket STOMP
CONNECT프레임에서도 JWT 검증 - Presence Topic 구독 시 약속 멤버 여부 검증
- 약속 생성
- 약속 목록 조회
- 약속 상세 조회
- 방장 전용 초대 코드 발급
- 초대 코드 기반 약속 참여
- 약속 목록은 커서 기반 무한 스크롤 지원
- 약속 참여자가 장소 후보 등록
- 활성 후보 목록 조회
- 후보 등록자 본인만 후보 삭제 가능
- 확정된 후보 삭제 방지
- 방장만 최종 장소 확정 가능
- 단일 투표 / 복수 투표 정책 지원
- 같은 후보 중복 투표 방지
- 단일 투표 정책에서 약속 내 중복 투표 방지
- 투표 마감 이후 투표 차단
- 약속 또는 후보 확정 이후 투표 차단
- 최다 득표 동점 후보가 2개 이상이면 재투표 가능
- 재투표 시 동점 후보만 활성화하고 기존 투표 내역 초기화
- STOMP WebSocket 기반 온라인 사용자 추적
- 약속별 접속자 목록 브로드캐스트
- 같은 사용자가 여러 탭으로 접속해도 프론트에는 한 명으로 표시
- WebSocket disconnect 이벤트 발생 시 세션 단위로 접속 상태 정리
- VAPID 공개키 조회
- 사용자별 Push Subscription 등록 / 갱신 / 만료 처리
- 약속 장소 확정 이벤트 발생 시 참여자에게 Web Push 발송
- 트랜잭션 커밋 이후 알림 발송 처리
- 만료된 구독 응답(
404,410) 수신 시 비활성화 - 알림 발송 이력 저장
- 약속별 댓글 생성
- 지도 경계값 기반 댓글 목록 조회
- 특정 약속 참여자만 댓글 조회/작성 가능
-
Language / Runtime: Java 21
-
Framework: Spring Boot 4.0.5, Spring Web MVC, Spring Data JPA
-
Database: MySQL, Hibernate / JPA
-
Auth: Spring Security, OAuth2 Login, JWT
-
Realtime: WebSocket, STOMP, Spring Simple Broker
-
Notification: Web Push, VAPID
-
Build: Gradle Wrapper
-
Etc.: Lombok, JPA Auditing, Bean Validation
Web / Mobile Client
│
├─ OAuth2 Login / JWT
│
▼
Zigma Backend (Spring Boot)
│
├─ Promise Domain
│ ├─ 약속 생성 / 초대 / 참여
│ ├─ 장소 후보 등록
│ ├─ 단일·복수 투표
│ ├─ 동점 후보 재투표
│ └─ 최종 장소 확정
│
├─ WebSocket STOMP
│ └─ 약속별 온라인 사용자 Presence
│
├─ Web Push
│ └─ 장소 확정 알림 발송
│
└─ MySQL
└─ 사용자 / 약속 / 후보 / 투표 / 댓글 / 알림 데이터
- HTTP API는 JWT 기반 stateless 인증을 사용합니다.
- WebSocket은
/ws엔드포인트로 연결하고, STOMPCONNECT시점에 JWT를 검증합니다. - Presence 구독은
/topic/promises/{promiseId}/presencedestination 기준으로 약속 멤버 여부를 확인합니다. - 장소 확정 이벤트는 트랜잭션 커밋 이후 별도 트랜잭션에서 Web Push 알림과 알림 이력을 처리합니다.
약속 생성
↓
초대 코드 발급
↓
참여자 초대 코드 입장
↓
장소 후보 등록
↓
단일 / 복수 투표
↓
최다 득표 후보 확정
├─ 동점 후보 2개 이상: 재투표
└─ 확정 완료: Web Push 알림 발송
src/main/java/org/hansung/zigma
├─ domain
│ ├─ user # 사용자, 프로필 조회
│ ├─ promise # 약속, 장소 후보, 투표, 재투표, 초대 코드
│ ├─ presence # WebSocket 기반 온라인 사용자 Presence
│ ├─ notification # Web Push 구독, 발송, 알림 이력
│ └─ comment # 약속별 지도 댓글
└─ global
├─ config # Security, Web, WebSocket, Jackson 설정
├─ jwt # JWT 필터, 토큰 Provider, UserDetails
├─ oauth # OAuth2 로그인, Provider별 사용자 정보
├─ response # 공통 응답(BaseResponse / Success / Error)
├─ exception # 전역 예외 처리
├─ entity # BaseEntity
├─ constant # 전역 상수
└─ util # 공통 유틸
| 항목 | 값 |
|---|---|
| Endpoint | /ws |
| Application Prefix | /app |
| Broker Prefix | /topic |
| 인증 | STOMP CONNECT native header Authorization: Bearer <token> |
| Destination | 설명 |
|---|---|
/app/promises/{promiseId}/presence/join |
약속 화면 입장 |
/app/promises/{promiseId}/presence/leave |
약속 화면 퇴장 |
/app/promises/{promiseId}/presence/ping |
Presence 테스트 메시지 |
| Topic | 설명 |
|---|---|
/topic/promises/{promiseId}/presence |
약속별 온라인 사용자 목록 수신 |
./gradlew test테스트는 다음 핵심 로직을 중심으로 작성되어 있습니다.
- 후보 확정 성공 / 실패 케이스
- 방장 권한 검증
- 동점 후보 재투표 로직
- 단일 / 복수 투표 정책 검증
- 투표 마감 / 확정 이후 투표 차단
- Web Push 알림 발송 및 만료 구독 처리
- Push Subscription 등록 / 갱신 / 해제