개념
같은 반죽을 다른 오븐에 넣으면 다르게 구워진다. 레시피가 같아도 그렇다. 환경은 결과를 바꾸는 보이지 않는 변수이고, 테스트에서는 그 변수가 결과의 신뢰도 자체를 결정한다.
그래서 이 레슨의 목표는 환경을 완벽하게 만드는 것이 아니다. 완벽한 환경은 운영뿐이고, 그것은 비용이 무한하다. 목표는 "지금 이 테스트 결과를 어디까지 믿을 수 있는가" 를 스스로 판단하는 것이다.
환경이 다르면 결과도 다르다
"내 컴퓨터에서는 됐는데요"라는 말은 QA와 개발 모두에게 익숙한 문장이다. 대부분의 원인은 코드가 아니라 환경 차이다 — OS 버전, 설정값, 연결된 외부 서비스, 데이터베이스 상태가 다르면 같은 코드도 다르게 동작한다.
중요한 점은 이것이 양방향이라는 것이다. 환경 차이는 결함을 숨기기도 하고, 없는 결함을 만들어 내기도 한다.
| 방향 | 모습 | 결과 |
|---|---|---|
| 숨긴다 | 데이터가 적어서 느린 쿼리가 안 느리다 | 운영에서 터진다 |
| 숨긴다 | 서버 1대라 동시성 문제가 안 난다 | 운영에서 터진다 |
| 만들어 낸다 | 외부 연동이 모의 서버라 응답이 다르다 | 없는 결함을 보고한다 |
| 만들어 낸다 | 환경 설정이 운영과 달라 기능이 꺼져 있다 | 없는 결함을 보고한다 |
아래 두 줄의 비용이 과소평가된다. 환경 탓인 현상을 결함으로 올리면 개발자가 시간을 쓰고 "재현 불가" 로 돌아오며(모듈 6 레슨 1), 그런 일이 반복되면 QA 리포트의 신뢰가 깎인다. 그래서 결함을 올리기 전에 환경을 확인하는 습관이 필요하다.
환경의 종류
- 개발(Dev) — 개발자가 코드를 짜면서 바로 확인하는 환경. 자주 바뀌고 불안정해도 괜찮다
- 스테이징(Staging) — 운영과 최대한 비슷하게 맞춘 환경. QA가 주로 테스트하는 곳
- 운영(Production) — 실제 사용자가 쓰는 환경
조직이 커지면 사이에 환경이 더 생긴다. 이름은 조직마다 다르지만 역할은 비슷하다.
| 환경 | 주로 쓰는 사람 | 데이터 | 안정성 |
|---|---|---|---|
| 개발(Dev) | 개발자 | 임의 | 불안정해도 된다 |
| QA·통합 | QA | 시딩된 합성 데이터 | 중간. 자주 배포된다 |
| 스테이징 | QA·기획·고객사 | 운영에 가까움 | 높아야 한다 |
| 사전 운영(Pre-prod) | 릴리즈 담당 | 운영 복제 | 운영과 거의 같다 |
| 운영 | 사용자 | 실제 | 최고 |
두 번째와 세 번째를 구분해 두는 것이 실무에서 중요하다. QA 환경은 하루에 여러 번 배포되므로 테스트 중에 바뀔 수 있고, 스테이징은 릴리즈 후보만 올라가므로 판정의 근거로 쓸 수 있다. 둘을 하나로 쓰면 "테스트하는 중에 빌드가 바뀌어서 결과가 뒤섞이는" 일이 생긴다.
그리고 환경마다 주인을 정해 둔다. 누가 배포하고, 누가 설정을 바꾸고, 누가 데이터를 초기화하는지 모르면 환경은 서서히 망가진다.
환경 패리티(Environment Parity)
스테이징 환경이 운영 환경과 얼마나 비슷한지를 환경 패리티라고 한다. 패리티가 낮으면(예: 스테이징은 서버 1대, 운영은 10대로 부하분산) 스테이징에서는 안 보이던 문제(동시성, 부하)가 운영에서만 드러난다. 반대로 패리티가 완벽하면 비용이 커진다 — 실무에서는 어느 정도까지 패리티를 맞출지가 항상 트레이드오프다.
모듈 5(레슨 9)에서 배운 생태계 다이어그램을 떠올려보자. 외부 결제 게이트웨이도 환경마다 "테스트 모드"와 "운영 모드"가 다를 수 있다 — 스테이징에서 결제 테스트를 할 때 진짜 돈이 오가지 않는 테스트 모드로 연결되어 있는지 확인하는 것도 환경 관리의 일부다.
패리티를 어디에 맞출까
전부 맞추는 것은 불가능하므로 우선순위가 필요하다. 효과가 큰 순서는 대체로 이렇다.
| 맞출 것 | 비용 | 안 맞추면 놓치는 것 |
|---|---|---|
| 소프트웨어 버전(DB·런타임·라이브러리) | 낮다 | 동작 차이·구문 차이. 가장 먼저 맞춘다 |
| 설정·기능 플래그 | 낮다 | 기능이 꺼져 있어 테스트 자체가 무의미 |
| 데이터의 양과 다양성 | 중간 | 성능·페이지네이션·정렬 문제 |
| 외부 연동 방식 | 중간 | 응답 형식·지연·실패 처리 |
| 인프라 구성(대수·부하분산) | 높다 | 동시성·세션 공유·캐시 일관성 |
| 네트워크 조건 | 높다 | 타임아웃·재시도 |
첫 두 줄은 비용이 거의 없으므로 변명의 여지가 없다. DB 버전이 다르면 쿼리 동작이 달라지는 경우가 실제로 있고, 맞추는 데 드는 비용은 설정 한 줄이다.
세 번째가 가장 자주 방치된다. 스테이징에 주문이 50건 있고 운영에 500만 건 있으면, 목록·검색·통계 화면의 성능 문제를 영원히 못 만난다. 전체 복제가 어렵다면 양만이라도 합성 데이터로 채워 둔다.
반대로 포기해도 되는 것을 분명히 해 두면 논쟁이 줄어든다. 서버 대수와 네트워크 조건은 비용이 크므로, 그 영역은 스테이징에서 보지 않는다고 선언하고 운영 감시로 대신한다(모듈 4 레슨 6의 전환 감시와 같은 구조).
환경 격리와 플래키 테스트
같은 스테이징 환경을 여러 팀이나 여러 자동화 파이프라인이 동시에 쓰면, 한쪽의 데이터 변경이 다른 쪽의 테스트에 영향을 준다. 이렇게 환경 공유로 인해 어떤 때는 통과하고 어떤 때는 실패하는 테스트를 플래키 테스트(Flaky Test)라 부른다. 플래키 테스트는 코드 결함처럼 보이지만, 원인이 환경 격리 부족인 경우가 실무에서 매우 흔하다 — 이 개념은 스테이지 4(자동화)에서 본격적으로 다시 다룬다.
플래키의 환경적 원인은 몇 가지로 정해져 있다. 목록을 알아 두면 진단이 빨라진다.
| 원인 | 증상 | 확인 방법 |
|---|---|---|
| 다른 사람과 환경 공유 | 혼자 돌리면 통과 | 지금 누가 쓰는지 확인 |
| 배포가 중간에 일어남 | 특정 시각대에만 실패 | 배포 로그와 실패 시각 대조 |
| 전역 설정 변경 | 갑자기 전부 실패 | 기능 플래그·설정 이력 |
| 외부 연동 지연 | 간헐적 타임아웃 | 연동 대상이 샌드박스인지 |
| 캐시 상태 | 두 번째 실행부터 통과 | 캐시 비우고 재실행 |
| 시각·시간대 | 자정 전후, 월말에 실패 | 서버 시간대 설정 |
첫 줄과 네 번째 줄이 대부분을 차지한다. 그리고 둘 다 코드를 봐서는 절대 알 수 없다. 그래서 플래키를 만나면 코드보다 환경을 먼저 본다.
여섯 번째도 의외로 많다. 서버 시간대가 UTC이고 테스트 기대값이 한국 시간이면 오전 9시 이전에 돌리는 테스트만 실패한다. 원인을 모르면 "아침에만 실패하는 이상한 테스트" 로 남는다.
환경은 서서히 어긋난다
처음에는 운영과 같게 만들어도, 몇 달 뒤에는 달라져 있다. 사람이 손으로 바꾼 것이 쌓이기 때문이다.
- 급해서 설정을 직접 바꾸고 기록하지 않았다
- 테스트하려고 기능 플래그를 켜 두고 되돌리지 않았다
- 라이브러리를 한쪽만 올렸다
- 데이터를 손으로 넣고 지웠다
이 어긋남을 줄이는 방법이 환경을 코드로 정의하는 것이다. 설정과 구성이 파일로 저장되어 있으면 다시 만들 수 있고, 무엇이 다른지 비교할 수 있다. QA가 직접 구축하지 않더라도, "이 환경은 재현 가능한가" 를 묻는 것은 QA의 몫이다.
재현이 불가능한 환경은 한 번 망가지면 복구에 며칠이 걸린다. 그 며칠 동안 테스트가 멈추고, 멈춘 만큼 릴리즈가 밀린다.
외부로 나가는 것을 막아 둔다
레슨 2에서 넘긴 문제가 여기 있다. 테스트 환경에서 실제 사용자에게 무언가가 도달하는 사고는 거의 항상 환경 설정 때문에 난다.
| 나가는 것 | 안전장치 |
|---|---|
| 메일·문자 | 발송을 차단하거나 테스트 수신함으로 전부 보냄 |
| 푸시 알림 | 테스트 기기 토큰만 허용 |
| 결제 | 샌드박스 키만 환경에 둔다. 운영 키를 두지 않는다 |
| 외부 API 쓰기 | 모의 서버로 바꾸거나 샌드박스 계정 |
| 배치·정산 | 테스트 환경에서는 아예 끈다 |
세 번째 줄이 원칙 중의 원칙이다. 운영 결제 키가 테스트 환경에 있으면 언젠가 실제 결제가 일어난다. 키를 두지 않으면 사고가 구조적으로 불가능 해진다.
레슨 2에서 본 "운영 데이터 복제" 가 특히 위험한 이유도 여기다. 복제된 데이터에는 실제 사용자의 연락처가 들어 있고, 발송 기능이 켜져 있으면 그 사람들에게 테스트 메일이 간다.
환경을 누가 쓰고 있나
공유 환경에서 가장 값싼 개선은 지금 누가 쓰는지 보이게 하는 것이다. 거창한 도구가 필요 없다.
- 팀 채널에 "QA 환경 사용 중 — 14:00까지" 를 남기는 규칙
- 환경 화면 상단에 환경 이름과 빌드 번호를 띄우기
- 배포 알림을 테스트 담당자에게 보내기
두 번째가 사고를 많이 막는다. 화면만 보고는 지금 어느 환경에 있는지 모르는 경우가 실제로 많고, 운영을 테스트 환경으로 착각해 데이터를 건드리는 사고가 그래서 난다.
운영에서만 확인할 수 있는 것
패리티를 아무리 높여도 운영에서만 보이는 것이 남는다.
| 운영에서만 | 왜 |
|---|---|
| 실제 트래픽 아래의 성능 | 부하를 똑같이 만들 수 없다 |
| 실제 데이터의 다양성 | 사용자가 넣는 값은 상상 밖이다 |
| 외부 서비스의 진짜 응답 | 샌드박스와 운영 동작이 다르다 |
| 캐시·CDN 동작 | 구성이 다르다 |
그래서 운영 확인을 계획에 넣는다. 다만 조건이 있다 — 읽기만 하거나, 영향 범위가 통제된 범위에서만 한다. 모듈 4 레슨 6의 카나리·감시 지표가 이 자리에 쓰이고, 배포 직후 스모크 스위트(레슨 1)를 운영에서 돌리는 것이 가장 흔한 형태다.
환경 때문에 못 본 것을 보고한다
이것이 QA가 환경을 아는 실질적인 이유다. 모듈 6 레슨 5의 "못 한 것" 절에 환경 공백을 적을 수 있게 된다.
"스테이징은 서버 1대 구성이라 동시성 문제는 이번 범위에서 확인하지 못했습니다. 결제 동시 요청은 운영 배포 후 감시 지표로 보겠습니다."
이렇게 적으면 두 가지가 생긴다. 판단하는 사람이 위험을 알게 되고, 반복해서 적히면 환경 투자의 근거가 된다. 말로만 "환경이 부족해요" 라고 하는 것과는 효과가 다르다.
사례 — 스테이징에서 멀쩡했던 세 가지
릴리즈 직후 장애 세 건이 났고, 셋 다 스테이징에서 통과한 것이었다. 원인을 추적하자 전부 환경 차이였다.
| 장애 | 스테이징 | 운영 |
|---|---|---|
| 주문 목록이 20초 만에 열림 | 주문 50건 | 주문 120만 건 |
| 같은 쿠폰이 두 번 사용됨 | 서버 1대 | 서버 6대(잠금이 한 대 안에서만) |
| 결제 실패 안내가 안 뜸 | 모의 서버가 항상 성공 응답 | 실제 실패 응답 형식이 달랐다 |
세 건 모두 테스트 설계의 문제가 아니었다. 케이스도 있었고 실행도 했고 통과했다. 환경이 그 케이스를 무의미하게 만든 것이다.
고친 것은 비용 순서로 셋이었다.
- 데이터 양 채우기(가장 싸다) — 주문 100만 건을 합성으로 시딩
- 모의 서버에 실패 응답 추가 — 실제 실패 형식을 받아 와 반영
- 서버 2대 구성으로 변경 — 비용이 들어 다음 분기로
그리고 3번이 끝나기 전까지는 보고서에 "동시성 미확인" 을 매번 적었다. 두 번째 릴리즈에서 그 줄이 근거가 되어 서버 증설이 승인됐다.
환경 관리 체크포인트
- 이 환경의 데이터베이스는 어떤 데이터로 채워져 있는가(레슨 2의 시딩과 연결)?
- 이 환경에 연결된 외부 서비스는 테스트용인가, 실제 서비스인가?
- 이 환경을 지금 나 혼자 쓰고 있는가, 다른 사람과 공유하고 있는가?
- 설정값(환경변수, 피처 플래그)이 운영과 어떻게 다른가?
실무에서 왜 필요한가
"스테이징에서는 문제없었는데 운영 배포하자마자 장애"는 QA 조직에서 가장 뼈아픈 실패 패턴 중 하나다. 대부분 환경 패리티가 낮았거나, 환경 격리가 안 돼서 테스트 자체가 오염된 상태로 진행된 경우다. 환경을 제대로 이해하고 관리하는 QA는 "이 테스트 결과를 얼마나 신뢰할 수 있는가"를 스스로 판단할 수 있다 — 이건 테스트 케이스 설계 능력만큼 중요한, 그러나 자주 간과되는 역량이다.
결과의 신뢰도를 등급으로 말할 수 있게 된다
같은 "통과" 가 아니다. 어디서 통과했는지에 따라 무게가 다르다.
| 어디서 통과 | 어디까지 믿을 수 있나 |
|---|---|
| 개발 환경 | "로직이 돈다" 까지 |
| QA 환경 | 기능이 의도대로 동작한다 |
| 스테이징 | 운영과 비슷한 조건에서 동작한다 |
| 사전 운영 | 운영에서도 거의 같을 것이다 |
이 구분을 보고에 담는 것이 환경을 아는 QA의 표시다. "통과했습니다" 대신 "QA 환경에서 통과했고, 성능·동시성은 확인 범위가 아닙니다" 라고 적으면 읽는 사람이 위험을 정확히 안다.
결함을 올리기 전에 한 번 걸러낸다
환경 탓인 현상을 결함으로 올리는 것은 QA가 가장 많이 신뢰를 잃는 경로다. "재현 불가" 로 돌아오는 일이 반복되면, 진짜 결함도 가볍게 취급된다.
올리기 전 30초짜리 확인이 이것을 막는다 — 지금 어느 환경인가, 빌드가 언제 바뀌었나, 외부 연동이 모의인가, 누가 같이 쓰고 있나. 네 질문이고, 이 중 하나에서 답이 나오는 경우가 생각보다 많다.
환경 투자는 QA가 요청하지 않으면 안 된다
개발·기획은 환경 부족을 체감하지 않는다. 불편을 매일 겪는 사람이 QA이고, 그 불편을 숫자와 사례로 바꿔 전달하지 않으면 아무도 예산을 쓰지 않는다. 보고서의 "못 한 것" 절이 그 통로다.
채용시장에서의 위치
환경 관리는 공고에 잘 안 적히고 면접에서 깊이가 드러나는 주제다. 특히 "스테이징에서 통과했는데 운영에서 터진 경험" 은 거의 모든 경력 면접에 등장한다.
| 질문 | 약한 답 | 강한 답 |
|---|---|---|
| "스테이징 통과 후 운영 장애 경험?" | "있었습니다. 운이 나빴습니다" | "데이터 양 차이로 성능 문제를 못 봤습니다. 이후 합성 데이터로 양을 채웠습니다" |
| "환경 패리티는 어디까지 맞추셨어요?" | "최대한 맞췄습니다" | "버전·설정은 전부, 데이터 양은 합성으로, 서버 대수는 포기하고 운영 감시로 대신했습니다" |
| "플래키 테스트는 어떻게 다루셨어요?" | "재실행해 봅니다" | "환경부터 봅니다. 공유·배포 타이밍·외부 연동 지연이 대부분입니다" |
| "테스트 결과를 얼마나 신뢰하세요?" | "통과하면 신뢰합니다" | "환경에 따라 신뢰 범위가 다릅니다. 보고에 확인 범위를 함께 적습니다" |
| "환경이 부족하면 어떻게 하셨어요?" | "그냥 했습니다" | "못 본 영역을 매 보고서에 적었고, 그게 증설 근거가 됐습니다" |
두 번째가 가장 변별력이 크다. "최대한 맞췄다" 는 답은 우선순위를 생각해 본 적 없다는 뜻으로 읽힌다. 무엇을 포기했는지 말할 수 있는 사람이 트레이드오프를 다뤄 본 사람이다.
다섯 번째도 좋은 답이다. 환경 부족을 불만이 아니라 근거로 바꾼 경험은 리드 역할에서 바로 쓰인다.
공고 표현으로는 "테스트 환경 구성·관리", "QA 인프라", "CI/CD 환경 이해" 가 이 레슨에 걸린다. 플래키의 코드 쪽 원인과 대응은 스테이지 4에서 이어 받는다.