SPRING

[스터디] 취업뽀개기 사이트 (1) _ N+1 문제 개선

연곰2 2025. 7. 13. 19:34

목표

✅기존 코드에서 n+1이 발생하는 지점을 찾아 정리하고,
성능 개선을 위한 다양한 문제 해결 방법을 도입해 비교/테스트하여 가장 최적의 방법 적용해보자!

 


1. 데이터 추가

데이터 추가 작성 코드 (NotProd.java)

테이블명 데이터 개수 비고

TechInterview 50 기본 엔티티
Question 50 기본 엔티티
ParticipantQnA 25,000 Question당 500개
Comment 25,000 Question당 500개
Contest 50 기본 엔티티
Participant 25,000 Contest당 500개
Problem 25,000 Contest당 500개
Answer 25,000 성능 고려하여 제한적 생성
Note 100 공개/비공개 각각 50개
총합 125,250개 전체 레코드 수

 

2. k6 테스트 - 콘테스트 목록

k6 테스트 코드 (contest-api-test.js)

 

k6_test/jpa/contest-api-test.js at main · chibbotec/k6_test

Contribute to chibbotec/k6_test development by creating an account on GitHub.

github.com

3. K6 시나리오

테스트 개요

  • 테스트 대상: Contest 목록 조회 API
  • 엔드포인트: GET /api/v1/tech-interview/{SPACE_ID}/contests
  • 테스트 유형: 부하 테스트 (Load Testing)
  • 인증: 인증 없음 (No Authentication)

부하 테스트 시나리오

  • 최대 동시 사용자: 30명
  • 테스트 패턴: 점진적 부하 증가 → 유지 → 감소

성능 임계값 (Thresholds)

  • 응답시간: 95%의 요청이 1초 이내 완료
  • 성공률: 95% 이상 성공률 유지
  • HTTP 실패율: 5% 미만
  • HTTP 응답시간: HTTP 요청의 95%가 1초 이내

테스트 시나리오 상세

  1. 연결 테스트: 테스트 시작 전 API 연결 상태 확인
  2. 환경 검증: Base URL, Space ID 등 환경 변수 확인
  3. 샘플 응답 검증: JSON 배열 형태의 응답 구조 확인

메인 테스트 로직

각 VU(Virtual User)가 반복 실행하는 작업:

  1. API 호출: Contest 목록 조회 GET 요청
  2. 응답 검증:
    • HTTP 상태 코드 200 확인
    • 응답 시간 1초 이내 확인
    • JSON 배열 형태 응답 확인
    • Content-Type이 application/json 확인
  3. 메트릭 수집: 성공/실패 카운트 및 응답시간 기록
  4. 대기: 0.1~0.6초 랜덤 대기 (서버 부하 분산)

결과 분석 항목

성능 지표

  • 처리량: 초당/분당 요청 수
  • 응답시간: 평균, 최소, 최대, P50, P90, P95, P99
  • 안정성: 성공률, HTTP 실패율
  • 리소스: 데이터 송수신량

테스트 결과

  • batch_size 적용 전
2025-06-23T16:54:32.312+09:00  INFO 62136 --- [techinterview] [nio-9040-exec-2] i.StatisticalLoggingSessionEventListener : Session Metrics {
    2707042 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    6689083 nanoseconds spent preparing 51 JDBC statements;
    258081169 nanoseconds spent executing 51 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    3000 nanoseconds spent executing 1 pre-partial-flushes;
    2375 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
=========================================================
        Contest List API 상세 성능 테스트 결과
=========================================================

🎯 테스트 대상
  URL                 : <http://localhost:9040/api/v1/tech-interview/1/contests>
  테스트 유형         : Contest 목록 조회 API

📊 테스트 실행 개요
  총 테스트 기간      : 101.18초 (1.7분)
  최대 동시 VU 수     : 30개
  평균 동시 VU 수     : 0.0개
  총 완료된 반복      : 1219회
  반복 처리율         : 12.048/초

🎯 API 요청 성능 분석
  총 요청 수          : 1219개
  성공한 요청         : 1219개 (100.00%)
  실패한 요청         : 0개
  API 성공률          : 100.00%
  
📈 처리량 분석
  초당 요청 수        : 12.05 req/s
  분당 요청 수        : 723 req/min
  VU당 평균 요청      : 40.6 req/VU

⏱️  애플리케이션 응답 시간
  평균 (Average)      : 1106.39ms
  최소 (Min)          : 267.00ms
  최대 (Max)          : 3031.00ms
  중앙값 (p50)        : 1123.00ms
  90th percentile     : 1822.00ms
  95th percentile     : 1927.40ms
  99th percentile     : 0.00ms

🌐 HTTP 네트워크 성능
  총 HTTP 요청 수     : 1220개
  HTTP 처리율         : 12.06/초
  HTTP 실패율         : 0.00%
  
🕐 HTTP 응답 시간 분포
  평균                : 1105.73ms
  최소                : 267.09ms
  최대                : 3031.04ms
  중앙값 (p50)        : 1122.53ms
  90th percentile     : 1822.51ms
  95th percentile     : 1927.11ms
  99th percentile     : 0.00ms

🔧 HTTP 요청 세부 타이밍
  연결 설정 시간      : 0.01ms
  서버 처리 시간      : 1005.84ms
  응답 수신 시간      : 99.85ms
  요청 차단 시간      : 0.02ms

📊 데이터 전송량
  수신된 데이터       : 2602690.10 KB
  전송된 데이터       : 202.54 KB
  평균 수신 속도      : 25722.97 KB/s
  평균 전송 속도      : 2.00 KB/s
  요청당 평균 응답크기: 2186345 bytes

💡 성능 등급 평가
  응답시간 (평균)     : 🔴 개선필요
  응답시간 (95%)      : 🟠 보통
  안정성 (성공률)     : 🟢 매우안정
  처리량 (req/s)      : 🔴 매우낮음

🎯 성능 임계값 달성 여부
  95% 응답시간 < 1초  : ❌ 미달성 (1927ms)
  성공률 > 95%        : ✅ 달성 (100.0%)
  HTTP 실패율 < 5%    : ✅ 달성 (0.0%)

🎯 권장사항
⚠️ 응답시간 최적화 필요 - DB 쿼리 성능 점검
  💡 처리량 개선 - 애플리케이션 병목 지점 분석 필요
  📈 다음 단계: VU 50개로 스트레스 테스트 진행
  🔧 성능 최적화 팁:
     - DB 인덱스 최적화
     - 응답 데이터 압축 (gzip)
     - Redis 캐시 도입
     - Connection Pool 튜닝

 

  • batch_size 적용 후
2025-06-23T16:53:55.317+09:00  INFO 61612 --- [techinterview] [nio-9040-exec-2] i.StatisticalLoggingSessionEventListener : Session Metrics {
    2110000 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    379958 nanoseconds spent preparing 2 JDBC statements;
    37612541 nanoseconds spent executing 2 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    4750 nanoseconds spent executing 1 pre-partial-flushes;
    2416 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
=========================================================
        Contest List API 상세 성능 테스트 결과
=========================================================

🎯 테스트 대상
  URL                 : <http://localhost:9040/api/v1/tech-interview/1/contests>
  테스트 유형         : Contest 목록 조회 API

📊 테스트 실행 개요
  총 테스트 기간      : 100.79초 (1.7분)
  최대 동시 VU 수     : 30개
  평균 동시 VU 수     : 0.0개
  총 완료된 반복      : 1388회
  반복 처리율         : 13.771/초

🎯 API 요청 성능 분석
  총 요청 수          : 1388개
  성공한 요청         : 1388개 (100.00%)
  실패한 요청         : 0개
  API 성공률          : 100.00%
  
📈 처리량 분석
  초당 요청 수        : 13.77 req/s
  분당 요청 수        : 826 req/min
  VU당 평균 요청      : 46.3 req/VU

⏱️  애플리케이션 응답 시간
  평균 (Average)      : 921.37ms
  최소 (Min)          : 206.00ms
  최대 (Max)          : 2490.00ms
  중앙값 (p50)        : 902.00ms
  90th percentile     : 1597.60ms
  95th percentile     : 1688.00ms
  99th percentile     : 0.00ms

🌐 HTTP 네트워크 성능
  총 HTTP 요청 수     : 1389개
  HTTP 처리율         : 13.78/초
  HTTP 실패율         : 0.00%
  
🕐 HTTP 응답 시간 분포
  평균                : 920.73ms
  최소                : 206.03ms
  최대                : 2489.47ms
  중앙값 (p50)        : 902.03ms
  90th percentile     : 1597.62ms
  95th percentile     : 1688.38ms
  99th percentile     : 0.00ms

🔧 HTTP 요청 세부 타이밍
  연결 설정 시간      : 0.01ms
  서버 처리 시간      : 827.16ms
  응답 수신 시간      : 93.52ms
  요청 차단 시간      : 0.02ms

📊 데이터 전송량
  수신된 데이터       : 2963226.68 KB
  전송된 데이터       : 230.60 KB
  평균 수신 속도      : 29400.36 KB/s
  평균 전송 속도      : 2.29 KB/s
  요청당 평균 응답크기: 2186127 bytes

💡 성능 등급 평가
  응답시간 (평균)     : 🟠 보통
  응답시간 (95%)      : 🟠 보통
  안정성 (성공률)     : 🟢 매우안정
  처리량 (req/s)      : 🔴 매우낮음

🎯 성능 임계값 달성 여부
  95% 응답시간 < 1초  : ❌ 미달성 (1688ms)
  성공률 > 95%        : ✅ 달성 (100.0%)
  HTTP 실패율 < 5%    : ✅ 달성 (0.0%)

🎯 권장사항
⚠️ 응답시간 최적화 필요 - DB 쿼리 성능 점검
  💡 처리량 개선 - 애플리케이션 병목 지점 분석 필요
  📈 다음 단계: VU 50개로 스트레스 테스트 진행
  🔧 성능 최적화 팁:
     - DB 인덱스 최적화
     - 응답 데이터 압축 (gzip)
     - Redis 캐시 도입
     - Connection Pool 튜닝

 

결론

  • 16.7% 응답시간 단축
  • 14.3% 처리량 증가
  • 17.8% 서버 처리시간 개선

하지만 95% 응답시간이 1초를 초과하기 때문에 추가적인 최적화 작업이 필요하다고 생각했습니다.

추가적인 성능 개선을 적용한 부분은 다음 글에 작성해보도록 하겠습니다! 😊