일부 요청은 시스템을 떠나기 전에 작업이 필요하고, 일부는 응답이 도착하는 순간 작업이 필요합니다. 결제 API는 타임스탬프와 비밀 키로 계산된 HMAC 서명을 원합니다. 로그인 엔드포인트는 이후의 모든 호출에 필요한 토큰을 반환합니다. 체크아웃 플로우는 응답이 실제로 200을 반환했고 올바른 주문 ID를 가지고 있는지 확인해야 합니다. 이 모든 것을 수동으로 할 수 있지만, 이는 빠르게 지루해지고 요청을 팀원과 공유하는 순간 깨져버립니다.
스크립트가 이러한 문제를 해결해 줍니다. Apidog에서는 요청에 작은 JavaScript 코드를 첨부하여 자동으로 실행할 수 있습니다. 한 세트는 요청이 전송되기 전에 실행되고, 다른 세트는 응답이 돌아온 후에 실행됩니다. 이전에 Postman 스크립트를 작성해 본 적이 있다면, Apidog의 엔진이 동일한 pm 객체 API와 호환되므로 익숙하게 사용할 수 있습니다. 이 가이드는 사전 요청 스크립트에서 요청에 서명하고, 사후 응답 스크립트에서 토큰을 추출하는 실제 예시를 통해 두 단계를 모두 설명합니다. 이 동작은 Apidog 스크립팅 문서에 자세히 설명되어 있지만, 탭 이름과 몇 가지 동작은 Postman과 다르며, 이러한 차이점은 중요합니다.
사전 및 사후 스크립트가 실제로 하는 일
Apidog은 스크립트를 두 단계로 실행하며, 명확한 이름을 사용합니다.
사전 처리 스크립트(Pre Processors)는 요청이 서버로 전송되기 전에 실행됩니다. 여기서는 타임스탬프 생성, 서명 계산, 임의의 주문 ID 설정 또는 변수를 읽어 헤더로 구성하는 등의 작업을 준비합니다. 이 시점에는 응답이 아직 존재하지 않으므로, 응답을 검사하는 모든 작업은 여기에서 사용할 수 없습니다.
사후 처리 스크립트(Post Processors)는 응답이 수신된 후에 실행됩니다. 여기서는 어설션을 통해 반환된 내용을 확인하고, 나중에 재사용할 값을 본문에서 추출합니다. 인증 토큰 추출, 새로 생성된 리소스 ID 확보, 상태 코드 확인, 페이지네이션을 위한 커서 저장 등을 할 수 있습니다.
이러한 구분에서 두 가지 규칙이 따릅니다. 첫째, pm.response (code, status, headers, responseTime, responseSize, text(), json() 포함)는 사후 처리 스크립트에서만 작동합니다. 요청을 보내기 전에는 읽을 응답이 없으므로, 사전 처리 스크립트에서 이를 호출해도 소용이 없습니다. 둘째, 변수는 두 단계가 서로 통신하는 방식입니다. 사전 처리 스크립트가 값을 설정하면 요청이 이를 사용하고, 사후 처리 스크립트는 이를 읽거나 덮어쓸 수 있습니다.
Postman에서 넘어오신다면, 먼저 레이블 변경 사항에 유의하십시오. Apidog의 탭은 "Pre-request Script"와 "Tests"가 아닌 사전 처리 스크립트(Pre Processors)와 사후 처리 스크립트(Post Processors)입니다. 동작은 매우 유사하지만, 화면상의 이름이 다릅니다.
설정: 요청을 열고 탭 찾기
따라하려면 Apidog을 다운로드하십시오. macOS, Windows, Linux에서 무료로 실행되므로 아직 설치하지 않았다면 Apidog 다운로드 페이지에서 받으십시오.
Apidog 내에서 스크립트를 작성하려는 API 요청을 엽니다. 모든 엔드포인트에는 일반적인 Params, Headers, Body 탭과 함께 사전 처리 스크립트(Pre Processors) 탭과 사후 처리 스크립트(Post Processors) 탭이 있습니다. 각 단계에 로직을 추가하려면 해당 탭을 열고 사용자 정의 스크립트 추가(add a Custom Script)를 선택하십시오. 그러면 pm 객체에 대해 일반 JavaScript를 작성할 수 있는 코드 편집기가 열립니다.
무언가를 작성하기 전에, 값이 어디에 저장되는지 아는 것이 도움이 됩니다. Apidog은 다음 우선순위 순서로 변수를 해결합니다:
로컬 변수 > 환경 변수 > 프로젝트 내에서 공유되는 전역 변수 > 팀 내에서 공유되는 전역 변수.
따라서 동일한 이름의 환경 변수보다 로컬 변수가 우선하며, 목록의 아래로 갈수록 우선순위가 낮아집니다. 값이 예상과 다를 때는 이 점을 명심하십시오. 우선순위가 더 높은 무언가가 해당 값을 가리고 있을 수 있습니다. 여러 요청에 걸쳐 유지되는 값을 원한다면, Apidog의 전역 매개변수는 우선순위가 낮지만 안정적인 프로젝트 전반의 설정을 위한 좋은 공간이 됩니다.
사전 처리 스크립트 예시: HMAC로 요청 서명하기
각 요청을 HMAC-SHA256 서명으로 인증하는 결제 엔드포인트를 호출한다고 가정해 봅시다. 이는 많은 공급업체가 웹훅 검증에 사용하는 패턴과 동일하며, Stripe의 서명 문서에 잘 설명되어 있습니다. 서버는 타임스탬프와 요청 본문을 포함하고 API 비밀 키로 서명된 값을 기대합니다. 매번 전송할 때마다 이 두 가지를 새로 생성해야 합니다.
Apidog은 crypto-js를 내장 라이브러리로 제공하므로 아무것도 설치할 필요가 없습니다. 사전 처리 스크립트(Pre Processors) 탭을 열고 사용자 정의 스크립트 추가(add a Custom Script)를 선택한 후 다음 코드를 작성하십시오:
// Pre Processor: sign the request before it is sent
const CryptoJS = require('crypto-js');
// current unix timestamp in seconds
const timestamp = Math.floor(Date.now() / 1000).toString();
// read the secret from an environment variable
const secret = pm.environment.get('payments_api_secret');
// build the string to sign: timestamp + newline + raw body
const body = pm.request.body ? pm.request.body.toString() : '';
const payload = timestamp + '\n' + body;
// compute the HMAC-SHA256 signature, hex encoded
const signature = CryptoJS.HmacSHA256(payload, secret).toString(CryptoJS.enc.Hex);
// stash both values as environment variables for the request to use
pm.environment.set('x_timestamp', timestamp);
pm.environment.set('x_signature', signature);
pm.console.log('Signed request at ' + timestamp);
이 스크립트는 서명을 계산하고 타임스탬프와 서명 모두 환경 변수에 저장합니다. 이제 이를 요청에 연결하십시오. 헤더(Headers) 탭에서 {{variableName}} 구문을 사용하여 저장된 값을 참조합니다:
X-Timestamp: {{x_timestamp}}
X-Signature: {{x_signature}}
전송할 때 Apidog은 사전 처리 스크립트를 먼저 실행하고, 두 변수를 설정한 다음, 이를 헤더에 삽입합니다. 서버는 전송 시점에 유효한 서명을 매번 수동 작업 없이 받게 됩니다. require('crypto-js') 호출은 전체 모듈을 가져옵니다. 서브모듈이 아닌 전체 라이브러리를 가져오므로 require('crypto-js')는 작동하지만 require('crypto-js/sha256')는 작동하지 않습니다.
주의할 점은 변수 작업이 환경 편집기에 입력했을 수 있는 초기 값이 아니라 현재 값에만 영향을 미친다는 것입니다. 서명은 일시적이어야 하므로 여기서는 이것이 원하는 동작입니다. Postman 측에서도 서명 패턴에 대한 설명이 필요하다면, Postman 사전 요청 스크립트에 대한 안내는 Postman의 레이블로 동일한 아이디어를 다루며, Apidog의 사전 처리 스크립트와 깔끔하게 매핑됩니다.
사후 처리 스크립트 예시: 토큰 추출 및 검증
이제 다른 단계입니다. 로그인 요청이 이후의 모든 인증된 호출에 필요한 토큰을 반환하는 상황을 상상해 보세요:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": { "id": 4812, "email": "dana@example.com" },
"expires_in": 3600
}
사후 처리 스크립트(Post Processors) 탭을 열고 사용자 정의 스크립트 추가(add a Custom Script)를 선택한 후, 본문에서 토큰을 추출하여 나중 요청을 위해 저장하십시오:
// Post Processor: verify the response, then extract the token
pm.test('Status is 200', function () {
pm.response.to.have.status(200);
});
const jsonData = pm.response.json();
pm.test('Response returns a token', function () {
pm.expect(jsonData.token).to.be.a('string').and.not.empty;
});
pm.test('User id is present', function () {
pm.expect(jsonData.user.id).to.be.a('number');
});
// store the token so other requests can send it
pm.environment.set('auth_token', jsonData.token);
pm.console.log('Saved token for user ' + jsonData.user.email);
여기서는 두 가지 일이 발생합니다. pm.test() 블록은 Apidog이 기본적으로 지원하는 Chai 스타일 pm.expect() 매처를 사용하여 응답이 예상하는 방식으로 구성되었는지 확인합니다. 그리고 pm.environment.set('auth_token', jsonData.token)는 토큰을 환경에 저장합니다. 이제 모든 후속 요청은 수동으로 아무것도 복사할 필요 없이 Authorization: Bearer {{auth_token}}을 보낼 수 있습니다.
이것의 어설션 부분은 그 자체로 주목할 만합니다. 좋은 사후 응답 검사는 수동적인 클릭 및 육안 검사를 실제 테스트로 바꿔주며, Apidog의 API 어설션 가이드는 알아둘 가치가 있는 매처와 패턴에 대해 더 깊이 설명합니다. 이러한 흐름에 실제와 같은 가짜 데이터를 공급하고 싶다면, Apidog의 Faker.js가 위에 표시된 변수 설정과 잘 어울립니다.
사후 처리 스크립트에서 명확히 기억해야 할 몇 가지 동작이 있습니다. pm.iterationData (테스트 데이터)는 읽기 전용이므로, 데이터 기반 값을 읽을 수는 있지만 스크립트에서 다시 쓸 수는 없습니다. 또한 pm.cookies는 요청과 함께 전송된 쿠키가 아니라 서버가 반환한 응답의 쿠키를 반환합니다.
공용 스크립트로 로직 재사용하기
HMAC 서명 블록을 작성했다면, 아마도 여러 요청에 걸쳐 사용하고 싶을 것입니다. 이를 10개의 엔드포인트에 복사-붙여넣기하는 것은 알고리즘이 변경될 때 10군데를 수정해야 한다는 의미입니다. Apidog의 해결책은 공용 스크립트(Public Scripts)입니다. 이는 한 번 작성하여 필요한 곳에 첨부할 수 있는 재사용 가능한 코드 조각입니다.
설정(Settings) > 공용 스크립트(Public Scripts)에서 하나를 생성한 다음, 요청의 사전 처리 스크립트(Pre Processors) 또는 사후 처리 스크립트(Post Processors) 탭에 추가합니다. 처리기 목록 내에서 공용 스크립트와 사용자 정의 스크립트는 나란히 있으며, 순서가 중요합니다. 공용 스크립트는 동일한 목록의 사용자 정의 스크립트보다 먼저 실행되며, 여러 공용 스크립트가 있는 경우 목록에 나열된 순서대로 위에서 아래로 실행됩니다.
사람들이 실수하기 쉬운 한 가지 함정이 있습니다. 사용자 정의 스크립트가 공용 스크립트에 정의된 함수를 호출하려면 해당 함수는 전역적이어야 합니다. 일반적인 function 선언이나 const로 바인딩된 함수는 해당 스크립트에 로컬이며 다음 스크립트에는 보이지 않습니다. var, let 또는 const 없이 할당하여 선언하십시오:
// In the Public Script: make sign() global by omitting the keyword
sign = function (payload, secret) {
const CryptoJS = require('crypto-js');
return CryptoJS.HmacSHA256(payload, secret).toString(CryptoJS.enc.Hex);
};
// In the Custom Script below it: call the global function by name
const timestamp = Math.floor(Date.now() / 1000).toString();
const secret = pm.environment.get('payments_api_secret');
pm.environment.set('x_timestamp', timestamp);
pm.environment.set('x_signature', sign(timestamp, secret));
공용 스크립트를 먼저 추가하고, 그 아래에 사용자 정의 스크립트를 배치하면 호출이 해결됩니다. 순서를 잘못 지정하거나 const를 추가하면 정의되지 않은 함수 오류가 발생합니다.
라이브러리, 외부 패키지 및 디버깅
위의 crypto-js 가져오기는 Apidog이 설정 없이 번들로 제공하는 라이브러리 세트 중 하나입니다. 다음 라이브러리 중 하나를 직접 require()할 수 있습니다:
crypto-js(v3.1.9-1) for hashing and HMACjsrsasign(v10.3.0) for JWT and RSA work, which needs Apidog 1.4.5 or laterchai(v4.2.0) for the assertion matcherslodash,moment,uuid,xml2js,cheerio,postman-collection,atob,btoa,csv-parse/lib/sync,tv4,ajv- Node built-ins like
path,assert,buffer,util,url,querystring,stream, andevents
목록에 없는 것이 필요하면 $$.liveRequire()를 사용하여 런타임에 가져올 수 있습니다. 이는 패키지를 즉시 가져옵니다:
$$.liveRequire('nanoid', (nanoid) => {
const id = nanoid.nanoid();
pm.environment.set('request_id', id);
});
해당 경로는 인터넷 연결이 필요합니다. 스크립트가 실행될 때 Apidog이 패키지를 다운로드하기 때문입니다. 번들 라이브러리는 필요하지 않습니다.
스크립트가 제대로 작동하지 않을 때는 로그를 통해 문제를 해결하십시오. pm.console.log()와 일반 console.log() 모두 Apidog의 콘솔에 출력되므로, 요청이 나가기 전 또는 반환된 후 스크립트가 정확히 무엇을 생성했는지 (예: 계산된 서명 또는 추출된 필드) 확인할 수 있습니다.
놀라지 않도록 명시할 만한 두 가지 제한 사항이 더 있습니다. 스크립트 내에서 추가 HTTP 호출을 실행하는 pm.sendRequest()는 Promise 대신 콜백 패턴을 사용하므로, await가 아닌 콜백으로 작성해야 합니다. 또한 Postman의 요청 체이닝을 위한 pm.nextRequest()는 여기에서 지원되지 않습니다. 분기 및 조건부 단계가 있는 실제 워크플로우 오케스트레이션이 필요할 때, Apidog은 대신 테스트 시나리오(Test Scenarios)를 사용하며, 여기서 조건(Condition) 및 If-Else 단계로 요청을 시각적으로 순서화합니다. 스크립트를 많이 작성하는 경우, 내장된 Apidog 스크립트 생성기가 자연어 설명에서 스크립트 초안을 작성하여 시작점을 제공할 수도 있습니다.
Apidog CLI로 워크플로우 자동화하기
스크립트는 보내기(Send)를 클릭할 때만 실행되는 것이 아닙니다. 요청과 어설션을 저장된 테스트 시나리오로 패키징하면 Apidog CLI는 해당 시나리오 전체를 헤드리스 방식으로 실행하며, 사전 처리 스크립트와 사후 처리 스크립트도 포함됩니다. 이것이 바로 서명 및 토큰 추출 로직을 수동 단계가 아닌 CI의 일부로 만드는 이유입니다.
CLI를 설치하고 인증한 다음, ID로 시나리오를 실행하십시오:
npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
apidog run --access-token $APIDOG_ACCESS_TOKEN -t <SCENARIO_ID> -e <ENV_ID> -r cli
-t 플래그는 테스트 시나리오 ID, -e는 환경 ID, -r은 리포터 (cli, html 또는 junit, 여러 개는 쉼표로 구분)를 선택합니다. Apidog 계정 설정에서 액세스 토큰을 생성하고 APIDOG_ACCESS_TOKEN으로 내보내면, 데스크톱에서 실행되던 동일한 시나리오가 사전 처리 스크립트와 사후 처리 스크립트를 포함하여 CI에서 실행됩니다.
한 가지 솔직한 주의사항: 로컬 파일이나 한 번 로드한 패키지처럼 본인 컴퓨터에만 존재하는 것에 의존하는 스크립트는 데스크톱 앱에서는 통과하지만, CLI에서는 실패할 수 있습니다. 실행기가 해당 종속성을 가지고 있지 않기 때문입니다. 스크립트를 번들 라이브러리나 $$.liveRequire()로 제한하여 어디에서나 동일하게 실행되도록 하십시오.
자주 묻는 질문
Apidog 스크립트가 기존 Postman 스크립트와 호환되나요?
대부분 그렇습니다. Apidog의 엔진은 동일한 pm 객체 API를 사용하므로, pm.environment.set(), pm.response.json(), pm.test(), pm.expect() 모두 익숙한 방식으로 작동합니다. 기억해야 할 두 가지 차이점은 탭 이름이 Pre-request Script와 Tests가 아닌 사전 처리 스크립트(Pre Processors)와 사후 처리 스크립트(Post Processors)라는 점, 그리고 pm.nextRequest()와 같이 지원되지 않는 몇 가지 호출이 있다는 점입니다. 대부분의 스크립트는 붙여넣고 실행됩니다.
사전 요청 스크립트에서 pm.response가 undefined를 반환하는 이유는 무엇인가요?
아직 응답이 없기 때문입니다. 사전 처리 스크립트는 요청이 전송되기 전에 실행되므로, 검사할 어떤 것도 돌아오지 않습니다. pm.response(상태, 본문, 헤더)를 읽는 모든 코드는 사후 처리 스크립트에 속합니다. 사전 단계에서 값이 필요하면, 대신 pm.request, 변수 또는 라이브러리에서 검색하십시오.
하나의 스크립트를 여러 요청에서 어떻게 공유할 수 있나요?
설정(Settings) > 공용 스크립트(Public Scripts) 아래의 공용 스크립트를 사용하십시오. 로직을 한 번 작성하고, 각 요청의 사전 처리 스크립트 또는 사후 처리 스크립트 탭에 첨부하며, 공용 스크립트가 동일한 목록의 사용자 정의 스크립트보다 먼저 실행된다는 점을 기억하십시오. 사용자 정의 스크립트에서 공용 스크립트 함수를 호출하려면, var, let 또는 const 없이 할당하여 전역으로 선언하십시오.
Apidog이 번들로 제공하지 않는 npm 패키지를 가져올 수 있나요?
네, $$.liveRequire('package-name', (pkg) => { ... })를 사용하면 됩니다. 이 함수는 런타임에 패키지를 다운로드하며 인터넷 연결이 필요합니다. crypto-js, moment, uuid와 같이 내장 목록에 있는 것은 네트워크 연결 없이 일반 require()를 사용하십시오. 전체 모듈만 가져올 수 있으며, 서브모듈 경로는 가져올 수 없다는 점에 유의하십시오.
내 스크립트가 출력한 내용을 어디에서 볼 수 있나요?
pm.console.log() 또는 console.log()를 사용하고 요청을 보낸 후 Apidog의 콘솔에서 출력을 읽으십시오. 시나리오에서 신뢰하기 전에 서명이 계산되었는지 또는 토큰이 추출되었는지 확인하는 가장 빠른 방법입니다.
마무리
사전 처리 스크립트와 사후 처리 스크립트는 정적 요청을 스스로 준비하고 작업을 확인하는 요청으로 바꿉니다. 보내기 전에 서명하고, 받은 후에 추출하고 어설션하며, 공유 로직을 공용 스크립트로 옮겨 한 번만 작성하십시오. pm API와 번들 라이브러리 덕분에 Postman에서 알고 있는 대부분의 기능이 바로 적용됩니다. Apidog을 열고 아무 요청이나 선택한 다음 첫 번째 사용자 정의 스크립트를 추가하여 단일 전송에서 두 단계가 모두 실행되는 것을 확인하십시오. 무료로 시작할 수 있으며 신용카드 정보가 필요 없습니다.
