확인 메일은 브라우저 테스트만으로는 끝까지 진행할 수 없는 가입 흐름의 한 부분입니다. 누군가는 주소를 보유하고, 메일을 받고, 코드를 다시 테스트로 돌려줘야 합니다. 임시 메일함 API가 바로 그 일을 합니다. 테스트 스위트가 HTTP로 서비스에 받은편지함 생성을 요청하고, 도착한 내용을 읽고, 케이스가 끝나면 받은편지함을 버립니다. 브라우저도, 여러 사람이 공유하는 받은편지함도, 수동 복사 붙여넣기도 필요 없습니다.
이 글은 그 구조에서 API 쪽을 다룹니다. 애플리케이션을 로컬 수신 엔드포인트로 향하게 하는 이야기가 아닙니다. 그것은 CI에서 메일을 붙잡는 방법이며, 서로 다른 문제를 풉니다. 로컬 캡처는 애플리케이션이 무엇을 보냈는지 보여주고, 임시 메일함 API는 실제 전달 경로를 거쳐 테스트가 소유한 주소에 무엇이 실제로 도착했는지 보여줍니다.
테스트에서 메일함 API를 쓰는 이유는?
다른 선택지가 진짜 사람의 받은편지함이거나 아무것도 없기 때문입니다.
공유 받은편지함은 형편없는 테스트 픽스처입니다. 여러 실행이 같은 메일함을 읽고, 이전 실행의 메일이 아직 남아 있고, 아무도 요청하지 않은 트래픽이 주소에 쌓입니다. 그러면 모든 단언이 어느 메일이 현재 케이스의 것인지 추측해야 하고, 그 추측이 바로 불안정성이 태어나는 곳입니다.
브라우저로 서비스 제공자의 웹 화면을 긁는 것은 두 번째 나쁜 선택입니다. 예고 없이 바뀌는 마크업, 세션 상태, 그리고 스위트가 계속 지켜봐야 하는 로그인에 테스트를 의존하게 만듭니다. 제공자가 버튼 모양을 바꾸는 순간, 제품과 무관한 이유로 초록 스위트가 빨개집니다.
메일함 API는 두 문제를 모두 없앱니다. 주소는 케이스를 위해 만들어지고, 구조상 비어 있으며, 테스트가 직접 호출할 수 있는 안정된 인터페이스로 읽습니다. 스위트는 제공자가 어떻게 생겼든 신경 쓰지 않고, 계약이 지켜지는지만 봅니다. 생성, 수신, 읽기, 삭제입니다.
프라이버시 측면의 이유도 있습니다. API로 만든 주소는 누구도 나타내지 않습니다. 개인의 메일함이 아니고, 진짜 메일이 도착할 곳도 아니며, 실행과 함께 버려집니다.
테스트에 정말 필요한 엔드포인트는 무엇인가?
메일함 API는 수십 개의 경로를 제공할 수 있지만, 테스트 클라이언트에 필요한 작업은 네 가지뿐입니다. 스위트가 쓰는 방식대로 이름을 붙여 두면 이해하기 쉽습니다.
생성은 주소와 핸들을 돌려줍니다. 주소는 테스트 대상 애플리케이션에 보내라고 알려 주는 값입니다. 핸들은 대개 토큰이나 식별자이며, 이후 모든 호출에서 그 받은편지함에 대해 물을 때 씁니다. 스위트는 둘을 하나의 객체로 다뤄야 하고, 주소에서 핸들을 다시 만들어 내서는 안 됩니다. 제공자는 둘을 무관하게 만들 수 있기 때문입니다.
목록은 본문이 아니라 요약을 돌려줍니다. 메일 한 통당 한 항목으로, 식별자와 보낸 사람, 제목, 도착 시각이 붙습니다. 폴링 루프가 써야 할 호출입니다. 값싸고, 초기에 중요한 유일한 질문, 즉 무엇이든 도착했는지에 답하기에 충분하기 때문입니다.
읽기는 메일 한 통을 전체로 돌려주며 텍스트와 HTML 부분을 포함합니다. 코드가 있는 곳이고, 이 호출은 목록이 일치를 보고한 뒤에만 해야 합니다.
비우기는 받은편지함에서 메일을 지우거나 통째로 삭제합니다. 테스트에 필요한 이유는 두 가지입니다. 새 주소를 만들지 않고 시도 사이를 초기화하는 것, 그리고 케이스가 끝날 때 정리하는 것입니다.
일부 서비스는 메일이 도착하거나 시간이 초과될 때까지 연결을 붙잡는 대기 또는 롱폴링 엔드포인트를 더합니다. 편리하지만 클라이언트는 목록으로 되돌아갈 수 있어야 합니다. 대기 호출이 속도 제한에 가장 잘 걸리는 부분이기 때문입니다.
불안정성 없이 코드를 폴링하려면?
이런 테스트에서 가장 흔한 실수는 고정 대기입니다. 정해진 초 수는 추측입니다. 전달이 느리면 너무 짧고, 빠르면 낭비처럼 길며, 부하가 높은 CI 실행기에서는 양쪽으로 틀립니다. 목록을 호출하고 일치를 확인해 찾는 즉시 반환하는 루프로 바꾸고, 상한을 두어 작업을 멈추는 대신 테스트를 실패하게 만듭니다.
일치 판정은 문제의 나머지 절반입니다. 테스트가 원하는 메일은 케이스가 만든 주소로 온 것이고, 받은편지함에 여러 종류의 메일이 들어올 수 있다면 제목에 안정된 조각을 가진 것입니다. 일치가 여럿이면 가장 최근 것을 고르고, 재시도로 인한 중복 전달이 읽기를 흐리지 않게 합니다. 무조건 첫 번째 메일을 집어서는 안 됩니다. 주소를 재사용할 때 바로 그것이 오래된 코드를 검증해 버리는 방법입니다.
추출에는 기준점이 있어야 합니다. 본문에는 참조 번호, 시각, 가격이 들어 있을 수 있고, 첫 숫자 묶음을 집는 파서는 가끔 그것을 대신 집습니다. 코드를 이끄는 문구를 먼저 찾고, 그 근처에서 코드를 읽고, 아무것도 맞지 않으면 본문을 함께 실어 실패시킵니다.
마지막으로 재전송 제한을 존중합니다. 코드 흐름은 보통 짧은 창 안에서 몇 번만 보내도록 허용하며, 그 제한은 테스트 대상 동작의 일부입니다. 새 코드를 얻으려고 버튼을 다시 누르는 테스트는 결국 거절당하고 잘못된 이유로 실패합니다. 재시도는 메일함을 다시 읽는 것이지, 다른 메일을 유발하는 것이 아닙니다.
엔드투엔드나 CI에 어떻게 연결하는가?
깔끔한 형태는 픽스처입니다. 흐름이 시작되기 전에 픽스처가 받은편지함을 만들어 주소를 돌려줍니다. 테스트는 그 주소로 애플리케이션을 구동합니다. 애플리케이션이 보냈다고 확인하면 단언이 메일함을 읽고 코드를 추출합니다. 케이스가 끝나면 픽스처가 받은편지함을 삭제합니다.
클라이언트는 작고 주입 가능하게 유지합니다. 하나의 모듈이 네 호출을 감싸고, 테스트는 스위트 곳곳에 흩어진 원시 HTTP가 아니라 그 모듈에 의존합니다. 그래야 단위 테스트에서 가짜로 바꿀 수 있고, 단언을 다시 쓰지 않고 같은 스위트를 다른 제공자로 돌릴 수 있습니다.
CI에서는 자격 증명을 작업의 비밀 저장소에 두고, 저장소에도 로그 줄에도 절대 넣지 않습니다. 작업마다, 또는 병렬 워커마다 전용 받은편지함을 주고, 생성한 주소에 실행을 식별하는 접두사를 붙입니다. 길 잃은 메일을 눈으로 보고 귀속시킬 수 있게 하기 위해서입니다. 클라이언트 타임아웃은 작업 자체의 타임아웃보다 짧게 둡니다. 멈춘 폴링이 갑작스러운 작업 취소가 아니라 분명한 메시지로 실패하도록 하기 위해서입니다.
재시도할 것은 읽기이지 흐름 전체가 아닙니다. 코드가 아직 오지 않았으면 기다렸다 다시 읽습니다. 가입을 다시 실행하면 두 번째 메일이 생기고, 단언의 후보가 하나 더 늘어날 뿐입니다. 그리고 메일함 API를 운영 흐름에 넣지 마십시오. 테스트 인프라이며, 스위트가 그것으로 실제 고객에게 보낼 수 있어서는 안 됩니다.
코드를 둘러싼 흐름 자체는 읽기 방식이 아니라 이메일 인증 흐름 테스트에서 다루고, 파싱 단계는 엔드투엔드 테스트의 OTP에서 자세히 설명합니다.
격리와 정리
케이스마다 주소 하나가 대부분의 케이스 간 실패를 막는 원칙입니다. 어느 메일이 누구 것인지 따질 필요가 없어지고, 받은편지함이 한 케이스의 트래픽만 받아 왔기 때문에 신선도 문제도 사라집니다.
정리는 명시적이고 무조건적으로 합니다. 성공 경로만이 아니라 케이스가 통과하든 실패하든 실행되는 뒷정리에서 받은편지함을 삭제합니다. 제공자의 수명 시간에만 기대는 것은 실수입니다. 메일이 같은 머신의 이후 실행에 읽힐 만큼 오래 남을 수 있고, 그 수명은 편의일 뿐 보장이 아닙니다.
정리가 실패하면 기록하고 스위트는 끝까지 돌립니다. 정리 오류는 알 가치가 있지만 제품 결함과 같지 않습니다. 그것 때문에 실행을 실패시키면 팀이 뒷정리 실패를 무시하도록 가르치게 됩니다. 주소가 받은 모든 것은 테스트 데이터로 취급합니다. 하나의 단언을 위해 존재하고, 내보내거나 공유해서는 안 되며, 누군가의 연락처로 다뤄져서도 안 됩니다.
한계와 주의점
메일함 API는 여전히 제3자 의존성이며, 그 한계가 여러분 테스트의 한계가 됩니다. 분당 속도 제한은 큰 병렬 실행에서 몰려드는 생성을 거절할 수 있습니다. 할당량은 동시에 존재할 수 있는 주소 수를 제한합니다. 메일은 지연될 수 있고, 지연된 메일은 도착하기 전까지 사라진 것과 똑같이 보입니다.
일회용 도메인은 또한 널리 차단됩니다. 제공자의 도메인이 바로 테스트하는 가입 양식에서 거절될 수 있고, 정당한 테스트를 이해하기 어려운 실패로 바꿉니다. 그럴 때 답은 제공자를 특별 취급하는 것이 아니라, 테스트 대상 제품이 일회용 주소를 의도적으로 거부하는지 파악하고 그 동작을 의도적으로 테스트하는 것입니다.
정직한 요약입니다. 메일함 API는 무엇이 도착했는지 단언하기에 맞는 도구입니다. 애플리케이션이 무엇을 내보냈는지 단언하려면 로컬 수신 엔드포인트가 더 빠르고 할당량도 없습니다. 성숙한 스위트는 보통 둘 다 씁니다. 대부분의 단언은 로컬 캡처로, 실제 전달 경로 자체가 테스트 대상일 때만 메일함 API로 처리합니다.
다음 단계
공유 받은편지함을 폴링해 코드를 읽는 테스트를 찾아, 메일함 API로 새 주소를 만드는 픽스처로 바꾸십시오. 주소를 실행과 함께 로그에 남기고, 뒷정리에서 삭제하고, 그동안 참아 왔던 불안정성이 얼마나 사라지는지 보십시오. 손으로 진짜 받은편지함이 필요하면 임시 메일 페이지가 곧바로 하나를 만듭니다. 거기서 나오는 주소는 한 번의 실행을 위한 발판이며, 결코 실제 신원이 아닙니다.