마트 계산대에서 바코드가 한 번에 읽히지 않고 다시 긁는 장면을 본 적이 있을 것입니다. 상품 바코드의 마지막 자리는 그런 순간을 줄이기 위해 붙어 있습니다. 이 글에서는 마지막 자리가 어떤 계산으로 나오는지, 길이가 다른 바코드에서 무엇이 달라지는지, 그리고 이 검사가 답하지 못하는 질문이 무엇인지 살펴봅니다.
상품 바코드의 마지막 자리는 어떻게 정해지나요?
마지막 한 자리를 제외한 나머지 자릿수에 자리마다 번갈아 다른 가중치를 곱해 모두 더합니다. 그 합계를 정해진 수로 나눈 나머지를 구하고, 그 값을 채워 올림해서 나오는 수를 마지막 자리로 씁니다. 이렇게 하면 앞의 자릿수가 한 글자라도 바뀌었을 때 마지막 자리가 맞지 않게 됩니다.
여기서 중요한 것은 계산의 방향입니다. 가중치는 왼쪽 끝이 아니라 오른쪽 끝에서부터 세어 붙입니다. 그래서 전체 길이가 달라지면 같은 자릿수에 적용되는 가중치가 뒤바뀝니다. 이 규칙을 놓치면 길이가 다른 바코드에서 계산이 조용히 어긋납니다.
두 가지 대표 길이에서 무엇이 달라지나요?
널리 쓰이는 두 가지 길이에서 마지막 자리의 계산 방식은 같지만, 가중치의 시작 위치가 달라집니다. 오른쪽에서 세어 붙이기 때문에 자릿수가 하나 늘거나 줄면 각 자리에 곱해지는 값이 서로 자리를 바꿉니다.
| 길이 구분 | 검증값 위치 | 가중치 적용의 특징 |
|---|---|---|
| 짧은 형식 | 마지막 한 자리 | 오른쪽 첫 자리부터 번갈아 적용 |
| 긴 형식 | 마지막 한 자리 | 같은 규칙, 시작 위치가 하나 밀림 |
즉 계산 절차를 하나만 구현해 두고 길이를 매개변수로 받는 구조가 자연스럽습니다. 길이별로 별도의 함수를 복사해 두면 한쪽만 고쳐지는 사고가 생깁니다. 이 계열이 검증값 알고리즘 가족에서 어디에 놓이는지는 체크 디지트 알고리즘 편에서 정리했습니다.
오른쪽에서 왼쪽으로 더하는 이유는 무엇인가요?
방향을 고정하는 이유는 재현성입니다. 같은 숫자열이 항상 같은 결과를 내려면, 어느 끝을 기준으로 세는지가 명확해야 합니다. 왼쪽에서 세는 규칙과 오른쪽에서 세는 규칙은 길이가 짝수일 때 서로 다른 값을 만들므로, 기준을 정하지 않으면 구현마다 답이 갈립니다.
또 하나의 이유는 자릿수가 늘어나는 상황에서의 안정성입니다. 접두부가 추가되어 자릿수가 늘어나면, 오른쪽 기준으로 세는 규칙은 이미 정해진 뒷부분의 가중치를 그대로 유지합니다. 번호 체계가 나중에 확장될 가능성을 남겨 두는 설계라고 볼 수 있습니다.
바코드 접두부는 무엇을 말해 주나요?
앞부분의 특정 자릿수는 번호를 부여하는 기관이 나라나 지역별로 나눠 둔 구간을 가리킵니다. 즉 그 값이 알려 주는 것은 이 번호를 어느 기관이 관리하는 구간에서 부여했는가입니다. 국제적으로 통용되는 상품 번호 체계에서는 이 구간 배분이 표준 문서로 공개되어 있습니다.
흔한 오해가 하나 있습니다. 접두부를 보고 그 상품이 어디에서 만들어졌다고 단정하는 것입니다. 번호 구간은 상품을 등록한 사업자의 소재나 관리 주체와 연결될 뿐, 실제 생산지와는 다를 수 있습니다. 상품을 다른 나라에서 위탁 생산하는 일은 흔하므로, 접두부는 원산지를 알려 주는 표시가 아닙니다.
마지막 자리가 맞으면 정품인가요?
아닙니다. 검증값이 막아 주는 것은 옮겨 적거나 스캐너가 읽는 과정의 실수입니다. 마지막 자리가 일치한다는 사실은 그 숫자열이 산술 규칙을 만족한다는 것만 뜻하며, 그 상품이 어느 브랜드의 정품인지, 유통 경로가 정상인지와는 아무 관계가 없습니다.
위조품도 규칙에 맞는 번호를 가질 수 있습니다. 검증값은 번호의 형식을 지키기 쉽게 만든 장치이지, 진품을 보증하는 장치가 아닙니다. 정품 확인이 필요하다면 제조사의 별도 확인 절차가 필요하고, 그것은 번호 계산과 다른 문제입니다. 확인한 범위를 넘어서는 판단을 하지 않는 원칙은 번호 검증의 원리에서 다시 짚었습니다.
여기서 한 가지 현장 문제를 더 짚어 둡니다. 바코드는 막대로 읽고, 사람은 아래 인쇄된 숫자를 읽습니다. 이 둘이 다를 때 어느 쪽을 믿을지 정해 두지 않으면 판정이 흔들립니다. 원칙은 막대에서 읽은 값과 인쇄된 값을 각각 따로 보관하고, 둘 다 검증한 뒤에 비교하는 것입니다. 인쇄된 숫자만 검증하고 막대를 무시하면 스캔 오류를 놓칩니다.
실제로 두 값이 어긋나는 경우는 드물지 않습니다. 인쇄가 흐리거나, 라벨을 다시 만들면서 숫자만 고친 경우가 그렇습니다. 이런 값을 만나면 어느 쪽이 맞는지 계산으로 단정할 수 없으므로 두 값을 함께 보고하고, 재확인을 요청하는 편이 안전합니다. 검증값은 어느 쪽이 규칙을 만족하는지 알려 줄 뿐, 어느 쪽이 실제 상품의 번호인지는 알려 주지 않습니다.
계산한 값과 읽어 들인 값을 나란히 남기는 습관도 같은 이유에서 중요합니다. 나중에 문제를 되짚으려면 실패한 값만이 아니라 성공한 값도 함께 기록해야 합니다. 실패 비율이 갑자기 오르는지 보려면 성공 건수가 있어야 하기 때문입니다. 기록에는 읽어 들인 원본, 정리한 값, 계산한 마지막 자리, 읽어 들인 마지막 자리, 그리고 사용한 길이 구분을 담습니다.
계산한 값과 읽어 들인 값을 나란히 남기는 습관은 원인 파악을 크게 줄여 줍니다. 두 값이 일치하는데도 실패했다면 문제는 계산이 아니라 입력 단계에 있고, 두 값이 다르다면 계산 규칙이나 길이 판단을 의심할 수 있습니다. 이 구분만으로도 재스캔을 안내할지, 입력을 다시 받을지 정할 수 있습니다.
개발자를 위한 메모: 스캔 오류를 어떻게 좁힐까
스캔이 실패했을 때 결과를 한 덩어리로 보고하면 원인을 찾기 어렵습니다. 다음 순서로 나눠 기록하는 편이 낫습니다.
- 정리 단계에서 읽어 들인 길이를 먼저 확인합니다. 한 자리 적거나 많으면 계산 이전에 원인이 정해집니다.
- 허용되지 않은 문자가 섞였는지 확인합니다. 스캐너 설정에 따라 앞뒤에 문자가 붙는 경우가 있습니다.
- 계산 결과와 읽어 들인 마지막 자리를 함께 남깁니다. 어느 쪽이 어긋났는지 보이면 재스캔과 재입력 중 무엇을 안내할지 정할 수 있습니다.
- 연속해서 읽는 환경이라면 인접한 바코드가 섞여 들어오는 경우를 따로 표시합니다. 이 오류는 값 자체의 문제가 아닙니다.
- 실패한 원본 문자열을 그대로 보관합니다. 정리한 값만 남기면 나중에 원인을 되짚을 수 없습니다.
이 글의 바코드 예시와 숫자는 계산 순서를 설명하기 위해 구성한 것이며, 실제로 유통되는 상품이나 사업자를 가리키지 않습니다. 검증값의 일치 여부는 상품의 진위나 거래의 정당성과 무관하며, 그 근거로 사용할 수 없습니다.
다음 단계
길이가 다른 두 형식의 값을 번호 검증 도구에 넣어 마지막 자리만 바꿨을 때 판정이 어떻게 달라지는지 확인해 보세요. 비슷한 방식으로 계산되는 다른 번호 체계는 ISBN과 ISSN의 체크 디지트에서 이어집니다.