Skip to content

feat: 몰입형 투표 startVoteId 지원 및 Amplitude 행동 로그 연동#253

Merged
Junhyukkkk merged 2 commits into
developfrom
feature/immersive-vote-start-vote-id
Jun 24, 2026
Merged

feat: 몰입형 투표 startVoteId 지원 및 Amplitude 행동 로그 연동#253
Junhyukkkk merged 2 commits into
developfrom
feature/immersive-vote-start-vote-id

Conversation

@Junhyukkkk

@Junhyukkkk Junhyukkkk commented Jun 24, 2026

Copy link
Copy Markdown
Member

📌 관련 이슈

  • closes #

🔍 작업 내용

몰입형 투표 피드에서 특정 투표로 바로 이동할 수 있도록 POST /api/immersive-votes/nextstartVoteId를 추가하고, 행동 로그를 Amplitude 대시보드로도 전송하는 연동을 추가했습니다.

📝 변경 사항

몰입형 투표 startVoteId 지원

  • ImmersiveNextRequeststartVoteId 필드 추가
  • startVoteId 지정 시 진행 중인 해당 투표를 피드 맨 앞에 배치하고 나머지를 랜덤으로 채움
  • 종료/없는 투표거나 excludeIds에 이미 포함된 경우 무시하고 기존 랜덤 동작 유지
  • Swagger 설명 갱신 및 단위 테스트 추가

Amplitude 애널리틱스 연동

  • RDB 적재와 별개로 Amplitude HTTP V2 API로 이벤트 전송
  • amplitude.enabled=true + API Key가 있을 때만 동작하며, 없으면 no-op (RDB 적재는 그대로)
  • AmplitudeClient, AmplitudeProperties 추가 및 application.yml 설정 추가

💬 리뷰어에게

  • startVoteId는 보통 첫 요청에만 전달되며, 이후 순환 요청에서는 excludeIds에 쌓여 자동으로 무시됩니다. 무한 순환 동작에는 영향이 없습니다.
  • Amplitude는 기본 비활성(enabled=false) 상태이며, 환경변수(AMPLITUDE_ENABLED, AMPLITUDE_API_KEY) 설정 시에만 실제 전송됩니다.

Summary by CodeRabbit

  • New Features

    • 행동 로그가 Amplitude로도 전송되도록 지원이 추가되었습니다.
    • 다음 투표를 조회할 때 특정 투표를 맨 앞에 고정해 보여주는 기능이 추가되었습니다.
    • Amplitude 전송 설정(활성화, API 키, 엔드포인트)이 추가되었습니다.
  • Bug Fixes

    • 다음 투표 조회에서 순환 재요청 흐름이 더 자연스럽게 동작하도록 개선되었습니다.
    • Amplitude 전송 시 익명/회원 식별 정보와 이벤트 속성 처리 방식이 정리되었습니다.

POST /api/immersive-votes/next 요청에 startVoteId를 보내면
진행 중인 해당 투표를 피드 맨 앞에 배치하고 나머지를 랜덤으로 채운다.
종료/없는 투표거나 excludeIds에 포함된 경우 무시하고 기존 랜덤 동작.
RDB 적재와 별개로 Amplitude HTTP V2 API로도 이벤트를 전송한다.
amplitude.enabled=true + API Key가 있을 때만 동작하며, 없으면 no-op.
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

Amplitude HTTP V2 이벤트 전송을 위한 AmplitudeProperties 설정 레코드와 AmplitudeClient 어댑터를 신규 추가하고 AnalyticsEventLogger에 연결한다. 별개로, ImmersiveVote 랜덤 피드 조회에 startVoteId 파라미터를 추가해 지정된 투표를 결과 맨 앞에 배치하는 기능을 구현한다.

Changes

Amplitude HTTP V2 이벤트 전송 연동

Layer / File(s) Summary
AmplitudeProperties 설정 레코드 및 YAML 바인딩
src/main/java/com/ject/vs/analytics/AmplitudeProperties.java, src/main/resources/application.yml
enabled/apiKey/endpoint 필드를 가진 @ConfigurationProperties 레코드를 추가하고, endpoint 기본값 초기화 및 isConfigured() 헬퍼를 구현한다. application.yml에 환경변수 바인딩을 포함한 amplitude 설정 블록을 추가한다.
AmplitudeClient 어댑터 구현
src/main/java/com/ject/vs/analytics/AmplitudeClient.java
@Async("analyticsExecutor")로 비동기 fire-and-forget 전송을 수행한다. buildPayload, buildEventProperties, resolveDeviceId 헬퍼로 HTTP V2 페이로드를 구성하며, 예외는 삼키고 경고 로그만 남긴다.
AnalyticsEventLogger 연결 및 AmplitudeClient 단위 테스트
src/main/java/com/ject/vs/analytics/AnalyticsEventLogger.java, src/unitTest/java/com/ject/vs/analytics/AmplitudeClientTest.java
AnalyticsEventLoggerAmplitudeClient 필드를 주입하고 GA4 전송 이후 amplitude.send(...)를 추가 호출한다. AmplitudeClientTest로 페이로드 구성 규칙(user_id/device_id, null 제외, is_member 병합)을 단위 테스트로 검증한다.

