Skip to content

K6 ramping-up 스크립트 작성#267

Merged
kelly6bf merged 18 commits into
devfrom
feature/#266-new_k6_script
May 15, 2026
Merged

K6 ramping-up 스크립트 작성#267
kelly6bf merged 18 commits into
devfrom
feature/#266-new_k6_script

Conversation

@kelly6bf

@kelly6bf kelly6bf commented May 8, 2026

Copy link
Copy Markdown

😉 연관 이슈

Resolves #266

🧑‍💻 수행 작업

  • ramping-up 스크립트 작성
  • 시나리오 테스트 작성

📢 참고 사항

X

Summary by CodeRabbit

릴리스 노트

  • 성능 및 테스트 개선

    • 다양한 API 엔드포인트에 대한 부하 테스트 및 스파이크 테스트 추가
    • 종합 시나리오 기반 성능 테스트 확대
    • 테스트 데이터 범위 업데이트로 더욱 광범위한 검증 범위 확보
  • 기타 개선

    • 오래된 테스트 파일 제거 및 코드 정리
    • API 엔드포인트 테스트 최적화

kelly6bf added 18 commits May 4, 2026 01:29
@kelly6bf kelly6bf self-assigned this May 8, 2026
@coderabbitai

coderabbitai Bot commented May 8, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

k6 로드 테스트 스크립트를 API 버전 업그레이드 및 디렉토리 재구성에 맞춰 전면 개편합니다. 이전 v1 테스트 파일을 제거하고 v2 엔드포인트 대응 및 새로운 구조의 램핑/스파이크 테스트를 추가합니다. 테스트 데이터 상수도 업데이트합니다.

Changes

테스트 데이터 설정 업데이트

Layer / File(s) Summary
상수 값 변경
k6/common/test-data/test-data-common.js
PAST_TOTAL_ACTIVITY_DAY30 * 6에서 30 * 12로 변경하고, CURRENT_FOR_READ_GROUP_PER_MEMBER_COUNTCURRENT_FOR_WRITE_GROUP_PER_MEMBER_COUNT 상수 추가.
초기화 함수 업데이트
k6/common/test-data/current-activity/clear-current-activity-data.js
clearCurrentActivityData() 함수의 기본 nDay 매개변수를 0에서 1로 변경하고, 콘솔 출력 메시지 형식 수정.

K6 로드 테스트 스크립트 전면 개편

