00127이 127이 될 때: 문서 AI 식별자와 숫자 정밀도

이 카테고리 글 목록

전체글 보기

문서번호 ‘00127’을 숫자 127로 저장해도 같은 번호일까? 두 값을 같게 취급한다는 확인된 규칙이 없다면 그렇다고 할 수 없다. 식별자는 계산할 수량이 아니라 대상을 구별하는 값이므로, 숫자로 바꾸기 전에 선행 0·자릿수·자료형을 그대로 보존해야 하는지 확인해야 한다. 긴 번호는 숫자로 읽는 순간 정밀도를 잃을 수도 있다.

이 글은 문서 AI의 추출 결과를 JSON, 업무 프로그램, 저장소로 옮기는 담당자를 위한 설명이다. 아래 접수번호와 자산번호는 가상이며 실제 고객·계정 식별자가 아니다. JavaScript의 작은 예제만 로컬에서 확인했고, AI 모델·외부 API·운영 저장소를 연결한 실험은 하지 않았다.

숫자처럼 생긴 이름과 계산할 수량을 구별한다

상품 수량은 덧셈과 범위 비교가 필요할 수 있다. 반면 접수번호·자산번호는 보통 해당 대상을 다시 찾는 데 쓴다. 가상의 원문에서 ‘접수번호 00127, 수량 3’을 읽었다면 두 필드를 같은 숫자 변환 규칙으로 처리할 이유가 없다. 접수번호의 규칙은 발급 기관과 소비 API의 계약에서, 수량의 규칙은 해당 업무에서 확인한다.

RFC 8259의 숫자 문법은 선행 0을 허용하지 않는다. 따라서 JSON에서 {"id":00127}은 유효한 숫자 표현이 아니다. {"id":"00127"}은 문자열로 원래 자릿수를 담고, {"id":127}은 숫자 127을 담는다. 둘은 자료형도 표현도 다르다. 문자열을 선택했더라도 원문을 잘못 읽었다면 오류는 남는다.

필드 상황 우선 확인할 계약 피해야 할 자동 변환
선행 0이 있는 접수번호 자릿수와 선행 0이 식별에 포함되는가 숫자로 바꾼 뒤 화면에서만 0을 붙이기
긴 숫자 모양의 식별자 전달 경로 전체의 타입과 정밀도 일반 숫자로 읽은 뒤 문자열로 되돌리기
문자·하이픈이 포함된 코드 대소문자·구분자 정규화가 허용되는가 구분자를 지워 다른 코드와 합치기
합계를 낼 수량 숫자 자료형·단위·허용 범위 모든 값을 식별자처럼 문자열로만 취급하기

큰 정수는 파싱에 성공해도 다른 값이 될 수 있다

가상 자산번호가 9007199254740993이라고 하자. JavaScript의 일반 Number는 모든 크기의 정수를 서로 구별하지 못한다. ECMAScript의 MAX_SAFE_INTEGER 명세는 안전한 정수의 최댓값을 9,007,199,254,740,991로 정의하고, 그 범위 밖의 서로 다른 정수가 같은 Number 값으로 표현될 수 있음을 설명한다. 범위를 넘는 모든 숫자가 반드시 틀린다는 뜻은 아니며, 정수의 정확성과 구별을 일괄 보장할 수 없다는 뜻이다.

다음은 로컬 Node.js에서 확인한 결정론적 예제다. 실제 자산 시스템에 값을 보내지는 않았다.

const parsed = JSON.parse('{"id":9007199254740993}');
String(parsed.id); // "9007199254740992"
Number.isSafeInteger(parsed.id); // false

const kept = JSON.parse('{"id":"9007199254740993"}');
kept.id; // "9007199254740993"

첫 결과를 문자열로 바꾸면 이미 달라진 번호를 글자로 옮길 뿐이다. 원래 번호는 복원되지 않는다. AI가 원문을 정확히 출력했더라도 중간 프로그램의 숫자 변환에서 손상이 시작될 수 있으므로, 모델 답변만 다시 생성하는 처방은 맞지 않을 수 있다.

