Fix: 현장 측정에서 찾은 조용한 실패 둘을 고친다 - #120
Merged
Merged
Conversation
Merged
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.
배경
이 라이브러리를 공개 프로젝트 열일곱 곳의 테스트 스위트에 실제로 붙여 봤다. 라이브러리를 뺀
대조군과 붙인 계측군을 매번 함께 돌려 차이를 봤고, 수치를 낸 표본이 다섯, 결함을 드러낸 실패가
셋이다. 측정 기록은 저장소 밖
oss-contrib/query-counter-field-test/RESULTS-2026-08-27.md에 있다.거기서 나온 결함 둘을 고친다. 둘 다 조용히 잘못되는 종류라 이 저장소가 이미 두 번 겪은 것과
같은 성질이다.
고친 것
하나. 감싼 DataSource 가 던진 예외의 타입이 바뀌었다.
Method.invoke는 대상이 던진 예외를InvocationTargetException으로 감싸는데 그것을 벗기지않았다. 그러면 선언되지 않은 체크 예외라 프록시가 다시
UndeclaredThrowableException으로감싼다. DB 설정이 깨진 프로젝트로 대조한 결과다.
SQLException→GenericJDBCExceptionSQLException→InvocationTargetException→UndeclaredThrowableExceptionInvocationTargetException: null테스트에서만 도는 라이브러리가 테스트가 받는 예외의 종류를 바꾼 것이다. 제약 위반을 검증하는
테스트라면 기대하던
DataIntegrityViolationException대신 엉뚱한 예외를 받는다. "붙였다는 이유로남의 테스트가 깨지면 안 된다" 는 첫 성질을 정면으로 어긴다.
둘. 쿼리가 0건인 테스트가 보고에서 통째로 빠졌다.
설정이 쿼리 기록 경로를 타고 테스트 경계로 오는 구조라, 쿼리가 없으면 설정도 안 와서 보고가 한
줄도 안 나왔다. 그래서 쿼리가 0건인 것과 계측이 안 붙은 것을 구별할 수 없었다. 계측이 안
붙는 문제를 #111, #112 로 고쳤는데 그것이 되살아나도 알아차릴 방법이 보고 모드에 없던 셈이다.
어느 스위트는 237개 중 88개가 침묵했다.
리스너가
hasApplicationContext()로 이미 떠 있는 것을 확인한 뒤에만 설정을 되살린다.컨텍스트 로딩을 강제하지 않는다는 제약은 그대로다. 그 조건을 지키는지 검증하는 테스트를 함께
넣었다.
검증
표본 여덟을 고치기 전후로 돌려 대조했다. 검증 자체가 변수가 되지 않도록, 고치기 전에 로컬
스냅샷으로 한 번 돌려 기준선과 같은 것을 먼저 확인했다.
침묵하던 테스트 252건이 보고에 들어왔고 N+1 판정은 한 자리도 안 바뀌었다.
라이브러리 테스트 206건과
./gradlew build(Spotless 포함) 통과.표본 이름을 가린 것은 사람이 특정되는 팀 프로젝트이기 때문이다. 거기서 나온 것은 이 라이브러리를
고치기 위한 표본이지 그 코드에 대한 지적이 아니다.
함께 넣은 문서
N+1 검사가 함께 잡는 세 가지를 README 두 벌에 적었다. 판정 기준이 "같은 SELECT 모양에 다른
파라미터 값" 이라 N+1 이 아닌데 그 모양이 되는 테스트 방식이 있다. 한 테스트에서 찾는 경우와 못
찾는 경우를 함께 확인할 때, 페이징을 다음 장으로 넘기며 확인할 때, 생성과 수정과 삭제를 차례로
할 때다. 표본 넷에서 보고된 83개 중 38개가 그랬고, 몇 개나 보이는지는 검사 대상 코드보다
스위트를 어떻게 썼는가에 훨씬 크게 좌우됐다(46개 중 4개인 스위트와 25개 전부인 스위트가 있었다).
반복 횟수로는 진짜와 가릴 수 없다는 것도 적었다.
판정 동작은 바꾸지 않았다. 억제 규칙을 세울 근거가 아직 부족하다. 표본 하나로 세운 규칙이
표본 둘에서 깨진 적이 있다.
CLAUDE.md의 낡은 서술 둘(QueryCountVerifier빚 수치, 리스너가 컨텍스트를 만질 수 없다는서술)을 고치고, 릴리스 절차 70줄을
docs/RELEASING.md로 분리했다.