Layer / File(s) Summary
레거시 테스트 제거
k6/test/api-load-test/read/*
이전 v1 API 테스트 파일 3개(10_get-my-group-activity-info..., 5_get-my-todos-filtered..., 9_get-my-group-activity...) 삭제 (총 186줄 제거).
API 단일 테스트 추가 (읽기)
k6/test/api-single-test/read/*
새로운 v2 엔드포인트 기반 테스트 추가: 도전 그룹 참여 여부 확인, todo 인증 조회, 참여 중인 그룹 정보, 그룹 내 todo, 팀 순위, 회원 todo 히스토리, 그룹 활동 요약, 인증 통계, 내 인증 목록 등을 위한 램핑 및 스파이크 테스트 (총 513줄 추가).
응답 검증 로직 및 경로 조정
k6/test/api-single-test/read/**/spike-test.js
공통 유틸 경로 재지정, 시나리오 이름 명시화 (default → v1/v2 테스트별 이름), 엔드포인트 변수화, 첫 VU/반복에서만 로깅하도록 조정.
시나리오 테스트 신규 추가
k6/test/scenario-test/scenario-01.js, scenario-02.js
E2E 로드 테스트 시나리오 추가: 여러 API 엔드포인트를 순차 호출하며 v2 엔드포인트 기반 응답 검증 및 조건부 인증 필드 확인 로직 포함 (총 478줄 추가).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항을 명확하게 반영하며, 'ramping-up 스크립트 작성'이라는 핵심 내용을 포함하고 있습니다.
Description check ✅ Passed PR 설명이 저장소의 템플릿 구조를 따르고 있으며, 연관 이슈(#266), 수행 작업, 참고 사항을 모두 포함하고 있습니다.
Linked Issues check ✅ Passed 변경사항들이 이슈 #266의 목표인 'API 변경에 따른 k6 스크립트 수정'을 충족하며, 여러 API 버전(v1/v2)의 ramping-up 및 spike 테스트 스크립트를 추가했습니다.
Out of Scope Changes check ✅ Passed PR의 변경사항들이 모두 k6 테스트 스크립트 관련이며, 일부 삭제된 로드 테스트 파일들도 레이아웃 변경의 일부로 k6 스크립트 정리와 관련있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#266-new_k6_script

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-spike-test.js (2)

40-41: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

VU별 테스트 데이터/토큰 인덱스 가드가 필요합니다.

Line 40~41/63에서 인덱스를 바로 사용하므로 데이터 길이가 부족하면 실패 원인이 불명확해집니다. 실행 초기에 명시적 검증을 추가해 주세요.

Also applies to: 63-63

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-spike-test.js`
around lines 40 - 41, The test uses vuIndex = __VU - 1 and then directly indexes
data.challengeGroupIds[vuIndex][0] and
data.otherChallengeGroupMemberIds[vuIndex][0] without guards; add an explicit
runtime check before calling requestApi that ensures data.challengeGroupIds and
data.otherChallengeGroupMemberIds are arrays, that they have an entry at index
vuIndex, and that those entries have a [0] element; if any check fails, throw or
log a clear error mentioning vuIndex, __VU, and the offending array (e.g.,
"data.challengeGroupIds") so failures are deterministic and informative; apply
the same guard around the other usage at the later call (line ~63) that also
uses vuIndex.

19-23: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Spike 테스트 설정이 불일치합니다. executor와 VU/iteration 재구성 필요합니다.

현재 executor: 'per-vu-iterations' + vus: 1 + iterations: 1 설정은 단 1개 요청만 실행하며, 스파이크 테스트(갑작스러운 부하 급증 후 복구)의 정의와 맞지 않습니다.

K6 공식 가이드에 따르면 스파이크 테스트는 다음 중 하나를 권장합니다:

  • ramping-vus: VU를 급격히 증가시킨 후 감소 (폐쇄형 모델)
  • ramping-arrival-rate: 요청률을 급격히 증가시킨 후 감소 (개방형 모델)

현재 executor를 변경하고, stages 필드로 급등→유지→복구 패턴을 정의해야 합니다. 주석 처리된 vus: 100, vus: 400 값을 참고하여 목표 부하 수준을 설정하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-spike-test.js`
around lines 19 - 23, The test config uses executor: 'per-vu-iterations' with
vus: 1 and iterations: 1 which only runs one request and doesn't implement a
spike; change the executor to a spike-appropriate executor (e.g., 'ramping-vus'
or 'ramping-arrival-rate'), remove/ignore iterations and single-vus settings,
and replace them with a stages array that models rapid ramp-up → sustain →
ramp-down using the commented values (e.g., target VUs like 100 and 400) and
keep maxDuration as needed; update the options object where executor, vus,
iterations, and stages are defined so the test performs a true spike pattern.
🟡 Minor comments (1)
k6/common/test-data/current-activity/clear-current-activity-data.js-7-9 (1)

7-9: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

기본값 주석과 실제 값이 불일치합니다.

Line [7]은 기본값이 0이라고 되어 있는데, Line [8]은 nDay = 1입니다. 실행 기준 혼선을 막기 위해 주석을 현재 동작에 맞게 갱신해주세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@k6/common/test-data/current-activity/clear-current-activity-data.js` around
lines 7 - 9, 주석과 실제 값이 불일치합니다: 현재 nDay 변수는 nDay = 1으로 설정되어 있으므로 주석(기본값은 0)을
nDay의 실제 값 및 동작에 맞게 수정하세요; 또는 의도한 기본값이 0이면 nDay를 0으로 변경하세요. 대상 식별자: nDay 변수와
getDateNDaysAgoMySqlDateFormatString(nDay) 호출부를 찾아 주석문을 "기본값은 1" 또는 "현재 실행값은 1"
등으로 갱신하거나 nDay 값을 0으로 맞추면 됩니다.
🧹 Nitpick comments (10)
k6/test/api-single-test/read/09_get-my-certifications/09_v2-spike-test.js (2)

10-22: ⚡ Quick win

스파이크 테스트에도 thresholds를 추가하는 것이 좋습니다.

현재는 성공/실패 기준이 명시되지 않아 CI에서 자동 판정이 약합니다. http_req_duration, http_req_failed 같은 최소 임계값을 추가하면 결과 해석이 일관됩니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@k6/test/api-single-test/read/09_get-my-certifications/09_v2-spike-test.js`
around lines 10 - 22, The test options lack thresholds, so add a thresholds
block under the exported options (inside scenarios → v2_09_spike_test or at the
top-level options) to enforce pass/fail criteria; for example define thresholds
for http_req_duration (p(95)<500 or similar) and http_req_failed (<0.01) and any
other SLA metrics you care about, using the options object and the
v2_09_spike_test scenario name to locate where to insert them.

52-52: ⚡ Quick win

타임아웃 1800s는 스파이크 테스트 목적과 맞지 않습니다.

스파이크에서는 짧은 시간에 급격한 열화를 잡아야 하므로, 30분 타임아웃은 신호를 흐립니다. 더 짧은 타임아웃으로 조정해 주세요.

Also applies to: 60-60

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@k6/test/api-single-test/read/09_get-my-certifications/09_v2-spike-test.js` at
line 52, The timeout variable currently set as const timeout = '1800s' is too
long for a spike test; change the timeout to a much shorter duration (e.g.,
'30s' or another appropriate short value) in this file (09_v2-spike-test.js) by
updating the const timeout declaration, and make the same shorter-timeout change
for the other occurrence referenced ("60-60") so both spike test configs use a
short timeout suited for detecting rapid degradation.
k6/test/api-single-test/read/09_get-my-certifications/09_v2-ramping-up-test.js (1)

62-62: ⚡ Quick win

요청 타임아웃(1800s)이 과도합니다.

Line 62의 30분 타임아웃은 장애/지연을 너무 늦게 드러내서 부하 테스트 신뢰도를 떨어뜨립니다. SLA 기준에 맞는 짧은 타임아웃(예: 5~30s)으로 조정하는 편이 좋습니다.

Also applies to: 70-70

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/09_get-my-certifications/09_v2-ramping-up-test.js`
at line 62, The request timeout value is set too high (const timeout = '1800s')
which hides failures; update the timeout variable(s) to a shorter SLA-aligned
value (for example '30s' or '5s' depending on your SLA) by changing the const
timeout declaration in this test file (and the similar declaration referenced at
line 70) to the chosen shorter string or make it configurable via an environment
variable (e.g., process.env.TEST_TIMEOUT) and use that variable in place of the
hardcoded '1800s'.
k6/test/api-single-test/read/08_get-my-certification-stats/08_v2-ramping-up-test.js (2)

1-2: 💤 Low value

'k6'에서 두 개를 별도로 import하는 것을 하나로 통합할 수 있습니다.

♻️ 제안하는 수정 방법
-import { sleep } from 'k6';
-import {check} from 'k6';
+import { sleep, check } from 'k6';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/08_get-my-certification-stats/08_v2-ramping-up-test.js`
around lines 1 - 2, The file currently imports from 'k6' twice (import { sleep }
from 'k6'; and import {check} from 'k6';); consolidate these into a single
import statement that includes both symbols (sleep and check) so the module is
imported once — update the imports where sleep and check are referenced
(symbols: sleep, check) to use a single import line importing both.

11-11: ⚡ Quick win

setupTimeout: '30m'이 실제 setup() 동작(5초 대기)과 맞지 않습니다.

setup()sleep(5)만 수행하므로 30분 타임아웃은 과도합니다. 실수로 장시간 대기가 발생해도 즉시 탐지되지 않습니다.

🔧 제안하는 수정 방법
-    setupTimeout: '30m',
+    setupTimeout: '30s',
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/08_get-my-certification-stats/08_v2-ramping-up-test.js`
at line 11, The test sets setupTimeout: '30m' which is inconsistent with the
actual setup() behavior (it only calls sleep(5)), so reduce the timeout to a
conservative short value to catch accidental long-running setup (for example
'1m' or '10s'); update the setupTimeout entry near the top of the file (the
setupTimeout property) to a much shorter duration consistent with setup() and
the sleep(5) call so failures are detected quickly.
k6/test/scenario-test/scenario-01.js (1)

194-196: ⚡ Quick win

콤마 연산자 사용 — 의도와 다른 문법으로 오해를 유발합니다

세 줄의 checks 할당이 콤마 연산자로 연결되어 있습니다. 기능적으로는 모두 실행되지만, 마치 첫 번째 할당만 실행되는 것처럼 보여 코드 유지보수 시 버그로 오인될 수 있습니다. 각각 세미콜론으로 분리된 독립 구문으로 작성하는 것을 권장합니다(위 수정 제안 참고).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@k6/test/scenario-test/scenario-01.js` around lines 194 - 196, The three
consecutive assignments to the checks object are mistakenly written as a single
comma-separated expression causing readability/confusion; change each assignment
to a separate statement so that checks['응답 데이터 - todos[0].certificationContent
존재'], checks['응답 데이터 - todos[0].certificationMediaUrl 존재'], and checks['응답 데이터 -
todos[0].reviewFeedback 존재'] are each terminated (use semicolons/newlines) and
remain independent expressions referencing
responseData?.todos[0].certificationContent,
responseData?.todos[0].certificationMediaUrl, and
responseData?.todos[0].reviewFeedback respectively.
k6/test/api-single-test/read/03_get-joining-challenge-groups-info/03_v1-ramping-up-test.js (1)

47-59: ⚡ Quick win

check() 람다 내 안전하지 않은 접근 패턴 및 일관성 없는 옵셔널 체이닝

Lines 47-48은 responseData?.를 사용하지만 Lines 49-58은 responseData.joiningChallengeGroups[0]?.responseData 자체에 대한 null 가드가 없습니다. API 오류로 responseData가 null이면 Line 49의 람다에서 예외가 발생하고, 이후 모든 체크가 실행되지 않습니다.

♻️ 수정 제안
-        '응답 데이터 - joiningChallengeGroups 빈 배열 X': () => responseData?.joiningChallengeGroups.length > 0,
-        '응답 데이터 - joiningChallengeGroups[0].groupId 존재': () => responseData.joiningChallengeGroups[0]?.groupId !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].groupName 존재': () => responseData.joiningChallengeGroups[0]?.groupName !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].currentMemberCount 존재': () => responseData.joiningChallengeGroups[0]?.currentMemberCount !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].maximumMemberCount 존재': () => responseData.joiningChallengeGroups[0]?.maximumMemberCount !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].joinCode 존재': () => responseData.joiningChallengeGroups[0]?.joinCode !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].status 존재': () => responseData.joiningChallengeGroups[0]?.status !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].startAt 존재': () => responseData.joiningChallengeGroups[0]?.startAt !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].endAt 존재': () => responseData.joiningChallengeGroups[0]?.endAt !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].progressDay 존재': () => responseData.joiningChallengeGroups[0]?.progressDay !== undefined,
-        '응답 데이터 - joiningChallengeGroups[0].progressRate 존재': () => responseData.joiningChallengeGroups[0]?.progressRate !== undefined,
+        '응답 데이터 - joiningChallengeGroups 빈 배열 X': () => (responseData?.joiningChallengeGroups?.length ?? 0) > 0,
+        '응답 데이터 - joiningChallengeGroups[0].groupId 존재': () => responseData?.joiningChallengeGroups?.[0]?.groupId !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].groupName 존재': () => responseData?.joiningChallengeGroups?.[0]?.groupName !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].currentMemberCount 존재': () => responseData?.joiningChallengeGroups?.[0]?.currentMemberCount !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].maximumMemberCount 존재': () => responseData?.joiningChallengeGroups?.[0]?.maximumMemberCount !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].joinCode 존재': () => responseData?.joiningChallengeGroups?.[0]?.joinCode !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].status 존재': () => responseData?.joiningChallengeGroups?.[0]?.status !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].startAt 존재': () => responseData?.joiningChallengeGroups?.[0]?.startAt !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].endAt 존재': () => responseData?.joiningChallengeGroups?.[0]?.endAt !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].progressDay 존재': () => responseData?.joiningChallengeGroups?.[0]?.progressDay !== undefined,
+        '응답 데이터 - joiningChallengeGroups[0].progressRate 존재': () => responseData?.joiningChallengeGroups?.[0]?.progressRate !== undefined,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/03_get-joining-challenge-groups-info/03_v1-ramping-up-test.js`
around lines 47 - 59, The check() lambdas access responseData inconsistently
(some use responseData?., others use responseData.joiningChallengeGroups[0]?.)
which can throw if responseData is null; update all predicates to guard
responseData and the array safely—for example replace accesses with
responseData?.joiningChallengeGroups?.length > 0 and
responseData?.joiningChallengeGroups?.[0]?.groupId !== undefined (and similarly
for groupName, currentMemberCount, maximumMemberCount, joinCode, status,
startAt, endAt, progressDay, progressRate) so every lambda uses optional
chaining on responseData and joiningChallengeGroups before indexing.
k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-spike-test.js (1)

49-56: ⚡ Quick win

check() 람다 내 연쇄 접근이 예외를 발생시키면 이후 모든 체크가 스킵됩니다

k6는 check() 콜백에서 예외가 발생하면 해당 체크만 실패로 기록하는 것이 아니라 그 뒤에 오는 모든 체크의 실행을 중단합니다 (관련 k6 이슈 #2865).

responseData?.certificationPeriods.length > 0 (Line 49)는 certificationPeriodsundefined이거나 빈 배열일 때 예외를 발생시켜 Lines 50-56의 체크가 전혀 실행되지 않습니다. 각 단계마다 ?.를 사용하면 이를 방지할 수 있습니다.

♻️ 수정 제안
-        '응답 데이터 - certificationPeriods 빈 배열 X': () => responseData?.certificationPeriods.length > 0,
-        '응답 데이터 - certificationPeriods[0].day 존재': () => responseData?.certificationPeriods[0].day !== undefined,
-        '응답 데이터 - certificationPeriods[0].createdCount 존재': () => responseData?.certificationPeriods[0].createdCount !== undefined,
-        '응답 데이터 - certificationPeriods[0].certificatedCount 존재': () => responseData?.certificationPeriods[0].certificatedCount !== undefined,
-        '응답 데이터 - certificationPeriods[0].certificationRate 존재': () => responseData?.certificationPeriods[0].certificationRate !== undefined,
-        '응답 데이터 - ranking.totalMemberCount 존재': () => responseData?.ranking.totalMemberCount !== undefined,
-        '응답 데이터 - ranking.myRank 존재': () => responseData?.ranking.myRank !== undefined,
+        '응답 데이터 - certificationPeriods 빈 배열 X': () => (responseData?.certificationPeriods?.length ?? 0) > 0,
+        '응답 데이터 - certificationPeriods[0].day 존재': () => responseData?.certificationPeriods?.[0]?.day !== undefined,
+        '응답 데이터 - certificationPeriods[0].createdCount 존재': () => responseData?.certificationPeriods?.[0]?.createdCount !== undefined,
+        '응답 데이터 - certificationPeriods[0].certificatedCount 존재': () => responseData?.certificationPeriods?.[0]?.certificatedCount !== undefined,
+        '응답 데이터 - certificationPeriods[0].certificationRate 존재': () => responseData?.certificationPeriods?.[0]?.certificationRate !== undefined,
+        '응답 데이터 - ranking.totalMemberCount 존재': () => responseData?.ranking?.totalMemberCount !== undefined,
+        '응답 데이터 - ranking.myRank 존재': () => responseData?.ranking?.myRank !== undefined,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-spike-test.js`
around lines 49 - 56, The chain accesses inside the check() callback can throw
and abort subsequent checks; update all properties on
responseData.certificationPeriods and ranking to use safe optional chaining
(e.g., change responseData?.certificationPeriods.length > 0 to
responseData?.certificationPeriods?.length > 0 and use
certificationPeriods?.[0]?.day, certificationPeriods?.[0]?.createdCount,
certificationPeriods?.[0]?.certificatedCount,
certificationPeriods?.[0]?.certificationRate and
responseData?.ranking?.totalMemberCount, responseData?.ranking?.myRank) so each
assertion like those in the check() lambda referencing responseData is resilient
and won’t throw if intermediate values are undefined.
k6/test/api-single-test/read/02_get-todo-certifications-for-reviewer/02_v1-ramping-up-test.js (1)

47-52: ⚡ Quick win

check() 람다에서 연쇄 접근 예외 발생 시 이후 체크가 스킵됩니다

responseData?.dailyTodoCertifications.length > 0 (Line 47)에서 dailyTodoCertificationsundefined이거나 빈 배열이면 예외가 발생하고, k6는 예외가 발생한 첫 번째 체크만 실패로 기록하고 이후 체크의 실행을 중단합니다. 200 VUs 부하 테스트에서 API 오류 응답이 발생하면 Lines 48-52의 필드 체크가 전혀 실행되지 않습니다.

♻️ 수정 제안
-        '응답 데이터 - dailyTodoCertifications 빈 배열 X': () => responseData?.dailyTodoCertifications.length > 0,
-        '응답 데이터 - dailyTodoCertifications[0].id 존재': () => responseData?.dailyTodoCertifications[0].id !== undefined,
-        '응답 데이터 - dailyTodoCertifications[0].content 존재': () => responseData?.dailyTodoCertifications[0].content !== undefined,
-        '응답 데이터 - dailyTodoCertifications[0].mediaUrl 존재': () => responseData?.dailyTodoCertifications[0].mediaUrl !== undefined,
-        '응답 데이터 - dailyTodoCertifications[0].todoContent 존재': () => responseData?.dailyTodoCertifications[0].todoContent !== undefined,
-        '응답 데이터 - dailyTodoCertifications[0].doer 존재': () => responseData?.dailyTodoCertifications[0].doer !== undefined,
+        '응답 데이터 - dailyTodoCertifications 빈 배열 X': () => (responseData?.dailyTodoCertifications?.length ?? 0) > 0,
+        '응답 데이터 - dailyTodoCertifications[0].id 존재': () => responseData?.dailyTodoCertifications?.[0]?.id !== undefined,
+        '응답 데이터 - dailyTodoCertifications[0].content 존재': () => responseData?.dailyTodoCertifications?.[0]?.content !== undefined,
+        '응답 데이터 - dailyTodoCertifications[0].mediaUrl 존재': () => responseData?.dailyTodoCertifications?.[0]?.mediaUrl !== undefined,
+        '응답 데이터 - dailyTodoCertifications[0].todoContent 존재': () => responseData?.dailyTodoCertifications?.[0]?.todoContent !== undefined,
+        '응답 데이터 - dailyTodoCertifications[0].doer 존재': () => responseData?.dailyTodoCertifications?.[0]?.doer !== undefined,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/02_get-todo-certifications-for-reviewer/02_v1-ramping-up-test.js`
around lines 47 - 52, The checks are throwing when
responseData.dailyTodoCertifications is undefined, skipping subsequent checks;
fix by first asserting it's an array and non-empty (e.g., replace
'responseData?.dailyTodoCertifications.length > 0' with a safe check using
Array.isArray(responseData?.dailyTodoCertifications) &&
responseData.dailyTodoCertifications.length > 0) and update the other checks to
safely reference the first item (e.g., guard with Array.isArray(...) &&
responseData.dailyTodoCertifications[0] !== undefined or use a temporary const
first = Array.isArray(responseData?.dailyTodoCertifications) &&
responseData.dailyTodoCertifications[0]; then use first?.id, first?.content,
first?.mediaUrl, first?.todoContent, first?.doer) so no check throws when the
array is missing.
k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-ramping-up-test.js (1)

57-63: ⚡ Quick win

check() 람다 내 연쇄 접근 예외로 이후 체크가 스킵될 수 있습니다

responseData?.certificationPeriods.length > 0 (Line 57)에서 certificationPeriodsundefined이거나 빈 배열이면 예외가 발생하고, 이후 Lines 58-63의 체크 실행이 중단됩니다.

♻️ 수정 제안
-        '응답 데이터 - certificationPeriods 빈 배열 X': () => responseData?.certificationPeriods.length > 0,
-        '응답 데이터 - certificationPeriods[0].day 존재': () => responseData?.certificationPeriods[0].day !== undefined,
-        '응답 데이터 - certificationPeriods[0].createdCount 존재': () => responseData?.certificationPeriods[0].createdCount !== undefined,
-        '응답 데이터 - certificationPeriods[0].certificatedCount 존재': () => responseData?.certificationPeriods[0].certificatedCount !== undefined,
-        '응답 데이터 - certificationPeriods[0].certificationRate 존재': () => responseData?.certificationPeriods[0].certificationRate !== undefined,
-        '응답 데이터 - ranking.totalMemberCount 존재': () => responseData?.ranking.totalMemberCount !== undefined,
-        '응답 데이터 - ranking.myRank 존재': () => responseData?.ranking.myRank !== undefined,
+        '응답 데이터 - certificationPeriods 빈 배열 X': () => (responseData?.certificationPeriods?.length ?? 0) > 0,
+        '응답 데이터 - certificationPeriods[0].day 존재': () => responseData?.certificationPeriods?.[0]?.day !== undefined,
+        '응답 데이터 - certificationPeriods[0].createdCount 존재': () => responseData?.certificationPeriods?.[0]?.createdCount !== undefined,
+        '응답 데이터 - certificationPeriods[0].certificatedCount 존재': () => responseData?.certificationPeriods?.[0]?.certificatedCount !== undefined,
+        '응답 데이터 - certificationPeriods[0].certificationRate 존재': () => responseData?.certificationPeriods?.[0]?.certificationRate !== undefined,
+        '응답 데이터 - ranking.totalMemberCount 존재': () => responseData?.ranking?.totalMemberCount !== undefined,
+        '응답 데이터 - ranking.myRank 존재': () => responseData?.ranking?.myRank !== undefined,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-ramping-up-test.js`
around lines 57 - 63, The lambdas used in the check object can throw when
certificationPeriods is undefined or empty; update each predicate to guard
access safely: replace 'responseData?.certificationPeriods.length > 0' with
Array.isArray(responseData?.certificationPeriods) &&
responseData.certificationPeriods.length > 0, and change the subsequent
predicates (the ones referencing certificationPeriods[0].day, .createdCount,
.certificatedCount, .certificationRate) to use safe indexing and optional
chaining (e.g. Array.isArray(responseData?.certificationPeriods) &&
responseData.certificationPeriods[0] !== undefined &&
responseData.certificationPeriods[0]?.day !== undefined) or alternatively check
the non-empty array first and then reference
responseData.certificationPeriods[0] in the later lambdas; also apply similar
safe checks for 'ranking.totalMemberCount' and 'ranking.myRank' using
responseData?.ranking?.totalMemberCount !== undefined and
responseData?.ranking?.myRank !== undefined to avoid exceptions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@k6/test/api-single-test/read/04_get-my-todos-in-group/04_v2-ramping-up-test.js`:
- Around line 57-58: The assertion for "응답 데이터 -
todos[0].canRequestCertificationReview 존재" is checking the wrong field (it
currently checks responseData?.todos[0].status !== undefined); update the
predicate to verify the actual field by replacing the check with
responseData?.todos[0].canRequestCertificationReview !== undefined so the test
key and its validation align (locate the failing assertion expression in the
test object where that string key is used).
- Around line 61-65: The conditional accesses on responseData.todos[0] are
unsafe; change the condition and subsequent property checks to use optional
chaining for the todos array and its first element (e.g., replace
responseData?.todos[0].status with responseData?.todos?.[0]?.status) and
likewise use responseData?.todos?.[0]?.certificationContent,
responseData?.todos?.[0]?.certificationMediaUrl and
responseData?.todos?.[0]?.reviewFeedback when assigning to the checks entries so
the test won't throw if todos is undefined or empty.

In `@k6/test/api-single-test/read/04_get-my-todos-in-group/04_v2-spike-test.js`:
- Around line 49-50: The assertion labeled '응답 데이터 -
todos[0].canRequestCertificationReview 존재' is checking the wrong field (it
currently tests todos[0].status); update the check to verify
todos[0].canRequestCertificationReview instead (e.g. replace the expression
responseData?.todos[0].status !== undefined with
responseData?.todos[0].canRequestCertificationReview !== undefined) so the
assertion actually validates the intended property.
- Around line 53-57: The conditional uses unsafe optional chaining on
responseData?.todos[0].status and can throw if todos is undefined; change the
guard to check responseData?.todos?.[0]?.status (or validate
Array.isArray(responseData?.todos) && responseData.todos.length) before
accessing index 0, and update the block that sets checks ('응답 데이터 -
todos[0].certificationContent 존재', '응답 데이터 - todos[0].certificationMediaUrl 존재',
'응답 데이터 - todos[0].reviewFeedback 존재') so those lambdas also use safe access
(todos?.[0]?.certificationContent, etc.) or skip setting them when todos is
absent.

In
`@k6/test/api-single-test/read/05_get-joining-challenge-group-team-ranking/05_v1-ramping-up-test.js`:
- Around line 44-46: The script uses the raw VU index (__VU -> vuIndex) to
access data.challengeGroupIds and can crash when the number of ramping VUs
exceeds the test data length; update the access in the area using vuIndex (and
the same pattern around the later reference) to first validate and normalize the
index: check that data.challengeGroupIds is non-empty and that
data.challengeGroupIds[normalizedIndex] exists (use a safe strategy like
normalizedIndex = vuIndex % data.challengeGroupIds.length or clamp vuIndex to
the last available index), and also guard against empty inner arrays before
calling requestApi/parseResponseBody (log or skip the VU if no data). Ensure you
apply the same guard/normalization where the code later reuses vuIndex.
- Around line 52-58: The checks using responseData?.ranking and
responseData?.ranking[0] can throw if ranking is undefined; update all
predicates that access ranking to use full optional chaining and safe-indexing
(e.g., responseData?.ranking?.length and responseData?.ranking?.[0]?.memberId
etc.) so each assertion (the predicates named like '응답 데이터 - ranking 빈 배열 X' and
the 'ranking[0].* 존재' checks) first verifies ranking exists before accessing its
elements/properties.

