Skip to content

feat: News API 통계 및 대시보드 기능 추가#498

Merged
DDINGJOO merged 120 commits into
mainfrom
develop
Jan 23, 2026
Merged

feat: News API 통계 및 대시보드 기능 추가#498
DDINGJOO merged 120 commits into
mainfrom
develop

Conversation

@DDINGJOO

@DDINGJOO DDINGJOO commented Jan 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • 대시보드 통계 API (/stats/dashboard) 추가
  • 뉴스 읽기/퀴즈/단어 수집 통계 추적 기능
  • 북마크 응답에 기사 상세 정보 포함
  • Bedrock 키워드에 meaningKo 저장 수정
  • UserWord API 카테고리 필터링 기능

Test plan

  • /stats/dashboard 엔드포인트 테스트
  • 뉴스 읽기 시 통계 업데이트 확인
  • 북마크 목록 조회 시 기사 정보 포함 확인
  • 기사 키워드에 한국어 뜻 포함 확인

hye-inA and others added 30 commits January 20, 2026 16:18
* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

* feat : 주제 + 소주제 + 레벨로 오픽 질문 조회 추가

* feat : OPIc 세션, 질문, 답변 종합 handler 구현

* feat : 오픽 주제, 소주제별 seed 데이터 추가

* refactor : Transcribe API KEY 환경변수명 수정

* refactor : Bedrock에 사용하는 클로드 모델 변경

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환
- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공
…servertime-fix

[MESP-174] feat: 타이머 동기화 버그 수정 (serverTime)
- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드
- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427
…domain-field

feat: WebSocket 메시지 구조 개선 - domain 필드 추가
- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428
- 기본 CRUD (save, findById, delete)
- roomId로 활성/전체 게임 세션 조회
- 상태, 라운드, 점수 업데이트 메서드
- 정답자 추가, 힌트 사용, 게임 종료 처리

Closes #429
- 게임 관련 필드 제거 (gameStatus, currentRound 등)
- activeGameSessionId 필드 추가
- 게임 상태는 GameSession으로 분리됨

Note: 의존 코드 수정은 #431에서 진행

Closes #430
- GameService: ChatRoom 대신 GameSession 사용
- GameStatsService: GameSession 매개변수로 변경
- CommandService: GameSession 기반 점수 조회
- GameHandler: GameSession 기반 REST API
- WebSocketMessageHandler: GameSession 기반 브로드캐스트
- GameStatusResponse, ScoreboardResponse: GameSession 매개변수

Closes #431
…gamesession-model

refactor: GameSession 모델 분리 및 게임 로직 리팩토링
- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

모든 응답에 serverTime 포함 (타이머 동기화)
출제자에게만 currentWord 포함

Closes #432, #433
…gamesession-api

feat: 게임 세션 REST API 구현
- GameConfig에 gameTimeLimit() 메서드 추가 (기본값: 420초)
- GameSchedulerClient 유틸리티 클래스 생성 (EventBridge Scheduler 연동)
- GameService에 스케줄 생성/취소 로직 추가
- GameAutoCloseHandler Lambda 함수 생성
- template.yaml에 Lambda, IAM Role, Schedule Group 추가

Closes #417
…-auto-close

feat: 게임 시작 7분 후 자동 종료 기능 구현
- Room 타입 분리 (CHAT/GAME)
  - RoomType, RoomStatus enum 추가
  - ChatRoom 모델에 type, gameType, gameSettings, status, hostId 필드 추가
  - GameSettings 모델 추가

- 방 생성/조회 API 수정
  - CreateRoomRequest에 type, gameType, gameSettings 필드 추가
  - 방 목록 조회 시 type, gameType, status 필터 지원

- 게임 시작 조건 검증
  - GAME 타입 방에서만 게임 시작 가능 (GAME_007 에러)

