testmon/
├── scripts/
│ ├── common/
│ │ ├── endpoints/
│ │ │ ├── read.js # 조회 API 모듈
│ │ │ ├── write.js # 저장 API 모듈
│ │ │ └── flows.js # 통합 시나리오 모듈
│ │ ├── config.js # 공통 설정 및 TEST_DATA
│ │ ├── utils.js # 유틸리티 함수
│ │ └── validators.js # 응답 검증 함수
│ └── tests/
│ ├── 1-read-only.js # 조회 전용 테스트
│ ├── 2-write-only.js # 저장 전용 테스트
│ └── 3-integration.js # 통합 테스트
├── results/ # 테스트 결과
├── config/ # 설정 파일
└── README.md # 이 파일
파일: scripts/common/config.js
// 서버 설정
export const SERVERS = {
prd: 'https://agree.kmi.or.kr',
dev: 'https://dev-agree.kmi.or.kr',
local: 'http://10.1.10.169:8080'
};
// 테스트 데이터 (중앙 관리)
export const TEST_DATA = {
// 예약 및 기본 정보
reservationNo: 'MjUwNjQzNjYyOQ==', // base64 인코딩
rgstno: '2506436629',
instcd: '111',
formId: '30',
userid: '2023060005',
// 동의서 상세 정보
CONSENT_DATA_RID: '',
orddd: '20231118',
pid: 'P001',
formname: '동의서 테스트',
statflag: 'Y',
// 기타 정보
lang: '1',
kicsFlag: 'N',
socialBackNumber: 'N'
};역할:
- ✅ 모든 테스트에서 사용할 기본 데이터 정의
- ✅ 서버 환경 설정
- ✅ HTTP 헤더, 타임아웃 등 공통 설정
파일: scripts/tests/2-write-only.js
export default function() {
// 1. 저장할 폼 데이터 준비
const formData = {
instcd: TEST_DATA.instcd,
reservation_no: TEST_DATA.rgstno,
FORM_ID: TEST_DATA.formId,
CONSENT_STATE: 'TEMP'
};
// 2. 서명 이미지 데이터 준비
const signatures = {
signatureImageTarget: 'data:image/gif;base64,...',
signatureImageDeputy: 'data:image/gif;base64,...',
counselorSign: 'data:image/gif;base64,...'
};
// 3. 저장 플로우 실행
const results = writeOnlyFlow(TEST_DATA, formData, signatures);
}역할:
- ✅ formData와 signatures 객체 생성
- ✅ writeOnlyFlow 호출
파일: scripts/common/endpoints/flows.js
export function writeOnlyFlow(testData, formData, signatures = null) {
const results = {};
// Step 1: 동의서 저장 (consentInsert)
results.consentInsert = WriteAPI.consentInsert(formData);
results.mstRid = results.consentInsert.mstRid; // ← mstRid 추출
// Step 2: 서명 이미지 포함 최종 저장
if (signatures && results.mstRid) {
const saveData = {
// 기본 정보
mstRid: results.mstRid, // ← Step 1에서 생성된 ID
instcd: testData.instcd,
CONSENT_DATA_RID: testData.CONSENT_DATA_RID || '',
FORM_ID: testData.formId,
RGSTNO: testData.rgstno,
formcode: testData.formCd || testData.formId,
orddd: testData.orddd || '',
pid: testData.pid || '',
formname: testData.formname || '',
statflag: testData.statflag || '',
// 서명 이미지
signatures: signatures,
// 기타 정보
lang: testData.lang || '1',
userid: testData.userid,
// URL 동적 생성
url: `${SERVERS.dev}/examination/consent_list/consent_view?` +
`rgstno=${testData.rgstno}&` +
`FORM_ID=${testData.formId}&` +
`mstRid=${results.mstRid}&` +
`instcd=${testData.instcd}&` +
`cmp=C&` +
`lang=${testData.lang || '1'}&` +
`save=&` +
`kicsFlag=${testData.kicsFlag || ''}&` +
`userid=${testData.userid}`,
kicsFlag: testData.kicsFlag || '',
socialBackNumber: testData.socialBackNumber || 'N'
};
results.updateDataSave = WriteAPI.updateConsentDataSave(saveData);
}
return results;
}역할:
- ✅ Step 1: consentInsert로 동의서 저장 → mstRid 획득
- ✅ Step 2: mstRid + testData로 완전한 saveData 객체 생성
- ✅ updateConsentDataSave 호출
중요 포인트:
mstRid는 Step 1의 API 응답에서 추출url은 동적으로 생성 (mstRid 포함)- 모든 필드는 testData에서 가져옴
파일: scripts/common/endpoints/write.js
export function consentInsert(formData, timeout = TIMEOUTS.normal) {
const response = http.post(
`${BASE_URL}/ajax/consentInsert`,
toFormData(formData),
{ headers: HEADERS.ajax, timeout, tags: { name: 'consentInsert' } }
);
const isValid = checkSaveResponse(response, 'consentInsert');
const mstRid = extractMstRid(response); // ← 응답에서 mstRid 추출
return {
response,
isValid,
mstRid // ← flows.js로 반환
};
}API 호출:
POST /ajax/consentInsert
Body: formData (form-urlencoded)
응답 예시:
{
"success": true,
"mstRid": "MST123456"
}export function updateConsentDataSave(saveData, timeout = TIMEOUTS.long) {
const requestData = {
// 기본 정보
instcd: saveData.instcd,
CONSENT_MST_RID: saveData.mstRid,
CONSENT_DATA_RID: saveData.CONSENT_DATA_RID || '',
FORM_ID: saveData.FORM_ID,
RGSTNO: saveData.RGSTNO,
formcode: saveData.formcode || '',
orddd: saveData.orddd,
pid: saveData.pid,
formname: saveData.formname || '',
statflag: saveData.statflag,
// 서명 이미지들
signatureImageTarget: saveData.signatures?.signatureImageTarget || null,
signatureImageDeputy: saveData.signatures?.signatureImageDeputy || null,
counselorSign: saveData.signatures?.counselorSign || null,
// 기타 정보
lang: saveData.lang,
userid: saveData.userid,
url: saveData.url, // ← flows.js에서 생성된 완전한 URL
kicsFlag: saveData.kicsFlag,
socialBackNumber: saveData.socialBackNumber
};
const response = http.post(
`${BASE_URL}/ApiHub/updateConsentDataSave`,
toFormData(requestData),
{ headers: HEADERS.ajax, timeout, tags: { name: 'updateConsentDataSave' } }
);
const isValid = checkSaveResponse(response, 'updateConsentDataSave', 5000);
return { response, isValid };
}API 호출:
POST /ApiHub/updateConsentDataSave
Body: requestData (form-urlencoded, 모든 필드 포함)
┌─────────────────────────────────────────────────────────────┐
│ 1. config.js - TEST_DATA │
│ ├─ instcd: '111' │
│ ├─ formId: '30' │
│ ├─ rgstno: '2506436629' │
│ ├─ userid: '2023060005' │
│ └─ ... (17개 필드) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 2. 2-write-only.js - 테스트 실행 │
│ ├─ formData 생성 │
│ ├─ signatures 생성 │
│ └─ writeOnlyFlow(TEST_DATA, formData, signatures) 호출 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 3. flows.js - writeOnlyFlow() │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Step 1: consentInsert(formData) │ │
│ │ └─ API 호출 → mstRid 획득 │ │
│ └────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Step 2: saveData 객체 생성 │ │
│ │ ├─ mstRid (Step 1에서 획득) │ │
│ │ ├─ testData의 모든 필드 │ │
│ │ ├─ signatures │ │
│ │ └─ url (동적 생성, mstRid 포함) │ │
│ └────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Step 3: updateConsentDataSave(saveData) │ │
│ │ └─ API 호출 → 최종 저장 │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 4. write.js - API 실제 호출 │
│ │
│ consentInsert: │
│ POST /ajax/consentInsert │
│ Body: formData │
│ Response: { mstRid: "MST123456" } │
│ │
│ updateConsentDataSave: │
│ POST /ApiHub/updateConsentDataSave │
│ Body: requestData (모든 필드 포함) │
│ Response: { success: true } │
└─────────────────────────────────────────────────────────────┘
consentInsert API 응답
↓
extractMstRid() 함수로 추출
↓
results.mstRid에 저장
↓
saveData.mstRid에 포함
↓
updateConsentDataSave API로 전송
url: `${SERVERS.dev}/examination/consent_list/consent_view?
rgstno=${testData.rgstno}&
FORM_ID=${testData.formId}&
mstRid=${results.mstRid}& // ← 동적으로 생성된 값
instcd=${testData.instcd}&
...`- config.js: 모든 기본 데이터 정의
- flows.js: 데이터 조합 및 플로우 제어
- write.js: API 호출만 담당
# Chocolatey 사용 (관리자 권한)
choco install k6
# 또는 직접 다운로드
# https://k6.io/docs/getting-started/installation/# 저장 전용 테스트
k6 run scripts/tests/2-write-only.js
# 조회 전용 테스트
k6 run scripts/tests/1-read-only.js
# 통합 테스트
k6 run scripts/tests/3-integration.js
# 결과를 파일로 저장
k6 run --out json=results/test-results.json scripts/tests/2-write-only.js- 페이지 접근 → 기본 코드 조회 → 동의서 목록 조회 → 서식 정보 조회
- 동의서 저장 (consentInsert) → 서명 이미지 저장 (updateConsentDataSave)
- 조회 플로우 + 저장 플로우 전체 실행
| API | Method | 경로 | 설명 |
|---|---|---|---|
| consentInsert | POST | /ajax/consentInsert | 동의서 신규 저장, mstRid 생성 |
| updateConsentDataSave | POST | /ApiHub/updateConsentDataSave | 서명 이미지 포함 최종 저장 |
| consentUpdateField | POST | /ajax/consentUpdateField | 동의서 필드 업데이트 |
| getConsentList | POST | /ajax/getConsentList | 동의서 목록 조회 |
| getConsentMstRid | POST | /ajax/getConsentMstRid | mstRid 확인 |
- ✅ 응답 시간 (Response Time)
- ✅ 처리량 (Throughput)
- ✅ 오류율 (Error Rate)
- ✅ 동시 사용자 처리 능력
- ✅ API 성공률 (Success Rate)
테스트 결과는 results/ 디렉토리에 저장됩니다:
write-only-test-{timestamp}.json- 상세 메트릭write-only-test-{timestamp}.txt- 요약 리포트