Skip to content

refactor : OPIc 질문 조회 로직 구조 변경 및 질문 데이터 추가#551

Merged
hye-inA merged 4 commits into
testfrom
develop
Jan 26, 2026
Merged

refactor : OPIc 질문 조회 로직 구조 변경 및 질문 데이터 추가#551
hye-inA merged 4 commits into
testfrom
develop

Conversation

@hye-inA

@hye-inA hye-inA commented Jan 26, 2026

Copy link
Copy Markdown
Member

개요

OPIc 세션 생성 시 질문 조회 로직을 수정 및 질문 데이터 577개를 추가

작업 내용

1. Backend 로직 변경

  • 조회 기준 변경: 기존 Topic + SubTopic + TargetLevel 일치 방식에서 → Topic + SubTopic 일치 방식으로 변경

    사용자가 선택한 목표 레벨(TargetLevel)은 AI 피드백 생성 시에만 사용하고, 질문 조회 시에는 배제하여 매칭

  • DynamoDB 모델 수정 (OPIcQuestion):

    GSI1SK (정렬키) 구조 변경: 기존 LEVEL#{Level} → 변경 SUBTOPIC#{SubTopic}

    이를 통해 소주제별 쿼리 속도 최적화 및 불필요한 필터링 로직 제거

  • Repository 리팩토링: findQuestionsByTopicAndSubTopic 메서드 구현 및 기존 레벨 기반 조회 메서드 삭제

2. 데이터 시딩 (Data Seeding)

  • 신규 데이터 생성: 기존 질문 파일들을 파싱하여 총 577개의 정제된 질문 데이터 추가

  • 데이터 구조: Topic(질문 유형)과 SubTopic(소재) 체계로 재분류

    예: Topic='DESCRIPTION', SubTopic='BANKS'

hye-inA and others added 4 commits January 26, 2026 00:41
* test: BadgeType enum 단위 테스트 추가

* test: BadgeKey 상수 단위 테스트 추가

* test: WordStatus enum 단위 테스트 추가

* test: TestType enum 단위 테스트 추가

* test: VocabularyConfig 단위 테스트 추가

* test: VocabKey 상수 단위 테스트 추가

* test: VocabularyErrorCode 단위 테스트 추가

* test: VocabularyException 단위 테스트 추가

* test: SpacedRepetitionContext 단위 테스트 추가

* test: GrammarLevel enum 단위 테스트 추가

* test: GrammarConfig 단위 테스트 추가

* test: GrammarErrorCode 단위 테스트 추가

* test: GrammarException 단위 테스트 추가

* test: GameStatus enum 단위 테스트 추가

* test: GameConfig 단위 테스트 추가

* test: ChattingErrorCode 단위 테스트 추가

* test: ChattingException 단위 테스트 추가

* fix: OPIc FeedbackResponse.java 문법 오류 수정

* style: AwsClients 코드 포맷팅

* style: EnvConfig 코드 포맷팅

* style: RoomTokenConfig 코드 포맷팅

* style: WebSocketConfig 코드 포맷팅

* style: JsonUtil 코드 포맷팅

* style: GameConfig 코드 포맷팅

* style: GrammarConfig 코드 포맷팅

* style: GrammarKey 코드 포맷팅

* style: GrammarErrorCode 코드 포맷팅

* style: GrammarException 코드 포맷팅

* style: BedrockGrammarCheckFactory 코드 포맷팅

* style: GrammarConversationService 코드 포맷팅

* style: FeedbackResponse 코드 포맷팅

* style: SessionReportResponse 코드 포맷팅

* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* Release: 캐치마인드 게임 분리, AI 회화 연습, CI/CD 파이프라인 (#469)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

---------

Co-authored-by: hyein Heo <128613248+hye-inA@users.noreply.github.com>

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* refactor : AI 말하기 Websocket 구현 -> REST API 구현으로 리팩토링 (#490)

* 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 리펙토링

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: update all API Gateway StageName to use Environment parameter

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* feat: add support for existing Cognito User Pool reuse across environments

* fix: add conditional Cognito ARN reference in API Gateway Authorizer

* fix: remove Cognito resources completely, use existing Cognito only

* fix: remove Cognito resources completely, use existing Cognito only

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

* feat: add S3 bucket resource and fix environment-specific endpoints

- Add ContentBucket S3 resource for content storage
- Replace hardcoded /dev with ${Environment} in all WebSocket endpoints
- Update Output URLs to use dynamic environment stage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add stack name prefix to news-collection schedule name

Prevent EventBridge rule name conflicts across environments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add X-Requested-With and Accept headers to CORS config

Enable additional headers for CloudFront CORS compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use environment variable for S3 bucket URLs

Replace hardcoded bucket name with BUCKET_NAME env var for multi-env support:
- PreSignUpHandler: dynamic default profile URL
- PostConfirmationHandler: dynamic default profile URL
- UserService: dynamic default profile URL
- BadgeType: dynamic badge image base URL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: disable authorizer for CORS preflight requests

Add AddDefaultAuthorizerToCorsPreflight: false to prevent
Cognito Authorizer from blocking OPTIONS requests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat : speaking REST API 람다 함수 추가  (#491)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

- 기존: {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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

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

---------

Co-authored-by: ddingjoo <ddingsha9@teambind.co.kr>

* refactor : speaking service 재사용

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

* feature : test 벡엔드 서버에 AI 말하기 연습 기능 배포 (#492)

* 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 영어 회화 연습 코드 리팩토링

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

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

* feature : handleChat 메서드 JsonNull 체크 추가 (#493)

* 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 체크 푸가

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

* feat(news): 뉴스 학습 배지 시스템 구현 (#473)

- 14개 뉴스 관련 배지 추가 (읽기, 퀴즈, 단어수집, 연속학습, 마스터)
- UserStats에 뉴스 통계 필드 추가
- 6개 뉴스 배지 Strategy 클래스 생성
- 뉴스 읽기/퀴즈/단어수집 시 통계 업데이트 및 배지 체크 연동

* fix: add PATCH method to CORS AllowMethods

* test: BadgeType 개수 테스트 수정 (15 -> 29)

* fix: CORS PATCH 메서드 추가

* docs: 뉴스 기능 프론트엔드 연동 가이드 작성

* fix: NewsCollectionFunction에 Bedrock, Comprehend 권한 추가

* fix: add null check for collectWord request body

- Add INVALID_REQUEST error code to NewsErrorCode
- Check body and word field before accessing in collectWord()
- Prevents NullPointerException when request body is malformed

* feat: enhance stats API and bookmark response for frontend

- 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.)

* feat: add category classification to news AI analysis

- 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

* fix: add /stats/dashboard endpoint to template.yaml

* fix: filter by ARTICLE# prefix in findById to avoid returning UserNewsRecord

* docs: add News API troubleshooting guide

* feat: add Cognito authorizer to News API and enhance keyword extraction

- 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

* Revert "Merge branch 'test' into prod"

This reverts commit c1a958eac6799d5838a76e4078ae304bcdb62278, reversing
changes made to a6662e0cfc46c6e12f20a89f0df285ff282160bc.

* feat: enhance bookmark and reading status tracking for News API

- 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

* refactor : session_id가 null 체크 추가

* fix : sessionId NullPointerException 에러 수정  (#496)

* 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>

* feat: enhance bookmark and reading status tracking for News API

- 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: add category filtering to UserWord API with enhanced query logic

- 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

* feat: add default value for ExistingCognitoClientId in template.yaml

- Set default to an empty string to ensure compatibility with templates using this parameter without explicitly specifying a value.

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* refactor: format code with consistent indentation and spacing

- Apply consistent formatting to improve code readability across multiple files
- Adjust indentation, spacing, and alignment in model classes, DTOs, and repository methods

* fix: filter by ARTICLE# prefix in findById to avoid returning bookmark records

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feature : Speaking Table & Function template.yaml 파일에 추가 (#513)

* fix: BadgeRepository 클라이언트 초기화 패턴 통일

- 개별 DynamoDbEnhancedClient 생성 대신 AwsClients.dynamoDbEnhanced() 싱글톤 사용
- 다른 Repository들과 동일한 패턴 적용
- 불필요한 import 제거

Closes #396

* feat: EnvConfig 유틸리티 추가 및 환경 변수 검증 적용

환경 변수 미설정 시 명확한 에러 메시지를 제공하는 EnvConfig 유틸리티를 추가하고,
기존 System.getenv 호출을 EnvConfig.getRequired/getOrDefault로 대체함.

- EnvConfig: getRequired, getOrDefault, getIntOrDefault, getLongOrDefault 메서드 제공
- Lambda Cold Start 시점에 환경 변수 누락을 조기 감지
- 기존 Config 클래스(WebSocketConfig, RoomTokenConfig) EnvConfig 사용으로 통일

Closes #403

* refactor: TestService submitTest 메서드 책임 분리

submitTest 메서드를 단일 책임 원칙에 맞게 리팩토링:
- gradeAnswers(): 답안 채점 및 결과 집계
- isAnswerCorrect(): 단일 답안 정답 여부 판단
- buildResultItem(): 결과 항목 생성
- saveTestResult(): 테스트 결과 저장
- GradingResult record: 채점 결과 캡슐화

TestService와 TestCommandService 모두 동일하게 적용

Closes #404

* refactor: 하드코딩된 설정값 환경 변수로 외부화

각 도메인별 Config 클래스를 생성하여 하드코딩된 값들을 환경 변수로 설정 가능하게 변경.
기본값이 있어 환경 변수 미설정 시에도 기존 동작 유지.

## 새로 추가된 Config 클래스
- GrammarConfig: SESSION_TTL_DAYS, MAX_HISTORY_MESSAGES, MAX_TOKENS 등
- GameConfig: TOTAL_ROUNDS, ROUND_TIME_LIMIT, QUICK_GUESS_THRESHOLD_MS
- VocabularyConfig: NEW_WORDS_COUNT, REVIEW_WORDS_COUNT, 상태 전이 임계값 등

## 지원하는 환경 변수
- GRAMMAR_SESSION_TTL_DAYS, GRAMMAR_MAX_HISTORY_MESSAGES, GRAMMAR_MAX_TOKENS
- GAME_TOTAL_ROUNDS, GAME_ROUND_TIME_LIMIT, GAME_QUICK_GUESS_THRESHOLD_MS
- VOCAB_NEW_WORDS_COUNT, VOCAB_REVIEW_WORDS_COUNT
- VOCAB_TRANSITION_TO_REVIEWING, VOCAB_TRANSITION_TO_MASTERED

Closes #406

* test: StudyLevel enum 단위 테스트 추가

* test: Difficulty enum 단위 테스트 추가

* test: StudyConfig 단위 테스트 추가

* test: EnvConfig 단위 테스트 추가

* test: PaginatedResult 단위 테스트 추가

* test: JsonUtil 단위 테스트 추가

* test: CursorUtil 단위 테스트 추가

* test: CommonErrorCode 단위 테스트 추가

* test: CommonException 단위 테스트 추가

* test: BadgeType enum 단위 테스트 추가

* test: BadgeKey 상수 단위 테스트 추가

* test: WordStatus enum 단위 테스트 추가

* test: TestType enum 단위 테스트 추가

* test: VocabularyConfig 단위 테스트 추가

* test: VocabKey 상수 단위 테스트 추가

* test: VocabularyErrorCode 단위 테스트 추가

* test: VocabularyException 단위 테스트 추가

* test: SpacedRepetitionContext 단위 테스트 추가

* test: GrammarLevel enum 단위 테스트 추가

* test: GrammarConfig 단위 테스트 추가

* test: GrammarErrorCode 단위 테스트 추가

* test: GrammarException 단위 테스트 추가

* test: GameStatus enum 단위 테스트 추가

* test: GameConfig 단위 테스트 추가

* test: ChattingErrorCode 단위 테스트 추가

* test: ChattingException 단위 테스트 추가

* fix: OPIc FeedbackResponse.java 문법 오류 수정

* style: AwsClients 코드 포맷팅

* style: EnvConfig 코드 포맷팅

* style: RoomTokenConfig 코드 포맷팅

* style: WebSocketConfig 코드 포맷팅

* style: JsonUtil 코드 포맷팅

* style: GameConfig 코드 포맷팅

* style: GrammarConfig 코드 포맷팅

* style: GrammarKey 코드 포맷팅

* style: GrammarErrorCode 코드 포맷팅

* style: GrammarException 코드 포맷팅

* style: BedrockGrammarCheckFactory 코드 포맷팅

* style: GrammarConversationService 코드 포맷팅

* style: FeedbackResponse 코드 포맷팅

* style: SessionReportResponse 코드 포맷팅

* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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 테스트
  - …
* style: SessionReportResponse 코드 포맷팅

* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* Release: 캐치마인드 게임 분리, AI 회화 연습, CI/CD 파이프라인 (#469)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

---------

Co-authored-by: hyein Heo <128613248+hye-inA@users.noreply.github.com>

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* refactor : AI 말하기 Websocket 구현 -> REST API 구현으로 리팩토링 (#490)

* 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 리펙토링

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: update all API Gateway StageName to use Environment parameter

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* feat: add support for existing Cognito User Pool reuse across environments

* fix: add conditional Cognito ARN reference in API Gateway Authorizer

* fix: remove Cognito resources completely, use existing Cognito only

* fix: remove Cognito resources completely, use existing Cognito only

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

* feat: add S3 bucket resource and fix environment-specific endpoints

- Add ContentBucket S3 resource for content storage
- Replace hardcoded /dev with ${Environment} in all WebSocket endpoints
- Update Output URLs to use dynamic environment stage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add stack name prefix to news-collection schedule name

Prevent EventBridge rule name conflicts across environments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add X-Requested-With and Accept headers to CORS config

Enable additional headers for CloudFront CORS compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use environment variable for S3 bucket URLs

Replace hardcoded bucket name with BUCKET_NAME env var for multi-env support:
- PreSignUpHandler: dynamic default profile URL
- PostConfirmationHandler: dynamic default profile URL
- UserService: dynamic default profile URL
- BadgeType: dynamic badge image base URL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: disable authorizer for CORS preflight requests

Add AddDefaultAuthorizerToCorsPreflight: false to prevent
Cognito Authorizer from blocking OPTIONS requests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat : speaking REST API 람다 함수 추가  (#491)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

- 기존: {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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

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

---------

Co-authored-by: ddingjoo <ddingsha9@teambind.co.kr>

* refactor : speaking service 재사용

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

* feature : test 벡엔드 서버에 AI 말하기 연습 기능 배포 (#492)

* 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 영어 회화 연습 코드 리팩토링

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

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

* feature : handleChat 메서드 JsonNull 체크 추가 (#493)

* 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 체크 푸가

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

* feat(news): 뉴스 학습 배지 시스템 구현 (#473)

- 14개 뉴스 관련 배지 추가 (읽기, 퀴즈, 단어수집, 연속학습, 마스터)
- UserStats에 뉴스 통계 필드 추가
- 6개 뉴스 배지 Strategy 클래스 생성
- 뉴스 읽기/퀴즈/단어수집 시 통계 업데이트 및 배지 체크 연동

* fix: add PATCH method to CORS AllowMethods

* test: BadgeType 개수 테스트 수정 (15 -> 29)

* fix: CORS PATCH 메서드 추가

* docs: 뉴스 기능 프론트엔드 연동 가이드 작성

* fix: NewsCollectionFunction에 Bedrock, Comprehend 권한 추가

* fix: add null check for collectWord request body

- Add INVALID_REQUEST error code to NewsErrorCode
- Check body and word field before accessing in collectWord()
- Prevents NullPointerException when request body is malformed

* feat: enhance stats API and bookmark response for frontend

- 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.)

* feat: add category classification to news AI analysis

- 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

* fix: add /stats/dashboard endpoint to template.yaml

* fix: filter by ARTICLE# prefix in findById to avoid returning UserNewsRecord

* docs: add News API troubleshooting guide

* feat: add Cognito authorizer to News API and enhance keyword extraction

- 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

* Revert "Merge branch 'test' into prod"

This reverts commit c1a958eac6799d5838a76e4078ae304bcdb62278, reversing
changes made to a6662e0cfc46c6e12f20a89f0df285ff282160bc.

* feat: enhance bookmark and reading status tracking for News API

- 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

* refactor : session_id가 null 체크 추가

* fix : sessionId NullPointerException 에러 수정  (#496)

* 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>

* feat: enhance bookmark and reading status tracking for News API

- 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: add category filtering to UserWord API with enhanced query logic

- 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

* feat: add default value for ExistingCognitoClientId in template.yaml

- Set default to an empty string to ensure compatibility with templates using this parameter without explicitly specifying a value.

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* refactor: format code with consistent indentation and spacing

- Apply consistent formatting to improve code readability across multiple files
- Adjust indentation, spacing, and alignment in model classes, DTOs, and repository methods

* fix: filter by ARTICLE# prefix in findById to avoid returning bookmark records

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feature : Speaking Table & Function template.yaml 파일에 추가 (#513)

* fix: BadgeRepository 클라이언트 초기화 패턴 통일

- 개별 DynamoDbEnhancedClient 생성 대신 AwsClients.dynamoDbEnhanced() 싱글톤 사용
- 다른 Repository들과 동일한 패턴 적용
- 불필요한 import 제거

Closes #396

* feat: EnvConfig 유틸리티 추가 및 환경 변수 검증 적용

환경 변수 미설정 시 명확한 에러 메시지를 제공하는 EnvConfig 유틸리티를 추가하고,
기존 System.getenv 호출을 EnvConfig.getRequired/getOrDefault로 대체함.

- EnvConfig: getRequired, getOrDefault, getIntOrDefault, getLongOrDefault 메서드 제공
- Lambda Cold Start 시점에 환경 변수 누락을 조기 감지
- 기존 Config 클래스(WebSocketConfig, RoomTokenConfig) EnvConfig 사용으로 통일

Closes #403

* refactor: TestService submitTest 메서드 책임 분리

submitTest 메서드를 단일 책임 원칙에 맞게 리팩토링:
- gradeAnswers(): 답안 채점 및 결과 집계
- isAnswerCorrect(): 단일 답안 정답 여부 판단
- buildResultItem(): 결과 항목 생성
- saveTestResult(): 테스트 결과 저장
- GradingResult record: 채점 결과 캡슐화

TestService와 TestCommandService 모두 동일하게 적용

Closes #404

* refactor: 하드코딩된 설정값 환경 변수로 외부화

각 도메인별 Config 클래스를 생성하여 하드코딩된 값들을 환경 변수로 설정 가능하게 변경.
기본값이 있어 환경 변수 미설정 시에도 기존 동작 유지.

## 새로 추가된 Config 클래스
- GrammarConfig: SESSION_TTL_DAYS, MAX_HISTORY_MESSAGES, MAX_TOKENS 등
- GameConfig: TOTAL_ROUNDS, ROUND_TIME_LIMIT, QUICK_GUESS_THRESHOLD_MS
- VocabularyConfig: NEW_WORDS_COUNT, REVIEW_WORDS_COUNT, 상태 전이 임계값 등

## 지원하는 환경 변수
- GRAMMAR_SESSION_TTL_DAYS, GRAMMAR_MAX_HISTORY_MESSAGES, GRAMMAR_MAX_TOKENS
- GAME_TOTAL_ROUNDS, GAME_ROUND_TIME_LIMIT, GAME_QUICK_GUESS_THRESHOLD_MS
- VOCAB_NEW_WORDS_COUNT, VOCAB_REVIEW_WORDS_COUNT
- VOCAB_TRANSITION_TO_REVIEWING, VOCAB_TRANSITION_TO_MASTERED

Closes #406

* test: StudyLevel enum 단위 테스트 추가

* test: Difficulty enum 단위 테스트 추가

* test: StudyConfig 단위 테스트 추가

* test: EnvConfig 단위 테스트 추가

* test: PaginatedResult 단위 테스트 추가

* test: JsonUtil 단위 테스트 추가

* test: CursorUtil 단위 테스트 추가

* test: CommonErrorCode 단위 테스트 추가

* test: CommonException 단위 테스트 추가

* test: BadgeType enum 단위 테스트 추가

* test: BadgeKey 상수 단위 테스트 추가

* test: WordStatus enum 단위 테스트 추가

* test: TestType enum 단위 테스트 추가

* test: VocabularyConfig 단위 테스트 추가

* test: VocabKey 상수 단위 테스트 추가

* test: VocabularyErrorCode 단위 테스트 추가

* test: VocabularyException 단위 테스트 추가

* test: SpacedRepetitionContext 단위 테스트 추가

* test: GrammarLevel enum 단위 테스트 추가

* test: GrammarConfig 단위 테스트 추가

* test: GrammarErrorCode 단위 테스트 추가

* test: GrammarException 단위 테스트 추가

* test: GameStatus enum 단위 테스트 추가

* test: GameConfig 단위 테스트 추가

* test: ChattingErrorCode 단위 테스트 추가

* test: ChattingException 단위 테스트 추가

* fix: OPIc FeedbackResponse.java 문법 오류 수정

* style: AwsClients 코드 포맷팅

* style: EnvConfig 코드 포맷팅

* style: RoomTokenConfig 코드 포맷팅

* style: WebSocketConfig 코드 포맷팅

* style: JsonUtil 코드 포맷팅

* style: GameConfig 코드 포맷팅

* style: GrammarConfig 코드 포맷팅

* style: GrammarKey 코드 포맷팅

* style: GrammarErrorCode 코드 포맷팅

* style: GrammarException 코드 포맷팅

* style: BedrockGrammarCheckFactory 코드 포맷팅

* style: GrammarConversationService 코드 포맷팅

* style: FeedbackResponse 코드 포맷팅

* style: SessionReportResponse 코드 포맷팅

* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT …
* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* Release: 캐치마인드 게임 분리, AI 회화 연습, CI/CD 파이프라인 (#469)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

---------

Co-authored-by: hyein Heo <128613248+hye-inA@users.noreply.github.com>

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* refactor : AI 말하기 Websocket 구현 -> REST API 구현으로 리팩토링 (#490)

* 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 리펙토링

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: update all API Gateway StageName to use Environment parameter

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* feat: add support for existing Cognito User Pool reuse across environments

* fix: add conditional Cognito ARN reference in API Gateway Authorizer

* fix: remove Cognito resources completely, use existing Cognito only

* fix: remove Cognito resources completely, use existing Cognito only

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

* feat: add S3 bucket resource and fix environment-specific endpoints

- Add ContentBucket S3 resource for content storage
- Replace hardcoded /dev with ${Environment} in all WebSocket endpoints
- Update Output URLs to use dynamic environment stage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add stack name prefix to news-collection schedule name

Prevent EventBridge rule name conflicts across environments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add X-Requested-With and Accept headers to CORS config

Enable additional headers for CloudFront CORS compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use environment variable for S3 bucket URLs

Replace hardcoded bucket name with BUCKET_NAME env var for multi-env support:
- PreSignUpHandler: dynamic default profile URL
- PostConfirmationHandler: dynamic default profile URL
- UserService: dynamic default profile URL
- BadgeType: dynamic badge image base URL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: disable authorizer for CORS preflight requests

Add AddDefaultAuthorizerToCorsPreflight: false to prevent
Cognito Authorizer from blocking OPTIONS requests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat : speaking REST API 람다 함수 추가  (#491)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

- 기존: {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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

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

---------

Co-authored-by: ddingjoo <ddingsha9@teambind.co.kr>

* refactor : speaking service 재사용

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

* feature : test 벡엔드 서버에 AI 말하기 연습 기능 배포 (#492)

* 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 영어 회화 연습 코드 리팩토링

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

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

* feature : handleChat 메서드 JsonNull 체크 추가 (#493)

* 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 체크 푸가

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

* feat(news): 뉴스 학습 배지 시스템 구현 (#473)

- 14개 뉴스 관련 배지 추가 (읽기, 퀴즈, 단어수집, 연속학습, 마스터)
- UserStats에 뉴스 통계 필드 추가
- 6개 뉴스 배지 Strategy 클래스 생성
- 뉴스 읽기/퀴즈/단어수집 시 통계 업데이트 및 배지 체크 연동

* fix: add PATCH method to CORS AllowMethods

* test: BadgeType 개수 테스트 수정 (15 -> 29)

* fix: CORS PATCH 메서드 추가

* docs: 뉴스 기능 프론트엔드 연동 가이드 작성

* fix: NewsCollectionFunction에 Bedrock, Comprehend 권한 추가

* fix: add null check for collectWord request body

- Add INVALID_REQUEST error code to NewsErrorCode
- Check body and word field before accessing in collectWord()
- Prevents NullPointerException when request body is malformed

* feat: enhance stats API and bookmark response for frontend

- 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.)

* feat: add category classification to news AI analysis

- 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

* fix: add /stats/dashboard endpoint to template.yaml

* fix: filter by ARTICLE# prefix in findById to avoid returning UserNewsRecord

* docs: add News API troubleshooting guide

* feat: add Cognito authorizer to News API and enhance keyword extraction

- 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

* Revert "Merge branch 'test' into prod"

This reverts commit c1a958eac6799d5838a76e4078ae304bcdb62278, reversing
changes made to a6662e0cfc46c6e12f20a89f0df285ff282160bc.

* feat: enhance bookmark and reading status tracking for News API

- 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

* refactor : session_id가 null 체크 추가

* fix : sessionId NullPointerException 에러 수정  (#496)

* 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>

* feat: enhance bookmark and reading status tracking for News API

- 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: add category filtering to UserWord API with enhanced query logic

- 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

* feat: add default value for ExistingCognitoClientId in template.yaml

- Set default to an empty string to ensure compatibility with templates using this parameter without explicitly specifying a value.

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* refactor: format code with consistent indentation and spacing

- Apply consistent formatting to improve code readability across multiple files
- Adjust indentation, spacing, and alignment in model classes, DTOs, and repository methods

* fix: filter by ARTICLE# prefix in findById to avoid returning bookmark records

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feature : Speaking Table & Function template.yaml 파일에 추가 (#513)

* fix: BadgeRepository 클라이언트 초기화 패턴 통일

- 개별 DynamoDbEnhancedClient 생성 대신 AwsClients.dynamoDbEnhanced() 싱글톤 사용
- 다른 Repository들과 동일한 패턴 적용
- 불필요한 import 제거

Closes #396

* feat: EnvConfig 유틸리티 추가 및 환경 변수 검증 적용

환경 변수 미설정 시 명확한 에러 메시지를 제공하는 EnvConfig 유틸리티를 추가하고,
기존 System.getenv 호출을 EnvConfig.getRequired/getOrDefault로 대체함.

- EnvConfig: getRequired, getOrDefault, getIntOrDefault, getLongOrDefault 메서드 제공
- Lambda Cold Start 시점에 환경 변수 누락을 조기 감지
- 기존 Config 클래스(WebSocketConfig, RoomTokenConfig) EnvConfig 사용으로 통일

Closes #403

* refactor: TestService submitTest 메서드 책임 분리

submitTest 메서드를 단일 책임 원칙에 맞게 리팩토링:
- gradeAnswers(): 답안 채점 및 결과 집계
- isAnswerCorrect(): 단일 답안 정답 여부 판단
- buildResultItem(): 결과 항목 생성
- saveTestResult(): 테스트 결과 저장
- GradingResult record: 채점 결과 캡슐화

TestService와 TestCommandService 모두 동일하게 적용

Closes #404

* refactor: 하드코딩된 설정값 환경 변수로 외부화

각 도메인별 Config 클래스를 생성하여 하드코딩된 값들을 환경 변수로 설정 가능하게 변경.
기본값이 있어 환경 변수 미설정 시에도 기존 동작 유지.

## 새로 추가된 Config 클래스
- GrammarConfig: SESSION_TTL_DAYS, MAX_HISTORY_MESSAGES, MAX_TOKENS 등
- GameConfig: TOTAL_ROUNDS, ROUND_TIME_LIMIT, QUICK_GUESS_THRESHOLD_MS
- VocabularyConfig: NEW_WORDS_COUNT, REVIEW_WORDS_COUNT, 상태 전이 임계값 등

## 지원하는 환경 변수
- GRAMMAR_SESSION_TTL_DAYS, GRAMMAR_MAX_HISTORY_MESSAGES, GRAMMAR_MAX_TOKENS
- GAME_TOTAL_ROUNDS, GAME_ROUND_TIME_LIMIT, GAME_QUICK_GUESS_THRESHOLD_MS
- VOCAB_NEW_WORDS_COUNT, VOCAB_REVIEW_WORDS_COUNT
- VOCAB_TRANSITION_TO_REVIEWING, VOCAB_TRANSITION_TO_MASTERED

Closes #406

* test: StudyLevel enum 단위 테스트 추가

* test: Difficulty enum 단위 테스트 추가

* test: StudyConfig 단위 테스트 추가

* test: EnvConfig 단위 테스트 추가

* test: PaginatedResult 단위 테스트 추가

* test: JsonUtil 단위 테스트 추가

* test: CursorUtil 단위 테스트 추가

* test: CommonErrorCode 단위 테스트 추가

* test: CommonException 단위 테스트 추가

* test: BadgeType enum 단위 테스트 추가

* test: BadgeKey 상수 단위 테스트 추가

* test: WordStatus enum 단위 테스트 추가

* test: TestType enum 단위 테스트 추가

* test: VocabularyConfig 단위 테스트 추가

* test: VocabKey 상수 단위 테스트 추가

* test: VocabularyErrorCode 단위 테스트 추가

* test: VocabularyException 단위 테스트 추가

* test: SpacedRepetitionContext 단위 테스트 추가

* test: GrammarLevel enum 단위 테스트 추가

* test: GrammarConfig 단위 테스트 추가

* test: GrammarErrorCode 단위 테스트 추가

* test: GrammarException 단위 테스트 추가

* test: GameStatus enum 단위 테스트 추가

* test: GameConfig 단위 테스트 추가

* test: ChattingErrorCode 단위 테스트 추가

* test: ChattingException 단위 테스트 추가

* fix: OPIc FeedbackResponse.java 문법 오류 수정

* style: AwsClients 코드 포맷팅

* style: EnvConfig 코드 포맷팅

* style: RoomTokenConfig 코드 포맷팅

* style: WebSocketConfig 코드 포맷팅

* style: JsonUtil 코드 포맷팅

* style: GameConfig 코드 포맷팅

* style: GrammarConfig 코드 포맷팅

* style: GrammarKey 코드 포맷팅

* style: GrammarErrorCode 코드 포맷팅

* style: GrammarException 코드 포맷팅

* style: BedrockGrammarCheckFactory 코드 포맷팅

* style: GrammarConversationService 코드 포맷팅

* style: FeedbackResponse 코드 포맷팅

* style: SessionReportResponse 코드 포맷팅

* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한…
* style: GrammarErrorCode 코드 포맷팅

* style: GrammarException 코드 포맷팅

* style: BedrockGrammarCheckFactory 코드 포맷팅

* style: GrammarConversationService 코드 포맷팅

* style: FeedbackResponse 코드 포맷팅

* style: SessionReportResponse 코드 포맷팅

* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* Release: 캐치마인드 게임 분리, AI 회화 연습, CI/CD 파이프라인 (#469)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

## 변경 사항

### 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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

---------

Co-authored-by: hyein Heo <128613248+hye-inA@users.noreply.github.com>

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* feat(news): 뉴스 도메인 기반 구조 구축 (#385)

- NewsCategory, QuizType enum 추가
- NewsKey 상수 클래스 추가
- NewsErrorCode 예외 클래스 추가
- NewsArticle, KeywordInfo, QuizQuestion 모델 추가
- NewsArticleRepository CRUD 구현
- NewsTable DynamoDB 테이블 정의
- CORS GatewayResponses 설정 추가

* feat(news): 뉴스 수집 파이프라인 구현 (#386)

- NewsApiClient: NewsAPI 연동 서비스
- RssFeedParser: RSS 피드 파싱 (BBC, VOA, NPR)
- NewsDuplicateChecker: URL 기반 중복 필터링
- NewsCollectorService: 수집 오케스트레이션
- NewsCollectionHandler: Lambda 핸들러
- EventBridge 스케줄러: 매일 18시 KST 실행

* refactor(news): NewsAPI 제거, RSS만 사용

- NewsApiClient 삭제
- SSM Parameter 의존성 제거
- RSS 소스당 7개씩 수집 (BBC, VOA, NPR = 약 21개/일)

* feat(news): AI 뉴스 분석 시스템 구현 (#387)

- NewsAnalysisService: AI 분석 통합 서비스
  - Bedrock: CEFR 난이도 분석 (A1~C2)
  - Bedrock: 3줄 요약 + 퀴즈 3문제 생성
  - Comprehend: 핵심 키워드 추출
- NewsCollectorService: 수집 시 자동 분석 연동
- GSI1/GSI2 키 자동 설정 (레벨별, 카테고리별 조회)

* feat(news): 뉴스 학습 API 구현 (#388)

- NewsQueryService: 뉴스 조회 서비스
- NewsHandler: API 핸들러
  - GET /news - 목록 조회 (level, category 필터)
  - GET /news/today - 오늘의 뉴스
  - GET /news/recommended - 내 레벨 맞춤 추천
  - GET /news/{articleId} - 상세 조회 (조회수 증가)
- template.yaml: NewsFunction Lambda 추가

* feat(news): 뉴스 학습 부가 기능 구현 (#389)

- 읽기 완료 기록 API (POST /news/{articleId}/read)
- 북마크 토글 API (POST /news/{articleId}/bookmark)
- 북마크 목록 조회 API (GET /news/bookmarks)
- 학습 통계 조회 API (GET /news/stats)
- TTS 오디오 URL 조회 API (GET /news/{articleId}/audio)
- UserNewsRecord 모델 추가
- UserNewsRepository 추가
- NewsLearningService 추가

* feat(news): 복합 퀴즈 시스템 구현 (#471)

- 퀴즈 조회 API (GET /news/{articleId}/quiz)
- 퀴즈 제출 API (POST /news/{articleId}/quiz)
- 퀴즈 기록 조회 API (GET /news/quiz/history)
- NewsQuizResult 모델 추가
- QuizAnswerResult 모델 추가
- NewsQuizRepository 추가
- NewsQuizService 추가

* feat(news): 단어 수집 & Vocabulary 연동 구현 (#472)

- 단어 수집 API (POST /news/{articleId}/words)
- 수집 단어 목록 API (GET /news/words)
- 단어 상세 조회 API (GET /news/{articleId}/words/{word})
- 단어 삭제 API (DELETE /news/{articleId}/words/{word})
- Vocabulary 연동 API (POST /news/words/{word}/sync)
- NewsWordCollect 모델 추가
- NewsWordRepository 추가
- NewsWordService 추가

* feat: add multi-environment deployment support (dev/test/prod)

* fix: update buildspec.yml to deploy prod environment with parameter overrides

* refactor : AI 말하기 Websocket 구현 -> REST API 구현으로 리팩토링 (#490)

* 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 리펙토링

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: revert buildspec.yml to build-only for CloudFormation deploy stage

* fix: update all API Gateway StageName to use Environment parameter

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: correct VocabularyTable and ContentBucket references in NewsFunction

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* fix: add stack name prefix to GameScheduleGroup and daily-stats schedule to avoid conflicts

* feat: add support for existing Cognito User Pool reuse across environments

* fix: add conditional Cognito ARN reference in API Gateway Authorizer

* fix: remove Cognito resources completely, use existing Cognito only

* fix: remove Cognito resources completely, use existing Cognito only

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

* feat: add S3 bucket resource and fix environment-specific endpoints

- Add ContentBucket S3 resource for content storage
- Replace hardcoded /dev with ${Environment} in all WebSocket endpoints
- Update Output URLs to use dynamic environment stage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add stack name prefix to news-collection schedule name

Prevent EventBridge rule name conflicts across environments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add X-Requested-With and Accept headers to CORS config

Enable additional headers for CloudFront CORS compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use environment variable for S3 bucket URLs

Replace hardcoded bucket name with BUCKET_NAME env var for multi-env support:
- PreSignUpHandler: dynamic default profile URL
- PostConfirmationHandler: dynamic default profile URL
- UserService: dynamic default profile URL
- BadgeType: dynamic badge image base URL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: disable authorizer for CORS preflight requests

Add AddDefaultAuthorizerToCorsPreflight: false to prevent
Cognito Authorizer from blocking OPTIONS requests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat : speaking REST API 람다 함수 추가  (#491)

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사용을 위한 환경변수 추가
- execute-api:ManageConnections 권한 추가

* fix: WebSocket Lambda 함수들에 WEBSOCKET_ENDPOINT 환경변수 추가

- WebSocketConnectFunction에 WEBSOCKET_ENDPOINT 추가
- WebSocketDisconnectFunction에 WEBSOCKET_ENDPOINT 추가
- execute-api:ManageConnections 권한 추가

* fix: Grammar WebSocket Lambda 환경 변수 및 권한 추가

- GrammarStreamingConnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- GrammarStreamingDisconnectFunction에 WEBSOCKET_ENDPOINT 환경 변수 추가
- 두 함수에 execute-api:ManageConnections 권한 추가

* feat: GSI1SK 확장성 있는 재설계 및 DB 레벨 필터링

- 기존: {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개 기존 방 마이그레이션 완료

* fix: increase stats query limit to 100 days

- Adjust maximum allowable limit for recent stats query from 30 to 100 days to support extended data range responses.

* feat: improve game round and connection management logic

- 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: 코드 정리 및 미사용 클래스 제거 (#459)

* 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

* refactor(all): DI 패턴 및 전략 패턴 적용 (#461)

- Repository, Service, Handler에 DI 생성자 추가 (테스트 용이성)
- BadgeService에 Strategy 패턴 적용 (뱃지 조건 검증 로직 분리)

* refactor: relocate and restructure seed data files

- Moved `question-homes.json` and `words.json` from subdirectories to `seed` folder.
- Updated file paths for better organization and clarity.

* chore: seed 데이터 폴더 구조 정리

* feat: add CI/CD pipeline configuration for CodePipeline

* fix: add SNS topic policy and DependsOn for notification rule

* fix: correct paths in buildspec.yml for CodeBuild

* fix: remove hardcoded JAVA_HOME, use runtime default

* fix: add gradle wrapper for CI/CD build

* fix: use single line sam package command with hardcoded bucket

* fix: use existing stack name group2-englishstudy-chatting

* fix: add missing WEBSOCKET_ENDPOINT env var to WebSocket connect functions

* docs: update FRONTEND-API-GUIDE with new RoomType/RoomStatus structure

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: update WebSocketDisconnectHandler to use GameSession model

- Remove references to deleted ChatRoom game fields
- Use GameSessionRepository to finish active game sessions
- Use ChatRoomRepository.updateStatus() for room state management

* perf: optimize CI/CD build time

- Add pip cache for SAM CLI dependencies
- Enable Gradle parallel builds and build cache
- Add SAM build cache (.aws-sam)
- Use sam build --parallel --cached
- Skip SAM CLI install if already cached
- Remove unnecessary 'clean' to leverage cache

* feat: add custom CodeBuild Docker image with pre-installed tools

- Dockerfile with Java 21 + SAM CLI + Gradle pre-installed
- build-and-push.sh script for ECR deployment
- Updated buildspec.yml for custom image (removes SAM CLI install)
- Expected build time reduction: ~30-40 seconds

* feature : AI 영어 회화 연습 기능 (#468)

* feat : WebSocket Connect, Disconnect 핸들러 & SpeakingConnecion 모델 구현

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

* feat : WebSocket 연결 정보 Repository 구현

* fix: remove typo in SpeakingConnectionRepository

* fix : 오타 수정

* chore: trigger build test with custom Docker image

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* chore: remove unnecessary newlines and whitespace across WebSocket handlers and related classes

* refactor : websocket -> rest api 전환

* feat : speaking handler REST로 교체

* feat : speaking 관련 dto 생성

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

* fix: add CORS headers to API Gateway error responses (#479)

API Gateway의 인증 실패 등 에러 응답에 CORS 헤더가 누락되어
CloudFront를 통한 프론트엔드 요청이 차단되는 문제 수정

- UNAUTHORIZED (401) 응답에 CORS 헤더 추가
- ACCESS_DENIED (403) 응답에 CORS 헤더 추가
- DEFAULT_4XX/5XX 응답에 CORS 헤더 추가
- EXPIRED_TOKEN 응답에 CORS 헤더 추가

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

---------

Co-authored-by: ddingjoo <ddingsha9@teambind.co.kr>

* refactor : speaking service 재사용

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

* feature : test 벡엔드 서버에 AI 말하기 연습 기능 배포 (#492)

* 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 영어 회화 연습 코드 리팩토링

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

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

* feature : handleChat 메서드 JsonNull 체크 추가 (#493)

* 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 체크 푸가

---------

Co-authored-by: DDING JOO <ddingsha9@teambind.co.kr>

* feat(news): 뉴스 학습 배지 시스템 구현 (#473)

- 14개 뉴스 관련 배지 추가 (읽기, 퀴즈, 단어수집, 연속학습, 마스터)
- UserStats에 뉴스 통계 필드 추가
- 6개 뉴스 배지 Strategy 클래스 생성
- 뉴스 읽기/퀴즈/단어수집 시 통계 업데이트 및 배지 체크 연동

* fix: add PATCH method to CORS AllowMethods

* test: BadgeType 개수 테스트 수정 (15 -> 29)

* fix: CORS PATCH 메서드 추가

* docs: 뉴스 기능 프론트엔드 연동 가이드 작성

* fix: NewsCollectionFunction에 Bedrock, Comprehend 권한 추가

* fix: add null check for collectWord request body

- Add INVALID_REQUEST error code to NewsErrorCode
- Check body and word field before accessing in collectWord()
- Prevents NullPointerException when request body is malformed

* feat: enhance stats API and bookmark response for frontend

- 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.)

* feat: add category classification to news AI analysis

- 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

* fix: add /stats/dashboard endpoint to template.yaml

* fix: filter by ARTICLE# prefix in findById to avoid returning UserNewsRecord

* docs: add News API troubleshooting guide

* feat: add Cognito authorizer to News API and enhance keyword extraction

- 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

* Revert "Merge branch 'test' into prod"

This reverts commit c1a958eac6799d5838a76e4078ae304bcdb62278, reversing
changes made to a6662e0cfc46c6e12f20a89f0df285ff282160bc.

* feat: enhance bookmark and reading status tracking for News API

- 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

* refactor : session_id가 null 체크 추가

* fix : sessionId NullPointerException 에러 수정  (#496)

* 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>

* feat: enhance bookmark and reading status tracking for News API

- 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: add category filtering to UserWord API with enhanced query logic

- 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

* feat: add default value for ExistingCognitoClientId in template.yaml

- Set default to an empty string to ensure compatibility with templates using this parameter without explicitly specifying a value.

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: SpeakingHandler getStringOrNull 컴파일 에러 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* fix: Bedrock 키워드(meaningKo 포함)를 article에 저장하도록 수정

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* feat: add dashboard stats API and enhance news stats tracking

- 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

* refactor: format code with consistent indentation and spacing

- Apply consistent formatting to improve code readability across multiple files
- Adjust indentation, spacing, and alignment in model classes, DTOs, and repository methods

* fix: filter by ARTICLE# prefix in findById to avoid returning bookmark records

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feature : Speaking Table & Function template.yaml 파일에 추가 (#513)

* fix: BadgeRepository 클라이언트 초기화 패턴 통일

- 개별 DynamoDbEnhancedClient 생성 대신 AwsClients.dynamoDbEnhanced() 싱글톤 사용
- 다른 Repository들과 동일한 패턴 적용
- 불필요한 import 제거

Closes #396

* feat: EnvConfig 유틸리티 추가 및 환경 변수 검증 적용

환경 변수 미설정 시 명확한 에러 메시지를 제공하는 EnvConfig 유틸리티를 추가하고,
기존 System.getenv 호출을 EnvConfig.getRequired/getOrDefault로 대체함.

- EnvConfig: getRequired, getOrDefault, getIntOrDefault, getLongOrDefault 메서드 제공
- Lambda Cold Start 시점에 환경 변수 누락을 조기 감지
- 기존 Config 클래스(WebSocketConfig, RoomTokenConfig) EnvConfig 사용으로 통일

Closes #403

* refactor: TestService submitTest 메서드 책임 분리

submitTest 메서드를 단일 책임 원칙에 맞게 리팩토링:
- gradeAnswers(): 답안 채점 및 결과 집계
- isAnswerCorrect(): 단일 답안 정답 여부 판단
- buildResultItem(): 결과 항목 생성
- saveTestResult(): 테스트 결과 저장
- GradingResult record: 채점 결과 캡슐화

TestService와 TestCommandService 모두 동일하게 적용

Closes #404

* refactor: 하드코딩된 설정값 환경 변수로 외부화

각 도메인별 Config 클래스를 생성하여 하드코딩된 값들을 환경 변수로 설정 가능하게 변경.
기본값이 있어 환경 변수 미설정 시에도 기존 동작 유지.

## 새로 추가된 Config 클래스
- GrammarConfig: SESSION_TTL_DAYS, MAX_HISTORY_MESSAGES, MAX_TOKENS 등
- GameConfig: TOTAL_ROUNDS, ROUND_TIME_LIMIT, QUICK_GUESS_THRESHOLD_MS
- VocabularyConfig: NEW_WORDS_COUNT, REVIEW_WORDS_COUNT, 상태 전이 임계값 등

## 지원하는 환경 변수
- GRAMMAR_SESSION_TTL_DAYS, GRAMMAR_MAX_HISTORY_MESSAGES, GRAMMAR_MAX_TOKENS
- GAME_TOTAL_ROUNDS, GAME_ROUND_TIME_LIMIT, GAME_QUICK_GUESS_THRESHOLD_MS
- VOCAB_NEW_WORDS_COUNT, VOCAB_REVIEW_WORDS_COUNT
- VOCAB_TRANSITION_TO_REVIEWING, VOCAB_TRANSITION_TO_MASTERED

Closes #406

* test: StudyLevel enum 단위 테스트 추가

* test: Difficulty enum 단위 테스트 추가

* test: StudyConfig 단위 테스트 추가

* test: EnvConfig 단위 테스트 추가

* test: PaginatedResult 단위 테스트 추가

* test: JsonUtil 단위 테스트 추가

* test: CursorUtil 단위 테스트 추가

* test: CommonErrorCode 단위 테스트 추가

* test: CommonException 단위 테스트 추가

* test: BadgeType enum 단위 테스트 추가

* test: BadgeKey 상수 단위 테스트 추가

* test: WordStatus enum 단위 테스트 추가

* test: TestType enum 단위 테스트 추가

* test: VocabularyConfig 단위 테스트 추가

* test: VocabKey 상수 단위 테스트 추가

* test: VocabularyErrorCode 단위 테스트 추가

* test: VocabularyException 단위 테스트 추가

* test: SpacedRepetitionContext 단위 테스트 추가

* test: GrammarLevel enum 단위 테스트 추가

* test: GrammarConfig 단위 테스트 추가

* test: GrammarErrorCode 단위 테스트 추가

* test: GrammarException 단위 테스트 추가

* test: GameStatus enum 단위 테스트 추가

* test: GameConfig 단위 테스트 추가

* test: ChattingErrorCode 단위 테스트 추가

* test: ChattingException 단위 테스트 추가

* fix: OPIc FeedbackResponse.java 문법 오류 수정

* style: AwsClients 코드 포맷팅

* style: EnvConfig 코드 포맷팅

* style: RoomTokenConfig 코드 포맷팅

* style: WebSocketConfig 코드 포맷팅

* style: JsonUtil 코드 포맷팅

* style: GameConfig 코드 포맷팅

* style: GrammarConfig 코드 포맷팅

* style: GrammarKey 코드 포맷팅

* style: GrammarErrorCode 코드 포맷팅

* style: GrammarException 코드 포맷팅

* style: BedrockGrammarCheckFactory 코드 포맷팅

* style: GrammarConversationService 코드 포맷팅

* style: FeedbackResponse 코드 포맷팅

* style: SessionReportResponse 코드 포맷팅

* style: SpeakingError 코드 포맷팅

* style: SpeakingErrorType 코드 포맷팅

* style: OPIcException 코드 포맷팅

* style: OPIcAnswer 코드 포맷팅

* style: OPIcQuestion 코드 포맷팅

* style: OPIcSession 코드 포맷팅

* style: OPIcRepository 코드 포맷팅

* style: FeedbackService 코드 포맷팅

* style: TranscribeProxyService 코드 포맷팅

* style: VocabularyConfig 코드 포맷팅

* style: DailyStudyCommandService 코드 포맷팅

* style: TestCommandService 코드 포맷팅

* style: TestService 코드 포맷팅

* style: CommonErrorCodeSpec 코드 포맷팅

* style: JsonUtilSpec 코드 포맷팅

* style: BadgeTypeSpec 코드 포맷팅

* style: ChattingErrorCodeSpec 코드 포맷팅

* style: GrammarLevelSpec 코드 포맷팅

* style: GrammarErrorCodeSpec 코드 포맷팅

* style: VocabularyErrorCodeSpec 코드 포맷팅

* feature : OPIc 세션관리 + 답변 처리 파이프라인 구현  (#413)

* feat : OPIc 질문 & 세션 관련 dto 생성

* refactor : @DynamoDbBean 주석 추가

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

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

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

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

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

* refactor : S3 Key 대신 Proxy에서 요청하는 Base64 값으로 변환

* feat: GAME_START, ROUND_END 메시지에 serverTime 추가

- broadcastGameStart(): serverTime, roundDuration 필드 추가
- broadcastRoundEnd(): serverTime, roundStartTime, roundDuration 필드 추가
- GameService.endRound(): data에 roundStartTime, roundDuration 포함
- 타이머 동기화 버그 수정을 위한 서버 시간 제공

* feat: WebSocketMessageHelper 유틸리티 클래스 추가

- domain 필드 포함 메시지 생성 헬퍼
- DOMAIN_CHAT, DOMAIN_GAME 상수 정의
- buildChatMessage(), buildGameMessage() 메서드

* feat: 모든 WebSocket 메시지에 domain 필드 추가

- ScoreUpdateMessage에 domain 필드 추가
- broadcastGameStart에 domain:"game" 추가
- broadcastRoundEnd에 domain:"game" 추가
- broadcastCorrectAnswerMessage에 domain:"game" 추가
- handleCommandResult 시스템 메시지에 domain:"game" 추가
- handleRegularMessage 채팅 메시지에 domain:"chat" 추가

Closes #426, #427

* feat: GameSession 모델 클래스 생성

- DynamoDB Enhanced Client 어노테이션 적용
- GSI1: roomId로 활성 게임 세션 조회 가능
- 게임 상태 관리용 헬퍼 메서드 포함

Closes #428

* feat: GameSessionRepository 구현

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

Closes #429

* refactor: ChatRoom에서 게임 필드 분리

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

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

Closes #430

* refactor: GameSession 기반으로 전체 게임 로직 리팩토링

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

Closes #431

* feat: GameSessionHandler Lambda 및 게임 세션 API 구현

- POST /rooms/{roomId}/games - 게임 세션 생성
- GET /games/{gameSessionId} - 게임 상태 조회 (재접속용)
- POST /games/{gameSessionId}/start - 게임 시작
- POST /games/{gameSessionId}/stop - 게임 종료

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

Closes #432, #433

* feat: 게임 시작 7분 후 자동 종료 기능 구현

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

Closes #417

* fix : 메모리 증가 및 Lambda 응답 제한 시간 Cognito 트리거 제한시간과 동일하게 수정 (#439)

* feat: 캐치마인드 게임 방 분리 기능 구현 (#455)

- 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

* feat: 참가자 닉네임 및 방장 변경 WebSocket 알림 구현 (#456)

- RoomParticipant DTO 추가 (userId, nickname, isHost)
- ChatRoomQueryService에 닉네임 조회 메서드 추가
  - getParticipantsWithNicknames(): 참가자 목록 + 닉네임
  - getHostNickname(): 방장 닉네임 조회
- ChatRoomHandler.getRoom() 응답에 participants, hostNickname 추가
- ChatRoomCommandService.leaveRoom()에서 방장 변경 시 WebSocket 브로드캐스트

Related: #440

* fix: ChatRoomFunction에 UserTable DynamoDB 권한 추가

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

Fixes #457

* fix: GameSettings에 @DynamoDbBean 어노테이션 추가

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

Fixes #457

* fix: ChatRoomFunction에 WEBSOCKET_ENDPOINT 환경변수 및 권한 추가

- leaveRoom에서 WebSocketBroadcaster 사…
@github-actions github-actions Bot added backend Backend code changes layer:entity Entity/Domain layer layer:repository Repository/DAO layer labels Jan 26, 2026
@hye-inA hye-inA changed the title refactor : refactor : OPIc 질문 조회 로직 구조 변경 및 질문 데이터 추가 Jan 26, 2026
@hye-inA hye-inA merged commit e5e043b into test Jan 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Backend code changes layer:entity Entity/Domain layer layer:repository Repository/DAO layer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant