리포지토리 쿼리를 실제 PG 컨테이너로 검증하는 테스트 슬라이스 도입 - #197
Merged
Merged
Conversation
기본 테스트 프로파일은 DataSource·Hibernate·Flyway 오토컨피그를 제외하고 모든 리포지토리를 @MockitoBean 으로 대체한다. 그래서 지금까지 코드베이스의 어떤 @query JPQL 도 자동 검증을 받은 적이 없다 — 문법 오류는 물론이고 "삭제된 행을 안 걸렀다" 같은 의미 결함도 CI 를 그대로 통과했다(#196 이 그랬다). @PostgresRepositoryTest 를 붙이면 실제 pgvector 컨테이너에서 돈다: - 스키마는 운영과 같은 Flyway 마이그레이션 + ddl-auto=validate → 엔티티 매핑과 마이그레이션 불일치도 컨텍스트 로딩에서 잡힌다 - 컨테이너는 JVM 당 하나 (테스트가 늘어도 기동 비용은 한 번) - @DataJpaTest 라 테스트마다 롤백 첫 사용처로 #196 에서 로컬 PG 로 수동 검증했던 케이스를 그대로 옮겼다. 필터를 되돌리면 실패하는 것을 확인했다(Expected size: 1 but was: 2). findSharedByOwner 는 삭제 세션을 포함해야 한다는 반대 방향 계약도 함께 고정한다 (탈퇴 시 토큰 회수용이라 여기 필터를 넣으면 살아있는 공유 링크가 남는다). Testcontainers 의존성은 이미 build.gradle 에 선언돼 있었고 쓰이지 않았다. junit-jupiter, spring-boot-testcontainers, spring-boot-data-jpa-test 만 추가.
This was referenced Aug 21, 2026
Merged
i3months
added a commit
to i3months/stackup
that referenced
this pull request
Aug 28, 2026
deleteAccount 는 soft delete 만 하고 encrypted_github_access_token 을 그대로 남겼다. 이 토큰은 `repo` 스코프로 발급된다 — 비공개 레포까지 읽을 수 있는 살아있는 자격증명이다. hard delete 는 Phase 2 라 실제로는 무기한 남는다. DB 가 유출되면 이미 떠난 사용자들의 비공개 레포까지 열린다. User.withdraw() 가 soft delete 와 토큰 폐기를 함께 한다. hasGithubLink() 가 이미 토큰 유무로 판정하므로, 지운 뒤 GitHub 연동 기능을 타면 NPE 가 아니라 AUTH_GITHUB_NOT_LINKED 로 떨어진다. V22 의 ck_users_provider_identity 가 provider='GITHUB' 인 모든 행에 토큰 NOT NULL 을 요구해 UPDATE 가 거부된다. 제약의 의도는 "살아있는 계정은 provider 에 맞는 식별자를 갖춰야 한다" 이므로 V28 로 삭제된 행을 예외로 둔다 — 유니크 인덱스들(V3·V22)이 이미 `WHERE is_deleted = FALSE` 로 쓰는 규약이다. GitHub 쪽 grant 무효화는 여전히 사용자 몫이다. 우리가 할 수 있는 건 사본을 갖지 않는 것까지다. 테스트는 Team-StackUp#197 의 @PostgresRepositoryTest 로 실제 DB 까지 내려간다. V28 을 빼면 CHECK 제약 위반으로 실패하는 것을 확인했다 — 목 기반 테스트로는 잡을 수 없는 종류다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
왜
#196 을 고치면서 드러난 구조적 공백이다.
기본 테스트 프로파일(
application-test.yml)은 DataSource·Hibernate·Flyway 오토컨피그를 명시적으로 제외하고, 모든@SpringBootTest가 리포지토리를@MockitoBean으로 대체한다.@DataJpaTest는 의존성에 아예 없었다.그 결과 코드베이스의 어떤
@QueryJPQL 도 자동 검증을 받은 적이 없다. 문법 오류는 물론이고 "삭제된 행을 안 걸렀다" 같은 의미 결함도 CI 를 그대로 통과한다 — #196 의 통계 쿼리 5개가 정확히 그랬고, 로컬에 PG 를 띄워 수동으로 확인해야 했다.무엇
@PostgresRepositoryTest를 붙이면 실제 pgvector 컨테이너에서 돈다.pgvector/pgvector:pg17infra/postgres/Dockerfile과 동일. 마이그레이션이 vector 타입·인덱스를 쓴다NULLS LAST)이 검증 밖으로 빠진다ddl-auto: validate유지@DataJpaTestTestcontainers 의존성은 이미
build.gradle에 선언돼 있었고 한 번도 쓰이지 않았다. 추가한 건junit-jupiter,spring-boot-testcontainers,spring-boot-data-jpa-test세 개뿐이다.첫 사용처
#196 에서 로컬 PG 로 수동 검증했던 케이스를 그대로 옮겼다.
statsQueriesExcludeDeletedSessions— 삭제한 세션이 최근 목록·평균 4종에서 빠진다. 필터를 되돌리면 실패하는 것을 확인했다 (Expected size: 1 but was: 2)findSharedByOwnerIncludesDeletedSessions— 반대 방향 계약을 고정한다. 이 쿼리는 탈퇴 시 공유 토큰 회수용이라 삭제된 세션도 포함해야 한다. 여기에 "일관성" 명목으로 필터를 넣으면 탈퇴해도 살아있는 공유 링크가 남는다지우기 전 상태(2건)도 함께 단언한다 — 필터가 "아무것도 안 거르는" 상태와 구분되도록.
비용
CI 백엔드 잡이 이미지 pull + 컨테이너 기동만큼 길어진다(로컬 기준 첫 실행 약 38초, 이후 캐시).
ubuntu-latest는 Docker 가 이미 있어 워크플로 변경은 없다.그래서 문서에 "쿼리 동작을 봐야 하는 테스트에만 쓰고, 서비스 로직은 계속 Mockito 단위 테스트로" 라고 명시했다. 기본값은 여전히 컨텍스트 없는 단위 테스트다.
문서
backend/CLAUDE.md §15갱신 — 테스트 종류 표에 리포지토리 항목 추가, §15.1 에 사용법·제약·운영 PG 버전 올릴 때 컨테이너 태그도 같이 올려야 한다는 점 명시.