전화번호 유효성 검사 API 연동: 형식·HLR·미확인 상태를 나누는 방법

회원가입이나 상담 신청 화면에서 전화번호를 받다 보면 숫자 길이만 확인하는 검사로는 부족하다고 느끼게 됩니다. 국가별 번호 체계가 다르고, 휴대전화와 유선번호를 구분해야 하는 업무도 있습니다. 그렇다고 조회 결과 하나로 고객 연락처를 잘못된 번호라고 확정하면 정상 사용자가 가입하지 못하거나 상담 요청이 사라지는 문제가 생깁니다.
APICK 전화번호 유효성 검사 API는 번호 형식과 통신망 조회 정보를 함께 제공합니다. 이 글의 목표는 값을 많이 받는 것보다 각각의 의미를 정확히 나눠 쓰는 데 있습니다. 형식 검사, HLR 조회 성공 여부, 활성 회선 정보, 사용자가 실제로 해당 번호를 보유하는지는 서로 다른 질문입니다. 입력 화면을 설계할 때부터 이 차이를 반영해야 안전한 검증 흐름을 만들 수 있습니다.
1. 가입 단계에서 풀려는 문제를 먼저 정하기
상담 신청이라면 연락 가능한 번호 형식인지 확인하고 오타 수정을 안내하는 것이 우선일 수 있습니다. 배송 알림이라면 현재 입력값이 문자 안내 대상에 적합한지 참고 정보가 필요할 수 있습니다. 어느 경우든 API가 반환한 통신사 이름이나 형식 유효성만으로 명의자, 본인 여부, 연락 동의를 확인했다고 표시해서는 안 됩니다. 번호 소유 확인이 필요하다면 별도로 승인된 인증 절차를 설계해야 합니다.
번호의 망 상태는 조회 시점의 정보이고 제공 범위도 국가와 통신망에 따라 다를 수 있습니다. 입력값이 형식상 정상인데 상태 정보를 받을 수 없었다면 사용자에게 재입력을 강요하는 대신 미확인 상태로 처리하는 편이 합리적입니다. 이때 다음 단계로 진행할지, 대체 연락 수단을 받을지는 업무 위험도에 따라 정합니다. 조회 실패를 고객의 잘못으로 설명하지 않는 것이 중요합니다.
2. 요청은 number 하나, 응답은 의미별로 나누기
공식 요청 명세의 요청 경로는 POST https://apick.app/rest/check_phone_valid입니다. 필수 문자열 필드 number에 전화번호를 넣습니다. 해외 번호는 공식 안내에 따라 +국가코드 형식을 사용합니다. 인증 헤더는 Authorization: Bearer, 본문은 multipart/form-data입니다. 번호를 숫자형으로 바꾸면 앞의 0이나 + 기호를 잃을 수 있으므로 문자열로 다루세요.
| 필드 | 형식과 처리 기준 |
|---|---|
data.국제번호 / data.지역번호 | 정리된 번호 문자열입니다. 원본과 정규화 결과의 용도를 나눕니다. |
data.유효성 | 국가별 번호 체계에 따른 형식 유효성 불리언입니다. |
data.국가 / data.지역 / data.국가코드 | 번호 관련 국가·지역 문자열입니다. |
data.모바일여부 / data.회선유형 | 상위 단계의 모바일 여부와 회선 유형입니다. HLR 정보와 출처를 구분합니다. |
data.hlr.활성회선여부 | 불리언 또는 null입니다. 상태 미제공일 때 null이 허용됩니다. |
data.hlr.개통상태 / data.hlr.상태코드 | 망 조회 상태 설명과 코드입니다. ok, absent, unknown, invalid, fixed-line, voip, unavailable, failed가 안내되어 있습니다. |
data.hlr.HLR유효 / data.hlr.번호유효 | 각각 HLR 조회 성공 여부와 망 기준 번호 유효성입니다. |
data.hlr.현재통신사 / data.hlr.원통신사 | 통신사 문자열입니다. 원통신사는 null이 허용됩니다. |
data.hlr.번호이동여부 / data.hlr.회선유형 / data.hlr.도달가능성 | null이 허용되는 정보입니다. 미제공 값을 false나 특정 회선 유형으로 바꾸지 않습니다. |
data.hlr.MCC / data.hlr.MNC | 모바일 번호용 국가·네트워크 코드 문자열입니다. |
data.success / api.success | 개별 처리 상태는 0 실패, 1 성공, 3 시간 초과이며 api.success는 API 정상 응답 불리언입니다. |
api.cost / api.ms / api.pl_id | 요금, 응답 시간, 결제 로그 ID입니다. |
그 밖에 HLR 객체에는 모바일여부, 위치, 국가, 국가코드, 국제번호, 지역번호 필드가 있으며 로밍여부와 이동통신사는 null이 허용됩니다. 후자의 상세 타입은 확인한 명세에 고정되어 있지 않으므로 추측으로 타입을 확정하지 마세요. 국가·지역 필드를 사람의 실시간 위치나 거주지로 해석해서도 안 됩니다.
3. curl 예제: 허가된 테스트 번호만 전송하기
전화번호는 개인 정보가 될 수 있으므로 공개 예제에 실제 고객 번호를 넣지 않습니다. 아래 코드는 직접 설정한 APICK_TEST_PHONE을 읽는 자리표시자 방식입니다. 운영 데이터나 실제 타인의 번호로 테스트하기 전에는 전송 목적과 처리 범위를 검토하세요. 이 글에서는 API를 실제로 호출하지 않았습니다.
curl --fail-with-body --request POST 'https://apick.app/rest/check_phone_valid' \
--header "Authorization: Bearer ${APICK_API_KEY:?Set APICK_API_KEY}" \
--form-string "number=${APICK_TEST_PHONE:?Set an authorized test number}"4. Node.js에서 null을 보존하는 상태 모델 만들기
가장 흔한 실수는 Boolean(null)이나 느슨한 조건문으로 미확인 값을 비활성으로 바꾸는 것입니다. 다음 예시는 형식 상태와 망 조회 상태를 따로 반환합니다. 상태 문자열은 이 예제에서 정한 내부 분류이며 APICK의 새로운 응답 필드가 아닙니다. 화면의 안내 문구 역시 내부 상태를 바탕으로 서비스가 작성합니다.
export async function inspectPhone(number) {
if (typeof number !== "string" || number.trim() === "")
throw new TypeError("A phone string is required");
const apiKey = process.env.APICK_API_KEY;
if (!apiKey) throw new Error("APICK_API_KEY is required");
const form = new FormData();
form.append("number", number.trim());
const response = await fetch("https://apick.app/rest/check_phone_valid", {
method: "POST",
headers: { Authorization: `Bearer ${apiKey}` },
body: form,
signal: AbortSignal.timeout(120_000)
});
if (!response.ok) throw new Error(`Phone HTTP ${response.status}`);
const body = await response.json();
if (body.api?.success !== true || body.data?.success !== 1)
throw new Error("Phone lookup did not succeed");
const d = body.data;
const hlr = d.hlr ?? {};
const format = d["유효성"] === true ? "valid"
: d["유효성"] === false ? "invalid" : "unknown";
const active = typeof hlr["활성회선여부"] === "boolean"
? hlr["활성회선여부"] : null;
// Missing or unsupported HLR information remains unknown.
const network = hlr["HLR유효"] !== true
? "unknown"
: active === true ? "active"
: active === false ? "not_active" : "unknown";
return {
format,
network,
active,
hlrSucceeded: hlr["HLR유효"] === true,
statusCode: typeof hlr["상태코드"] === "string"
? hlr["상태코드"] : null,
cost: body.api.cost,
logId: body.api.pl_id
};
}
const number = process.env.APICK_TEST_PHONE;
if (!number) throw new Error("Set an authorized test number");
const result = await inspectPhone(number);
// Do not print the raw phone number or full response.
console.log({ format: result.format, network: result.network, cost: result.cost });공식 Node.js SDK에는 client.validatePhone(number) 메서드가 있습니다. SDK를 쓰더라도 업무상 유효, 미확인, 확인 필요 상태를 정하는 책임은 애플리케이션에 남습니다. 공식 정적 응답 예시에도 형식 유효성이 true인 동시에 HLR 상태가 unavailable이고 활성회선여부가 null인 경우가 제시되어 있습니다. 이 조합을 오류 데이터라고 보고 값을 덮어쓰지 않도록 테스트하세요.
5. 거절보다 확인을 돕는 화면 만들기
형식이 맞지 않는다면 입력한 국가와 번호를 다시 확인하도록 안내할 수 있습니다. HLR 제공 범위가 부족하면 현재 상태를 확인하지 못했다고 설명하고, 가능한 다음 절차를 보여주세요. absent 같은 값은 설명과 함께 보관하되 그 값을 받은 이유를 임의로 추정하지 않습니다. 통신망 결과가 한 번 좋지 않았다는 이유만으로 기존 고객의 연락처를 삭제하거나 계정을 차단하는 자동화는 피하는 편이 안전합니다.
정보가 서로 어긋나 보일 때는 원본 상태 코드, 조회 시각, 애플리케이션의 최종 판단을 구분해 저장하세요. 개발자는 어떤 데이터에서 어떤 안내가 나왔는지 추적할 수 있고 고객지원 담당자는 API 용어를 그대로 전달하지 않아도 됩니다. 고객이 번호를 수정하면 이전 결과를 무효화하는 기준도 필요합니다. 다른 번호의 검사 결과가 현재 입력창에 남는 비동기 화면 오류를 특히 점검하세요.
6. HLR 포함 40P, 입력 이벤트마다 호출하지 않기
2026-10-11 UTC 기준 공식 요금표는 전화번호 유효성 검사를 건당 40P로 안내하며 개발가이드는 HLR 조회가 이 요금에 포함된다고 명시합니다. 단순 예상으로 100회는 4,000P, 1,000회는 40,000P입니다. 번호 하나를 입력하는 중에 키 입력마다 호출하면 같은 신청에서 여러 번 비용이 발생할 수 있으므로 형식상 입력이 끝났을 때나 제출 단계에 요청하는 구조가 적절합니다.
이 수치는 호출 횟수에 단가를 곱한 예산 예시입니다. 실제 차감은 응답의 api.cost와 계정 내역으로 확인해야 하며 HLR 상태가 미제공이라는 이유만으로 무료라고 추정하면 안 됩니다. 네트워크에서 응답을 받지 못한 경우도 무조건 반복하지 말고 앞선 요청의 처리 여부와 재시도 정책을 확인하세요. 장기 캐시는 상태가 변할 수 있다는 점과 데이터 보관 목적을 함께 고려해야 합니다.
7. 로그, 보관 기간, 접근 권한을 함께 설계하기
번호 원문을 일반 애플리케이션 로그에 남기지 않는 것부터 시작하세요. 필요하다면 내부 요청 ID, 상태 분류, 비용, 조회 시각처럼 장애 분석에 필요한 최소 정보만 기록합니다. 전체 응답이 반드시 필요한 업무라면 접근할 수 있는 사람, 보관 기간, 삭제 절차를 미리 정해야 합니다. 번호를 단순 해시로 바꾸는 것만으로 모든 재식별 위험이 사라진다고 보지 말고 별도의 보안 검토를 거치세요.
API 키는 서버의 비밀 관리 수단으로 보관하고 프런트엔드 번들에 포함하지 않습니다. 사용자가 입력한 번호를 외부 서비스로 보내는 흐름은 서비스의 개인 정보 처리 안내와 실제 운영이 일치하는지도 확인하세요. 이 글은 구체적 법률 적합성을 보증하지 않습니다. 불필요한 대량 검사를 줄이고 적법하게 수집한 연락처를 필요한 업무 범위에서 처리하는 설계가 출발점입니다.
자주 묻는 질문
유효성이 true면 본인 인증이 끝난 건가요?
아닙니다. 형식 검증이나 HLR 조회로 명의와 소유를 확정할 수 없습니다. 필요한 본인·소유 확인은 별도 절차로 설계하세요.
활성회선여부가 null이면 사용할 수 없는 번호인가요?
그렇게 해석하면 안 됩니다. 국가·통신망의 제공 범위에 따른 미확인 상태일 수 있으며 unavailable과 실패도 구분해야 합니다.
HLR 조회는 40P에 추가로 과금되나요?
확인한 개발가이드는 HLR 조회가 40P 요금에 포함된다고 안내합니다. 변경 가능성이 있으므로 도입 시 현재 요금표를 다시 확인하세요.
다음 단계: 실제 화면 하나에 연결해 보기
연동을 시작할 때는 APICK 공식 개발가이드에서 현재 요청 규격을 확인하고, 요금 안내에서 적용 단가를 다시 확인하세요. 서버 프로젝트에서 SDK를 사용한다면 공식 Node.js 한국어 가이드도 함께 볼 수 있습니다. 테스트 범위를 작게 정한 뒤 입력 검증, 오류 화면, 사용 포인트 기록까지 연결하면 운영 단계에서 바꿀 부분이 선명해집니다.
확인 기준: 2026-10-11 UTC. 이 글의 API 필드와 단가는 위 공식 자료를 확인해 작성했습니다. 코드는 설명용 예시이며 실제 유료 API 호출로 실행 검증하지 않았습니다. 예제의 입력은 가상 데이터 또는 사용자가 직접 설정할 자리표시자입니다. 서비스 정책과 문서는 변경될 수 있습니다.
댓글
댓글 쓰기