Skip to content

MSG-222 feat: 활성 미션 조회 API — GET /api/missions/active (유형별 렌더 shape, 1h 캐시) - #58

Open
Ss0Mae wants to merge 5 commits into
developfrom
feature/MSG-222-missions-active
Open

MSG-222 feat: 활성 미션 조회 API — GET /api/missions/active (유형별 렌더 shape, 1h 캐시)#58
Ss0Mae wants to merge 5 commits into
developfrom
feature/MSG-222-missions-active

Conversation

@Ss0Mae

@Ss0Mae Ss0Mae commented Jul 24, 2026

Copy link
Copy Markdown
Member

🎫 관련 티켓

작업 내용

  • GET /api/missions/active — 활성 미션 전역 목록, 시드 전엔 빈 배열 200 (커밋 5개: 엔티티·리포지토리 → 서비스·DTO → 컨트롤러 → 문서 → 하네스 규칙)
  • 유형→shape 단일 분기: COURSE→PATH(missions.path 원문 + 스팟 seq순) / EVENT→BOX(mission_grids bbox 합성) / THEME·CONTINUOUS→CELLS / AREA→REGION(regionCode만)
  • active 판정: (start_at IS NULL OR start_at <= now) AND (end_at IS NULL OR now <= end_at) — 무기간 코스 상시 활성
  • 1h 전역 캐시: 단일 volatile CacheEntry + 더블체크 락 (단일 인스턴스 전제, 멀티 시 Redis 이관 주석)
  • 테스트 20건 (판정 5 · shape 9 · 캐시 2 · 컨트롤러 4), 전체 green

🤔 고민한 내용

  • shape 다형성: sealed interface + record 4종, type 필드가 판별자라 @JsonTypeInfo 불필요
  • 캐시: Spring Cache/Caffeine 인프라가 없어 수동 홀더 최소 구현 — 시간당 1회·수백 행 쿼리라 과한 스택 배제
  • REGION은 regionCode만 — boundary_geom(수백KB~MB)을 전역 캐시 응답에 싣지 않고 기존 region API에 위임
  • Codex 3라운드 수정 3건: 빈 테이블 가정 테스트 스코프화, 캐시 refresh 경쟁(더블체크 락), 스냅샷·만료 찢어진 읽기(단일 volatile). 타임존 지적은 코드베이스 관용 일관성 사유로 수용 — 시드 티켓에서 start/end_at 저장 규약 확정 (스펙 §미해결 3)

👀 리뷰 포인트

  • CONTINUOUS→CELLS 기본 매핑, 축제·팝업 BOX 통일 (기획 미확정 2건 — 스펙 §미해결 1·2, 뒤집혀도 분기 한 줄)
  • MissionQueryServiceImpl 생성자 2개 (테스트용 clock/TTL 주입 — 코드베이스 유일 @Autowired, reviewer 수용 근거는 스펙 참조)

🤖 Generated with Claude Code

@claude

claude Bot commented Jul 24, 2026

Copy link
Copy Markdown

Claude finished @Ss0Mae's task in 2m 42s —— View job


📋 MSG-222 PR 리뷰

작업 목록

  • 컨벤션 규칙(.claude/rules/) 확인
  • PR diff 및 변경 파일 분석
  • 컨벤션 위반 여부 검토
  • Owner A/B 도메인 경계 침범 여부 검토
  • 버그/누락된 테스트 검토
  • 리뷰 코멘트 작성

종합 평가

구조·테스트 커버리지 모두 탄탄합니다. MissionQueryServiceImpl의 더블체크 락 캐시(volatile CacheEntry 단일 발행으로 스냅샷+만료시각 찢어진 읽기 방지), 유형→shape 단일 분기, PATH의 @JsonRawValue passthrough 설계 모두 스펙(docs/MSG-222.md) 근거와 일치합니다. 테스트 20건(판정/shape/캐시/컨트롤러)도 경계값(무기간, 만료, 시작전, 단일격자 BOX 등)을 잘 짚었습니다.

컨벤션

  • .claude/rules/response-pattern.md, project-conventions.md 기준 위반 없음 — 컨트롤러가 SuccessResponse.of(...)만 반환, DTO 네이밍(MissionResponseDto)·import 순서·엔티티 명명 모두 준수.
  • MissionQueryServiceImpl의 생성자 2개(@Autowired + 테스트용 clock/TTL 주입)는 @RequiredArgsConstructor 원칙(project-conventions.md)과 형식상 다르지만, Clock/long ttlMillis는 애초에 Lombok @RequiredArgsConstructor로 자동 주입될 수 없는 필드라 이 예외는 타당해 보입니다. PR 설명에도 이미 리뷰 포인트로 명시돼 있어 별도 이슈 제기는 생략합니다.

Owner 경계

  • mission 패키지는 .claude/CLAUDE.md의 "협업 원칙" 표(Owner A: grid.*/region.*, Owner B: user.*/video.*/auth.*/usergrid.*)에 없는 신규 도메인입니다. status.md에는 이번 PR에서 mission (Owner B)로 명시했지만, CLAUDE.md 본문 표는 갱신되지 않았습니다 — 사소하지만 후속 PR에서 참고할 수 있게 업데이트를 권장합니다.
  • com.msg.fillmap.grid.GridEncoder 직접 import(MissionQueryServiceImpl.java:15-16)는 video/usergrid/region 서비스들도 동일하게 사용하는 기존 관례(순수 유틸이라 인터페이스 계약 밖)라 경계 침범으로 보지 않습니다.

버그 / 누락된 테스트

  • 사소한 테스트 갭: chk_missions_path 제약은 "non-COURSE는 path NULL"만 강제하고 "COURSE는 path NOT NULL"은 강제하지 않습니다. 즉 path가 NULL인 COURSE 미션이 DB에 들어올 수 있는데, pathShape()(MissionQueryServiceImpl.java:134-143)가 이 경우를 다루는 테스트가 없습니다(@JsonRawValue가 null을 그대로 null 필드로 내보내 크래시는 안 나지만, FE 계약상 의도된 동작인지 명시가 없음). 시드 티켓(MSG-224 등)에서 막힐 값이라 blocking은 아니지만, 계약 문서에 한 줄 명시하거나 방어 테스트 추가를 고려해볼 만합니다.
  • 그 외 로직·경계 조건(활성 판정 5케이스, shape 4종, 캐시 TTL 내/후, 인증 401)은 충분히 커버되어 있습니다.

전체적으로 merge에 지장을 줄 결함은 발견하지 못했습니다. 위 두 항목은 참고 수준입니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant