์ด๋ฉ์ผ ์ฃผ์๋ฅผ ์์งํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ค๋ฉด ๊ธฐ๋ณธ์ ์ธ ํผ ์ ํจ์ฑ ๊ฒ์ฌ ์ด์์ด ํ์ํฉ๋๋ค. ์ด๋ฉ์ผ ๊ฒ์ฆ API๋ ์ด๋ฉ์ผ ์ฃผ์๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ ฅ๋๊ธฐ ์ ์ ์ค์ ๋ก ์กด์ฌํ๊ณ , ์ ์ก ๊ฐ๋ฅํ๋ฉฐ, ์์ ํ๊ฒ ์ฌ์ฉํ ์ ์๋์ง ํ์ธํ๋ ์ธํ๋ผ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ ์ธ์ฆ ๋ฐ ์๋ํฌ์ธํธ๋ถํฐ ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ์ต์ ํ ์ ๋ต์ ์ด๋ฅด๊ธฐ๊น์ง ๊ฐ๋ฐ์๊ฐ ์ด๋ฉ์ผ ๊ฒ์ฆ API๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ์ ํตํฉํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ๊ฒ์ ๋ค๋ฃน๋๋ค.
์ด๋ฉ์ผ ๊ฒ์ฆ API ์ดํดํ๊ธฐ
์ด๋ฉ์ผ ๊ฒ์ฆ API๋ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ ๋ฐ์ ์์ธํ ์ ํจ์ฑ ๊ฒ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ์น ์๋น์ค์ ๋๋ค. ํ์๋ง ํ์ธํ๋ ํด๋ผ์ด์ธํธ ์ธก ์ ํจ์ฑ ๊ฒ์ฌ์ ๋ฌ๋ฆฌ, ์ด๋ฌํ API๋ ๊ตฌ๋ฌธ ์ ํจ์ฑ ๊ฒ์ฌ, ๋๋ฉ์ธ ํ์ธ, MX ๋ ์ฝ๋ ์กฐํ, SMTP ํ์ธ ๋ฐ ์ผํ์ฉ ์ด๋ฉ์ผ ๊ฐ์ง์ catch-all ๋๋ฉ์ธ ์๋ณ๊ณผ ๊ฐ์ ์ถ๊ฐ ์ธํ ๋ฆฌ์ ์ค๋ฅผ ํฌํจํ ํฌ๊ด์ ์ธ ์๋ฒ ์ธก ๊ฒ์ฌ๋ฅผ ์ํํฉ๋๋ค.
BillionVerify์ ๊ฐ์ ์ ๋ฌธ ์ด๋ฉ์ผ ๊ฒ์ฆ ์๋น์ค๋ RESTful API๋ฅผ ํตํด ๊ฒ์ฆ ๊ธฐ๋ฅ์ ๋ ธ์ถํ์ฌ ๊ฐ๋ฐ์๊ฐ ์ด๋ฉ์ผ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ๋ฑ๋ก ํ๋ก์ฐ, ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ ๋ฐ ์ผ๊ด ๊ฒ์ฆ ์ํฌํ๋ก์ฐ์ ์ง์ ํตํฉํ ์ ์๋๋ก ํฉ๋๋ค.
์ด๋ฉ์ผ ๊ฒ์ฆ API๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋?
์ค์๊ฐ ์ ํจ์ฑ ๊ฒ์ฌ ์ฌ์ฉ์ ๋ฑ๋ก์ด๋ ํผ ์ ์ถ ์ค์ ์ฆ์ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ ํ์ธํฉ๋๋ค. ์ฌ์ฉ์๋ ์ ํจํ์ง ์์ ์ฃผ์์ ๋ํด ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ๋ฐ์ ์ฒซ ๋ฒ์งธ ์ํธ ์์ฉ๋ถํฐ ๋ฐ์ดํฐ ํ์ง์ ๊ฐ์ ํฉ๋๋ค.
ํ์ฅ ๊ฐ๋ฅํ ์ธํ๋ผ ์ด๋ฉ์ผ ๊ฒ์ฆ ์ธํ๋ผ๋ฅผ ๊ตฌ์ถํ๊ณ ์ ์งํ๋ ค๋ฉด ์๋นํ ๋ฆฌ์์ค๊ฐ ํ์ํฉ๋๋ค. API๋ ์ด์ ์ค๋ฒํค๋ ์์ด ๋ถ์ฐ ๊ฒ์ฆ ์์คํ , ๊นจ๋ํ IP ํํ ํ ๋ฐ ์ง์์ ์ผ๋ก ์ ๋ฐ์ดํธ๋๋ ์ธํ ๋ฆฌ์ ์ค์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํฌ๊ด์ ์ธ ๊ฒ์ฌ ์ ๋ฌธ ์ด๋ฉ์ผ ๊ฒ์ฆ API๋ ๋ณต์ ํ๋ ๋ฐ ์๋นํ ๊ฐ๋ฐ ๋ ธ๋ ฅ์ด ํ์ํ ์ฌ๋ฌ ์ ํจ์ฑ ๊ฒ์ฌ ๊ธฐ์ ์ ๊ฒฐํฉํฉ๋๋ค. ๋จ์ผ API ํธ์ถ๋ก ๊ตฌ๋ฌธ ์ ํจ์ฑ ๊ฒ์ฌ, ๋๋ฉ์ธ ํ์ธ, SMTP ํ์ธ, ์ผํ์ฉ ์ด๋ฉ์ผ ๊ฐ์ง ๋ฑ์ ์ํํ ์ ์์ต๋๋ค.
์ ํ์ฑ๊ณผ ์ ๋ขฐ์ฑ ์ด๋ฉ์ผ ๊ฒ์ฆ ์๋น์ค๋ ์ ํ์ฑ์ ๋ง์ ํฌ์๋ฅผ ํฉ๋๋ค. ์ด๋ค์ ์ผํ์ฉ ๋๋ฉ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ ์งํ๊ณ , catch-all ๊ตฌ์ฑ์ ์ถ์ ํ๋ฉฐ, ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๊ฐ์ ๋๋ ์ ๊ตํ ๊ฐ์ง ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํฉ๋๋ค.
API ์ธ์ฆ ๋ฐฉ๋ฒ
API ์ก์ธ์ค ๋ณด์์ ๋ชจ๋ ์ด๋ฉ์ผ ๊ฒ์ฆ ํตํฉ์ ๊ธฐ๋ณธ์ ๋๋ค. ๋๋ถ๋ถ์ ์๋น์ค๋ ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก์ ๋ง๋ ์ฌ๋ฌ ์ธ์ฆ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค.
API ํค ์ธ์ฆ
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ธ์ฆ ๋ฐฉ๋ฒ์ ์์ฒญ ํค๋ ๋๋ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋๋ API ํค๋ฅผ ์ฌ์ฉํฉ๋๋ค. API ํค๋ ์ฌ์ฉ๋ ์ถ์ ๋ฐ ์๋ ์ ํ์ ํ์ฉํ๋ฉด์ ๊ฐ๋จํ ํตํฉ์ ์ ๊ณตํฉ๋๋ค.
ํค๋ ๊ธฐ๋ฐ ์ธ์ฆ
const response = await fetch('https://api.billionverify.com/v1/verify', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ email: 'user@example.com' })
});
Bearer ํ ํฐ์ด ์๋ Authorization ํค๋๊ฐ ๊ถ์ฅ๋๋ ์ ๊ทผ ๋ฐฉ์์
๋๋ค. ์ด๋ ์๊ฒฉ ์ฆ๋ช
์ URL ๋ฐ์ ์ ์งํ์ฌ ์๋ฒ ์ก์ธ์ค ๋ก๊ทธ์ ์ค์๋ก ๊ธฐ๋ก๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์ ์ธ์ฆ
์ผ๋ถ API๋ ํน์ ์ปจํ ์คํธ์์ ๋ ๊ฐ๋จํ ํตํฉ์ ์ํด ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ก ํค๋ฅผ ๋ฐ์ต๋๋ค:
GET https://api.billionverify.com/v1/verify?email=user@example.com&api_key=YOUR_API_KEY
ํธ๋ฆฌํ์ง๋ง ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์ ์ธ์ฆ์ ๋ก๊ทธ ๋ฐ ๋ธ๋ผ์ฐ์ ๊ธฐ๋ก์ ์๊ฒฉ ์ฆ๋ช ์ ๋ ธ์ถํฉ๋๋ค. ๊ฐ๋ฅํ๋ฉด ํค๋ ๊ธฐ๋ฐ ์ธ์ฆ์ ์ฌ์ฉํ์ธ์.
API ํค ๋ชจ๋ฒ ์ฌ๋ก
ํ๊ฒฝ ๋ณ์ ์์ค ์ฝ๋์ API ํค๋ฅผ ํ๋์ฝ๋ฉํ์ง ๋ง์ธ์. ํ๊ฒฝ ๋ณ์์ ์ ์ฅํ์ธ์:
const apiKey = process.env.BILLIONVERIFY_API_KEY;
ํค ์ํ API ํค๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ์ํํ๊ณ ์์์ด ์์ฌ๋๋ฉด ์ฆ์ ์ํํ์ธ์. ๋๋ถ๋ถ์ ์๋น์ค๋ ์ํํ ์ํ์ ๊ฐ๋ฅํ๊ฒ ํ๋ ์ฌ๋ฌ ํ์ฑ ํค๋ฅผ ํ์ฉํฉ๋๋ค.
ํ๊ฒฝ๋ณ๋ก ํค ๋ถ๋ฆฌ ๊ฐ๋ฐ, ์คํ ์ด์ง ๋ฐ ํ๋ก๋์ ์ ์๋ก ๋ค๋ฅธ API ํค๋ฅผ ์ฌ์ฉํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ํ ์คํธ ํธ๋ํฝ์ด ํ๋ก๋์ ํ ๋น๋์ ์ํฅ์ ๋ฏธ์น๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ ๋๋ฒ๊น ์ ๋จ์ํํฉ๋๋ค.
ํค ๊ถํ ์ ํ API๊ฐ ๋ฒ์๊ฐ ์ง์ ๋ ๊ถํ์ ์ง์ํ๋ ๊ฒฝ์ฐ ๊ฐ ํค๋ฅผ ํ์ํ ์์ ์ผ๋ก๋ง ์ ํํ์ธ์. ๋จ์ผ ์ด๋ฉ์ผ ๊ฒ์ฆ์๋ง ์ฌ์ฉ๋๋ ํค๋ ๋๋ ์ฒ๋ฆฌ ๊ถํ์ด ํ์ํ์ง ์์ต๋๋ค.
ํต์ฌ API ์๋ํฌ์ธํธ
์ด๋ฉ์ผ ๊ฒ์ฆ API๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก์ ๋ํ ์๋ํฌ์ธํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ฐ ์๋ํฌ์ธํธ์ ๋ชฉ์ ์ ์ดํดํ๋ฉด ํตํฉ์ ์ ํฉํ ์ ๊ทผ ๋ฐฉ์์ ์ ํํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋จ์ผ ์ด๋ฉ์ผ ๊ฒ์ฆ
๊ธฐ๋ณธ ์๋ํฌ์ธํธ๋ ์์ฒญ๋น ํ๋์ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ ๊ฒ์ฆํฉ๋๋ค:
POST /v1/verify
{
"email": "user@example.com"
}
์๋ต ๊ตฌ์กฐ
{
"email": "user@example.com",
"is_valid": true,
"is_deliverable": true,
"is_disposable": false,
"is_role_based": false,
"is_catch_all": false,
"is_free_provider": true,
"syntax_valid": true,
"domain_valid": true,
"mx_found": true,
"smtp_check": "passed",
"risk_score": 15,
"suggestion": null,
"verification_time_ms": 1234
}
์ฃผ์ ์๋ต ํ๋
| ํ๋ | ํ์ | ์ค๋ช |
|---|---|---|
is_valid | boolean | ์ ๋ฐ์ ์ธ ์ ํจ์ฑ ํ๊ฐ |
is_deliverable | boolean | ์ด๋ฉ์ผ์ด ๋ฉ์์ง๋ฅผ ๋ฐ์ ์ ์๋์ง ์ฌ๋ถ |
is_disposable | boolean | ์์/์ผํ์ฉ ์ด๋ฉ์ผ ์ฃผ์ |
is_role_based | boolean | info@, support@์ ๊ฐ์ ์ผ๋ฐ ์ฃผ์ |
is_catch_all | boolean | ๋๋ฉ์ธ์ด ๋ชจ๋ ์ฃผ์๋ฅผ ์๋ฝํจ |
smtp_check | string | SMTP ๊ฒ์ฆ ๊ฒฐ๊ณผ |
risk_score | number | ์ํ ํ๊ฐ (0-100, ๋ฎ์์๋ก ์ข์) |
suggestion | string | ๊ฐ์ง๋ ๊ฒฝ์ฐ ์คํ ์์ ์ ์ |
์ผ๊ด ์ด๋ฉ์ผ ๊ฒ์ฆ
๋๋ ๋ชฉ๋ก์ ๊ฒ์ฆํ๊ธฐ ์ํด ์ผ๊ด ์๋ํฌ์ธํธ๋ ์ฌ๋ฌ ์ด๋ฉ์ผ์ ๋ฐ์ต๋๋ค:
POST /v1/verify/batch
{
"emails": [
"user1@example.com",
"user2@example.com",
"user3@example.com"
]
}
์ผ๊ด ์๋ํฌ์ธํธ๋ ์ด๋ฉ์ผ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ์ฌ ์์ฐจ์ ์ธ ๋จ์ผ ์ด๋ฉ์ผ ์์ฒญ๋ณด๋ค ๋น ๋ฅด๊ฒ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค. ๋๋ถ๋ถ์ ์๋น์ค๋ ์ผ๊ด ํฌ๊ธฐ(์ผ๋ฐ์ ์ผ๋ก ์์ฒญ๋น 100-1000๊ฐ ์ด๋ฉ์ผ)๋ฅผ ์ ํํ๋ฉฐ ๋งค์ฐ ํฐ ์ผ๊ด ์ฒ๋ฆฌ๋ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋ ์ ์์ต๋๋ค.
๋๋ ํ์ผ ์ ๋ก๋
์ผ๊ด ์๋ํฌ์ธํธ์ ๋๋ฌด ํฐ ๋ชฉ๋ก์ ๊ฒฝ์ฐ ํ์ผ ์ ๋ก๋ API๊ฐ ์๋ฐฑ๋ง ๊ฐ์ ๋ ์ฝ๋๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค:
const formData = new FormData();
formData.append('file', emailListFile);
const uploadResponse = await fetch('https://api.billionverify.com/v1/bulk/upload', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
body: formData
});
const { job_id } = await uploadResponse.json();
ํ์ผ ์ ๋ก๋ ์๋ํฌ์ธํธ๋ ์งํ ์ํฉ์ ์ถ์ ํ๊ธฐ ์ํ ์์ ID๋ฅผ ๋ฐํํฉ๋๋ค. ๊ฒฐ๊ณผ๋ ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ๊ฒ์๋ฉ๋๋ค:
// ์์
์ํ ํ์ธ
const statusResponse = await fetch(
`https://api.billionverify.com/v1/bulk/status/${job_id}`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { status, progress, estimated_completion } = await statusResponse.json();
// ์๋ฃ๋๋ฉด ๊ฒฐ๊ณผ ๋ค์ด๋ก๋
if (status === 'completed') {
const resultsResponse = await fetch(
`https://api.billionverify.com/v1/bulk/download/${job_id}`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
}
์นํ ์๋ฆผ
๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๊ฒฝ์ฐ ๊ฒ์ฆ์ด ์๋ฃ๋๋ฉด ์๋ฆผ์ ๋ฐ๋๋ก ์นํ ์ ๊ตฌ์ฑํ์ธ์:
POST /v1/webhooks
{
"url": "https://yourapp.com/webhooks/email-verification",
"events": ["bulk.completed", "bulk.failed"],
"secret": "your_webhook_secret"
}
์นํ ์ ํด๋ง์ ์ ๊ฑฐํ์ฌ ๋๋ ์์ ์ ํจ์จ์ฑ์ ํฅ์์ํต๋๋ค.
์ค๋ฅ ์ฒ๋ฆฌ ์ ๋ต
๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ๋ ํตํฉ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ๋ฐฉํดํ์ง ์๊ณ ์ฐ์ํ๊ฒ ์คํจ๋ฅผ ์ฒ๋ฆฌํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
HTTP ์ํ ์ฝ๋
์ด๋ฉ์ผ ๊ฒ์ฆ API๋ ํ์ค HTTP ์ํ ์ฝ๋๋ฅผ ์ฌ์ฉํฉ๋๋ค:
| ์ฝ๋ | ์๋ฏธ | ์กฐ์น |
|---|---|---|
| 200 | ์ฑ๊ณต | ์๋ต ์ฒ๋ฆฌ |
| 400 | ์๋ชป๋ ์์ฒญ | ์์ฒญ ํ์ ์์ |
| 401 | ์ธ์ฆ๋์ง ์์ | API ํค ํ์ธ |
| 403 | ๊ธ์ง๋จ | ๊ถํ ํ์ธ |
| 404 | ์ฐพ์ ์ ์์ | ์๋ํฌ์ธํธ URL ํ์ธ |
| 429 | ์๋ ์ ํ๋จ | ๋ฐฑ์คํ ๊ตฌํ |
| 500 | ์๋ฒ ์ค๋ฅ | ๋ฐฑ์คํ๋ก ์ฌ์๋ |
| 503 | ์๋น์ค ์ฌ์ฉ ๋ถ๊ฐ | ๋์ค์ ์ฌ์๋ |
์ฌ์๋ ๋ก์ง ๊ตฌํ
๋คํธ์ํฌ ๋ฌธ์ ๋ฐ ์ผ์์ ์ธ ์ค๋ฅ์๋ ์ฌ์๋ ๋ฉ์ปค๋์ฆ์ด ํ์ํฉ๋๋ค:
async function verifyEmailWithRetry(email, maxRetries = 3) {
const delays = [1000, 2000, 4000]; // ์ง์ ๋ฐฑ์คํ
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch('https://api.billionverify.com/v1/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.BILLIONVERIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ email })
});
if (response.status === 429) {
// ์๋ ์ ํ๋จ - ๋๊ธฐ ํ ์ฌ์๋
const retryAfter = response.headers.get('Retry-After') || delays[attempt];
await sleep(parseInt(retryAfter) * 1000);
continue;
}
if (response.status >= 500) {
// ์๋ฒ ์ค๋ฅ - ๋ฐฑ์คํ๋ก ์ฌ์๋
await sleep(delays[attempt]);
continue;
}
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return await response.json();
} catch (error) {
if (attempt === maxRetries - 1) {
throw error;
}
await sleep(delays[attempt]);
}
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
๊ฒ์ฆ ๊ฒฐ๊ณผ ์ฒ๋ฆฌ
๋ชจ๋ ๊ฒ์ฆ์ด ๋ช ํํ ๋ต์ ๋ฐํํ๋ ๊ฒ์ ์๋๋๋ค. ๋ถํ์คํ ๊ฒฐ๊ณผ๋ฅผ ์ ์ ํ ์ฒ๋ฆฌํ์ธ์:
function handleVerificationResult(result) {
if (result.is_valid && result.is_deliverable) {
return { status: 'valid', action: 'accept' };
}
if (!result.syntax_valid || !result.domain_valid) {
return { status: 'invalid', action: 'reject' };
}
if (result.is_disposable) {
return { status: 'risky', action: 'reject_or_warn' };
}
if (result.is_catch_all) {
// ๋ช
ํํ๊ฒ ๊ฒ์ฆํ ์ ์์ - ๋ชจ๋ํฐ๋ง๊ณผ ํจ๊ป ์๋ฝ ๊ณ ๋ ค
return { status: 'uncertain', action: 'accept_with_caution' };
}
if (result.risk_score > 70) {
return { status: 'high_risk', action: 'manual_review' };
}
return { status: 'unknown', action: 'accept_with_monitoring' };
}
์๋ ์ ํ ๋ฐ ์ต์ ํ
์ด๋ฉ์ผ ๊ฒ์ฆ API๋ ๊ณต์ ํ ์ฌ์ฉ๊ณผ ์์คํ ์์ ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ์๋ ์ ํ์ ๊ตฌํํฉ๋๋ค. ํจ๊ณผ์ ์ธ ํตํฉ์ ์ฒ๋ฆฌ๋์ ๊ทน๋ํํ๋ฉด์ ์ด๋ฌํ ์ ํ์ ์กด์คํฉ๋๋ค.
์๋ ์ ํ ์ดํด
์๋ ์ ํ์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ๋ฌ ์์ค์์ ์ ์ฉ๋ฉ๋๋ค:
- ์ด๋น ์์ฒญ ์: ์ด๋น ์ต๋ API ํธ์ถ ์
- ๋ถ/์๊ฐ๋น ์์ฒญ ์: ์ง์์ ์ธ ์๋ ์ ํ
- ์ผ์ผ/์๋ณ ํ ๋น๋: ์ด ๊ฒ์ฆ ํ์ฉ๋
- ๋์ ์ฐ๊ฒฐ: ๋์ ์์ฒญ ์ ํ
์๋ ์ ํ ์ ๋ณด๋ ์๋ต ํค๋๋ฅผ ํ์ธํ์ธ์:
const response = await fetch('https://api.billionverify.com/v1/verify', {
// ... ์์ฒญ ์ต์
});
const rateLimit = response.headers.get('X-RateLimit-Limit');
const remaining = response.headers.get('X-RateLimit-Remaining');
const resetTime = response.headers.get('X-RateLimit-Reset');
console.log(`Rate limit: ${remaining}/${rateLimit}, resets at ${resetTime}`);
์๋ ์ ํ ๊ตฌํ
์ ํ์ ๋๋ฌํ์ง ์๋๋ก ์์ฒญ ์๋๋ฅผ ์ฌ์ ์ ๊ด๋ฆฌํ์ธ์:
class RateLimiter {
constructor(requestsPerSecond) {
this.interval = 1000 / requestsPerSecond;
this.lastRequest = 0;
}
async waitForSlot() {
const now = Date.now();
const timeSinceLastRequest = now - this.lastRequest;
if (timeSinceLastRequest < this.interval) {
await sleep(this.interval - timeSinceLastRequest);
}
this.lastRequest = Date.now();
}
}
// ์ฌ์ฉ๋ฒ
const limiter = new RateLimiter(10); // ์ด๋น 10๊ฐ ์์ฒญ
async function verifyEmailsWithRateLimit(emails) {
const results = [];
for (const email of emails) {
await limiter.waitForSlot();
const result = await verifyEmail(email);
results.push(result);
}
return results;
}
์ผ๊ด ์ฒ๋ฆฌ ์ต์ ํ
์ฌ๋ฌ ์ด๋ฉ์ผ์ ๊ฒ์ฆํ ๋ ํจ์จ์ฑ์ ๊ทน๋ํํ์ธ์:
์ผ๊ด ์๋ํฌ์ธํธ ์ฌ์ฉ ๊ฐ ์ด๋ฉ์ผ์ ๋ํ ๋จ์ผ ์์ฒญ์ ๋คํธ์ํฌ ์๋ณต์ ๋ญ๋นํฉ๋๋ค. ์ผ๊ด ์๋ํฌ์ธํธ๋ ์์ฒญ๋น ์ฌ๋ฌ ์ด๋ฉ์ผ์ ๊ฒ์ฆํฉ๋๋ค:
// ๋นํจ์จ์ : 100๊ฐ์ ๊ฐ๋ณ ์์ฒญ
for (const email of emails) {
await verifyEmail(email);
}
// ํจ์จ์ : 1๊ฐ์ ์ผ๊ด ์์ฒญ
const results = await verifyEmailBatch(emails);
๋๋ ๋ชฉ๋ก ์ฒญํฌ ๋ถํ ๋งค์ฐ ํฐ ๋ชฉ๋ก์ ์ต์ ์ ์ผ๊ด ํฌ๊ธฐ๋ก ๋ถํ ํ์ธ์:
function chunkArray(array, chunkSize) {
const chunks = [];
for (let i = 0; i < array.length; i += chunkSize) {
chunks.push(array.slice(i, i + chunkSize));
}
return chunks;
}
async function verifyLargeList(emails) {
const chunks = chunkArray(emails, 100); // ์ผ๊ด๋น 100๊ฐ ์ด๋ฉ์ผ
const results = [];
for (const chunk of chunks) {
const batchResults = await verifyEmailBatch(chunk);
results.push(...batchResults);
}
return results;
}
์ ํ์ด ์๋ ๋ณ๋ ฌ ์ฒ๋ฆฌ ์๋ ์ ํ์ ์กด์คํ๋ฉด์ ์ฌ๋ฌ ์ผ๊ด ์ฒ๋ฆฌ๋ฅผ ๋์์ ์ฒ๋ฆฌํ์ธ์:
async function verifyWithConcurrency(emails, concurrency = 5) {
const chunks = chunkArray(emails, 100);
const results = [];
for (let i = 0; i < chunks.length; i += concurrency) {
const batch = chunks.slice(i, i + concurrency);
const batchResults = await Promise.all(
batch.map(chunk => verifyEmailBatch(chunk))
);
results.push(...batchResults.flat());
}
return results;
}
์บ์ฑ ์ ๋ต
๊ฒ์ฆ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํ๋ฉด API ๋น์ฉ์ด ์ ๊ฐ๋๊ณ ๋ฐ๋ณต๋๋ ์ด๋ฉ์ผ์ ๋ํ ์๋ต ์๊ฐ์ด ๊ฐ์ ๋ฉ๋๋ค.
์บ์ฑ ์๊ธฐ
๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ ๊ฒ์ฆ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํ์ธ์:
- ๋์ผํ ์ด๋ฉ์ผ์ด ์ฌ๋ฌ ๋ฒ ๊ฒ์ฆ๋ ์ ์๋ ๊ฒฝ์ฐ
- ์ค์๊ฐ ๊ฒ์ฆ์ด ์ค์ํ์ง ์์ ๊ฒฝ์ฐ
- ๋น์ฉ ์ต์ ํ๊ฐ ์ค์ํ ๊ฒฝ์ฐ
๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ ์บ์ฑํ์ง ๋ง์ธ์:
- ์ ์ ๋๊ฐ ์ค์ํ ๊ฒฝ์ฐ (์: ๊ณ ๊ฐ์น ๊ฑฐ๋)
- ์ฌ์ฉ ์ฌ๋ก์์ ์ด๋ฉ์ผ ์ํ๊ฐ ์์ฃผ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ
- ์ ์ฅ ๋น์ฉ์ด API ๋น์ฉ์ ์ด๊ณผํ๋ ๊ฒฝ์ฐ
์บ์ ๊ตฌํ
class VerificationCache {
constructor(ttlMs = 24 * 60 * 60 * 1000) { // 24์๊ฐ ๊ธฐ๋ณธ TTL
this.cache = new Map();
this.ttl = ttlMs;
}
get(email) {
const entry = this.cache.get(email.toLowerCase());
if (!entry) return null;
if (Date.now() > entry.expiry) {
this.cache.delete(email.toLowerCase());
return null;
}
return entry.result;
}
set(email, result) {
this.cache.set(email.toLowerCase(), {
result,
expiry: Date.now() + this.ttl
});
}
}
// ์ฌ์ฉ๋ฒ
const cache = new VerificationCache();
async function verifyEmailCached(email) {
const cached = cache.get(email);
if (cached) {
return { ...cached, fromCache: true };
}
const result = await verifyEmail(email);
cache.set(email, result);
return { ...result, fromCache: false };
}
์บ์ TTL ๊ณ ๋ ค์ฌํญ
๋ค์ํ ๊ฒฐ๊ณผ ์ ํ์๋ ๋ค๋ฅธ ์บ์ ๊ธฐ๊ฐ์ด ํ์ํฉ๋๋ค:
| ๊ฒฐ๊ณผ ์ ํ | ๊ถ์ฅ TTL | ์ด์ |
|---|---|---|
| ์ ํจํ์ง ์์ ๊ตฌ๋ฌธ | 30์ผ | ๋ณ๊ฒฝ๋์ง ์์ |
| ๋๋ฉ์ธ์ด ์กด์ฌํ์ง ์์ | 7์ผ | ๋๋ฉ์ธ์ด ๊ฑฐ์ ๋ํ๋์ง ์์ |
| ์ ํจ + ์ ์ก ๊ฐ๋ฅ | 24-48์๊ฐ | ์ํ๊ฐ ๋ณ๊ฒฝ๋ ์ ์์ |
| ์ผํ์ฉ | 7์ผ | ์ผํ์ฉ ์ํ๋ ์์ ์ ์ |
| Catch-all | 24์๊ฐ | ๊ตฌ์ฑ์ด ๋ณ๊ฒฝ๋ ์ ์์ |
๋ณด์ ๋ชจ๋ฒ ์ฌ๋ก
์ธ๋ถ API๋ฅผ ํตํฉํ๋ฉด ์ธ์ฆ์ ๋์ด ๋ณด์ ๊ณ ๋ ค ์ฌํญ์ด ๋ฐ์ํฉ๋๋ค.
์ ๋ ฅ ์ ํจ์ฑ ๊ฒ์ฌ
API์ ๋ณด๋ด๊ธฐ ์ ์ ์ด๋ฉ์ผ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ์ธ์:
function isValidEmailFormat(email) {
if (typeof email !== 'string') return false;
if (email.length > 254) return false;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
async function verifyEmailSafely(email) {
if (!isValidEmailFormat(email)) {
return { is_valid: false, reason: 'Invalid format' };
}
return await verifyEmail(email);
}
์์ ํ ๋ก๊น
์ ์ฒด API ํค๋ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋กํ์ง ๋ง์ธ์:
function logApiRequest(email, response) {
// ๊ธฐ๋กํ์ง ๋ง์ธ์: API ํค, ํ๋ก๋์
์์ ์ ์ฒด ์ด๋ฉ์ผ ์ฃผ์
console.log({
email_domain: email.split('@')[1],
status: response.status,
is_valid: response.is_valid,
timestamp: new Date().toISOString()
});
}
HTTPS๋ง ์ฌ์ฉ
ํญ์ API ํต์ ์ HTTPS๋ฅผ ์ฌ์ฉํ์ธ์. ํ๋ก๋์ ์์ SSL ์ธ์ฆ์๋ฅผ ํ์ธํ์ธ์:
// Node.js - ํ๋ก๋์
์์ ์ธ์ฆ์ ํ์ธ์ ๋นํ์ฑํํ์ง ๋ง์ธ์
const https = require('https');
const agent = new https.Agent({
rejectUnauthorized: true // ๊ธฐ๋ณธ๊ฐ์ด์ง๋ง ๋ช
์์ ์ผ๋ก
});
์ธ๊ธฐ ํ๋ ์์ํฌ์์ ํตํฉ
Express.js ๋ฏธ๋ค์จ์ด
์ด๋ฉ์ผ ๊ฒ์ฆ์ ์ํ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฏธ๋ค์จ์ด๋ฅผ ๋ง๋์ธ์:
const emailVerificationMiddleware = async (req, res, next) => {
const { email } = req.body;
if (!email) {
return next();
}
try {
const result = await verifyEmail(email);
req.emailVerification = result;
if (!result.is_valid) {
return res.status(400).json({
error: 'Invalid email address',
details: result
});
}
next();
} catch (error) {
// Fail open - API ์ค๋ฅ ์ ๋ฑ๋ก์ ์ฐจ๋จํ์ง ์์
req.emailVerification = { verified: false, error: error.message };
next();
}
};
// ์ฌ์ฉ๋ฒ
app.post('/register', emailVerificationMiddleware, (req, res) => {
// req.emailVerification์ ๊ฒ์ฆ ๊ฒฐ๊ณผ ํฌํจ
});
React Hook
ํ๋ก ํธ์๋ ์ด๋ฉ์ผ ๊ฒ์ฆ์ ์ํ ์ฌ์ฉ์ ์ ์ ํ ์ ๋ง๋์ธ์:
import { useState, useCallback } from 'react';
import debounce from 'lodash/debounce';
function useEmailVerification() {
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const verify = useCallback(
debounce(async (email) => {
if (!email || !email.includes('@')) {
setResult(null);
return;
}
setLoading(true);
setError(null);
try {
const response = await fetch('/api/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email })
});
const data = await response.json();
setResult(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}, 500),
[]
);
return { verify, result, loading, error };
}
๋ชจ๋ํฐ๋ง ๋ฐ ๋ถ์
API ์ฌ์ฉ๋ ๋ฐ ๊ฒ์ฆ ๊ฒฐ๊ณผ๋ฅผ ์ถ์ ํ์ฌ ํตํฉ์ ์ต์ ํํ์ธ์.
๋ชจ๋ํฐ๋งํ ์ฃผ์ ์งํ
- API ์๋ต ์๊ฐ: ์ง์ฐ ์๊ฐ ์ถ์ธ ์ถ์
- ์ค๋ฅ์จ: ์ ํ๋ณ ์คํจ ๋ชจ๋ํฐ๋ง
- ์บ์ ์ ์ค๋ฅ : ์บ์ฑ ํจ์จ์ฑ ์ธก์
- ๊ฒ์ฆ ๋ถํฌ: ์ ํจ/์ ํจํ์ง ์์/์ํ ๋น์จ ์ถ์
- ๊ฒ์ฆ๋น ๋น์ฉ: ์ค์ ๋น์ฉ ๊ณ์ฐ
๋ถ์์ ์ํ ๋ก๊น
function logVerification(email, result, metadata) {
const logEntry = {
timestamp: new Date().toISOString(),
email_domain: email.split('@')[1],
is_valid: result.is_valid,
is_deliverable: result.is_deliverable,
is_disposable: result.is_disposable,
risk_score: result.risk_score,
response_time_ms: metadata.responseTime,
from_cache: metadata.fromCache,
source: metadata.source // registration, import, etc.
};
// ๋ถ์ ์์คํ
์ผ๋ก ์ ์ก
analytics.track('email_verification', logEntry);
}
BillionVerify API ํตํฉ
BillionVerify๋ ๊ฐ๋ฐ์๋ฅผ ์ํด ์ค๊ณ๋ ํฌ๊ด์ ์ธ ์ด๋ฉ์ผ ๊ฒ์ฆ API๋ฅผ ์ ๊ณตํฉ๋๋ค. API๋ ์ฌ๋ฌ ๊ฒ์ฆ ๊ธฐ์ ์ ๋จ์ผ ํธ์ถ๋ก ๊ฒฐํฉํ์ฌ ์์ธํ ์ธ์ฌ์ดํธ์ ํจ๊ป ๋น ๋ฅด๊ณ ์ ํํ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณตํฉ๋๋ค.
๋น ๋ฅธ ์์
async function verifyWithBillionVerify(email) {
const response = await fetch('https://api.billionverify.com/v1/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.BILLIONVERIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ email })
});
return await response.json();
}
๊ธฐ๋ฅ
- ์ค์๊ฐ ๊ฒ์ฆ: ๋จ์ผ ์ด๋ฉ์ผ ๊ฒ์ฆ์ ๋ํ 1์ด ๋ฏธ๋ง์ ์๋ต ์๊ฐ
- ์ผ๊ด ์ฒ๋ฆฌ: ์์ฒญ๋น ์ต๋ 1000๊ฐ์ ์ด๋ฉ์ผ ๊ฒ์ฆ
- ๋๋ ํ์ผ ์ ๋ก๋: ๋น๋๊ธฐ ์์ ์ฒ๋ฆฌ๋ก ์๋ฐฑ๋ง ๊ฐ์ ๋ ์ฝ๋ ์ฒ๋ฆฌ
- ํฌ๊ด์ ์ธ ๊ฒ์ฌ: ๊ตฌ๋ฌธ, ๋๋ฉ์ธ, MX, SMTP, ์ผํ์ฉ, catch-all ๊ฐ์ง
- ์ํ ์ ์ ํ๊ฐ: ์ด์ง ์ ํจ/์ ํจํ์ง ์์์ ๋์ด์ ๋ฏธ๋ฌํ ์ํ ํ๊ฐ
- ์คํ ์ ์: ์ผ๋ฐ์ ์ธ ์คํ ๊ฐ์ง ๋ฐ ์์ ์ ์
- ์นํ ์ง์: ๋๋ ์์ ์๋ฃ์ ๋ํ ์๋ฆผ ์์
API ๋ฌธ์๋ ๋ชจ๋ ์๋ํฌ์ธํธ, ์๋ต ํ์ ๋ฐ ์ฌ๋ฌ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ํตํฉ ์์ ์ ๋ํ ์์ธํ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค.
๊ฒฐ๋ก
์ด๋ฉ์ผ ๊ฒ์ฆ API๋ฅผ ํตํฉํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ด๋ฉ์ผ ๋ฐ์ดํฐ ํ์ง์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ด ๋ณํํฉ๋๋ค. ๋ฑ๋ก ์ค ์ค์๊ฐ ์ ํจ์ฑ ๊ฒ์ฌ๋ถํฐ ๊ธฐ์กด ๋ชฉ๋ก์ ์ผ๊ด ์ฒ๋ฆฌ๊น์ง, API๋ ๊ฒ์ฆ ์์คํ ์ ๊ตฌ์ถํ๊ณ ์ ์งํ๋ ๋ณต์ก์ฑ ์์ด ํฌ๊ด์ ์ธ ์ด๋ฉ์ผ ๊ฒ์ฆ์ ์ํ ์ธํ๋ผ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ฑ๊ณต์ ์ธ ํตํฉ์ ์ํ ํต์ฌ ์ฌํญ:
- ์ฌ์ฉ ์ฌ๋ก์ ์ ํฉํ ์๋ํฌ์ธํธ ์ ํ: ์ค์๊ฐ์ ๋จ์ผ ๊ฒ์ฆ, ์ค๊ฐ ๋ชฉ๋ก์ ์ผ๊ด ์ฒ๋ฆฌ, ๋๋ ๋ฐ์ดํฐ์ธํธ๋ ๋๋ ์ ๋ก๋
- ์ฌ์๋ ๋ก์ง๊ณผ ์ฐ์ํ ์ฑ๋ฅ ์ ํ๋ฅผ ํตํ ๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ ๊ตฌํ
- ํด๋ผ์ด์ธํธ ์ธก ์ ํ ๋ฐ ํจ์จ์ ์ธ ์ผ๊ด ์ฒ๋ฆฌ๋ฅผ ํตํด ์๋ ์ ํ ์กด์ค
- ๋น์ฉ ์ ๊ฐ๊ณผ ์ฑ๋ฅ ํฅ์์ ์ํ ์ ๋ต์ ์บ์ฑ
- ๋ฐ์ดํฐ ํ์ง์ ์ง์์ ์ผ๋ก ๊ฐ์ ํ๊ธฐ ์ํ ๊ฒ์ฆ ๊ฒฐ๊ณผ ๋ชจ๋ํฐ๋ง ๋ฐ ๋ถ์
์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๊ธฐ์กด ์์คํ ์ ๊ฐ์ ํ๋ , BillionVerify์ ๊ฐ์ ์ด๋ฉ์ผ ๊ฒ์ฆ API๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ชจ๋ ์ด๋ฉ์ผ ์ฃผ์๊ฐ ์ ํจํ๊ณ , ์ ์ก ๊ฐ๋ฅํ๋ฉฐ, ์์ ํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋ณด์ฅํ๋ ๋ฐ ํ์ํ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. API ํตํฉ์ ์ด๋ฉ์ผ ๋ฆฌ์คํธ ์ ์ ์ ์ ๋ฌ์ฑ ๊ฐ์ ์ ๊ธฐ์ด์ ๋๋ค.
BillionVerify์ ํฌ๊ด์ ์ธ ์ด๋ฉ์ผ ๊ฒ์ฆ ์๋ฃจ์ ์ ์ค์๊ฐ ๊ฒ์ฆ๋ถํฐ ๋๋ ์ฒ๋ฆฌ๊น์ง ๋ชจ๋ ์๊ตฌ์ฌํญ์ ์ถฉ์กฑํฉ๋๋ค. ์ง๊ธ ํตํฉ์ ์์ํ๊ณ ์ ๋ฌธ ์ด๋ฉ์ผ ๊ฒ์ฆ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ดํฐ ํ์ง๊ณผ ์ด๋ฉ์ผ ์ ์ก๋ฅ ์ ๋ฏธ์น๋ ์ฐจ์ด๋ฅผ ๊ฒฝํํ์ธ์. ๋ํ ์ด๋ฉ์ผ ๋ง์ผํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ฐธ๊ณ ํ์ฌ ์ ์ฒด ์บ ํ์ธ ์ฑ๊ณผ๋ฅผ ์ต์ ํํ์ธ์.