Skip to content

삭제한 세션이 통계·점수 추이에 계속 잡히던 문제 - #196

Merged
i3months merged 1 commit into
devfrom
fix/stats-exclude-deleted-sessions
Aug 20, 2026
Merged

삭제한 세션이 통계·점수 추이에 계속 잡히던 문제#196
i3months merged 1 commit into
devfrom
fix/stats-exclude-deleted-sessions

Conversation

@i3months

Copy link
Copy Markdown
Member

문제

UserStatsService.forUser 는 한 응답 안에서 두 종류의 숫자를 만든다.

항목 삭제 세션 제외?
총 세션 수 / 완료 수 countByUser_IdAndDeletedFalse
평균 점수 4종
최근 점수 추이 10건

SessionFeedbackRepository 의 5개 쿼리 어디에도 deleted 필터가 없었다.

결과 1 — 같은 화면 안에서 숫자가 어긋난다. 기록을 지우면 "완료 3회"라고 쓰여 있는데 추이 그래프엔 점이 5개 찍힌다.

결과 2 — 삭제가 삭제가 아니다. 사용자가 '기록 삭제'로 기대하는 것은 그 세션이 통계에서도 사라지는 것이다.

이건 프로젝트가 이미 세운 원칙이기도 하다:

  • getByToken — 세션이 삭제되면 공유 토큰이 남아 있어도 404. 주석에 그대로 적혀 있다: "사용자가 '기록 삭제'로 기대하는 것은 공유 링크까지의 소멸이다"
  • InterviewMessageRepositorym.session.deleted = false 로 거른다

통계 쿼리만 그 원칙에서 빠져 있었다. 설계 판단이 아니라 누락이다.

수정

5개 쿼리(평균 4 + findRecentByOwner)에 필터 추가:

WHERE f.session.user.id = :userId
  AND f.deleted = false
  AND f.session.deleted = false

findSharedByOwner일부러 그대로 뒀다. 회원 탈퇴 시 공유 토큰을 회수(UserDeletionShareRevokeListener)하는 용도라, 삭제된 세션의 토큰도 같이 회수해야 한다. 여기에 필터를 넣으면 탈퇴해도 살아있는 공유 링크가 남는다.

검증 — 그리고 이 PR 에 자동 테스트가 없는 이유

이 저장소에는 DB 를 타는 테스트가 하나도 없다. application-test.yml 이 DataSource·Hibernate·Flyway 오토컨피그를 명시적으로 제외하고, 모든 @SpringBootTest 는 리포지토리를 @MockitoBean 으로 대체한다. @DataJpaTest 는 의존성에 아예 없다. 즉 코드베이스의 모든 @Query JPQL 이 자동 검증 대상 밖이다.

그래서 로컬 Postgres(docker compose up -d postgres)에 임시 통합 테스트를 붙여 직접 확인했다:

  • 수정 후: 삭제한 세션이 findRecentByOwner 와 평균 4종 모두에서 빠진다 — 통과
  • 수정 전(리포지토리만 되돌림): Expected size: 1 but was: 2 — 삭제한 세션의 피드백이 그대로 조회됨
  • 컨텍스트가 뜨고 리포지토리 빈이 생성됐다는 것 자체가 JPQL 파싱 검증이기도 하다

CI 백엔드 잡에 Postgres 가 없어 이 테스트를 그대로 옮길 수 없어 제거했다. 백엔드 전체 스위트는 통과한다.

후속 제안 (별도 PR — 팀 결정 사항)

backend/.../CLAUDE.md §8 은 Repository 테스트를 @DataJpaTest + Testcontainer PG 로 규정하고 있는데 그 인프라가 없다. 도입하면 이번 같은 쿼리 결함이 CI 에서 잡힌다. 다만 모든 PR 의 CI 시간에 영향을 주므로 여기 끼워 넣지 않았다. 이번에 쓴 검증 테스트를 시드로 쓸 수 있다.

UserStatsService 의 총/완료 세션 수는 countByUser_IdAndDeletedFalse 로 삭제
세션을 빼는데, 같은 응답의 평균 점수 4종과 최근 점수 추이는 필터가 없었다.
그래서 기록을 지우면 "완료 3회"인데 추이 그래프엔 점이 5개 찍히는 식으로
같은 화면 안에서 숫자가 어긋난다.

무엇보다 사용자가 '기록 삭제'로 기대하는 것은 그 세션이 통계에서도 사라지는
것이다. 이 원칙은 이미 코드에 있다 — getByToken 은 세션이 삭제되면 공유 토큰이
남아 있어도 404 를 준다("'기록 삭제'로 기대하는 것은 공유 링크까지의 소멸").
InterviewMessageRepository 도 m.session.deleted = false 로 거른다. 통계 쿼리만
그 원칙에서 빠져 있었다.

5개 쿼리(평균 4 + 최근 목록)에 f.deleted / f.session.deleted 필터를 추가했다.
findSharedByOwner 는 일부러 두었다 — 회원 탈퇴 시 공유 토큰을 회수하는 용도라
삭제된 세션의 토큰도 같이 회수해야 한다.

실 DB(로컬 Postgres) 로 수정 전/후를 확인했다. 수정 전에는 삭제한 세션의
피드백이 그대로 조회된다(Expected size: 1 but was: 2).
@i3months
i3months merged commit 3adc50d into dev Aug 20, 2026
5 checks passed
@i3months
i3months deleted the fix/stats-exclude-deleted-sessions branch August 20, 2026 15:52
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