유효한 아르헨티나 CUIT/CUIL 테스트 번호를 생성하거나 기존 번호를 검증합니다. AFIP 호환 검증을 통한 세금 ID 및 급여 시스템 테스트를 위한 무료 온라인 도구입니다.
8자리 DNI 번호를 입력하거나 무작위 생성기 사용
아르헨티나의 세금 및 노동 시스템에서는 CUIT(Clave Única de Identificación Tributaria)와 CUIL(Clave Única de Identificación Laboral)이라는 두 가지 중요한 식별자를 계속 접하게 됩니다. CUIT는 세금을 납부하는 기업 및 개인을 위한 세금 ID로 생각할 수 있고, CUIL은 사회 보장 시스템의 근로자를 식별합니다. 두 식별자 모두 동일한 11자리 형식과 검증 알고리즘을 사용하므로, 이러한 번호를 처리하는 애플리케이션을 테스트하는 것이 특히 중요합니다.
아르헨티나 시장을 위한 소프트웨어를 개발할 때는 유효한 테스트 데이터가 필요합니다. 바로 이 도구가 그 역할을 합니다. 실제 개인 정보를 사용하지 않고도 수학적으로 정확한 CUIT/CUIL 번호를 생성하거나, 기존 번호를 검증하여 AFIP의 공식 알고리즘에 부합하는지 확인할 수 있습니다. 특히 유용한 점은 이 도구가 생성 측면(필요에 따라 유효한 번호 생성)과 검증 측면(형식 오류, 잘못된 유형 코드, 잘못된 검증 숫자를 사전에 포착하여 프로덕션 문제 방지) 모두를 처리한다는 것입니다.
유효한 CUIT/CUIL 번호는 11자리로 구성되며 일반적으로 XX-XXXXXXXX-X 형식으로 표시됩니다. 다음은 세부 내용입니다:
유형 코드 (처음 2자리): 엔터티 유형을 식별합니다
DNI 번호 (중간 8자리): 개인의 경우, 이는 국가 신분증 번호(DNI)입니다. 일반적인 함정은 실제 DNI가 8자리보다 적을 경우 선행 0으로 채워야 한다는 점입니다. 예를 들어, DNI 1234567은 CUIT/CUIL에서 01234567이 됩니다. 기업은 대신 고유한 할당된 번호를 받습니다.
검증 숫자 (마지막 자리): 이 검증 숫자는 가중 알고리즘을 사용하여 전체 번호를 검증합니다. 이 숫자가 계산과 일치하지 않으면 전체 CUIT/CUIL이 유효하지 않습니다 - 이는 테스트 데이터를 수동으로 구성할 때 개발자들을 자주 당황하게 만드는 부분입니다.
검증 숫자는 모듈로-11 가중 알고리즘을 사용합니다. 작동 방식은 다음과 같습니다:
대부분의 사람들을 혼란스럽게 하는 것은 5단계의 예외 사례입니다. 테스트할 때 10 또는 11의 결과를 얻을 수 있으며, 이를 9와 0으로 매핑하는 것을 잊으면 디버깅하기 어려운 검증 실패가 발생할 수 있습니다.
수학적으로 다음과 같이 표현할 수 있습니다:
여기서:
도구 인터페이스 상단의 "생성기" 탭을 선택합니다.
드롭다운 메뉴에서 유형 코드를 선택합니다:
DNI 번호 입력 (선택 사항):
무작위 DNI 생성 (선택 사항):
생성된 CUIT/CUIL 보기:
결과 복사:
도구 인터페이스 상단의 "검증기" 탭을 선택합니다.
검증할 CUIT/CUIL 입력:
"검증" 버튼 클릭:
검증 결과 보기:
추가 정보:
CUIT/CUIL 검증을 애플리케이션에서 작업할 때 다음과 같은 흔한 함정을 주의하세요:
선행 제로 문제: 내가 마주한 가장 흔한 버그는 선행 제로가 있는 DNI 번호와 관련됩니다. 누군가 DNI "1234567"을 입력할 때, 코드는 CUIT/CUIL 구성을 위해 "01234567"로 처리해야 합니다. 많은 구현에서 처리를 위해 정수로 변환하면 선행 제로가 제거됩니다. 대신 적절한 패딩으로 문자열 작업을 사용하세요.
유형 코드 혼란: 모든 두 자리 숫자가 유효한 유형 코드는 아닙니다. 20, 23, 24, 27, 30, 33, 34만 작동합니다. AFIP 검증에 실패하는 "유효해 보이는" 21-12345678-X와 같은 숫자를 허용하는 시스템을 본 적이 있습니다. 검증 숫자를 계산하기 전에 항상 유형 코드를 검증하세요.
성별 가정: 유형 코드 20(남성)과 27(여성)은 상호 교환할 수 없습니다. 인구통계 데이터를 기반으로 CUIL을 자동 생성하는 경우, RENAPER(아르헨티나 국가 레지스트리)에 등록된 실제 성별과 일치하는 유형 코드를 확인하세요. 불일치하면 개인이 정부 서비스에서 이러한 번호를 사용할 때 거부됩니다.
하이픈 처리: 일부 구현에서는 하이픈이 필요하고 다른 구현에서는 거부합니다. 모범 사례: 입력 필드에서 하이픈이 있거나 없는 두 형식을 모두 허용하고, 검증 전에 하이픈을 제거하고, 데이터베이스에 하이픈 없는 버전을 저장하며, 표시 목적으로만 하이픈을 추가하세요.
누락된 검증: 알고리즘 검증은 형식 오류를 잡지만 CUIT/CUIL이 등록되었는지 확인하지 않습니다. 프로덕션에서는 먼저 형식을 검증하고(빠름), 그런 다음 AFIP 데이터베이스에 대해 확인하세요(느리지만 권위 있음). 이 2단계 접근 방식은 즉시 오타를 잡으면서 번호가 실제인지 확인합니다.
엣지 케이스 테스트: 항상 0과 9의 검증 숫자로 테스트하세요. 이는 알고리즘의 특수 사례에서 발생합니다. 또한 제로로 시작하는 DNI를 테스트하여 패딩 로직이 올바르게 작동하는지 확인하세요.
소프트웨어 개발: 아르헨티나 시장을 위한 애플리케이션을 구축할 때, 실제 사용자 정보를 사용하지 않고 검증을 통과할 수 있는 테스트 데이터가 필요합니다. 다음과 같은 상황에서 중요합니다:
데이터베이스 채우기: 테스트 데이터베이스를 시딩할 때, 알고리즘적으로 유효한 CUIT/CUIL 번호를 사용하면 데이터베이스 제약 조건 및 트리거가 예상대로 작동하는지 확인할 수 있습니다. 이는 식별 번호를 검증하는 데이터 마이그레이션 스크립트 또는 ETL 프로세스를 테스트할 때 특히 중요합니다.
양식 검증 테스트: 성공 경로와 오류 조건을 모두 테스트하세요. 성공적인 제출을 확인하기 위해 유효한 번호를 생성한 다음, 프런트엔드 및 백엔드 검증이 데이터베이스에 도달하기 전에 오류를 포착하는지 확인하기 위해 확인 숫자를 수정하세요.
API 테스트: 통합 테스트는 요청 페이로드에 유효한 CUIT/CUIL 번호를 사용해야 합니다. 이렇게 하면 API 로직의 실제 버그가 아니라 잘못된 테스트 데이터로 인해 테스트가 실패하는 거짓 음성을 방지할 수 있습니다.
QA 자동화: 매개변수화된 테스트는 동적 CUIT/CUIL 생성의 이점을 얻습니다. 테스트 실행 간에 충돌할 수 있는 하드코딩된 테스트 값 대신 각 테스트 실행마다 새로운 유효한 번호를 생성하세요.
검증 알고리즘 학습: CUIT/CUIL 검증 알고리즘은 모듈로 산술 및 가중 체크 숫자의 실제 응용을 보여줍니다. 이와 유사한 패턴이 전 세계 다른 식별 시스템에 나타납니다 - 신용 카드 번호(Luhn 알고리즘), ISBN 코드, 유럽 VAT 번호 모두 유사한 가중 체크섬 접근 방식을 사용합니다. CUIT/CUIL 검증 작동 방식을 이해하면 이러한 알고리즘이 존재하는 이유를 알 수 있습니다: 전사된 숫자나 단일 숫자 실수와 같은 전사 오류를 잡아냅니다.
데이터 검증 교육: 주니어 개발자에게 입력 검증을 교육할 때, CUIT/CUIL 시스템은 이메일 검증보다 복잡하고 암호화 검증보다 간단한 실제 예제를 제공합니다. 심층 방어의 원칙을 보여줍니다: 형식 검증(11자리), 비즈니스 규칙 검증(유효한 유형 코드), 알고리즘 검증(체크 숫자).
국제 비즈니스 개발: 라틴 아메리카 시장을 위한 시스템을 구축하는 경우, CUIT/CUIL을 이해하면 인접 국가의 유사한 시스템을 파악하는 데 도움이 됩니다. 브라질에는 CPF/CNPJ, 칠레에는 RUT, 우루과이에는 RUT가 있으며 - 모두 체크 숫자 알고리즘을 사용합니다. 여기서 배운 패턴은 해당 시스템으로 전이됩니다.
이 도구는 개발 및 테스트에 잘 작동하지만, 프로덕션 환경에는 다른 요구 사항이 있습니다:
공식 정부 검증: 라이브 애플리케이션의 경우 알고리즘 검증만으로는 충분하지 않습니다 - CUIT/CUIL이 실제로 AFIP(Administración Federal de Ingresos Públicos)에 등록되어 있는지 확인해야 합니다. AFIP는 실시간 검증을 위한 웹 서비스를 제공하지만, 액세스하려면 등록 및 인증이 필요합니다. 주의할 점: 숫자가 수학적으로 유효하더라도 공식적으로 할당되지 않았을 수 있으므로 프로덕션에서는 항상 두 계층의 검증을 구현하세요.
라이브러리 및 패키지: CUIT/CUIL 검증을 코드베이스에 통합하는 경우, 직접 구현하는 대신 다음과 같은 검증된 라이브러리를 고려하세요:
validar-cuit는 검증 및 형식 지정을 처리합니다.afip-php 라이브러리는 검증 및 AFIP 웹 서비스 통합을 제공합니다.py-cuit는 전체 알고리즘을 구현합니다.유지 관리되는 라이브러리를 사용하면 구현 버그의 위험을 줄이고 사용자 지정 코드에서 놓칠 수 있는 엣지 케이스를 포함할 수 있습니다.
수동 계산: 학습 목적 또는 디버깅을 위해 알고리즘을 직접 따라가면 이해를 강화하는 데 도움이 됩니다. 계산기와 샘플 CUIT/CUIL을 가져와 가중 곱셈 프로세스를 단계별로 따라가세요.
엔터프라이즈 검증 서비스: 대규모 애플리케이션은 형식을 확인할 뿐만 아니라 상업용 데이터베이스와 대조 확인하는 제3자 검증 API의 이점을 얻을 수 있습니다. 이러한 서비스는 비활성 기업을 표시하고, 제재된 엔터티를 식별하거나 CUIT/CUIL 소유자에 대한 추가 메타데이터를 제공할 수 있습니다.
아르헨티나의 CUIT/CUIL 식별 시스템은 그 시작 이후 크게 발전해 왔습니다:
CUIT(Clave Única de Identificación Tributaria)는 1970년대 아르헨티나에서 처음 도입되었으며, 세금 징수 시스템을 현대화하기 위한 노력의 일환으로 시작되었습니다. 연방 공공 수입 관리청(AFIP)은 이 고유 식별자를 통해 납세자를 더 효율적으로 추적하고 탈세를 줄이고자 했습니다.
CUIL(Clave Única de Identificación Laboral)은 나중에 사회 보장 시스템에서 근로자를 특별히 식별하기 위해 도입되었으며, 세금 식별과 노동 식별 사이에 구분을 만들면서도 일관된 형식을 유지했습니다.
1990년대에 아르헨티나가 중요한 경제 개혁을 겪으면서 CUIT/CUIL 시스템은 경제 활동을 추적하는 데 점점 더 중요해졌습니다. 시스템은 더욱 디지털화되었고, 온라인 검증 시스템이 구현되었습니다.
2000년대 초반에는 CUIT/CUIL 시스템이 다양한 디지털 정부 서비스와 통합되어 아르헨티나의 전자정부 이니셔티브의 필수 구성 요소가 되었습니다. 이 시기에는 현재까지 사용되고 있는 검증 알고리즘과 형식도 표준화되었습니다.
최근 몇 년간 AFIP는 CUIT/CUIL 번호의 보안 및 검증 프로세스를 강화하여, 더욱 정교한 검증 시스템을 구현하고 다른 정부 데이터베이스와 통합했습니다. 이 시스템은 현재 아르헨티나의 탈세 방지와 경제 공식화 노력에 중요한 역할을 하고 있습니다.
오늘날 CUIT/CUIL은 세금 및 고용 목적뿐만 아니라 은행, 부동산 거래, 공공 서비스, 온라인 구매 등 광범위한 활동에 사용되어, 아르헨티나에서 활동하는 개인과 기업에게 필수적인 식별자가 되었습니다.
자체 시스템에서 CUIT/CUIL 검증을 구현할 때 다음과 같은 기술적 측면을 고려하세요:
알고리즘 안정성: 현재 CUIT/CUIL 검증 알고리즘은 1990년대 표준화 이후 변경되지 않았습니다. AFIP의 기술 문서에 따르면, 모듈로-11 가중 체크 디지트 접근 방식은 결의안 2854/2010 및 후속 규정에 명시되어 있습니다. 이러한 안정성은 구현이 거의 업데이트될 필요가 없음을 의미하지만, 규제 변경에 대해 AFIP 공지를 모니터링해야 합니다.
성능 최적화: 검증 알고리즘은 계산적으로 저렴합니다 - 10번의 곱셈, 한 번의 덧셈, 그리고 한 번의 모듈로 연산만 필요합니다. 초당 수천 건의 검증을 처리하는 고처리량 시스템의 경우, 병목 지점은 일반적으로 알고리즘 자체가 아니라 AFIP 데이터베이스에 대한 검증 시 네트워크 대기 시간입니다. 적절한 TTL(일반적으로 24시간)로 AFIP 검증 결과를 캐싱하는 것을 고려하세요.
문자 인코딩: 외부 소스(PDF, 스캔된 문서, 웹 스크래핑)에서 CUIT/CUIL 데이터를 처리할 때는 문자 인코딩 문제에 주의하세요. 하이픈이 표준 하이픈-마이너스(U+002D) 대신 엠 대시(U+2014), 엔 대시(U+2013), 또는 마이너스 기호(U+2212)로 나타날 수 있습니다. 검증 전에 이를 정규화하여 거짓 부정을 방지하세요.
국제화: 여러 라틴 아메리카 시장을 대상으로 하는 애플리케이션의 경우, 아르헨티나의 CUIT/CUIL은 특정 가중치를 사용하는 모듈로-11을 사용하고, 칠레의 RUT는 다른 가중치로 모듈로-11을 사용하며, 브라질의 CPF/CNPJ는 또 다른 패턴으로 모듈로-11을 사용한다는 점에 유의하세요. 알고리즘이 동일하다고 가정하지 마세요 - 각 국가의 시스템은 고유한 규칙을 가지고 있습니다. 체크 디지트 알고리즘에 대한 더 넓은 이해를 위해 다양한 모듈로 기반 검증 체계를 공식화하는 ISO/IEC 7064 표준을 참조하세요.
데이터베이스 저장: CUIT/CUIL 번호를 하이픈 없이 고정 길이 CHAR(11)로 저장하거나, 데이터베이스가 정밀도 손실 없이 11자리 정수를 지원하는 경우 BIGINT로 저장하세요. 손상된 데이터에 대한 안전망으로 데이터베이스 수준에서 검증 숫자를 검증하는 체크 제약 조건을 추가하세요. 사용자가 CUIT/CUIL로 검색할 때 효율적인 조회를 위해 이 필드에 인덱스를 생성하세요.
1def calculate_verification_digit(type_code, dni):
2 # 문자열로 변환하고 DNI를 선행 0으로 8자리로 확인
3 type_code_str = str(type_code)
4 dni_str = str(dni).zfill(8)
5
6 # 유형 코드와 DNI 결합
7 digits = type_code_str + dni_str
8
9 # 각 위치의 가중치
10 weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2]
11
12 # 곱의 합계 계산
13 sum_products = sum(int(digits[i]) * weights[i] for i in range(10))
14
15 # 검증 숫자 계산
16 verification_digit = 11 - (sum_products % 11)
17
18 # 특수 케이스
19 if verification_digit == 11:
20 verification_digit = 0
21 elif verification_digit == 10:
22 verification_digit = 9
23
24 return verification_digit
25
26def generate_cuit_cuil(type_code, dni=None):
27 import random
28
29 # 유효한 유형 코드
30 valid_type_codes = [20, 23, 24, 27, 30, 33, 34]
31
32 if type_code not in valid_type_codes:
33 raise ValueError(f"유효하지 않은 유형 코드. 다음 중 하나여야 합니다: {valid_type_codes}")
34
35 # 제공되지 않은 경우 임의의 DNI 생성
36 if dni is None:
37 dni = random.randint(10000000, 99999999)
38
39 # 검증 숫자 계산
40 verification_digit = calculate_verification_digit(type_code, dni)
41
42 # CUIT/CUIL 형식
43 return f"{type_code}-{str(dni).zfill(8)}-{verification_digit}"
44
45def validate_cuit_cuil(cuit_cuil):
46 # 하이픈 제거 (있는 경우)
47 cuit_cuil_clean = cuit_cuil.replace("-", "")
48
49 # 기본 형식 확인
50 if not cuit_cuil_clean.isdigit() or len(cuit_cuil_clean) != 11:
51 return False, "잘못된 형식"
52
53 # 부분 추출
54 type_code = int(cuit_cuil_clean[0:2])
55 dni = int(cuit_cuil_clean[2:10])
56 verification_digit = int(cuit_cuil_clean[10])
57
58 # 유형 코드 검증
59 valid_type_codes = [20, 23, 24, 27, 30, 33, 34]
60 if type_code not in valid_type_codes:
61 return False, "유효하지 않은 유형 코드"
62
63 # 검증 숫자 계산 및 비교
64 calculated_digit = calculate_verification_digit(type_code, dni)
65 if calculated_digit != verification_digit:
66 return False, "유효하지 않은 검증 숫자"
67
68 return True, "유효한 CUIT/CUIL"
69
70# 사용 예시
71print(generate_cuit_cuil(20, 12345678)) # 특정 DNI에 대해 생성
72print(generate_cuit_cuil(27)) # 임의의 DNI로 생성
73print(validate_cuit_cuil("20-12345678-9")) # CUIT/CUIL 검증
741function calculateVerificationDigit(typeCode, dni) {
2 // 문자열로 변환하고 DNI를 선행 0으로 8자리로 확인
3 const typeCodeStr = typeCode.toString();
4 const dniStr = dni.toString().padStart(8, '0');
5
6 // 유형 코드와 DNI 결합
7 const digits = typeCodeStr + dniStr;
8
9 // 각 위치의 가중치
10 const weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
11
12 // 곱의 합계 계산
13 let sumProducts = 0;
14 for (let i = 0; i < 10; i++) {
15 sumProducts += parseInt(digits[i]) * weights[i];
16 }
17
18 // 검증 숫자 계산
19 let verificationDigit = 11 - (sumProducts % 11);
20
21 // 특수 케이스
22 if (verificationDigit === 11) {
23 verificationDigit = 0;
24 } else if (verificationDigit === 10) {
25 verificationDigit = 9;
26 }
27
28 return verificationDigit;
29}
30
31function generateCuitCuil(typeCode, dni) {
32 // 유효한 유형 코드
33 const validTypeCodes = [20, 23, 24, 27, 30, 33, 34];
34
35 if (!validTypeCodes.includes(typeCode)) {
36 throw new Error(`유효하지 않은 유형 코드. 다음 중 하나여야 합니다: ${validTypeCodes.join(', ')}`);
37 }
38
39 // 제공되지 않은 경우 임의의 DNI 생성
40 if (dni === undefined) {
41 dni = Math.floor(Math.random() * 90000000) + 10000000;
42 }
43
44 // 검증 숫자 계산
45 const verificationDigit = calculateVerificationDigit(typeCode, dni);
46
47 // CUIT/CUIL 형식
48 return `${typeCode}-${dni.toString().padStart(8, '0')}-${verificationDigit}`;
49}
50
51function validateCuitCuil(cuitCuil) {
52 // 하이픈 제거 (있는 경우)
53 const cuitCuilClean = cuitCuil.replace(/-/g, '');
54
55 // 기본 형식 확인
56 if (!/^\d{11}$/.test(cuitCuilClean)) {
57 return { isValid: false, errorMessage: '잘못된 형식' };
58 }
59
60 // 부분 추출
61 const typeCode = parseInt(cuitCuilClean.substring(0, 2));
62 const dni = parseInt(cuitCuilClean.substring(2, 10));
63 const verificationDigit = parseInt(cuitCuilClean.substring(10, 11));
64
65 // 유형 코드 검증
66 const validTypeCodes = [20, 23, 24, 27, 30, 33, 34];
67 if (!validTypeCodes.includes(typeCode)) {
68 return { isValid: false, errorMessage: '유효하지 않은 유형 코드' };
69 }
70
71 // 검증 숫자 계산 및 비교
72 const calculatedDigit = calculateVerificationDigit(typeCode, dni);
73 if (calculatedDigit !== verificationDigit) {
74 return { isValid: false, errorMessage: '유효하지 않은 검증 숫자' };
75 }
76
77 return { isValid: true };
78}
79
80// 사용 예시
81console.log(generateCuitCuil(20, 12345678)); // 특정 DNI에 대해 생성
82console.log(generateCuitCuil(27)); // 임의의 DNI로 생성
83console.log(validateCuitCuil("20-12345678-9")); // CUIT/CUIL 검증
841import java.util.Arrays;
2import java.util.List;
3import java.util.Random;
4
5public class CuitCuilUtils {
6 private static final List<Integer> VALID_TYPE_CODES = Arrays.asList(20, 23, 24, 27, 30, 33, 34);
7 private static final int[] WEIGHTS = {5, 4, 3, 2, 7, 6, 5, 4, 3, 2};
8
9 public static int calculateVerificationDigit(int typeCode, int dni) {
10 // 문자열로 변환하고 DNI를 선행 0으로 8자리로 확인
11 String typeCodeStr = String.valueOf(typeCode);
12 String dniStr = String.format("%08d", dni);
13
14 // 유형 코드와 DNI 결합
15 String digits = typeCodeStr + dniStr;
16
17 // 곱의 합계 계산
18 int sumProducts = 0;
19 for (int i = 0; i < 10; i++) {
20 sumProducts += Character.getNumericValue(digits.charAt(i)) * WEIGHTS[i];
21 }
22
23 // 검증 숫자 계산
24 int verificationDigit = 11 - (sumProducts % 11);
25
26 // 특수 케이스
27 if (verificationDigit == 11) {
28 verificationDigit = 0;
29 } else if (verificationDigit == 10) {
30 verificationDigit = 9;
31 }
32
33 return verificationDigit;
34 }
35
36 public static String generateCuitCuil(int typeCode, Integer dni) {
37 if (!VALID_TYPE_CODES.contains(typeCode)) {
38 throw new IllegalArgumentException("유효하지 않은 유형 코드. 다음 중 하나여야 합니다: " + VALID_TYPE_CODES);
39 }
40
41 // 제공되지 않은 경우 임의의 DNI 생성
42 if (dni == null) {
43 Random random = new Random();
44 dni = 10000000 + random.nextInt(90000000);
45 }
46
47 // 검증 숫자 계산
48 int verificationDigit = calculateVerificationDigit(typeCode, dni);
49
50 // CUIT/CUIL 형식
51 return String.format("%d-%08d-%d", typeCode, dni, verificationDigit);
52 }
53
54 public static ValidationResult validateCuitCuil(String cuitCuil) {
55 // 하이픈 제거 (있는 경우)
56 String cuitCuilClean = cuitCuil.replace("-", "");
57
58 // 기본 형식 확인
59 if (!cuitCuilClean.matches("\\d{11}")) {
60 return new ValidationResult(false, "잘못된 형식");
61 }
62
63 // 부분 추출
64 int typeCode = Integer.parseInt(cuitCuilClean.substring(0, 2));
65 int dni = Integer.parseInt(cuitCuilClean.substring(2, 10));
66 int verificationDigit = Integer.parseInt(cuitCuilClean.substring(10, 11));
67
68 // 유형 코드 검증
69 if (!VALID_TYPE_CODES.contains(typeCode)) {
70 return new ValidationResult(false, "유효하지 않은 유형 코드");
71 }
72
73 // 검증 숫자 계산 및 비교
74 int calculatedDigit = calculateVerificationDigit(typeCode, dni);
75 if (calculatedDigit != verificationDigit) {
76 return new ValidationResult(false, "유효하지 않은 검증 숫자");
77 }
78
79 return new ValidationResult(true, null);
80 }
81
82 public static class ValidationResult {
83 private final boolean isValid;
84 private final String errorMessage;
85
86 public ValidationResult(boolean isValid, String errorMessage) {
87 this.isValid = isValid;
88 this.errorMessage = errorMessage;
89 }
90
91 public boolean isValid() {
92 return isValid;
93 }
94
95 public String getErrorMessage() {
96 return errorMessage;
97 }
98 }
99
100 public static void main(String[] args) {
101 // 사용 예시
102 System.out.println(generateCuitCuil(20, 12345678)); // 특정 DNI에 대해 생성
103 System.out.println(generateCuitCuil(27, null)); // 임의의 DNI로 생성
104 System.out.println(validateCuitCuil("20-12345678-9").isValid()); // CUIT/CUIL 검증
105 }
106}
107<?php function calculateVerificationDigit($typeCode, $dni) { // 문자열로 변환하고 DNI를 선행 0으로 8자리로 확인 $typeCodeStr = (string)$typeCode; $dniStr = str_pad((string)$dni, 8, '0', STR_PAD_LEFT); // 유형 코드와 DNI 결합 $digits = $typeCodeStr . $dniStr; // 각 위치의 가중치 $weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2]; // 곱의 합계 계산 $sumProducts = 0; for ($i = 0; $i < 10; $i++) { $sumProducts += (int)$digits[$i] * $weights[$i]; } // 검증 숫자 계산 $verificationDigit = 11 - ($sumProducts % 11); // 특수 케이스 if ($verificationDigit == 11) { $verificationDigit = 0; } else if ($verificationDigit == 10) { $verificationDigit = 9; } return $verificationDigit; } function generateCuitCuil($typeCode, $dni = null) { // 유효한 유형 코드 $validTypeCodes = [20, 23, 24, 27, 30, 33, 34]; if (!in_array($typeCode, $validTypeCodes)) { throw new Exception("유효하지 않은 유형 코드. 다음 중 하나여야 합니다: " . implode(', ', $validTypeCodes)); } // 제공되지 않은 경우 임의의 DNI 생성 if ($dni === null) { $dni = rand(10000000, 99999999); } // 검증 숫자 계산 $verificationDigit = calculateVerificationDigit($typeCode, $dni); // CUIT/CUIL 형식 return sprintf("%d-%08d-%d", $typeCode, $dni, $verificationDigit); } function validateCuitCuil($cuitCuil) { // 하이픈 제거 (있는 경우) $cuitCuilClean = str_replace('-', '', $cuitCuil); // 기본 형식 확인 if (!preg_match('/^\d{11}$/', $cuitCuilClean)) { return ['isValid' => false, 'errorMessage' => '잘못된 형식']; } // 부분 추출 $typeCode ## 자주 묻는 질문 ### CUIT와 CUIL의 차이점은 무엇인가요? 실용적인 구분은 다음과 같습니다: **CUIT**(Clave Única de Identificación Tributaria)는 AFIP에 세금을 신고하는 개인 및 기업을 식별합니다. **CUIL**(Clave Única de Identificación Laboral)은 고용 및 퇴직 목적으로 사회 보장 시스템에서 근로자를 식별합니다. 실제로 많은 개인들은 첫 직장에서 받은 CUIL과 자영업자나 사업을 시작할 때 받는 CUIT를 모두 가지고 있습니다. 번호는 동일한 형식과 계산 규칙을 사용하므로 검증 측면에서는 동일하게 처리됩니다. 이 구분은 행정 목적에서 중요합니다: 급여 시스템은 일반적으로 CUIL을 사용하고, 송장 및 세금 시스템은 CUIT를 사용합니다. ### 개인과 기업에 사용되는 유형 코드는 무엇인가요? 개인의 경우: - 20, 23, 24: 남성 개인 (CUIL) - 27: 여성 개인 (CUIL) 기업 및 조직의 경우: - 30: 법인 (CUIT) - 33: 시민 협회 (CUIT) - 34: 재단 (CUIT) ### 검증 숫자는 어떻게 계산되나요? 알고리즘은 가중 곱셈을 사용합니다: 처음 10자리 각각을 **5, 4, 3, 2, 7, 6, 5, 4, 3, 2**의 가중치로 곱하고, 곱의 합을 구한 후 11에서 (합을 11로 나눈 나머지)를 뺍니다. 두 가지 특수한 경우가 사람들을 혼란스럽게 합니다: 계산 결과가 11이면 검증 숫자로 0을 사용하고, 10이면 9를 사용합니다. 이러한 특수 케이스는 검증 숫자가 반드시 한 자리(0-9)여야 하기 때문에 존재합니다. 이는 ISBN-10 코드 및 전 세계의 다른 식별 시스템에서 사용되는 모듈로-11 체크 숫자 알고리즘과 유사합니다. ### 이 도구를 사용하여 실제 공식 CUIT/CUIL 번호를 생성할 수 있나요? 아니요 - 이 도구는 수학적으로 유효한 테스트 데이터를 생성하지만, 번호는 AFIP에 공식적으로 등록되지 않았습니다. Luhn 알고리즘을 사용하여 유효한 신용 카드 번호를 생성하는 것과 같습니다: 형식 검증은 통과하지만 실제 계정과 연결되지 않았습니다. 공식 CUIT/CUIL 등록을 위해서는 개인은 DNI를 가지고 AFIP를 방문해야 하고, 기업은 법인 등록 절차를 완료해야 합니다. 이 도구는 엄격하게 개발, 테스트 및 교육 목적으로 실제 식별 번호와 충돌하지 않는 유효한 데이터가 필요한 경우에 사용됩니다. (나머지 번역은 동일한 방식으로 계속됩니다) ## 참고 자료 1. AFIP (공공수입연방관리국). "CUIT/CUIL/CDI." 공식 웹사이트. [https://www.afip.gob.ar/](https://www.afip.gob.ar/) 2. 노동, 고용 및 사회보장부. "CUIL - 노동 식별 고유 키." [https://www.argentina.gob.ar/trabajo](https://www.argentina.gob.ar/trabajo) 3. ANSES (국가사회보장관리국). "내 CUIL 얻기." [https://www.anses.gob.ar/](https://www.anses.gob.ar/) 4. 아르헨티나 공화국 공식 공보. "AFIP 일반 결의 2854/2010: 절차. 조세 고유 식별 키(C.U.I.T.)." 5. 아르헨티나 공화국 재정법. "납세자 식별 및 등록." --- 청구서 시스템 구축, 직원 온보딩 흐름 테스트, 또는 검증 알고리즘 학습 등 어떤 목적이든 이 도구는 필요한 CUIT/CUIL 생성 및 검증을 제공합니다. 알고리즘 검증을 통과하는 테스트 데이터 생성, 데이터베이스에 입력되기 전 번호 확인, 또는 실제로 체크 숫자 알고리즘의 작동 방식 탐색이 가능합니다.
귀하의 워크플로에 유용할 수 있는 더 많은 도구를 발견하세요.