7.3 KiB
7.3 KiB
이벤트 접속 국가별 언어 필터 구현 리뷰
1. 리뷰 정보
| 항목 | 내용 |
|---|---|
| 리뷰 대상 | Phase 1~2 전체 구현과 P1-GATE, P2-GATE |
| 기준 commit 또는 working tree | 기준 2ad30f90699a03162000d3b87be39f45b92740af + 미커밋 구현 변경 |
| 리뷰 일자 | 2026-08-20 |
| 리뷰어 | Codex, 독립 리뷰 agent event_language_review |
| 기준 문서 | prd.md, plan-task.md |
| 리뷰 상태 | 수정 검증 완료 |
2. 리뷰 목적과 범위
목적
- 구현이
EVENT-LANG-001~009와 기존 API 경계를 충족하는지 확인한다. - 완료 기록과 실제 코드·테스트 결과가 일치하는지 확인한다.
포함 범위
- 코드: 관리자 이벤트 등록·목록, 앱 이벤트 controller/service/repository,
Event,SecurityConfig - 테스트: 관리자·앱 controller 통합, service, repository, 기존 국가 판정 통합 테스트
- 문서:
prd.md,plan-task.md, 운영 DDL
제외 범위
- 운영 DB DDL 실제 실행과 배포
- 이벤트 언어와 관계없는 기능
3. 판정 기준
| 심각도 | 기준 |
|---|---|
| Blocker | 보안·데이터 손실 위험 또는 핵심 흐름 불능 |
| High | 확정 요구사항·기존 API 경계 위반 또는 주요 회귀 |
| Medium | 제한된 조건의 기능·복구 문제 |
| Low | 비핵심 유지보수성·문서 정합성 문제 |
4. 검토한 근거
문서와 코드
- 요구사항:
EVENT-LANG-001~009 - 계획:
P1-T1~P2-GATE - 코드:
AdminEventBannerController,AdminEventBannerService,AdminEventBannerRepository,EventController,EventService,EventRepository,Event,SecurityConfig - 테스트:
AdminEventBannerControllerIntegrationTest,EventControllerIntegrationTest,EventServiceTest,EventRepositoryTest,MemberContentPreferenceIntegrationTest
실행 환경
OS: Darwin 25.0.0 x86_64
Java: OpenJDK 17.0.15
Build: Gradle Wrapper 8.1.1
DB: 테스트용 H2 MySQL mode
실행한 검증
| 명령 또는 수동 검증 | 결과 | 핵심 증거 |
|---|---|---|
직접 영향 5개 클래스 cleanTest test |
성공 | 겹침 제거 후 exit code 0, 27개 테스트 통과, BUILD SUCCESSFUL in 46s |
| 독립 리뷰의 동일 5개 클래스 실행 | 성공 | exit code 0, BUILD SUCCESSFUL in 56s |
| 전체 호출자·기준 HEAD 보안 설정 diff 대조 | 발견 | 기준 HEAD의 /event/popup은 anyRequest().authenticated() 적용 |
| 수정 후 독립 정적 재리뷰 | 성공 | Critical·Important·Minor 추가 발견 없음, Ready to merge 판정 |
git diff --check HEAD |
성공 | exit code 0, whitespace 오류 없음 |
동시에 실행된 두 Gradle cleanTest가 같은 XML 결과 경로를 사용해 한 차례 writer 경합이 발생했다. 테스트 assertion은 모두 통과했고, 병행 실행을 중단한 뒤 동일 명령을 재실행해 성공 종료를 확인했다.
5. 발견 사항 요약
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|---|---|---|---|---|---|
REV-EVENT-LANG-001 |
High | 수정 완료 | GET /event/popup의 기존 인증 경계가 익명 공개로 확장됨 |
P2-T1 |
P2-R1 |
언어 저장·관리자 전체 언어 조회·앱 KO/JA QueryDSL 필터·콘텐츠 메인 null 언어 경로에서는 추가 확정 문제를 찾지 못했다.
6. 발견 사항 상세
REV-EVENT-LANG-001 — GET /event/popup의 기존 인증 경계가 익명 공개로 확장됨
- 심각도: High
- 상태: 수정 완료
- 관련 요구사항:
EVENT-LANG-005, 기존 접근 정책 유지 - 소유 Task:
P2-R1
관찰 내용
기준 HEAD의 SecurityConfig는 GET /event만 permitAll()이고, /event/popup은 마지막 anyRequest().authenticated()를 적용받는다. 수정 전 구현은 /event/popup exact matcher를 추가해 익명 요청도 허용했다. 국가별 언어 필터에는 인증 정책 변경이 필요하지 않으므로 요청 범위를 넘어선 보안 경계 확장이었다.
근거
- 기준 코드:
SecurityConfig.kt의/eventmatcher 다음에/event/popupmatcher가 없고 마지막 규칙은anyRequest().authenticated()다. - 수정 전 코드:
SecurityConfig.kt에GET /event/popuppermitAll()한 줄이 추가됐다. - 수정 전 테스트:
EventControllerIntegrationTest의 팝업 2개가 익명 200을 기대해 확장된 동작을 고정했다. - 문서:
prd.md가 두 API 모두 기존 로그인·비로그인 접근이라고 잘못 기술했다.
재현 또는 검증 절차
- 수정 전 security filter를 켠 상태로 인증 없이
GET /event/popup을 호출한다. - 수정 전 결과는 HTTP 200이다.
- 기준 HEAD의 matcher 순서에서는 HTTP 401이다.
- 요구되는 결과는 기존 인증 경계를 유지하는 HTTP 401이며, 인증 사용자의 국가별 팝업 필터는 계속 동작해야 한다.
영향
명시 승인 없이 endpoint 접근 범위가 넓어지고, PRD가 실제 기준 동작과 불일치한다.
권장 조치
SecurityConfig의 신규 matcher 한 줄을 제거한다. 통합 테스트에는 익명 팝업 401 회귀를 추가하고, JP·국가 누락 팝업 언어 테스트는 MemberAdapter 인증 사용자로 실행한다. /event의 기존 익명 접근과 언어 조회 구현은 변경하지 않는다.
판정 기록
- 2026-08-20 — 기준 HEAD·현재 diff·security-on 통합 테스트를 대조해 확정했다.
- 2026-08-20 —
P2-R1에서 exactpermitAll()을 제거하고 익명 401·인증 사용자 KO/JA 팝업과 직접 영향 28개 테스트를 통과해 수정 완료로 판정했다.
7. 확정 항목의 plan·goal 전환
REV-EVENT-LANG-001을 plan-task.md의 P2-R1 회귀 수정 Goal로 전환했다.
8. 리뷰 종료 판정
| 판정 항목 | 결과 | 근거 |
|---|---|---|
| 리뷰 범위 전체 확인 | 충족 | 문서·production diff·전체 호출자·DDL·직접 영향 테스트 확인 |
| 후보 항목 판정 완료 | 충족 | 1건 확정, 나머지 substantive issue 없음 |
| 확정 항목 plan 반영 | 충족 | P2-R1 추가 |
| 검증 명령과 결과 기록 | 충족 | 4절 기록 |
최종 결론: 수정 검증 완료
남은 항목: 없음
9. 수정 후 검증 기록
1차 수정 검증 — 2026-08-20
- 무엇을:
REV-EVENT-LANG-001의 익명 팝업 공개를 제거하고 기존 인증 경계를 복원했다. - 왜: 국가별 언어 필터와 무관한 보안 접근 범위 확장을 제거하기 위해서다.
- 어떻게:
- RED:
EventControllerIntegrationTest5개 중 익명 팝업 401만 실제 200으로 실패했고 인증 팝업·익명 목록 4개는 통과했다. - GREEN:
SecurityConfig의 exact matcher 한 줄 제거 후 controller 통합 테스트 5개가BUILD SUCCESSFUL in 38s로 통과했다. - 회귀: 직접 영향 5개 클래스 28개가 failures
0, errors0, skipped0,BUILD SUCCESSFUL in 42s로 통과했다. - 정적 검증:
ktlintCheck,tasks --all,git diff --check HEAD가 모두 성공했고 기준 HEAD 대비SecurityConfigdiff가 없다. - 독립 재리뷰: 수정 후 최종 diff와 문서를 다시 검토해 Critical·Important·Minor 모두 추가 발견 없음으로 판정했다.
- RED:
- 남은 항목: 운영 DB DDL 실제 반영은 기존 범위대로 미실행이며, 리뷰 확정 항목은 남아 있지 않다.