- 게임 재시작 API 구현 (#452)
  - POST /rooms/{roomId}/game/restart 엔드포인트 추가
  - 방장만 재시작 가능 (GAME_009 에러)
  - 게임 진행 중 재시작 불가 (GAME_008 에러)

- 방장 변경 로직 구현 (#453)
  - 방장 퇴장 시 다음 멤버에게 자동 이전
  - 모든 멤버 퇴장 시 방 자동 삭제

- WebSocket 메시지 타입 추가 (#454)
  - ROOM_STATUS_CHANGE, HOST_CHANGE 메시지 타입 추가
  - WebSocketMessageHelper에 빌더 메서드 추가

- 테스트 추가
  - RoomType, RoomStatus enum 테스트
  - GameSettings 모델 테스트
  - ChattingErrorCode 테스트 업데이트

Related: #440, #441, #442, #443, #444, #445, #446
Closes: #447, #448, #449, #450, #451, #452, #453, #454
- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440
- 참가자/방장 닉네임 조회를 위한 UserTable 읽기 권한 추가
- DynamoDBReadPolicy로 UserTable 접근 허용

Fixes #457
- DynamoDB Enhanced Client가 중첩 객체를 직렬화/역직렬화할 수 있도록 수정
- ChatRoom 저장/조회 시 GameSettings 변환 오류 해결

Fixes #457
- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가
- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가
- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가
## 변경 사항

### GSI1SK 포맷 변경
- 기존: {level}#{createdAt}
- 신규: {type}#{gameType}#{status}#{level}#{createdAt}

### 지원 쿼리 패턴
- 전체 방: GSI1PK = "ROOMS"
- 게임방만: begins_with(GSI1SK, "GAME#")
- 캐치마인드만: begins_with(GSI1SK, "GAME#CATCHMIND#")
- 대기중 캐치마인드: begins_with(GSI1SK, "GAME#CATCHMIND#WAITING#")

### 파일 수정
- ChatRoomCommandService.java: 방 생성 시 새 GSI1SK 포맷 적용
- ChatRoomRepository.java: findByFilters() 메서드 추가, updateStatus() 메서드 추가
- ChatRoomQueryService.java: 메모리 필터링 제거, DB 레벨 필터링으로 변경
- GameService.java: 게임 시작/종료 시 방 상태 업데이트 (GSI1SK 포함)

### 마이그레이션
- scripts/migrate-gsi1sk.sh: 기존 데이터 마이그레이션 스크립트
- 37개 기존 방 마이그레이션 완료
- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.
- Added handling for game round timeout (`ROUND_TIMEOUT`) in WebSocketMessageHandler.
- Enhanced game start broadcast to include `currentWord` for the drawer only.
- Updated ConnectionRepository to remove duplicate user connections in the same room.
- Added `currentWordEnglish` to GameSession for better answer verification.
- Normalized ChatRoom levels to match database storage format.
- Updated template.yaml to include DynamoDBReadPolicy for VocabTable.
* refactor: remove unused WebSocketResponseUtil

* refactor: add AutoCloseable to WebSocketBroadcaster

* refactor: remove unused TestService

* refactor: remove unused WordService

* refactor: remove unused DailyStudyService

* refactor: remove unused UserWordService

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* style: remove p tag from javadoc

* fix: resolve N+1 query in StatsService
- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)
- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.
DDINGJOO and others added 22 commits January 23, 2026 10:45
- Add DAILY stats update for news read/quiz/word collection
- Add /stats/dashboard endpoint with frontend-requested format
  - today: wordsLearned, newsRead, quizzesTaken, wordsTotal
  - overall: totalWordsLearned, totalNewsRead, averageAccuracy, streaks
  - weeklyProgress: last 7 days with date/wordsLearned/newsRead
- Add news-related fields to all stats API responses
- Fix bookmark API to include full article details (title, summary, etc.)
- Add category field to AnalysisResult record
- Update Bedrock prompt to classify articles into categories
  (WORLD, POLITICS, BUSINESS, TECH, SCIENCE, HEALTH, SPORTS, ENTERTAINMENT, LIFESTYLE)
- Parse and set category from AI response
- Set GSI2 (CATEGORY#) index when category is available
- Set CognitoAuthorizer for all News API endpoints in template.yaml
- Update Bedrock AI to extract keywords with meanings and examples
- Add fallback to Comprehend for keyword extraction when Bedrock fails
- Modify KeywordInfo model to include example field
- Adjust AI prompt to include keyword extraction with examples
- Update AnalysisResult to store keywords and parse them from AI response
This reverts commit c1a958e, reversing
changes made to a6662e0.
- Add bookmark and reading status to individual article responses
- Include bookmark status in paginated news responses
- Modify `KeywordInfo` to support Korean translations (`meaningKo`)
- Update AI prompts to extract Korean meanings for keywords
* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

* feat : WebSocket 메시지 처리 handler, service 구현

* feat : WebSocket 연결 정보 Repository 구현

* fix : 오타 수정

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

* refacotor : 기존 service 코드 로직 재사용 및 repository 리펙토링

* feat : speaking rest API 람다 함수 추가

* refactor : speaking service 재사용

* refactor : AI 영어 회화 연습 코드 리팩토링

* feat : handleChat 메서드 JsonNull 체크 푸가

* refactor : session_id가 null 체크 추가

* feat : template 환경변수 리펙토링

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>
- Add bookmark and reading status to individual article responses
- Include bookmark status in paginated news responses
- Modify `KeywordInfo` to support Korean translations (`meaningKo`)
- Update AI prompts to extract Korean meanings for keywords
- Introduce `category` filtering to `getUserWords` API
- Update WordCategory enums to include "news" category
- Apply category filter after enrichment with word info
- Adjust query limits for bookmarked and incorrect words queries
- Set default to an empty string to ensure compatibility with templates using this parameter without explicitly specifying a value.
- Keep meaningKo and example fields in KeywordInfo
- Keep auto-sync feature in NewsWordService (Word + UserWord auto-creation)
- Keep batch bookmark check in NewsLearningService
- Keep keywords parsing with meaningKo in NewsAnalysisService
- Accept new Speaking handlers from prod
- Introduce `/stats/dashboard` API for retrieving integrated user stats (today, overall, weekly progress, and level distribution)
- Update `UserStats` model to include additional fields for news stats (newsRead, newsQuizCompleted, newsQuizPerfect, newsWordsCollected, etc.)
- Add atomic updates to track news reading, quiz, and word stats in `UserStatsRepository`
- Modify CloudFormation `template.yaml` to register the new `/stats/dashboard` endpoint
- Introduce `/stats/dashboard` API for retrieving integrated user stats (today, overall, weekly progress, and level distribution)
- Update `UserStats` model to include additional fields for news stats (newsRead, newsQuizCompleted, newsQuizPerfect, newsWordsCollected, etc.)
- Add atomic updates to track news reading, quiz, and word stats in `UserStatsRepository`
- Modify CloudFormation `template.yaml` to register the new `/stats/dashboard` endpoint
- Introduce `/stats/dashboard` API for retrieving integrated user stats (today, overall, weekly progress, and level distribution)
- Update `UserStats` model to include additional fields for news stats (newsRead, newsQuizCompleted, newsQuizPerfect, newsWordsCollected, etc.)
- Add atomic updates to track news reading, quiz, and word stats in `UserStatsRepository`
- Modify CloudFormation `template.yaml` to register the new `/stats/dashboard` endpoint
- Apply consistent formatting to improve code readability across multiple files
- Adjust indentation, spacing, and alignment in model classes, DTOs, and repository methods
@github-actions github-actions Bot added backend Backend code changes docs Documentation changes layer:entity Entity/Domain layer layer:dto DTO layer layer:repository Repository/DAO layer layer:service Service layer labels Jan 23, 2026
@github-actions

github-actions Bot commented Jan 23, 2026

Copy link
Copy Markdown

Jira: MESP-270

@DDINGJOO DDINGJOO merged commit 1bb81d0 into main Jan 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Backend code changes docs Documentation changes layer:dto DTO layer layer:entity Entity/Domain layer layer:repository Repository/DAO layer layer:service Service layer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants