Skip to content

Fix: 아무도 비우지 않는 기록이 무한히 쌓이지 않게 한다 - #118

Merged
jjh75607 merged 1 commit into
masterfrom
fix/bound-uncollected-records
Aug 19, 2026
Merged

jjh75607 merged 1 commit into
masterfrom
fix/bound-uncollected-records

Conversation

@jjh75607

Copy link
Copy Markdown
Owner

Pull Request

Related Issue

Summary

테스트 스레드가 아닌 곳의 기록에 상한을 뒀다. 1만 개에 닿으면 그 뒤는 담지 않고 한 번 알린다.

Details

무엇이 새고 있었나

other-threads.enabled 를 켜지 않은 채 실제 HTTP 요청을 보내는 테스트를 돌리면, 쿼리가 서버 워커 스레드에서 나가 그 스레드의 ThreadLocal 에 담긴다. 비우는 것은 테스트 스레드에서만 돌기 때문에 아무도 비우지 않는다.

읽을 수도 없는 기록이다. 테스트에서 보이지 않는다는 것이 #112 를 만든 이유다. 그러니 순전히 낭비다.

왜 버리지 않고 상한인가

#112 에서 아예 버리는 쪽으로 고쳐 봤다가 되돌렸다. 두 가지가 걸렸다.

걸린 것 내용
기존 테스트 다섯 개 리스너를 직접 부르면서 테스트 컨텍스트를 설정하지 않는다
@TestExecutionListenersMERGE_WITH_DEFAULTS 없이 선언한 프로젝트 우리 리스너가 안 돌아 컨텍스트가 비는데, 그런 구성에서 기록이 통째로 사라진다

뒤엣것이 결정적이다. 활성화하지 않은 사용자에게 영향을 주지 않는 것이 이 라이브러리의 첫 성질이라, 버리는 방향은 그 성질을 깬다.

상한은 그 성질을 지키면서 무한히 쌓이는 것만 막는다. 1만은 실제로 쓰이는 경로에 닿지 않을 만큼 넉넉하다. 테스트 하나가 1만 개를 쓰면 그건 다른 문제다.

안내

10000 queries piled up on a thread that is not a test thread, and nothing clears them.
Later ones are dropped. If these come from a server handling requests for an acceptance
test, set query-counter.other-threads.enabled=true to count them instead.

버리기만 하고 입을 닫으면 왜 수가 안 맞는지 알 수 없다. 그래서 제대로 세는 길을 함께 가리킨다.

한 번만 알리는 표시로 AtomicBoolean 을 쓴다. 한 번 알렸으면 그대로 두는 것이 맞는 값이라, 테스트 사이에 리셋해야 했던 예전의 static 플래그와 성질이 다르다.

개수를 물을 자리를 따로 뒀다

getQueries() 는 복사본을 만든다. 쿼리마다 그것을 불러 크기를 재면 O(n) 이 매번 붙는다. recordedCount() 를 뒀다.

테스트

두 개를 더했다.

무엇
테스트 스레드가 아니면 상한까지만 담는다
테스트 스레드에서는 상한을 넘겨도 계속 담는다. 테스트 끝에 비워지므로 쌓일 일이 없다

지원 버전 셋(3.0.0, 3.5.16, 4.1.0)을 로컬에서 빌드했다.

`other-threads.enabled` 를 켜지 않은 채 실제 HTTP 요청을 보내는 테스트를 돌리면, 서버 워커
스레드의 `ThreadLocal` 에 기록이 쌓인다. 비우는 것은 테스트 스레드에서만 돌므로 아무도 비우지
않는다. 읽을 수도 없는 기록이라 순전히 낭비다.

#112 에서 아예 버리는 쪽으로 고쳐 봤다가 되돌렸다. 리스너를 직접 부르는 기존 테스트 다섯 개가
깨지고, `@TestExecutionListeners` 를 `MERGE_WITH_DEFAULTS` 없이 선언한 프로젝트에서는 우리
리스너가 안 돌아 컨텍스트가 비는데 그런 구성에서 기록이 통째로 사라진다.

그래서 상한을 뒀다. 1만 개에 닿으면 그 뒤는 담지 않고 한 번 알린다. 안내에서
`other-threads.enabled` 를 가리켜 제대로 세는 길을 알려준다. 실제로 쓰이는 경로에는 닿지 않을
만큼 넉넉한 값이라, 꺼져 있을 때의 동작은 사실상 그대로다.

개수를 물을 자리를 따로 뒀다. `getQueries()` 는 복사본을 만들어서 쿼리마다 부를 수 없다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jjh75607
jjh75607 force-pushed the fix/bound-uncollected-records branch from 24c1e23 to 64dbd0c Compare August 19, 2026 06:52
@jjh75607
jjh75607 merged commit 6b3cf85 into master Aug 19, 2026
6 checks passed
@jjh75607
jjh75607 deleted the fix/bound-uncollected-records branch August 19, 2026 06: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