npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

korean-id

v1.5.0

Published

한국 식별번호 통합 검증 라이브러리 (BRN/RRN/CRN/FRN/PCC/DLN/Passport/VRN)

Readme

korean-id

npm version npm downloads license TypeScript CodeQL

한국어 | English


한국 식별번호 8종을 검증하는 TypeScript 라이브러리입니다. 순수 연산만 사용하며 zero dependency입니다.

| 타입 | 함수 | 설명 | |------|------|------| | 사업자등록번호 (BRN) | validateBRN | 체크섬 + 세무서/업태/일련번호 검증 | | 주민등록번호 (RRN) | validateRRN | 체크섬 + 생년월일 + 성별/세기 검증 (체크섬은 { checksum: false }로 생략 가능) | | 법인등록번호 (CRN) | validateCRN | 체크섬 검증 | | 외국인등록번호 (FRN) | validateFRN | 체크섬 + 생년월일 + 외국인 코드 검증 | | 개인통관고유부호 (PCC) | validatePCC | P + 12자리 포맷 검증 | | 운전면허번호 (DLN) | validateDLN | 지역코드 + 포맷 검증 (체크섬 미검증) | | 여권번호 | validatePassport | 접두사(M/S/R/O/D, 하위호환 G) + 포맷 검증 (구형 M12345678 / 차세대 M123A4567) | | 자동차등록번호 (VRN) | validateVRN | 포맷 + 한글 용도 문자 검증 (현행 2019~ / 구형 2006~2018 / 일반사업용 서울 82바 1234) |

설치

npm i korean-id

사용법

통합 검증: validate()

입력값의 타입을 몰라도 자동으로 감지하여 검증합니다.

import { validate } from 'korean-id';

validate('119-81-10010');
// { type: 'BRN', result: { success: true, data: { officeCode: '119', typeCode: '81', serialNumber: '10010' } } }

validate('123가4567');
// { type: 'VRN', result: { success: true, data: { usage: '자가용', char: '가', format: 'current' } } }

validate('M12345678');
// { type: 'PASSPORT', result: { success: true, data: { type: '복수여권', prefix: 'M', format: 'legacy' } } }

validate('서울 82바 1234');
// { type: 'VRN', result: { success: true, data: { usage: '영업용', char: '바', format: 'legacy', region: '서울' } } }

개별 검증

import { validateBRN, validateRRN, validateCRN, validateFRN } from 'korean-id';
import { validatePCC, validateDLN, validatePassport, validateVRN } from 'korean-id';

validateBRN('119-81-10010');
// { success: true, data: { officeCode: '119', typeCode: '81', serialNumber: '10010' } }

validateBRN('000-00-00000');
// { success: false, code: 'INVALID_OFFICE_CODE', message: 'Invalid tax office code' }

validateRRN('900101-1123459');
// { success: true, data: { birthDate: '1990-01-01', gender: 'male', century: '1900s' } }

validateCRN('110111-0006249');
// { success: true }

validateFRN('900101-5123452');
// { success: true, data: { birthDate: '1990-01-01', gender: 'male', century: '1900s' } }

validatePCC('P123456789012');
// { success: true, data: { number: '123456789012' } }

validateDLN('11-22-123456-78');
// { success: true, data: { region: '서울', regionCode: '11' } }

validatePassport('M12345678');       // 구형
// { success: true, data: { type: '복수여권', prefix: 'M', format: 'legacy' } }

validatePassport('M123A4567');       // 차세대 전자여권 (2021-12~)
// { success: true, data: { type: '복수여권', prefix: 'M', format: 'current' } }

validateVRN('123가4567');
// { success: true, data: { usage: '자가용', char: '가', format: 'current' } }

validateVRN('12가3456'); // 구형 포맷
// { success: true, data: { usage: '자가용', char: '가', format: 'legacy' } }

validateVRN('서울 82바 1234'); // 일반사업용 (지역명 포함)
// { success: true, data: { usage: '영업용', char: '바', format: 'legacy', region: '서울' } }

택시·버스·화물 등 자동차운수사업용은 2019년 번호판 3자리 확대 대상이 아니라 현재도 지역명 + 2자리로 발급됩니다. 지역명은 고시 제6조에 따라 일반사업용에만 붙으므로 서울82가1234(자가용)나 서울82허1234(대여사업용)는 거부합니다. 지역명 목록은 VRN_REGIONS 상수로 내보냅니다.