In
`@k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-ramping-up-test.js`:
- Around line 48-49: The code uses vuIndex = __VU - 1 and directly indexes
data.challengeGroupIds[vuIndex][0] and
data.otherChallengeGroupMemberIds[vuIndex][0], which can throw when the number
of VUs exceeds the length of the test data; add an explicit bounds check where
vuIndex is computed (variable vuIndex) to verify vuIndex <
data.challengeGroupIds.length and vuIndex <
data.otherChallengeGroupMemberIds.length (or use a safe modulo mapping if
intended), and if the check fails throw or log a clear error mentioning __VU and
vuIndex before calling requestApi; apply the same guard at the other occurrence
that indexes these arrays (the second occurrence noted in the comment).
- Around line 58-66: The check() validators use responseData?.todos without
guarding that todos is an array or has elements, which can throw when todos is
undefined; update each predicate in the check for this test (the check() block
referencing responseData and todos) to first verify
Array.isArray(responseData?.todos) and responseData.todos.length > 0 before
accessing todos[0] properties, then check the individual fields (historyId,
todoId, content, status, canRequestCertification, canRequestCertificationReview,
isRead) only when the array and element exist.

In
`@k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-spike-test.js`:
- Around line 50-57: The assertions in the test use incomplete optional chaining
and will throw if responseData.todos is null/undefined; update each predicate to
safely access todos and its first element (e.g., change
responseData?.todos.length to responseData?.todos?.length and
responseData?.todos[0].historyId to responseData?.todos?.[0]?.historyId) for all
keys shown ('응답 데이터 - todos 빈 배열 X', '응답 데이터 - todos[0].historyId 존재', '응답 데이터 -
todos[0].todoId 존재', '응답 데이터 - todos[0].content 존재', '응답 데이터 - todos[0].status
존재', '응답 데이터 - todos[0].canRequestCertification 존재', '응답 데이터 -
todos[0].canRequestCertificationReview 존재', '응답 데이터 - todos[0].isRead 존재').

In
`@k6/test/api-single-test/read/08_get-my-certification-stats/08_v2-ramping-up-test.js`:
- Line 56: The test's global timeout constant timeout currently set to '1800s'
is far too long for a p(95)<500ms performance goal; change the timeout value
used by the test runner from '1800s' to a short, realistic value (e.g., '10s' or
'30s') to fail fast on slow responses and avoid masking latency issues—update
the const timeout declaration (timeout) and ensure any consumers of timeout in
this script (ramping VU setup or request wrappers) use the new shorter value.
- Line 39: The test fails because the token file
open('../../../../common/secret/tokens.json') may be missing and token indexing
via vuIndex = __VU - 1 can go out of bounds; update the setup to (1) handle a
missing tokens.json by failing fast with a clear error or by using a
configurable fallback (ensure open(...) is wrapped with existence/error
handling), (2) protect token selection used with vuIndex by validating the
tokens array length and either using modulo indexing or a safe guard that
assigns an anonymous/skip behavior when tokens[vuIndex] is undefined, (3) reduce
the per-request timeout currently set to 1800s to a value consistent with your
p(95)<500ms goal (e.g., a few seconds) and make the timeout constant easier to
tune, (4) align the declared setupTimeout with the actual setup duration (make
setupTimeout reflect the real setup time or extend setup to match intention),
and (5) simplify imports by consolidating sleep and check imports instead of
duplicating them.

In
`@k6/test/api-single-test/read/09_get-my-certifications/09_v2-ramping-up-test.js`:
- Around line 39-40: The test uses vuIndex = __VU - 1 and then uses
tokens[vuIndex] in requestApi which can be undefined when the VU count exceeds
the tokens array; update requestApi (or the call site) to validate the index
against the tokens array (tokens) and either map it safely using modulo (e.g.,
tokens[vuIndex % tokens.length]) or explicitly check tokens.length and fail/log
a clear error when there are not enough tokens, ensuring the header never
becomes undefined; reference symbols: vuIndex, requestApi, tokens, and the
header usage inside requestApi.
- Around line 47-55: The checks on nested fields (responseData.certifications
and certificationInfo) can throw when those arrays or elements are missing;
update each predicate to safely guard before accessing .length or [0] — e.g.,
verify Array.isArray(responseData?.certifications) &&
responseData.certifications.length > 0 before using [0], and similarly ensure
responseData.certifications[0] &&
Array.isArray(responseData.certifications[0].certificationInfo) &&
certificationInfo.length > 0 before accessing certificationInfo[0] and its
properties (id, content, status, certificationContent, certificationMediaUrl,
reviewFeedback) so every assertion returns false instead of throwing when data
is absent.

In `@k6/test/api-single-test/read/09_get-my-certifications/09_v2-spike-test.js`:
- Around line 39-47: The assertions access responseData.certifications and
certificationInfo directly which can throw if those arrays are missing or empty;
update each check (the arrow functions referencing responseData, certifications,
certifications[0], certificationInfo, certificationInfo[0]) to first confirm
Array.isArray(responseData?.certifications) &&
responseData.certifications.length > 0 and similarly for certificationInfo
(Array.isArray(responseData.certifications[0]?.certificationInfo) &&
responseData.certifications[0].certificationInfo.length > 0) before accessing
[0] properties, and use optional chaining (?.) for property existence checks
like id/content/status/certificationContent/certificationMediaUrl/reviewFeedback
so failures are recorded rather than throwing.
- Around line 31-32: Ensure you validate the token index before using it: add a
guard that checks vuIndex (computed as __VU - 1) is within bounds of the tokens
array (e.g., vuIndex >= 0 && vuIndex < tokens.length) before calling
requestApi(vuIndex) or accessing tokens[vuIndex]; if out of range, either select
a safe fallback token (like tokens[vuIndex % tokens.length]) or abort with a
clear error/log. Apply the same bounds check where tokens[vuIndex] is used
elsewhere (notably the access referenced around line 53) so the authentication
header cannot break when VU count exceeds tokens.length.

In `@k6/test/scenario-test/scenario-01.js`:
- Line 189: The test entry with key '응답 데이터 -
todos[0].canRequestCertificationReview 존재' is incorrectly checking
todos[0].status; update the arrow function so it verifies
responseData?.todos?.[0]?.canRequestCertificationReview !== undefined instead of
responseData?.todos[0].status !== undefined, ensuring you use optional chaining
(todos?.[0] or todos && todos[0]) to avoid runtime errors; locate the offending
lambda by the exact key string and replace the checked property from status to
canRequestCertificationReview.
- Around line 193-197: The current condition accesses
responseData?.todos[0].status and can throw when responseData is present but
todos is an empty array; change the guard to first confirm todos is an array
with at least one element (e.g. Array.isArray(responseData?.todos) &&
responseData.todos.length > 0) before checking todos[0].status, then only set
the checks (keys like '응답 데이터 - todos[0].certificationContent 존재',
'...certificationMediaUrl 존재', '...reviewFeedback 존재') when that guard passes so
no direct property access on undefined occurs.

In `@k6/test/scenario-test/scenario-02.js`:
- Line 204: The test assertion named '응답 데이터 -
todos[0].canRequestCertificationReview 존재' is checking the wrong field; update
the lambda used for this check so it verifies
responseData?.todos[0].canRequestCertificationReview instead of
responseData?.todos[0].status (locate the assertion key string '응답 데이터 -
todos[0].canRequestCertificationReview 존재' in the k6 scenario-02 test and
replace the checked property).
- Around line 208-212: The code accesses responseData?.todos[0].status which
throws when todos is an empty array; update the condition to first ensure todos
has an element (e.g., responseData?.todos?.length > 0 or
responseData?.todos?.[0]) before checking .status, and replace the
comma-separated assignments with separate statements terminated by semicolons so
the three checks (the keys on the checks object for certificationContent,
certificationMediaUrl, reviewFeedback) are independent assignments executed only
when todos[0] exists.
- Around line 32-41: The iteration_duration threshold is too low and will always
fail—update the thresholds block so iteration_duration reflects the actual
minimum loop sleep time (~21s) plus expected API latency (e.g., set
iteration_duration to something like 'p(95)<22000' or a suitable value >=21000);
also add missing per-endpoint http_req_duration thresholds for the two endpoints
named in the scenario:
'http_req_duration{name:05_get-joining-challenge-group-team-ranking}' and
'http_req_duration{name:06_get-member-today-todo-histories}' (use the same
p(95)<300 ceiling used by the other endpoint thresholds or adjust if those
endpoints need different targets).

---

Outside diff comments:
In
`@k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-spike-test.js`:
- Around line 40-41: The test uses vuIndex = __VU - 1 and then directly indexes
data.challengeGroupIds[vuIndex][0] and
data.otherChallengeGroupMemberIds[vuIndex][0] without guards; add an explicit
runtime check before calling requestApi that ensures data.challengeGroupIds and
data.otherChallengeGroupMemberIds are arrays, that they have an entry at index
vuIndex, and that those entries have a [0] element; if any check fails, throw or
log a clear error mentioning vuIndex, __VU, and the offending array (e.g.,
"data.challengeGroupIds") so failures are deterministic and informative; apply
the same guard around the other usage at the later call (line ~63) that also
uses vuIndex.
- Around line 19-23: The test config uses executor: 'per-vu-iterations' with
vus: 1 and iterations: 1 which only runs one request and doesn't implement a
spike; change the executor to a spike-appropriate executor (e.g., 'ramping-vus'
or 'ramping-arrival-rate'), remove/ignore iterations and single-vus settings,
and replace them with a stages array that models rapid ramp-up → sustain →
ramp-down using the commented values (e.g., target VUs like 100 and 400) and
keep maxDuration as needed; update the options object where executor, vus,
iterations, and stages are defined so the test performs a true spike pattern.

---

Minor comments:
In `@k6/common/test-data/current-activity/clear-current-activity-data.js`:
- Around line 7-9: 주석과 실제 값이 불일치합니다: 현재 nDay 변수는 nDay = 1으로 설정되어 있으므로 주석(기본값은
0)을 nDay의 실제 값 및 동작에 맞게 수정하세요; 또는 의도한 기본값이 0이면 nDay를 0으로 변경하세요. 대상 식별자: nDay 변수와
getDateNDaysAgoMySqlDateFormatString(nDay) 호출부를 찾아 주석문을 "기본값은 1" 또는 "현재 실행값은 1"
등으로 갱신하거나 nDay 값을 0으로 맞추면 됩니다.

---

Nitpick comments:
In
`@k6/test/api-single-test/read/02_get-todo-certifications-for-reviewer/02_v1-ramping-up-test.js`:
- Around line 47-52: The checks are throwing when
responseData.dailyTodoCertifications is undefined, skipping subsequent checks;
fix by first asserting it's an array and non-empty (e.g., replace
'responseData?.dailyTodoCertifications.length > 0' with a safe check using
Array.isArray(responseData?.dailyTodoCertifications) &&
responseData.dailyTodoCertifications.length > 0) and update the other checks to
safely reference the first item (e.g., guard with Array.isArray(...) &&
responseData.dailyTodoCertifications[0] !== undefined or use a temporary const
first = Array.isArray(responseData?.dailyTodoCertifications) &&
responseData.dailyTodoCertifications[0]; then use first?.id, first?.content,
first?.mediaUrl, first?.todoContent, first?.doer) so no check throws when the
array is missing.

In
`@k6/test/api-single-test/read/03_get-joining-challenge-groups-info/03_v1-ramping-up-test.js`:
- Around line 47-59: The check() lambdas access responseData inconsistently
(some use responseData?., others use responseData.joiningChallengeGroups[0]?.)
which can throw if responseData is null; update all predicates to guard
responseData and the array safely—for example replace accesses with
responseData?.joiningChallengeGroups?.length > 0 and
responseData?.joiningChallengeGroups?.[0]?.groupId !== undefined (and similarly
for groupName, currentMemberCount, maximumMemberCount, joinCode, status,
startAt, endAt, progressDay, progressRate) so every lambda uses optional
chaining on responseData and joiningChallengeGroups before indexing.

In
`@k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-ramping-up-test.js`:
- Around line 57-63: The lambdas used in the check object can throw when
certificationPeriods is undefined or empty; update each predicate to guard
access safely: replace 'responseData?.certificationPeriods.length > 0' with
Array.isArray(responseData?.certificationPeriods) &&
responseData.certificationPeriods.length > 0, and change the subsequent
predicates (the ones referencing certificationPeriods[0].day, .createdCount,
.certificatedCount, .certificationRate) to use safe indexing and optional
chaining (e.g. Array.isArray(responseData?.certificationPeriods) &&
responseData.certificationPeriods[0] !== undefined &&
responseData.certificationPeriods[0]?.day !== undefined) or alternatively check
the non-empty array first and then reference
responseData.certificationPeriods[0] in the later lambdas; also apply similar
safe checks for 'ranking.totalMemberCount' and 'ranking.myRank' using
responseData?.ranking?.totalMemberCount !== undefined and
responseData?.ranking?.myRank !== undefined to avoid exceptions.

