개발자가 테스트에 일회용 이메일을 활용하는 방법
이메일 기능 테스트는 지루합니다. Gmail 계정 #47을 만들고, 인증하고, 받은편지함을 확인하고, 이메일 스크린샷을 찍고, 매 테스트마다 반복합니다.
일회용 이메일이 이를 바꿉니다: 주소 생성, 플로우 테스트, 탭 닫기. 정리 작업 제로, 수동 작업 제로.
테스트 문제
기존 이메일 테스트 워크플로우:
1. [email protected]으로 테스트 사용자 생성
2. 비밀번호 재설정 트리거
3. 다른 탭에서 Gmail 열기
4. 이메일 대기
5. 200개의 다른 테스트 이메일 중에서 찾기
6. 테스트 완료
7. 받은편지함에 247개의 테스트 이메일
문제점:
- 받은편지함 오염
- 병렬화 불가능 (같은 주소가 재사용됨)
- Gmail이 테스트 이메일을 스팸으로 표시할 수 있음
- 수백 개의 테스트 계정을 수동으로 정리해야 함
솔루션: 일회용 이메일 API
tempy.email 사용:
// 메일박스 생성
const mailbox = await fetch('https://tempy.email/api/v1/mailbox', {
method: 'POST'
}).then(r => r.json());
// 테스트에서 사용
await yourApp.signup({ email: mailbox.email });
// 이메일 가져오기
const emails = await fetch(
`https://tempy.email/api/v1/mailbox/${mailbox.email}/emails`
).then(r => r.json());
console.log(emails[0].subject); // "이메일을 인증해주세요"
// 주소가 자동으로 만료 - 정리 불필요
실제 사용 사례
1. 통합 테스트
def test_welcome_email():
# 임시 메일박스 생성
r = requests.post('https://tempy.email/api/v1/mailbox')
email = r.json()['email']
# 사용자 생성
create_user(email=email)
# 받은편지함 확인
time.sleep(2)
emails = requests.get(f'https://tempy.email/api/v1/mailbox/{email}/emails')
assert "Welcome" in emails.json()[0]['subject']
2. E2E 테스트 (Cypress/Playwright)
// 테스트 실행마다 고유한 이메일 생성
const mailbox = await cy.request('POST', 'https://tempy.email/api/v1/mailbox');
cy.visit('/signup');
cy.get('[name="email"]').type(mailbox.body.email);
cy.get('button').click();
// 인증 이메일 대기
cy.wait(2000);
cy.request(`https://tempy.email/api/v1/mailbox/${mailbox.body.email}/emails`)
.then((res) => {
const link = extractLink(res.body[0].bodyHtml);
cy.visit(link);
});
3. 부하 테스트
1000건의 가입을 병렬로 테스트 — 각각 고유한 주소:
await Promise.all(
Array(1000).fill().map(async () => {
const m = await createMailbox();
await testSignup(m.email);
// 자동 만료, 정리 불필요
})
);
4. 이메일 템플릿 검증
// 테스트 이메일 발송
await sendEmail({
to: tempAddress,
template: 'order_confirmation',
data: { order: '12345', total: '$99' }
});
// 템플릿이 올바르게 렌더링되었는지 확인
const email = await getEmail(tempAddress);
assert(email.bodyHtml.includes('Order #12345'));
assert(email.bodyHtml.includes('$99'));
API 레퍼런스
메일박스 생성:
POST https://tempy.email/api/v1/mailbox
→ { "email": "[email protected]", "expires_at": "..." }
이메일 가져오기:
GET https://tempy.email/api/v1/mailbox/{address}/emails
→ [{ "subject": "...", "bodyHtml": "...", ... }]
TTL 연장:
POST https://tempy.email/api/v1/mailbox/{address}/extend
→ 5분 추가
모범 사례
테스트마다 고유한 주소 사용:
// 각 테스트가 깨끗한 받은편지함을 받음
test('signup', async () => {
const email = await createUniqueEmail();
await testWith(email);
});
이메일 폴링:
async function pollForEmail(address, timeout = 10000) {
const start = Date.now();
while (Date.now() - start < timeout) {
const emails = await getEmails(address);
if (emails.length > 0) return emails[0];
await sleep(500);
}
throw new Error('이메일이 수신되지 않았습니다');
}
공유 주소 사용 금지:
// 나쁜 예 - 다른 테스트의 이메일이 섞임
const SHARED_EMAIL = '[email protected]';
시간 절약
이전: 10분/테스트 x 100 테스트/주 = 1000분/주 = 주 16.7시간
이후: 30초/테스트 x 100 테스트 = 주 50분
절약: 개발자당 주 15시간 이상.
CI/CD 통합
# .github/workflows/test.yml
name: Email Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test -- email.test.js
env:
TEMP_EMAIL_API: https://tempy.email/api/v1
API 키 불필요. 속도 제한 없음. 그냥 동작합니다.
받은편지함 오염을 멈추세요. tempy.email로 더 스마트하게 테스트하세요.