같은 평가 카드가 청록색과 노란색 두 목록으로 나뉘고 돋보기로 실패 카드를 살펴보는 삽화
같은 입력을 두 결과 목록과 대조하는 기존 AI 생성 개념도. 식별자의 원문과 변환 후 값을 비교하는 맥락으로 재사용했다. 실제 번호·숫자 정밀도나 오류율을 나타내는 그림은 아니다.

원문에서 마지막 소비자까지 타입을 따라간다

작성자는 ‘원문의 문자 표현 → 추출 응답 → 파싱 직후 값 → 저장·전송 값 → 다시 읽은 값’을 같은 항목으로 대조할 것을 제안한다. 대조 대상에는 값뿐 아니라 자료형과 자릿수도 포함한다. 원문과 추출 응답은 같은데 파싱 직후 다르면 그 변환부터 고친다. 원문부터 추출이 다르면 OCR의 문자와 표 연결 점검이 먼저다.

받는 API가 식별자를 문자열로 요구한다면 최초 추출부터 문자열로 유지하는 것이 한 방법이다. API가 숫자를 요구한다면 문자열을 무작정 보내지 말고 허용 범위와 정확한 정수 처리 수단을 확인한다. 일반 Number를 거치지 않는 정수 처리 경로를 선택하더라도 직렬화와 저장 단계가 그 타입을 지원하는지 확인해야 한다. 이미 반올림된 Number를 나중에 큰 정수 타입으로 바꿔도 원문은 돌아오지 않는다.

고정 다섯 자리 규칙이 확인된 번호라면 ‘127’을 ‘00127’로 표시하는 것이 허용될 수 있다. 하지만 그 규칙이 없으면 원래 ‘127’인지 ‘00127’인지 알아낼 수 없다. 겉모양을 맞추려고 자릿수·구분자·대소문자를 임의 보정하지 않는다. 원문 위치를 추적할 때에도 민감한 식별자 전체를 일반 로그에 남길 필요는 없다.

식별의 의미와 표현 보존은 함께 확인한다

값을 보존했어도 잘못된 필드를 연결하면 다른 대상이 선택된다. 문서번호인지 고객번호인지, 어느 발급처·계정 범위의 값인지 확인해야 한다. 같은 문자열이 다른 시스템에서 다른 대상을 가리킬 수 있기 때문이다. 웹훅의 전달·사건·업무 대상 구분은 식별자의 역할을 구별하는 기존 글에서 설명한다. 여기서 다룬 문제는 역할을 정한 뒤에도 변환 과정이 그 값을 훼손할 수 있다는 점이다.

검증 자료에는 선행 0, 안전한 정수 범위 안팎, 문자·구분자가 섞인 번호와 정상 수량을 포함할 수 있다. 예상 결과는 발급 규칙과 API 계약으로 정한다. 새 변환 규칙이 이 사례를 통과하더라도 전체 문서 정확성을 보증하지는 않는다. 값의 부재는 누락·null·빈 문자열·0의 구별, 시간 표현은 날짜와 시간대의 의미 보존으로 따로 점검한다.

자주 묻는 질문

모든 숫자를 문자열로 바꾸면 해결되나요?

식별자의 표현 보존에는 도움이 될 수 있지만 수량·단가처럼 계산할 값의 규칙까지 대신하지는 못한다. 소비 API가 요구하는 타입도 맞아야 한다. 필드의 목적과 전달 계약을 확인해 변환을 정한다.

정수 타입 검증을 통과했으면 원래 번호와 같은가요?

아니다. 이미 반올림된 값도 정수일 수 있다. 허용 범위·안전한 정수 여부와 원문 문자열 대조를 구별해야 한다. 최종 저장값을 다시 읽을 때까지 중간 자동 변환이 없는지도 확인한다.

두 번호가 같아 보이는데 검색 결과가 다르면 무엇부터 보나요?

원문의 자릿수·선행 0·구분자와 실제 전송 타입을 먼저 대조한다. 그 값이 어느 발급처와 필드의 식별자인지도 맞춘다. 문자열 길이나 정밀도 손실이 아니라 다른 대상 범위가 원인일 수도 있으므로, 화면 표시만 보고 두 번호를 합치지 않는다.

이 카테고리의 다른 글

전체글 보기

“00127이 127이 될 때: 문서 AI 식별자와 숫자 정밀도”에 대한 3개의 생각

댓글 남기기