In
`@k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-spike-test.js`:
- Around line 49-56: The chain accesses inside the check() callback can throw
and abort subsequent checks; update all properties on
responseData.certificationPeriods and ranking to use safe optional chaining
(e.g., change responseData?.certificationPeriods.length > 0 to
responseData?.certificationPeriods?.length > 0 and use
certificationPeriods?.[0]?.day, certificationPeriods?.[0]?.createdCount,
certificationPeriods?.[0]?.certificatedCount,
certificationPeriods?.[0]?.certificationRate and
responseData?.ranking?.totalMemberCount, responseData?.ranking?.myRank) so each
assertion like those in the check() lambda referencing responseData is resilient
and won’t throw if intermediate values are undefined.

In
`@k6/test/api-single-test/read/08_get-my-certification-stats/08_v2-ramping-up-test.js`:
- Around line 1-2: The file currently imports from 'k6' twice (import { sleep }
from 'k6'; and import {check} from 'k6';); consolidate these into a single
import statement that includes both symbols (sleep and check) so the module is
imported once — update the imports where sleep and check are referenced
(symbols: sleep, check) to use a single import line importing both.
- Line 11: The test sets setupTimeout: '30m' which is inconsistent with the
actual setup() behavior (it only calls sleep(5)), so reduce the timeout to a
conservative short value to catch accidental long-running setup (for example
'1m' or '10s'); update the setupTimeout entry near the top of the file (the
setupTimeout property) to a much shorter duration consistent with setup() and
the sleep(5) call so failures are detected quickly.

