- Naver Sports의 highLight 엔드포인트를 통해 득점 발생 타석의 상세 데이터를 추출하는 기능을 구현했습니다.
- 단순 이닝별 점수 보강을 넘어 타석 결과, 주자 이동, 아웃 카운트 및 베이스 상태 변화를 포함한 정밀한 정보를 제공합니다.
- KBO와 네이버 간의 경기 ID 체계 차이를 자동으로 처리하며, 병렬 요청 구조로 전체 조회 성능을 최적화했습니다.
- 득점 주자의 출루 위치와 타점 발생 상황을 구조화된 데이터로 파싱하여 상세 조회 기능을 고도화했습니다.
- KBO 게임센터의 스코어보드, 박스스코어, 키플레이어 데이터를 통합 조회하는 기능을 구현했습니다.
- 경기 상태(종료, 진행 중, 시작 전)에 따라 TTL을 30초에서 7일까지 유연하게 적용하는 동적 캐싱 시스템을 도입했습니다.
- KBO 공식 데이터에서 이닝별 득점이 누락되는 경우를 대비해 네이버 스포츠 API를 통한 데이터 보완 로직을 추가했습니다.
- Firestore의 중첩 배열 저장 제한을 회피하기 위해 테이블 데이터를 객체 배열 구조로 파싱하도록 설계했습니다.
- CLI 상세 조회 명령어와 REST API 엔드포인트를 추가하고, HTML 엔티티 디코딩 및 관련 단위 테스트를 보완했습니다.
- 전체 및 팀별 스코어보드 기능을 구현하고 순위 변동 시각화를 위한 스냅샷 시스템을 도입했습니다.
- `dailyArchive` 시점에 `rankSnapshot`을 기록하여 이전 대비 순위 변화량을 정확히 산출합니다.
- 상위권 데이터를 RTDB에 사전 계산하여 저장하고 `MemCache`를 적용해 조회 성능을 최적화했습니다.
- Firestore 복합 색인과 Count Aggregation으로 동점자 처리 및 상위 퍼센타일 산출 로직을 구현했습니다.
- 주간 결과 타입을 `DailyJudgment`로 전환하여 판정 세부 상태가 통계 응답에 포함되도록 수정했습니다.
- 전체 및 팀별 스코어보드 기능을 구현하고, 순위 변동(delta)을 시각화하기 위한 스냅샷 시스템을 도입했습니다.
- `dailyArchive` 과정에서 사용자의 현재 순위를 `rankSnapshot`으로 기록하여, 다음 판정 시점의 순위 변화량을 정확히 계산합니다.
- 상위권 데이터는 RTDB에 사전 계산(precompute)하여 저장함으로써 대규모 조회 요청에 대응하고, `MemCache`를 통해 API 응답 성능을 최적화했습니다.
- Firestore 복합 색인과 Count Aggregation을 활용하여 동점자 처리가 포함된 랭킹 및 상위 퍼센타일 산출 로직을 구현했습니다.
- 관련 서비스 레이어, 저장소 함수, API 핸들러 및 단위 테스트 코드를 추가했습니다.
- `dailyArchive` 과정에 `judgeDay`를 통합하여 경기 결과에 따른 일간 판정, 스트릭 업데이트, 티어 포인트 가산을 자동화했습니다.
- 주간 모든 경기를 성공적으로 예측했을 때 '주간 마스터 티켓'을 지급하는 `judgeWeekIfNeeded` 로직을 구현했습니다.
- Firestore 트랜잭션을 사용하여 판정 결과 반영의 원자성을 확보하고, 중복 처리를 방지하는 멱등성 가드를 적용했습니다.
- `statsService`가 실시간 계산 대신 사용자 문서에 저장된 스트릭과 티어 정보를 활용하도록 고도화하고 관련 유틸리티와 테스트 코드를 추가했습니다.
- KBO 리그의 경기 일정 특성을 반영하여 주간 통계 산출 기준을 기존 ISO 주차 방식에서 화요일~월요일 주기로 변경했습니다.
- `tuesdayOf` 유틸리티를 추가하여 특정 날짜가 속한 주의 시작일(화요일)을 기준으로 주간 데이터를 판정하고 집계하도록 개선했습니다.
- 서비스 내의 모든 주요 함수에 JSDoc 주석을 추가하여 각 로직의 역할과 매개변수에 대한 상세한 설명을 보완했습니다.
- 코드 포맷팅을 정리하고 불필요한 ISO 주차 계산 로직을 제거하여 통계 산출 파이프라인을 최적화했습니다.
- `MemCache` 유틸리티 클래스를 도입하여 인메모리 캐싱 로직을 구조화하고 Promise Coalescing을 통해 동일 키에 대한 중복 fetch 요청을 방지했습니다.
- 투표 요약(`getSummary`) 정보에 5초 TTL 캐시를 적용하고, 투표 데이터 변경 시 해당 캐시를 즉시 무효화하여 데이터 정합성을 유지했습니다.
- 기존 `gameListService`에 개별적으로 구현되어 있던 수동 캐시 관리 로직을 `MemCache`로 교체하여 코드 중복을 제거했습니다.
- 투표 요약 API 응답에 `Cache-Control` 헤더를 추가하여 클라이언트 및 인프라 계층에서의 효율적인 캐싱을 지원합니다.
- 사용자 프로필 수정을 위한 `PATCH` 핸들러와 `updateMe` 서비스를 구현하여 닉네임, 응원팀, 지식 수준 변경 기능을 추가했습니다.
- HTML 정규식 파싱 오류로 인해 `null`이 반환되던 `gameId` 문제를 해결하기 위해 일정 메타데이터 기반의 ID 생성 로직을 도입했습니다.
- `updateUser`가 `FieldValue`를 수용하도록 개선하여 응원팀 설정 해제(필드 삭제)가 가능하도록 수정했습니다.
- 닉네임 중복 확인 및 변경 규칙 검증을 포함한 유저 서비스 테스트 케이스를 작성하고 `TODO.md` 이슈를 해결했습니다.
- Firestore 트리거(`onGameCompleted`)를 도입하여 경기 종료(`completed`) 및 취소(`cancelled`) 시 투표 결과 판정과 데이터 정리를 자동화했습니다.
- `dailyArchive` 과정에 자가치유(self-healing) 로직인 `reconcileDayVotes`를 추가하여, 트리거 누락이나 지연된 상태 변경 건을 아카이빙 시점에 보정합니다.
- `markGameEnded`가 직접 로직을 수행하는 대신 Firestore 문서만 업데이트하도록 변경하여, 결과 처리 흐름을 트리거로 일원화했습니다.
- 경기 일정 수집부터 통계 산출까지의 전체 투표 파이프라인과 운영 방법을 상세히 기술한 `VOTE_FLOW.md` 문서를 작성했습니다.
- 게임 리스트 조회 시 Firestore 공유 캐시 대신 인스턴스 단위 인메모리 캐시를 사용하는 기술적 근거를 상세히 기록했습니다.
- 실시간 경기 중 빈번한 데이터 변경으로 인한 Firestore 비용 부담과 레이턴시 문제를 해결하기 위한 결정임을 명시했습니다.
- 향후 트래픽 증가나 외부 API의 일시적인 503 오류 등 서비스 안정성에 영향을 줄 수 있는 상황에 대비하여, 공유 캐시로의 격상 검토안을 TODO에 추가했습니다.
- `GameStatus` 타입을 `scheduled`, `live`, `completed`, `cancelled`로 변경하여 상태 관리의 일관성을 높였습니다.
- 사용자 프로필의 `favoriteTeamCode`를 선택 사항으로 변경하고, null 또는 undefined 입력에 대한 처리를 추가했습니다.
- KBO 데이터 병합 과정에 상세 로그를 도입하여 실시간 데이터 매칭 및 외부 API 호출 실패 상황에 대한 가시성을 확보했습니다.
- 상태 값 변경에 따라 영향받는 서비스 로직과 테스트 코드를 일괄 업데이트했습니다.
- KBO 일정 조회 시 오늘 날짜의 경기에 대해 실시간 점수와 경기 상태를 병합하는 기능을 추가했습니다.
- `GameStatus` 타입에 'live'를 추가하고, 게임센터 API 데이터를 기반으로 상태를 변환하는 로직을 구현했습니다.
- 외부 API 연동 시 발생할 수 있는 일시적인 오류(503 등)에 대비하여 예외 발생 시 기존 캐시 데이터를 반환하도록 예외 처리를 적용했습니다.
- 경기 ID 또는 팀 정보와 시간을 조합한 복합 키를 사용하여 스케줄 데이터와 실시간 데이터를 정확하게 매칭합니다.
- KBO 데이터 조회 성능 최적화를 위한 3계층 캐싱 전략 및 구조를 상세히 문서화했습니다.
- Firestore 기반의 일 단위 스케줄 캐시와 경기 상태에 따른 동적 TTL 적용 로직을 명시했습니다.
- 라이브 경기 정보 조회를 위한 10초 만료 메모리 캐시와 RTDB 기반의 메트릭 수집 방식을 설명했습니다.
- 분산 락을 활용한 동시성 제어 및 매일 새벽 수행되는 캐시 무효화와 프리워밍 과정을 포함했습니다.
- KBO 일정 조회 기능에 일(day) 단위 필터링을 추가하여 API와 CLI에서 특정 날짜의 경기만 조회할 수 있도록 개선했습니다.
- 일 단위 일정 요청 시 캐시가 없으면 월간 데이터를 조회하여 캐시를 보충하는 효율적인 캐싱 전략을 도입했습니다.
- `gameListService`에 10초 TTL 기반의 메모리 캐시를 적용하여 외부 API 호출 빈도를 최적화했습니다.
- 캐시의 적중률(Hit/Miss)을 일자별로 RTDB에 기록하는 메트릭 수집 로직을 추가하여 모니터링 기반을 마련했습니다.
- KBO 게임센터 API를 연동하여 실시간 경기 데이터(선발 투수, 이닝, 스코어 등) 조회 기능을 구현했습니다.
- 경기 일정 캐시를 일 단위로 관리하도록 개선하고, 경기 상태에 따라 TTL을 동적으로 적용하는 로직을 도입했습니다.
- 일정 데이터 요청 시 선발 투수 정보를 병합하여 제공하도록 기능을 강화했습니다.
- CLI 명령과 API 엔드포인트에 실시간 경기 정보를 확인할 수 있는 경로를 추가했습니다.
- 닉네임 선점 및 검증을 위한 예약 시스템을 구현하고 관련 로직을 추가했습니다.
- 유저 데이터 및 하위 컬렉션을 완전히 삭제하는 회원 탈퇴 기능을 구현했습니다.
- 토큰의 프로필 사진 변경 시 유저 정보를 자동으로 동기화하도록 개선했습니다.
- RTDB를 활용하여 닉네임 예약 상태를 관리하고, 회원 가입 시 이를 검증하도록 변경했습니다.
- KBO 선수 기록 조회 로직을 공통화하고 투수, 수비, 주루 카테고리 추가
- CLI 명령어를 hitter에서 player <type>으로 통합 및 필터 옵션 강화
- ASP.NET AJAX 응답 파싱 방식을 개선하여 데이터 누락 문제 해결
- 정규시즌과 포스트시즌의 서로 다른 페이지 구조 및 컬럼 대응 지원