체크섬 옵션 (RRN/FRN)

validateRRN과 validateFRN은 기본적으로 체크섬을 검증합니다. 이는 기존 동작과 같습니다.

2020-10-05 주민등록법 시행규칙 제204호 개편으로 신규 부여·변경 주민등록번호는 뒷자리가 성별 1자리 + 임의번호 6자리가 되면서 검증번호 자리가 사라졌습니다. 이런 번호를 다뤄야 하면 체크섬만 건너뛸 수 있습니다.

validateRRN('900101-1123450');
// { success: false, code: 'INVALID_CHECKSUM', message: 'Invalid checksum' }

validateRRN('900101-1123450', { checksum: false });
// { success: true, data: { birthDate: '1990-01-01', gender: 'male', century: '1900s' } }

// 체크섬만 건너뛸 뿐 생년월일·성별코드는 계속 검증합니다
validateRRN('901301-1123450', { checksum: false });
// { success: false, code: 'INVALID_BIRTH_DATE', message: 'Invalid birth date' }

기존 체계 번호에는 체크섬이 여전히 성립하므로 기본값은 체크섬을 검증하는 것입니다. 다음 major에서 기본값을 미검증으로 바꿀 예정입니다.

같은 옵션을 isRRN·isFRN·validate()·CLI에서도 쓸 수 있습니다.

isRRN('900101-1123450');                     // false
isRRN('900101-1123450', { checksum: false }); // true

// 13자리는 RRN/FRN/CRN이 자릿수만으로 갈리지 않아 체크섬이 유일한 확증 신호입니다.
// 기본값에서는 RRN 확증 실패 후 CRN으로 넘어가고, CRN마저 실패하면 CRN 실패로 보고합니다.
validate('900101-1123450');
// { type: 'CRN', result: { success: false, code: 'INVALID_CHECKSUM', ... } }

// { checksum: false }를 주면 CRN 확증 실패 뒤 RRN으로 한 단계 더 폴백합니다.
validate('900101-1123450', { checksum: false });
// { type: 'RRN', result: { success: true, ... } }
npx korean-id 900101-1123450               # ✗ CRN, exit 1
npx korean-id --no-checksum 900101-1123450 # ✓ RRN, exit 0

오류 코드

검증 실패 결과에는 code가 함께 실립니다. message는 사람이 읽는 영문 문장이라 문구가 정정될 수 있으므로, 실패 사유로 분기하거나 자체 문구로 번역해야 한다면 code를 쓰세요.

import type { IdErrorCode } from 'korean-id';

const result = validateRRN('900101-1123450');
if (!result.success && result.code === 'INVALID_CHECKSUM') {
  // 체크섬만 어긋난 경우. 2020-10 이후 발급분이면 { checksum: false }로 재시도할 수 있다
}

INPUT_REQUIRED · NON_NUMERIC · INVALID_LENGTH · INVALID_FORMAT · INVALID_CHECKSUM · INVALID_BIRTH_DATE · INVALID_GENDER_CODE · INVALID_OFFICE_CODE · INVALID_BUSINESS_TYPE_CODE · INVALID_SERIAL_NUMBER · INVALID_REGION_CODE · INVALID_PREFIX · INVALID_CHARACTER · INVALID_REGION · REGION_NOT_ALLOWED · UNDETECTABLE

하위호환을 위해 선택 필드로 선언되어 있으나 라이브러리가 반환하는 실패 결과에는 항상 채워집니다. 다음 major에서 필수 필드가 됩니다.

잘못된 입력

타입은 string이지만 null·undefined·숫자·객체를 넘겨도 예외를 던지지 않습니다.

validateBRN(null as unknown as string);  // { success: false, code: 'INPUT_REQUIRED', message: 'Input is required' }
isBRN(undefined as unknown as string);   // false
formatBRN(123 as unknown as string);     // null
validate(null as unknown as string);     // { type: null, code: 'INPUT_REQUIRED', ... }

타입 가드

import { isBRN, isRRN, isCRN, isFRN, isPCC, isDLN, isPassport, isVRN } from 'korean-id';

isBRN('119-81-10010')   // true
isRRN('900101-1123459') // true
isVRN('123가4567')       // true
isVRN('서울 82바 1234')   // true

// isRRN·isFRN은 validateRRN·validateFRN과 같은 체크섬 옵션을 받습니다
isRRN('900101-1123450', { checksum: false }) // true

포맷팅

import { formatBRN, formatRRN, formatCRN, formatFRN, formatDLN, formatPCC, formatVRN } from 'korean-id';

formatBRN('1198110010')      // '119-81-10010'
formatRRN('9001011123459')   // '900101-1123459'
formatDLN('112212345678')    // '11-22-123456-78'
formatPCC('p123456789012')   // 'P123456789012'
formatVRN('123가 4567')       // '123가4567'
formatVRN('서울 82바 1234')   // '서울82바1234'

마스킹

import { maskRRN, maskBRN, maskFRN, maskCRN, maskDLN, maskPCC, maskPassport, maskVRN } from 'korean-id';

maskRRN('900101-1123459')    // '900101-1******'
maskBRN('119-81-10010')      // '119-81-***10'
maskCRN('110111-0006249')    // '110111-***6249'
maskDLN('11-22-123456-78')   // '11-22-******-78'
maskPCC('P123456789012')     // 'P123456******'
maskPassport('M12345678')    // 'M1234****'
maskVRN('123가4567')          // '123가****'
maskVRN('서울 82바 1234')     // '서울82바****'

상수

import { DLN_REGIONS, PASSPORT_TYPES, VRN_USAGE_CHARS, VRN_REGIONS } from 'korean-id';

DLN_REGIONS['11']          // '서울'
PASSPORT_TYPES['M']        // '복수여권'
PASSPORT_TYPES['O']        // '관용여권'
VRN_USAGE_CHARS['렌터카']   // ['허', '하', '호']
VRN_REGIONS               // ['서울', '부산', ... ] 17종

관용여권 접두사를 O(Official)로 기재한 공개 자료는 여럿 있으나, 정부의 1차 원문은 확인하지 못했습니다. 기존에 쓰이던 G는 근거를 찾지 못했지만 하위호환을 위해 남겨두었으며 다음 major에서 제거될 예정입니다. 새 코드에서는 O를 쓰세요.

CLI

npx korean-id 119-81-10010
# ✓ BRN (사업자등록번호)
#   officeCode: 119
#   typeCode: 81
#   serialNumber: 10010

npx korean-id --json M12345678
# {"type":"PASSPORT","result":{"success":true,"data":{"type":"복수여권","prefix":"M","format":"legacy"}}}

npx korean-id 서울 82바 1234
# ✓ VRN (자동차등록번호)
#   usage: 영업용
#   char: 바
#   format: legacy
#   region: 서울

npx korean-id --no-checksum 900101-1123450
# ✓ RRN (주민등록번호)
#   birthDate: 1990-01-01
#   gender: male
#   century: 1900s

npx korean-id --help

값이 유효하면 종료 코드 0을 반환하고, 무효하거나 타입을 감지하지 못하면 1을 반환합니다.

반환 타입

// 성공 시 data 필수, 실패 시 message 필수 (discriminated union)
type ValidateResult<T = undefined> =
  | { success: true; data: T }   // T가 undefined면 data 없음 (CRN)
  | { success: false; code?: IdErrorCode; message: string };

// 사용 예
const result = validateBRN('119-81-10010');
if (result.success) {
  result.data.officeCode  // 타입 안전하게 접근
} else {
  result.code             // 분기용 오류 코드
  result.message          // 사람이 읽는 오류 메시지
}

// validate() 반환 타입
type DetectResult =
  | { type: 'BRN'; result: ValidateResult<BRNData> }
  | { type: 'RRN'; result: ValidateResult<RRNData> }
  | { type: 'CRN'; result: ValidateResult }
  | { type: 'FRN'; result: ValidateResult<FRNData> }
  | { type: 'PCC'; result: ValidateResult<PCCData> }
  | { type: 'DLN'; result: ValidateResult<DLNData> }
  | { type: 'PASSPORT'; result: ValidateResult<PassportData> }
  | { type: 'VRN'; result: ValidateResult<VRNData> }
  | { type: null; code?: IdErrorCode; message: string };

기여

CONTRIBUTING.md를 참고하세요.

라이선스

MIT