In
`@k6/test/api-single-test/read/09_get-my-certifications/09_v2-ramping-up-test.js`:
- Line 62: The request timeout value is set too high (const timeout = '1800s')
which hides failures; update the timeout variable(s) to a shorter SLA-aligned
value (for example '30s' or '5s' depending on your SLA) by changing the const
timeout declaration in this test file (and the similar declaration referenced at
line 70) to the chosen shorter string or make it configurable via an environment
variable (e.g., process.env.TEST_TIMEOUT) and use that variable in place of the
hardcoded '1800s'.

In `@k6/test/api-single-test/read/09_get-my-certifications/09_v2-spike-test.js`:
- Around line 10-22: The test options lack thresholds, so add a thresholds block
under the exported options (inside scenarios → v2_09_spike_test or at the
top-level options) to enforce pass/fail criteria; for example define thresholds
for http_req_duration (p(95)<500 or similar) and http_req_failed (<0.01) and any
other SLA metrics you care about, using the options object and the
v2_09_spike_test scenario name to locate where to insert them.
- Line 52: The timeout variable currently set as const timeout = '1800s' is too
long for a spike test; change the timeout to a much shorter duration (e.g.,
'30s' or another appropriate short value) in this file (09_v2-spike-test.js) by
updating the const timeout declaration, and make the same shorter-timeout change
for the other occurrence referenced ("60-60") so both spike test configs use a
short timeout suited for detecting rapid degradation.

In `@k6/test/scenario-test/scenario-01.js`:
- Around line 194-196: The three consecutive assignments to the checks object
are mistakenly written as a single comma-separated expression causing
readability/confusion; change each assignment to a separate statement so that
checks['응답 데이터 - todos[0].certificationContent 존재'], checks['응답 데이터 -
todos[0].certificationMediaUrl 존재'], and checks['응답 데이터 -
todos[0].reviewFeedback 존재'] are each terminated (use semicolons/newlines) and
remain independent expressions referencing
responseData?.todos[0].certificationContent,
responseData?.todos[0].certificationMediaUrl, and
responseData?.todos[0].reviewFeedback respectively.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: a932f2cc-a2a8-4710-8699-0f0a78e90014

📥 Commits

Reviewing files that changed from the base of the PR and between c3f31e2 and a0a243c.

📒 Files selected for processing (35)
  • k6/common/test-data/current-activity/clear-current-activity-data.js
  • k6/common/test-data/test-data-common.js
  • k6/test/api-load-test/read/10_get-my-group-activity-info-and-certifications-sort-by-group-created-at-v1.js
  • k6/test/api-load-test/read/5_get-my-todos-filtered-date-status-v1.js
  • k6/test/api-load-test/read/9_get-my-group-activity-info-and-certifications-sort-by-todo-completed-at-v1.js
  • k6/test/api-single-test/read/01_check-challenge-group-participation-required/01_v1-ramping-up-test.js
  • k6/test/api-single-test/read/01_check-challenge-group-participation-required/01_v1-spike-test.js
  • k6/test/api-single-test/read/02_get-todo-certifications-for-reviewer/02_v1-ramping-up-test.js
  • k6/test/api-single-test/read/02_get-todo-certifications-for-reviewer/02_v1-spike-test.js
  • k6/test/api-single-test/read/03_get-joining-challenge-groups-info/03_v1-ramping-up-test.js
  • k6/test/api-single-test/read/03_get-joining-challenge-groups-info/03_v1-spike-test.js
  • k6/test/api-single-test/read/04_get-my-todos-in-group/04_v2-ramping-up-test.js
  • k6/test/api-single-test/read/04_get-my-todos-in-group/04_v2-spike-test.js
  • k6/test/api-single-test/read/05_get-joining-challenge-group-team-ranking/05_v1-ramping-up-test.js
  • k6/test/api-single-test/read/05_get-joining-challenge-group-team-ranking/05_v1-spike-test.js
  • k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-ramping-up-test.js
  • k6/test/api-single-test/read/06_get-member-today-todo-histories/06_v2-spike-test.js
  • k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-ramping-up-test.js
  • k6/test/api-single-test/read/07_get-my-group-activity-summary/07_v2-spike-test.js
  • k6/test/api-single-test/read/08_get-my-certification-stats/08_v2-ramping-up-test.js
  • k6/test/api-single-test/read/08_get-my-certification-stats/08_v2-spike-test.js
  • k6/test/api-single-test/read/09_get-my-certifications/09_v2-ramping-up-test.js
  • k6/test/api-single-test/read/09_get-my-certifications/09_v2-spike-test.js
  • k6/test/api-single-test/write/1_create-challenge-group-v1/create-challenge-group-v1-k6-test.js
  • k6/test/api-single-test/write/1_create-challenge-group-v1/run.sh
  • k6/test/api-single-test/write/2_join-challenge-group-v1/join-challenge-group-v1-k6-test.js
  • k6/test/api-single-test/write/2_join-challenge-group-v1/run.sh
  • k6/test/api-single-test/write/3_create-daily-todos-v1/create-daily-todos-v1-k6-test.js
  • k6/test/api-single-test/write/3_create-daily-todos-v1/run.sh
  • k6/test/api-single-test/write/4_certify-daily-todo-v1/certify-daily-todo-v1-k6-test.js
  • k6/test/api-single-test/write/4_certify-daily-todo-v1/run.sh
  • k6/test/api-single-test/write/5_review-daily-todo-certification-v1/review-daily-todo-certification-v1-k6-test.js
  • k6/test/api-single-test/write/5_review-daily-todo-certification-v1/run.sh
  • k6/test/scenario-test/scenario-01.js
  • k6/test/scenario-test/scenario-02.js
💤 Files with no reviewable changes (3)
  • k6/test/api-load-test/read/10_get-my-group-activity-info-and-certifications-sort-by-group-created-at-v1.js
  • k6/test/api-load-test/read/9_get-my-group-activity-info-and-certifications-sort-by-todo-completed-at-v1.js
  • k6/test/api-load-test/read/5_get-my-todos-filtered-date-status-v1.js

Comment thread k6/test/scenario-test/scenario-01.js
Comment thread k6/test/scenario-test/scenario-01.js
Comment thread k6/test/scenario-test/scenario-02.js
Comment thread k6/test/scenario-test/scenario-02.js
@dogether-project dogether-project deleted a comment from coderabbitai Bot May 15, 2026
@kelly6bf kelly6bf merged commit 185b694 into dev May 15, 2026
8 checks passed
@kelly6bf kelly6bf deleted the feature/#266-new_k6_script branch May 15, 2026 12:07
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.

[BE] K6 테스트 스크립트 수정

1 participant