요약
Postman에서 수동 실행 시 설정한 변수가 컬렉션 러너(Collection Runner)에서는 사라지는 경우가 많습니다. 대부분의 원인은 변수 스코프 불일치입니다. pm.environment.set은 활성 환경에 쓰지만, 러너는 실행 컨텍스트와 변수 유지 방식이 수동 실행과 다릅니다. 이 글에서는 왜 이런 문제가 발생하는지, 어떤 스코프를 써야 하는지, 그리고 러너에서 안정적으로 동작하도록 설정하는 방법을 정리합니다.
소개
Postman에서 API를 수동으로 테스트할 때는 다음 흐름이 정상적으로 동작할 수 있습니다.
- 로그인 요청 실행
- 응답 후 스크립트에서 토큰 저장
- 후속 요청에서
{{token}}사용 - 인증 성공
예를 들어 로그인 요청의 Tests 또는 응답 후 스크립트에서 다음처럼 토큰을 저장합니다.
pm.environment.set('token', pm.response.json().access_token);
수동 실행에서는 후속 요청이 토큰을 잘 읽습니다.
하지만 Run Collection으로 컬렉션을 실행하면 로그인 요청은 성공했는데 다음 요청이 401 Unauthorized로 실패할 수 있습니다. 원인은 대개 토큰이 설정되지 않았거나, 설정되었지만 러너가 기대한 스코프에서 읽지 못했기 때문입니다.
핵심은 Postman의 변수 스코프와 러너의 변수 유지 방식을 정확히 구분하는 것입니다.
Postman의 변수 스코프 계층 구조
Postman은 변수 이름을 해석할 때 다음 우선순위로 값을 찾습니다.
로컬 변수(Local variables)
현재 스크립트 실행 중에만 사용됩니다. 요청 간 공유되지 않습니다.데이터 변수(Data variables)
컬렉션 러너에서 CSV 또는 JSON 데이터 파일로 주입됩니다.컬렉션 변수(Collection variables)
특정 컬렉션에 연결됩니다. 같은 컬렉션의 요청들이 공유할 수 있습니다.환경 변수(Environment variables)
선택된 환경에 연결됩니다. 여러 컬렉션에서 공유할 수 있습니다.글로벌 변수(Global variables)
모든 컬렉션과 환경에서 접근할 수 있습니다.
예를 들어 요청 URL이나 헤더에서 {{token}}을 사용하면 Postman은 위 순서대로 token을 찾고, 가장 먼저 발견한 값을 사용합니다.
따라서 같은 이름의 변수가 여러 스코프에 있으면 예상과 다른 값이 사용될 수 있습니다.
컬렉션 러너에서 변수가 사라지는 이유
1. 현재 값과 초기 값이 다릅니다
Postman 변수에는 보통 두 가지 값이 있습니다.
- Initial value / 초기 값: Postman 클라우드에 동기화되며 팀원과 공유될 수 있습니다.
- Current value / 현재 값: 로컬 머신에 저장되며 동기화되지 않습니다.
스크립트에서 다음 코드를 실행하면:
pm.environment.set('token', value);
Postman은 활성 환경의 현재 값을 업데이트합니다.
수동 테스트에서는 이 현재 값이 같은 Postman 세션 안에서 계속 유지되므로 정상적으로 보입니다.
하지만 컬렉션 러너는 실행 시작 시점의 환경 상태를 로드하고, 실행이 끝난 뒤에는 설정에 따라 변경된 값을 유지하지 않을 수 있습니다. 그래서 러너 안에서는 토큰이 잠시 존재했지만 실행 후 환경 패널에서는 사라진 것처럼 보일 수 있습니다.
2. pm.environment.set은 활성 환경이 필요합니다
다음 코드는 환경 변수에 값을 씁니다.
pm.environment.set('token', pm.response.json().access_token);
하지만 컬렉션 러너에서 환경을 선택하지 않고 실행하면 쓸 대상 환경이 없습니다.
이 경우 pm.environment.set이 기대한 대로 동작하지 않고, 후속 요청에서 {{token}}을 찾지 못할 수 있습니다.
러너 실행 전에는 반드시 환경 드롭다운을 확인해야 합니다.
3. “Keep variable values” 옵션이 꺼져 있을 수 있습니다
컬렉션 러너에는 Keep variable values / 변수 값 유지 옵션이 있습니다.
이 옵션이 꺼져 있으면 러너는 실행 중 변경된 환경 변수 값을 실행 후 유지하지 않습니다. 즉, 스크립트가 토큰을 설정하더라도 실행 종료 후 환경에는 반영되지 않을 수 있습니다.
중요한 점은 다음과 같습니다.
- 같은 러너 실행 안의 다음 요청에서는 값이 사용될 수 있습니다.
- 하지만 실행이 끝난 뒤 환경에 저장되지 않을 수 있습니다.
- 다음 실행에서 다시 빈 값으로 시작할 수 있습니다.
해결 방법 1: 러너에서 “Keep variable values” 확인하기
러너 실행 후에도 환경 변수 값이 유지되어야 한다면 다음을 확인합니다.
- 컬렉션 러너를 엽니다.
- 실행할 컬렉션을 선택합니다.
- 환경을 선택합니다.
- Keep variable values / 변수 값 유지 옵션을 켭니다.
- 컬렉션을 실행합니다.
이 설정은 다음과 같은 경우에 유용합니다.
- 로그인 요청에서 새 토큰을 발급받고 환경에 저장해야 할 때
- 러너 실행 후 다른 요청이나 도구에서 같은 토큰을 재사용해야 할 때
- 다음 컬렉션 실행이 이전 실행에서 갱신한 값을 사용해야 할 때
반대로 다음 상황에서는 주의해야 합니다.
- 반복 실행(iteration)마다 독립적인 상태가 필요할 때
- 1번째 반복에서 설정한 값이 2번째 반복에 영향을 주면 안 될 때
- 테스트 간 상태 오염을 피해야 할 때
이 경우에는 각 반복 시작 시 변수를 명시적으로 초기화하거나 데이터 파일을 사용합니다.
// 반복 시작 시 토큰 초기화 예시
pm.collectionVariables.unset('token');
해결 방법 2: 실행 중 공유 값은 컬렉션 변수로 저장하기
토큰이 같은 컬렉션 실행 안에서만 필요하다면 환경 변수보다 컬렉션 변수가 더 적합합니다.
로그인 요청의 응답 후 스크립트:
const json = pm.response.json();
pm.collectionVariables.set('token', json.access_token);
후속 요청의 사전 요청 스크립트:
const token = pm.collectionVariables.get('token');
console.log('collection token:', token);
요청 헤더에서는 다음처럼 사용할 수 있습니다.
Authorization: Bearer {{token}}
컬렉션 변수는 다음 경우에 적합합니다.
- 로그인 → 사용자 조회 → 주문 생성처럼 한 컬렉션 플로우 안에서만 필요한 값
- 환경을 선택하지 않아도 동작해야 하는 값
- 러너 실행 중 요청 간 상태 공유가 필요한 값
즉, 다음처럼 구분하면 됩니다.
// 여러 컬렉션에서 공유해야 하는 값
pm.environment.set('baseUrl', 'https://api.example.com');
// 현재 컬렉션 플로우에서만 필요한 값
pm.collectionVariables.set('token', accessToken);
해결 방법 3: 실행 전에 환경이 선택되어 있는지 확인하기
pm.environment.set을 사용한다면 러너에서 반드시 환경을 선택해야 합니다.
체크리스트는 다음과 같습니다.
- Collection Runner를 엽니다.
- Environment 드롭다운에서 올바른 환경을 선택합니다.
- 로그인 요청이 실제로 먼저 실행되는지 순서를 확인합니다.
- 후속 요청에서
{{token}}을 참조하는지 확인합니다. - 필요한 경우 Keep variable values를 켭니다.
환경 변수가 필요하지 않다면 다음처럼 컬렉션 변수로 바꾸는 편이 안전합니다.
pm.collectionVariables.set('token', pm.response.json().access_token);
해결 방법 4: 항상 필요한 값은 초기 값도 설정하기
baseUrl, clientId, tenantId처럼 실행 시작부터 필요한 값은 Current value뿐 아니라 Initial value에도 설정합니다.
환경 편집기에서 다음을 확인합니다.
- Initial value가 비어 있지 않은가?
- Current value만 로컬에 설정되어 있지는 않은가?
- 팀원이 실행해도 같은 값이 필요한가?
- CI 또는 Newman에서 실행할 때 환경 파일에 값이 포함되어 있는가?
예를 들어 baseUrl이 Current value에만 있으면 내 Postman에서는 동작하지만 팀원이나 CI에서는 비어 있을 수 있습니다.
권장 방식:
baseUrl
Initial value: https://api.example.com
Current value: https://api.example.com
민감한 값은 팀 공유 여부를 고려해야 합니다. 토큰이나 비밀번호처럼 공유하면 안 되는 값은 Initial value에 넣지 않는 것이 더 안전할 수 있습니다.
해결 방법 5: 콘솔 로그로 실제 스코프 확인하기
변수가 어디에 저장되고 어디에서 읽히는지 확인하려면 Postman Console을 사용합니다.
메뉴에서 다음을 엽니다.
View > Show Postman Console
로그인 요청의 응답 후 스크립트:
const json = pm.response.json();
pm.collectionVariables.set('token', json.access_token);
console.log('set collection token:', pm.collectionVariables.get('token'));
console.log('env token after set:', pm.environment.get('token'));
후속 요청의 사전 요청 스크립트:
console.log('before request - collection token:', pm.collectionVariables.get('token'));
console.log('before request - environment token:', pm.environment.get('token'));
console.log('before request - resolved token:', pm.variables.get('token'));
pm.variables.get('token')은 Postman의 변수 해석 우선순위에 따라 최종적으로 어떤 값이 사용되는지 확인할 때 유용합니다.
같은 이름의 변수가 여러 스코프에 있으면 다음처럼 이름을 분리하는 것도 좋습니다.
collectionAuthToken
environmentAuthToken
또는 토큰은 컬렉션 변수로만 관리하고 환경 변수에는 두지 않는 방식으로 충돌을 줄일 수 있습니다.
권장 구현 패턴
가장 안정적인 방식은 인증 토큰처럼 실행 중 생성되는 값은 컬렉션 변수로 저장하고, 환경별 고정값은 환경 변수로 관리하는 것입니다.
환경 변수
baseUrl
clientId
clientSecret
요청 URL:
{{baseUrl}}/auth/login
로그인 요청 응답 후 스크립트
const json = pm.response.json();
if (!json.access_token) {
throw new Error('access_token이 응답에 없습니다.');
}
pm.collectionVariables.set('token', json.access_token);
console.log('token saved to collection variables');
인증이 필요한 요청의 헤더
Authorization: Bearer {{token}}
토큰 존재 여부 검증
사전 요청 스크립트에서 토큰이 없을 때 명확히 실패시키면 디버깅이 쉬워집니다.
const token = pm.collectionVariables.get('token');
if (!token) {
throw new Error('token 컬렉션 변수가 없습니다. 로그인 요청이 먼저 실행되었는지 확인하세요.');
}
이 패턴을 사용하면 다음 문제가 줄어듭니다.
- 환경 미선택으로 인한
pm.environment.set실패 - 러너 실행 후 환경 값 초기화
- 팀원 로컬 Current value 차이
- 같은 이름의 환경 변수와 컬렉션 변수 충돌
Apidog가 변수 스코프를 처리하는 방법
Apidog도 전역, 환경, 컬렉션, 로컬 스코프 구조를 사용합니다. 차이는 변수 관리 UI와 실행 중 상태 확인 방식에 있습니다.
Apidog의 변수 편집기에서는 초기 값과 현재 값이 명확하게 구분되어 표시됩니다. 이 때문에 현재 값만 설정해 두고 팀 실행이나 러너 실행에서 값이 누락되는 실수를 줄일 수 있습니다.
또한 Apidog는 Postman 호환성을 위해 다음 API를 지원합니다.
pm.environment.set('token', value);
pm.environment.get('token');
pm.collectionVariables.set('token', value);
pm.collectionVariables.get('token');
Postman에서 가져온 컬렉션도 같은 스크립트 문법을 유지할 수 있습니다.
Apidog의 테스트 러너는 명시적으로 구성하지 않는 한 단계 사이의 변수 값을 재설정하지 않습니다. 따라서 수동 테스트에서 기대한 것처럼 실행 중 요청 간 상태가 유지되는 흐름을 만들기 쉽습니다.
일반적인 실수 요약
| 실수 | 증상 | 해결 방법 |
|---|---|---|
| 환경이 선택되지 않음 |
pm.environment.set이 기대대로 동작하지 않음 |
환경을 선택하거나 컬렉션 변수 사용 |
| Current value만 설정됨 | 팀원 또는 CI에서 변수 누락 | 필요한 값은 Initial value도 설정 |
| Keep variable values가 꺼져 있음 | 러너 실행 후 변수 값이 유지되지 않음 | 러너 구성에서 Keep variable values 확인 |
| 실행 중 상태에 환경 변수 사용 | 수동 실행은 통과하지만 러너에서 실패 |
pm.collectionVariables.set 사용 |
| 같은 이름의 변수가 여러 스코프에 있음 | 예상과 다른 값이 사용됨 | 콘솔로 각 스코프 로깅 |
| 로그인 요청 순서가 뒤에 있음 | 후속 요청에서 토큰 없음 | 컬렉션 실행 순서 조정 |
| 토큰 없음에도 테스트가 계속 진행됨 | 원인 파악이 어려운 401 발생 | 사전 요청 스크립트에서 명시적으로 실패 처리 |
자주 묻는 질문
pm.environment.set은 수동 모드에서는 작동하는데 러너에서는 왜 실패하나요?
수동 모드에서는 선택된 환경의 현재 값이 같은 세션에서 유지됩니다. 반면 러너는 실행 시작 시 환경 상태를 로드하고, 설정에 따라 실행 후 변경 사항을 유지하지 않을 수 있습니다. 실행 후에도 값을 저장하려면 Keep variable values를 켜야 합니다.
pm.environment.set과 pm.collectionVariables.set의 차이는 무엇인가요?
pm.environment.set은 선택된 환경에 값을 씁니다. 이 환경은 여러 컬렉션에서 공유될 수 있습니다.
pm.collectionVariables.set은 현재 컬렉션에 값을 씁니다. 같은 컬렉션 실행 안에서 요청 간 값을 공유할 때 적합합니다.
토큰처럼 로그인 요청에서 생성되고 같은 컬렉션 안에서만 쓰는 값은 보통 컬렉션 변수가 더 안전합니다.
Newman에서도 같은 문제가 발생하나요?
네. Newman도 같은 스코프 모델을 사용합니다. 기본적으로 Newman은 실행 후 변경된 환경 상태를 자동으로 저장하지 않습니다.
실행 후 환경 상태를 파일로 남기려면 --export-environment를 사용합니다.
newman run collection.json \
-e environment.json \
--export-environment environment.updated.json
다음 실행에서 업데이트된 환경을 사용하려면:
newman run collection.json \
-e environment.updated.json
Newman의 --export-environment는 언제 사용하나요?
한 실행에서 생성된 토큰이나 상태를 다음 실행에 넘겨야 할 때 사용합니다.
예를 들어 CI 파이프라인에서 첫 번째 단계가 인증 토큰을 생성하고, 두 번째 단계가 그 토큰을 사용해야 한다면 --export-environment로 최종 환경을 파일에 저장할 수 있습니다.
Apidog는 pm.collectionVariables.set을 지원하나요?
네. Apidog는 Postman 호환 스크립팅 API를 지원하므로 다음과 같은 코드를 사용할 수 있습니다.
pm.collectionVariables.set('token', value);
pm.collectionVariables.get('token');
pm.environment.set('token', value);
pm.environment.get('token');
Postman에서 한 컬렉션의 변수를 다른 컬렉션으로 전달하려면 어떻게 하나요?
여러 컬렉션에서 공유해야 한다면 환경 변수 또는 글로벌 변수를 사용할 수 있습니다.
pm.globals.set('token', value);
하지만 글로벌 변수는 스코프가 넓어 이름 충돌과 상태 오염을 만들 수 있습니다. 팀 환경에서는 가능하면 환경 변수로 범위를 제한하는 편이 안전합니다.
마무리
Postman에서 수동 실행은 통과하지만 컬렉션 러너에서 실패한다면 대부분 변수 스코프와 유지 방식 문제입니다.
실무에서는 다음 규칙을 적용하면 안정적입니다.
- 실행 중 생성되는 토큰은
pm.collectionVariables.set으로 저장합니다. - 환경별 고정값은 환경 변수에 저장하고 Initial value를 확인합니다.
-
pm.environment.set을 쓸 때는 러너에서 환경이 선택되어 있는지 확인합니다. - 실행 후 값이 유지되어야 하면 Keep variable values를 켭니다.
- 문제 발생 시
pm.variables.get,pm.environment.get,pm.collectionVariables.get을 모두 로그로 확인합니다.
이렇게 스코프를 명확히 나누면 수동 테스트와 러너 실행 간의 차이로 발생하는 401, 누락 변수, 잘못된 값 사용 문제를 크게 줄일 수 있습니다.
Top comments (0)