Skip to content

MSG-235 feat: 팝업 미션 적재 — 팝가 시드·type POPUP 신설·주 1회 수동 갱신 - #89

Merged
Ss0Mae merged 10 commits into
developfrom
feature/MSG-235-popup-seed
Jul 31, 2026
Merged

MSG-235 feat: 팝업 미션 적재 — 팝가 시드·type POPUP 신설·주 1회 수동 갱신#89
Ss0Mae merged 10 commits into
developfrom
feature/MSG-235-popup-seed

Conversation

@Ss0Mae

@Ss0Mae Ss0Mae commented Jul 31, 2026

Copy link
Copy Markdown
Member

🎫 관련 티켓

  • Closes MSG-235
  • PRD: docs/prd/MSG-235-prd.md (검토됨) / 스펙: docs/MSG-235.md

작업 내용

  • 팝가 수집본(전국 2,593건 검증 완료 스냅샷)의 진행 중·예정 팝업 343건을 미션으로 적재하는 시더를 만들었다. 초기 시드와 주 1회 수동 갱신이 같은 러너 하나로 돈다. 이걸로 미션 3종 축(축제·코스·팝업)이 완결된다.
  • 미션 유형 POPUP을 신설했다(성민 확정). 지도 홈 확정안이 축제와 팝업을 별도 칩으로 두는데 둘 다 EVENT면 FE가 구분을 못 해서다. V14가 CHECK를 확장하고, 조회는 case EVENT, POPUP -> BOX 한 줄, 판정 엔진은 유형 무관 단일 쿼리라 0줄 수정이다.
  • 멱등 키는 팝가 id다. missions에 외부 id 자리가 없어 V14에 source_key 컬럼과 (source, source_key) 부분 유니크 인덱스를 함께 넣었다. 앱 dedupe가 뚫려도 DB가 막는다.
  • 갱신은 정리를 적재보다 먼저 한다. 축제와 반대 순서인데, 팝업 키는 id뿐이라 연장된 팝업이 적재부터 하면 skip된 채 구 행이 지워져 다음 주까지 노출 공백이 난다. 정리부터 하면 같은 실행에서 새 날짜로 재적재된다.
  • 종료 정리 쿼리는 :source 파라미터로 일반화해 축제 것을 흡수했다(동일 SQL 2벌 방지). 축제 시더·테스트는 호출부만 전환했고 assertion은 그대로라 회귀 검증력이 산다.
  • reader는 코스의 전량 거부 계약을 승계했다. 산출물의 periodType은 읽지도 않는다. 주 1회 갱신이면 최대 7일 낡는데 날짜는 안 낡아서, openDate/closeDate로 직접 판정한다.
  • 테스트 신규 34건(reader 11, 러너 통합 12, shape 11), 전체 767건 green (축제 회귀 31건 포함).

🤔 고민한 내용

  • 통합 테스트 격리를 축제식 남반구 합성 좌표로 못 했다. 이번 reader가 좌표 한국 범위를 검증해서 남반구가 파싱 단계에서 거부된다. 한국 범위 좌표 + nanoTime 합성 source_key로 격리 책임을 좌표에서 키로 옮겼고, 정리·멱등이 전부 source 한정이라 실데이터와 경합이 없다.
  • 스탬프 걸린 채 종료됐다가 연장되는 팝업은 정리가 못 지우고(스탬프 보호) 적재가 skip해서 낡은 날짜로 숨는다. 삼중 교집합의 희귀 사례라 수용했고, 주 1회 수동 실행이라 운영자 눈으로 걸린다. 스펙 D3에 수용 근거를 남겼다.
  • 검증 위반 롤백 테스트는 축제식 TransactionTemplate 대신 "검증이 정리·적재보다 먼저라 DB 변이가 0"을 단언하는 쪽으로 했다. 리뷰어 판정: 순서 회귀를 실제로 잡는 테스트고, 무변경 검증으로는 축제식보다 강하다.

👀 리뷰 포인트

  • V14의 CHECK 재생성(기존 5종 + POPUP 6종 정확 일치)과 부분 유니크 인덱스 WHERE 절 — 마이그레이션이라 되돌리기 비싸다.
  • 정리 쿼리 파라미터화가 축제 경로에 회귀를 안 만드는지 — 축제 통합 테스트 전건 green으로 확인했지만 diff로 한 번 더 봐주면 좋다.
  • 검증 경로: 상주 리뷰어 체크리스트 A~I 위반 0건, Codex 교차 리뷰 1라운드 지적 0건 수렴.
  • 실적재는 운영 절차(스펙 D8)로 별도 진행한다 — 산출물 복사 + 플래그 on 기동.

@claude

claude Bot commented Jul 31, 2026

Copy link
Copy Markdown

Claude finished @Ss0Mae's task in 3m 24s —— View job


PR 리뷰 완료

  • 컨텍스트 수집 (rules, diff, 변경 파일)
  • 요청 파악 (PR 리뷰 요청, 한국어)
  • 컨벤션 위반 검토
  • Owner A/B 도메인 경계 검토
  • 버그·엣지케이스 검토
  • 테스트 커버리지 검토
  • 리뷰 코멘트 작성

전체적으로 설계 문서(D3·D4)와 구현·테스트가 잘 맞물려 있고, 정리→적재 순서 반전 근거나 부분 유니크 인덱스 백스톱 등 의도가 코드 주석에 잘 남아 있습니다. 아래 2건만 짚습니다.

1. MissionSchemaMigrationTest가 V14(POPUP 6종)로 갱신되지 않음

src/test/java/com/msg/fillmap/mission/MissionSchemaMigrationTest.java:102-115

@DisplayName("type이_5종_외_값이면_chk_missions_type_위반으로_INSERT가_실패한다")
void type이_5종_외_값이면_chk_missions_type_위반으로_INSERT가_실패한다() { ... }

@DisplayName("코스_5종_전부는_INSERT된다")
void 코스_5종_전부는_INSERT된다() {
	for (String type : List.of("COURSE", "AREA", "EVENT", "THEME", "CONTINUOUS")) {
		assertThat(insertMinimalMission(type)).isPositive();
	}
}

PR 설명의 "리뷰 포인트"에서 직접 "V14의 CHECK 재생성(기존 5종 + POPUP 6종 정확 일치)"을 되돌리기 비싼 변경으로 짚었는데, 정작 chk_missions_type 자체를 검증하는 이 스키마 테스트는 여전히 5종 기준입니다. List.of(...)"POPUP"이 빠져 있고 @DisplayName도 "5종"으로 남아 있어, CHECK 제약이 실수로 POPUP을 누락한 채 재생성돼도 이 테스트만으로는 못 잡습니다. PopupMissionSeederIntegrationTest가 POPUP INSERT 성공을 간접 겸증하긴 하지만, CHECK 제약 자체의 전종 목록 검증은 이 파일이 정본이므로 POPUP을 리스트에 추가하고 @DisplayName을 6종으로 갱신하는 게 맞아 보입니다.

Fix this →

2. status.md의 "없는 것" 목록이 이번 커밋으로 모순됨

.claude/docs/status.md:49-51

49번 줄에 이번 PR이 추가한 - MSG-235: 팝업 미션 적재(...) 항목이 있는데, 바로 다음 51번 줄은 그대로 - **없는 것**: 팝업 시드(MSG-235). 축제·코스 실적재는...로 남아 있어 "구현했다"와 "없다"가 한 화면에 공존합니다. MSG-224·225가 각각 구현되면서 "없는 것" 목록에서 빠진 선례와 비교하면, 이번엔 팝업 시드(MSG-235) 문구를 "없는 것"에서 제거(또는 "실적재는 운영 절차"로만 남기기)하는 걸 빠뜨린 것으로 보입니다. status.md는 CLAUDE.md가 "구현 현황 중 먼저 확인"하라고 명시한 문서라 정확도가 중요합니다.

확인한 항목 (문제 없음)

  • 도메인 경계: 신규 코드는 전부 com.msg.fillmap.mission.*(Owner B) 안에 있고, GridEncoder(Owner A) 사용은 FestivalMissionSeeder와 동일한 기존 패턴을 재사용한 것 — 새로운 경계 침범 아님.
  • **정리→적재 순서 반전(D4)**과 정리 쿼리 파라미터화(deleteEndedFestivalsWithoutStampsdeleteEndedBySourceWithoutStamps(:source)): 축제 쪽 콜사이트·테스트가 assertion 변경 없이 시그니처만 전환됐고, 회귀 테스트가 그대로 통과하는 구조라 축제 경로 회귀 위험은 낮아 보입니다.
  • 멱등 키(source_key) 및 부분 유니크 인덱스: 엔티티·마이그레이션·통합 테스트(같은_source와_source_key_중복_INSERT는_DB가_거부한다 등)가 서로 일치합니다.
  • reader 전량 거부 계약: 좌표·날짜·id 정수·중복 등 케이스별 테스트가 촘촘합니다.
  • 응답 패턴/컨벤션: 컨트롤러 변경 없음(DTO allowableValues만 갱신), 기존 ApiResponseDto 패턴에 영향 없음. import 순서·들여쓰기 등 스타일은 기존 파일과 일관됩니다.

@github-actions

Copy link
Copy Markdown

테스트 커버리지

Overall Project 91.92% -0.48% 🍏
Files changed 90.6% 🍏

File Coverage
MissionType.java 100% 🍏
Mission.java 100% 🍏
MissionResponseDto.java 100% 🍏
PopupRecord.java 100% 🍏
MissionQueryServiceImpl.java 98.46% 🍏
PopupJsonlReader.java 98.18% -1.82% 🍏
FestivalMissionSeeder.java 86.54% 🍏
PopupMissionSeeder.java 80.17% -19.83% 🍏

@github-actions

Copy link
Copy Markdown

테스트 커버리지

Overall Project 91.92% -0.48% 🍏
Files changed 90.6% 🍏

File Coverage
MissionType.java 100% 🍏
Mission.java 100% 🍏
MissionResponseDto.java 100% 🍏
PopupRecord.java 100% 🍏
MissionQueryServiceImpl.java 98.46% 🍏
PopupJsonlReader.java 98.18% -1.82% 🍏
FestivalMissionSeeder.java 86.54% 🍏
PopupMissionSeeder.java 80.17% -19.83% 🍏

@Ss0Mae
Ss0Mae merged commit a0b44e0 into develop Jul 31, 2026
1 check passed
@Ss0Mae Ss0Mae self-assigned this Jul 31, 2026
@Ss0Mae Ss0Mae added the feat 기능 추가 (MSG-XXX feat:) label Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 기능 추가 (MSG-XXX feat:)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant