Files
document-haness/docs/n+1liner/tech-log-studio/jpa-feed-query-performance/question/question-concurrency-stability.md
T
DongHyeonkaandClaude Opus 5 ab59130196 chore: 이전 세션이 남긴 변경을 커밋한다
이번 파이프라인 작업과 무관하게 작업 트리에 남아 있던 것을 그대로 올린다.
사용자가 「전부 커밋」으로 정했고, 이번 작업과 섞이지 않게 커밋만 나눴다.

대부분은 clean-architecture-backend-template 의 그림 정본 재배치다 —
final/assets/diagrams/<이름>/ 에 있던 것이 CLAUDE.md 가 적은 배치인
final/assets/<이름>/ 로 옮겨졌고 .techviz/<이름>/ 이 함께 들어왔다.
삽입 줄의 대부분(3.15M)이 그 .techviz context.json 이다.

그 밖에 ca-tmpl·document-haness 의 정리, .claude/agents/ 열한 개,
writing-practitioner-guides 스킬, .playwright-mcp 세션 산출물,
scripts/check-ssot-facts.py 와 그 시험이 들어 있다.

이 커밋의 내용은 내가 만든 것이 아니라 이전 세션이 남긴 것이고 검증하지 않았다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:02:02 +09:00

5.3 KiB

id, kind, slug, title, topic, topicName, project, status, studio, questionStatus, sourceRevision, source
id kind slug title topic topicName project status studio questionStatus sourceRevision source
6cbe963f-86f8-4df6-be5a-900712970d01 QUESTION concurrency-stability 실제 동시 트래픽에서도 이 구조가 안정적인가 jpa-feed-query-performance JPA 피드 조회 성능 Liner N + 1문제 게시 전 https://hyeonworks.com/studio/documents/6cbe963f-86f8-4df6-be5a-900712970d01/edit OPEN n+1liner-lab@2026-08
final/document.md#4-5
final/document.md#18

실제 동시 트래픽에서도 이 구조가 안정적인가

지금까지의 측정은 단일 스레드 퍼시스턴스 통합 테스트에서 아이템 수 N을 키울 때 쿼리 수와 읽는 행수가 얼마나 늘어나는지만 확인했다. 여러 요청이 겹칠 때의 처리량과 커넥션 풀 안정성은 이 테스트가 재지 않았으므로, 조회 구조가 실제 부하를 견디는지는 아직 모른다.

관계

  • PostgreSQL Query Plan 측정 기준 무엇을 어디까지 재고 어떤 도구로 잴지 그 기록에서 정했다.
  • feed_visible을 Production CQRS로 승격할 것인가 고트래픽 읽기에서 사전계산이 실제로 필요한지는 부하 결과를 봐야 정할 수 있다.

사실

  • 측정은 단일 스레드에서 이미 열린 테스트 트랜잭션 안의 어댑터 호출만 쟀고, HTTP 종단은 거치지 않았다.
  • 지연 값은 DB 캐시가 이미 채워진 상태에서 잰 로컬 비교값이고, 7회 반복 중 앞 2회를 워밍업으로 버린 5개가 표본이다.
  • 표본이 5개뿐이어서 p50·p99 대신 중앙값과 최댓값으로 적었다.
  • N=1,000에서 왕복 수는 2,022개에서 23개로, 엔티티 로드는 1,569개에서 0개로, 자식 전송은 1,509행에서 최대 60행으로 줄었다.
  • 100번째 페이지에서 OFFSET은 20행을 만들려고 2,000행을 읽었고 keyset은 20행만 읽었다.
  • 한 요청만 놓고 보면 왕복 수는 페이지 크기에 묶여 있다. 그 왕복이 트래픽에 곱해진 값은 요청을 동시에 보내야 나오고, 그 측정은 하지 않았다.
  • 고트래픽 처리량과 커넥션 풀 안정성, 동시성은 이 측정의 범위 밖이라고 문서 첫머리에 적어 두었다.
  • 커넥션 풀과 Little's Law는 이번 조회 문제를 해결한 뒤 별도 주제로 검증할 수 있다고 다음 단계에 함께 적어 두었다.

가정

  • 왕복 수가 줄면 같은 트래픽에서 DB 부하도 줄어든다.
  • 요청마다 반복되는 왕복이 처리량에 곱해지므로, 왕복이 줄면 처리량 한계도 올라간다.
  • 단일 스레드에서 잰 요청당 쿼리 수와 읽는 행수는 여러 요청이 동시에 돌아도 달라지지 않는다.

미지수

  • 목표 처리량에서 커넥션 풀이 포화되는가. 포화되지 않으려면 풀을 몇 개로 잡아야 하고 요청은 얼마나 기다리는가.
  • 요청이 동시에 몰릴 때 지연이 어느 구간에 몰리는가. 꼬리 지연은 어디까지 벌어지는가.
  • hibernate.default_batch_fetch_size=100은 세션 전체에 걸리는 설정인데, 여러 세션이 동시에 도는 동안에도 세션마다 따로 적용되는가.
  • 깊은 페이지 요청이 섞이면 전체 지연이 얼마나 밀리는가.
  • DB 캐시가 비어 있거나 ANALYZE를 돌리지 않아 통계가 낡은 상태에서 실행계획이 달라지는가.
  • 운영 알람의 기준으로 어느 지표를 삼을 것인가.

제약

  • 단일 스레드에서 잰 값으로는 동시 실행을 말할 수 없어서, 부하 테스트와 APM(Application Performance Monitoring, 애플리케이션 성능 모니터링)으로 도구를 바꿔야 한다.
  • 안정적인 꼬리 지연(p99)을 말하려면 워밍업 뒤 100회 넘게 반복한 독립 세트가 여러 개 있어야 한다.
  • 부하 테스트 환경의 데이터 규모와 하드웨어를 운영에 맞추지 않으면 거기서 나온 결과를 운영으로 그대로 옮길 수 없다.

선택지

1. 부하 테스트와 APM으로 확인한다

목표 처리량을 먼저 정하고 HTTP 종단 지연과 처리량, 커넥션 풀 사용률을 함께 잰다. 왕복이 줄어든 만큼 처리량이 올라가는지 부하에서 확인한다.

2. 반복 횟수를 늘린 지연 측정부터 한다

같은 단일 스레드 조건에서 반복을 100회 넘게 늘려 꼬리 지연부터 안정시킨다. 동시성은 아직 다루지 않는다.

3. 현재 범위를 명시하고 운영 판단은 미룬다

쿼리 수와 읽는 행수가 줄었다는 데까지만 주장하고 처리량은 다루지 않는다. 필요해지면 그때 부하 테스트를 연다.

운영에 올린 뒤에야 문제를 발견할 수 있다.

다음 검증

  1. 목표 처리량과 허용 지연을 먼저 정한다. 이 두 값이 없으면 부하 결과가 통과인지 실패인지 판정할 수 없다.

  2. 운영과 비슷한 데이터 규모를 준비하되 하이라이트 개수의 Zipf 형태 편중은 그대로 둔다.

  3. 부하 테스트로 HTTP 종단 지연과 처리량을 측정하고, 커넥션 풀 사용률과 대기 시간을 함께 본다.

  4. 개선 전후 구조를 같은 조건에서 비교해 왕복이 줄어든 것이 처리량으로 이어지는지 확인한다.

  5. 깊은 페이지 요청과 얕은 페이지 요청을 섞어 지연이 어디까지 벌어지는지 본다.

  6. 운영 알람으로 쓸 지표를 정한다.