플레이키 테스트
Flaky Test
개념
코드를 하나도 고치지 않았는데 어떤 때는 통과하고 어떤 때는 실패하는 테스트로, 자동 검증의 결과를 믿을 수 없게 만드는 문제입니다.
등장 배경
자동 테스트가 값을 갖는 이유는 결과가 약속을 지키기 때문입니다. 초록불이면 안 건드린 곳이 안 깨졌다는 뜻이고 빨간불이면 방금 고친 것 때문에 무언가 망가졌다는 뜻입니다. 이 약속 위에서 개발자는 남의 코드까지 고칠 용기를 얻습니다.
약속이 깨지는 장면은 늘 비슷합니다. 페이지덱에서 태오가 문서 정렬 순서를 고친 변경을 올렸는데 빨간불이 떴습니다. 실패한 것은 결제 화면 테스트였고, 태오가 건드린 코드와는 아무 관계가 없었습니다. 원인을 30분 들여다보다가 혹시 싶어 다시 돌리니 초록불이 나왔습니다. 그대로 합쳤습니다.
문제는 그다음입니다. 두 주쯤 지나자 팀 전체가 빨간불을 보면 로그를 열기 전에 재실행 버튼부터 눌렀습니다. 그러던 어느 날 진짜로 깨진 변경이 그 습관을 타고 그대로 나갔습니다. 플레이키 테스트에 따로 이름이 붙은 이유가 이것입니다. 실패하는 테스트 한 건이 아니라 신호 체계 전체가 망가지는 문제라서, 버그와 구분해 따로 관리합니다.
작동 방식
테스트가 코드가 아니라 실행할 때마다 달라지는 조건에 기대고 있을 때 생깁니다. 원인은 대개 네 갈래입니다.
- 시간에 기댑니다. 화면이 뜨기를 기다리는 자리에 2초를 세고 다음 줄로 넘어가도록 적어 두면, 서버가 조금 느린 날 2.1초가 걸려 실패합니다. 브라우저를 실제로 띄워 사용자가 하는 대로 눌러 보는 E2E 테스트에서 가장 흔합니다.
- 순서에 기댑니다. 앞 테스트가 만들어 둔 사용자 계정을 뒤 테스트가 그대로 쓰는 경우입니다. 하나씩 차례로 돌 때는 멀쩡하다가, 속도를 높이려고 여러 개를 동시에 돌리는 순간 순서가 뒤엉켜 깨집니다.
- 바깥에 기댑니다. 남의 서버나 네트워크에 실제로 요청을 보내면 그쪽 사정이 그대로 결과가 됩니다. 이런 자리를 잘라 내려고 성공이라고만 답하는 가짜를 놓고 돌리는 것이 목인데, 이걸 안 쓰고 진짜 결제사 시험 서버에 붙여 두면 그 서버 점검 시간마다 빨간불이 뜹니다.
- 환경과 무작위성에 기댑니다. 현재 시각을 그대로 쓰는 테스트는 자정을 넘기는 순간이나 월말에만 깨지고, 무작위 값을 쓰는 테스트는 어쩌다 한 번 경계값을 뽑았을 때만 깨집니다. 시간대와 언어 설정이 개발자 노트북과 서버에서 다를 때도 같은 일이 일어납니다.
찾아내는 방법은 단순합니다. 코드를 바꾸지 않은 채로 같은 테스트를 50번 돌려 실패 횟수를 셉니다. 한 번이라도 실패하면 그 테스트는 결정적이지 않고, 실패율이 3퍼센트를 넘으면 목록에 올립니다. 사람이 기억에 의존해 "걔 좀 이상해" 하고 말하는 것보다 이 숫자가 훨씬 빠르게 합의를 만듭니다.
당장 고칠 수 없으면 일단 떼어 냅니다. 본 검증에서 빼고 따로 돌리는 자리로 옮긴 뒤 담당자와 기한을 붙여 둡니다. 다만 떼어 낸 목록이 길어지도록 두면 결국 지운 것과 같아집니다.
쓰이는 곳
이 말이 가장 자주 오가는 자리는 지속적 통합입니다. 변경을 자주 합치고 그때마다 자동으로 검증하는 방식인데, 합쳐도 되는지를 빨간불과 초록불 하나로 판정하기 때문에 신호가 흔들리면 방식 자체가 서지 않습니다. 검증에 15분이 걸리는 팀에서 절반이 헛빨간불이면 하루에 몇 시간씩 기다림만 쌓입니다.
테스트 층을 어떻게 짤지 정할 때도 이 문제가 근거가 됩니다. 함수 하나만 떼어 확인하는 단위 테스트는 바깥에 기대는 것이 거의 없어 플레이키가 드뭅니다. 반대로 E2E 는 브라우저와 네트워크와 시간을 전부 안고 돌아서 대부분의 불안정이 여기 몰립니다. E2E 를 가입과 결제 같은 몇십 개로만 유지하라는 조언에는 느리다는 이유 말고 이 이유도 함께 들어 있습니다.
재실행 정책을 정하는 자리에서도 다뤄집니다. 실패하면 자동으로 한 번 더 돌리게 걸어 두면 당장은 조용해지지만, 증상이 가려지는 대신 원인이 남습니다. 자동 재시도를 쓰더라도 재시도로 살아난 건수를 따로 세어 두는 이유입니다.
그래서 이 값을 주간 지표로 보는 팀이 많습니다. 페이지덱은 매주 월요일에 지난주 헛빨간불 비율과 격리해 둔 테스트 수를 함께 봅니다. 비율이 5퍼센트를 넘긴 주에는 새 기능보다 이쪽을 먼저 잡습니다.
실무 용례
"이거 플레이키예요. 다시 돌려 보세요."
실패 원인이 방금 올린 변경이 아니니 로그를 파지 말라는 뜻입니다.
"그 말 나온 지 두 달 됐어요. 이번엔 원인 잡고 갑시다."
같은 테스트를 계속 재실행으로 넘겨 왔으니 이제 고치자는 제안입니다.
"격리 목록이 서른 개 넘었는데요."
본 검증에서 빼 둔 테스트가 쌓여 실제로 지켜지는 범위가 줄었다는 경고입니다.
페이지덱에서 결제 화면 테스트가 열흘째 오락가락하자 태오가 그 테스트만 100번 돌려 봤습니다. 실패한 열한 번이 전부 오전 9시 정각 근처에 몰려 있었습니다. 외부 결제사 시험 서버가 그 시간대에 재시작하는 것이 원인이었습니다.
고치는 방법은 둘이었습니다. 시험 서버에 붙는 대신 성공만 답하는 가짜를 놓거나, 실패했을 때 잠깐 기다렸다 한 번 더 요청하도록 바꾸는 것입니다. 태오는 앞쪽을 골랐습니다. 뒤쪽은 테스트를 조용하게 만들 뿐, 같은 상황에서 실제 사용자가 겪을 일은 그대로 남기 때문입니다.
흔한 오해
다시 돌리면 통과하니 큰 문제가 아니라고 보는 경우가 가장 많습니다. 한 건만 놓고 보면 30초 더 기다리는 일이라 그렇게 느껴집니다. 하지만 이 문제의 비용은 시간이 아니라 신뢰 쪽에서 나갑니다. 헛빨간불을 몇 번 겪은 사람은 그다음부터 로그를 읽지 않고, 그 습관은 진짜 실패에도 똑같이 적용됩니다. 테스트를 붙여 둔 이유가 통째로 사라지는데 지표상으로는 아무 일도 일어나지 않아 보입니다.
테스트 쪽 사정일 뿐이라고 보는 것도 오해입니다. 불안정한 것은 테스트 코드이니 제품은 멀쩡하다고 생각하기 쉽습니다. 그런데 순서나 시점에 따라 결과가 달라진다는 사실 자체가 제품 코드에서도 같은 일이 일어날 수 있다는 신호인 경우가 있습니다. 두 요청이 동시에 들어올 때만 값이 어긋나는 종류의 결함은 실험실에서 재현하기가 어렵고, 플레이키 테스트가 그 몇 안 되는 재현 창구일 때가 있습니다. 원인을 보지 않고 지워 버리면 그 창구까지 함께 닫힙니다.
같이 보면 좋은 페이지
연관 용어
마지막 업데이트 2026-09-16