ImmersiveVote getNextRandom startVoteId 우선 배치

Layer / File(s) Summary
startVoteId DTO 및 UseCase 인터페이스 변경
src/main/java/com/ject/vs/vote/adapter/web/dto/ImmersiveNextRequest.java, src/main/java/com/ject/vs/vote/port/in/ImmersiveVoteQueryUseCase.java
ImmersiveNextRequestLong startVoteId 필드를 추가하고, ImmersiveVoteQueryUseCase.getNextRandom 시그니처에 startVoteId 파라미터를 추가하며 Javadoc을 갱신한다.
ImmersiveVoteQueryService 구현 변경 및 테스트
src/main/java/com/ject/vs/vote/port/ImmersiveVoteQueryService.java, src/unitTest/java/com/ject/vs/vote/port/ImmersiveVoteQueryServiceTest.java
startVoteId가 유효한 경우 해당 투표를 맨 앞에 배치하고 나머지를 (size-1)로 랜덤 채우도록 구현을 변경한다. excludeIds 방어적 복사/정규화를 추가하며, 4가지 케이스를 Mock 기반 단위 테스트로 검증한다.
ImmersiveVoteController 연결 및 API 문서 갱신
src/main/java/com/ject/vs/vote/adapter/web/ImmersiveVoteController.java
getNextRandom 호출 인자에 request.startVoteId()를 추가하고, @Operation 설명에 startVoteId 동작과 클라이언트 재요청 흐름을 반영한다.

Sequence Diagram(s)

sequenceDiagram
  participant Client as 클라이언트
  participant Controller as ImmersiveVoteController
  participant Service as ImmersiveVoteQueryService
  participant Repo as VoteRepository

  Client->>Controller: GET /next-random (excludeIds, startVoteId, size)
  Controller->>Service: getNextRandom(excludeIds, startVoteId, size, userId, anonymousId)
  alt startVoteId 유효 (진행 중 & excludeIds에 없음)
    Service->>Repo: findById(startVoteId)
    Repo-->>Service: Vote
    Service->>Repo: findRandomExcluding(now, exclude+startVoteId, size-1)
    Repo-->>Service: 랜덤 투표 목록
    Service-->>Controller: [startVote, ...randomVotes]
  else startVoteId 없거나 무효
    Service->>Repo: findRandom / findRandomExcluding(now, excludeIds, size)
    Repo-->>Service: 랜덤 투표 목록
    Service-->>Controller: [...randomVotes]
  end
  Controller-->>Client: ImmersiveNextResult
Loading
sequenceDiagram
  participant Logger as AnalyticsEventLogger
  participant GA4 as GA4Client
  participant Amplitude as AmplitudeClient
  participant API as Amplitude HTTP V2

  Logger->>GA4: send(event)
  Logger->>Amplitude: send(eventName, userId, anonymousId, member, platform, props)
  Note over Amplitude: `@Async`("analyticsExecutor") — 비동기
  Amplitude->>Amplitude: isConfigured() 확인
  Amplitude->>API: POST /2/httpapi (JSON payload)
  API-->>Amplitude: 응답 (예외 시 warn 로그)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • JECT-Study/JECT2-4th-Server#233: AnalyticsEventLogger의 로깅 인프라를 신규 추가한 PR로, 이번 PR에서 해당 로거에 AmplitudeClient를 주입해 Amplitude 전송을 연결하므로 직접적으로 연관됩니다.
  • JECT-Study/JECT2-4th-Server#235: AnalyticsEventLogger.log(AnalyticsEvent)analytics_events에 적재하도록 변경한 PR로, 이번 PR이 동일 메서드에 Amplitude 전송을 추가로 연결하므로 코드 레벨에서 연관됩니다.

Suggested labels

feature

Suggested reviewers

  • KII1ua
  • tlarbals824

🐇 이벤트를 보내고, 피드를 정렬해~
Amplitude로 폴짝폴짝 날아가네 ✨
startVoteId가 맨 앞에 앉아
랜덤 친구들을 뒤에서 부르지 🎲
토끼의 로그는 절대 잃지 않아!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 몰입형 투표 startVoteId 지원과 Amplitude 행동 로그 연동이라는 핵심 변경을 정확히 요약한 제목입니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/immersive-vote-start-vote-id

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.

@github-actions

Copy link
Copy Markdown

빌드 성공
배포 준비 완료!

@Junhyukkkk Junhyukkkk merged commit 2ab8e1a into develop Jun 24, 2026
4 of 5 checks passed
@Junhyukkkk Junhyukkkk deleted the feature/immersive-vote-start-vote-id branch June 24, 2026 15:48
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