마지막 한 자리를 계산하는 규칙은 하나가 아니라 여러 개이며, 서로 다른 제도는 서로 다른 규칙을 씁니다. 체크 디지트 알고리즘을 하나의 가족으로 묶어 보면 그 차이가 어디에서 생기는지 훨씬 선명해집니다. 이 글은 가족의 공통 골격과 구성원 사이의 차이, 그리고 새로 규칙을 도입할 때 무엇을 먼저 정해야 하는지 다룹니다.
체크 디지트 알고리즘 가족은 어떻게 생겼나요?
구성원이 여럿이어도 뼈대는 같습니다. 앞의 자릿수에 자리마다 다른 가중치를 곱해 더하고, 그 합계를 정해진 수로 나눈 나머지를 구한 다음, 그 나머지나 그 여수를 한 자리 문자로 바꿔 마지막에 붙입니다. 이 세 단계를 벗어나는 알고리즘은 사실상 없습니다.
차이는 세 군데에서만 생깁니다. 어떤 가중치를 어느 자리에 적용하는지, 무엇으로 나누는지, 그리고 나머지를 어떤 문자로 옮기는지입니다. 그래서 가족을 이해한다는 것은 세 매개변수를 이해한다는 뜻이고, 특정 알고리즘 하나를 외우는 것과는 다른 종류의 지식입니다.
mod-10, mod-11, mod-97은 무엇이 다른가요?
세 갈래는 나누는 수가 다릅니다. 나누는 수가 커지면 구분할 수 있는 나머지의 가짓수가 늘어나므로, 더 많은 오류 조합을 서로 다른 결과로 갈라낼 수 있습니다. 대신 나머지가 한 자리를 넘길 수 있다는 부담이 따라옵니다.
| 갈래 | 나누는 수의 성격 | 함께 따라오는 제약 |
|---|---|---|
| mod-10 계열 | 나머지가 늘 한 자리 | 더하기 한 번으로 표현되지만 구분력이 좁음 |
| mod-11 계열 | 나머지가 두 자리일 수 있음 | 남는 값을 문자로 옮기는 규칙이 필요 |
| mod-97 계열 | 나머지가 훨씬 넓음 | 긴 문자열에 어울리며 중간 계산 처리가 필요 |
mod-11 계열에서 나머지가 두 자리로 나오는 경우를 어떻게 표기할지가 구현에서 가장 먼저 부딪히는 문제입니다. 어떤 제도는 열 번째 값을 알파벳 한 글자로 적도록 정하고, 어떤 제도는 나머지가 특정 값이 되는 조합 자체를 쓰지 않도록 정합니다. 두 방식은 계산이 아니라 표기의 문제이며, 제도가 공개한 설명을 그대로 따라야 합니다.
가중치와 모듈러스를 바꾸면 무엇이 달라지나요?
가중치는 어떤 종류의 실수를 서로 다른 결과로 갈라놓을지 결정합니다. 모든 자리에 같은 수를 곱하면, 이웃한 두 자리를 바꿔 적은 값은 합계가 그대로여서 원래 값과 구별되지 않습니다. 반대로 자리마다 다른 수를 곱하면 두 자리를 바꿨을 때 합계가 어긋나므로 그 실수가 드러납니다.
그래서 가중치 설계는 검출 대상의 목록에서 출발합니다. 손으로 옮겨 적는 값이라면 자리 뒤바꿈이 흔하고, 기계가 만들어 내는 값이라면 다른 실수가 흔합니다. 어느 쪽을 우선할지 정하지 않고 가중치를 고르면, 정작 잡아야 할 오류를 놓치는 규칙이 됩니다.
왜 어떤 알고리즘은 자리 바꿈을 못 잡나요?
이웃한 두 자리를 서로 바꿔 적는 실수를 생각해 봅시다. 두 자리에 같은 가중치가 적용되면 두 항의 합은 순서와 무관하게 같습니다. 합계가 같으니 나머지도 같고, 체크 디지트도 같습니다. 즉 그 오류는 규칙이 보기에 원래 값과 완전히 동일한 값입니다.
가중치가 자리마다 다르면 두 항이 바뀌면서 합계가 달라지고, 대부분의 경우 나머지가 어긋나 오류가 드러납니다. 다만 가중치가 달라도 결과가 우연히 같아지는 조합은 남습니다. 그래서 어떤 알고리즘도 모든 자리 바꿈을 잡는다고 단정할 수 없습니다. 이 차이가 실제 판정에 어떻게 반영되는지는 번호 검증의 원리에서 층별 검출 범위로 다시 정리합니다.
알고리즘을 고를 때 무엇을 정해야 하나요?
새 번호 체계를 설계하거나 검증 규칙을 도입할 때는 다음 네 가지를 먼저 확정하는 편이 좋습니다.
- 번호의 최대 길이가 어느 정도인지, 자릿수가 고정인지 가변인지
- 숫자만 쓰는지, 알파벳이 섞이는지
- 오류가 주로 사람의 입력에서 오는지, 기계 생성 과정에서 오는지
- 나머지가 두 자리로 나올 때 그것을 어떻게 표기할지
이 네 가지가 정해지면 나누는 수와 가중치의 범위도 좁혀집니다. 반대로 이 답 없이 알고리즘부터 고르면, 나중에 표기 규칙을 바꾸면서 이미 발급된 값과 새 값의 규칙이 갈라지는 상황이 생깁니다. 번호 체계에서 규칙 변경은 과거 데이터와의 호환 문제이므로, 처음 정할 때 여유를 두는 편이 쌉니다.
계산 절차를 매개변수로 돌리다 보면 매개변수 자체가 잘못된 경우를 만납니다. 가중치 목록의 길이가 자릿수와 맞지 않거나, 나누는 수가 0이거나, 나머지를 값으로 옮기는 규칙이 빠진 경우입니다. 이런 상태로 계산을 돌리면 예외가 나거나, 더 나쁘게는 조용히 틀린 값이 나옵니다.
그래서 계산 절차의 앞에 매개변수 점검을 둡니다. 가중치 목록이 비어 있지 않은지, 자릿수와 순환 규칙이 서로 맞는지, 나머지 변환 규칙이 모든 경우를 덮는지 확인합니다. 이 점검은 계산 결과가 아니라 설정의 문제를 잡아내므로, 실패 사유도 산술 불일치와 구분해 표시해야 합니다. 설정 오류를 값의 오류로 보고하면 담당자가 엉뚱한 곳을 고치게 됩니다.
이어서 살펴볼 문제는 매개변수가 여러 벌 섞이는 상황입니다. 제도마다 알고리즘이 다르면 목록 하나에 여러 계산 절차가 섞입니다. 이때 가장 흔한 사고는 하나의 매개변수 묶음을 모든 값에 적용하는 것입니다. 길이가 겹치는 구간에서는 계산이 조용히 성공하고, 결과만 틀린 채로 통과합니다.
이를 막으려면 각 값에 대해 어떤 매개변수를 적용했는지 결과에 남겨야 합니다. 같은 값이 두 제도에 걸치면 두 결과를 나란히 보여주고, 어느 쪽이 성립하는지 사용자가 판단할 수 있게 합니다. 시험 자료에도 제도별 대표 값을 함께 두고, 새 매개변수를 추가할 때 기존 제도의 결과가 바뀌지 않았는지 확인하는 절차를 붙여 두면 이런 사고를 초기에 잡을 수 있습니다.
개발자를 위한 메모: 가족 단위로 구현하기
- 알고리즘마다 함수를 새로 쓰기보다, 가중치 목록과 나누는 수와 나머지 변환 규칙을 매개변수로 받는 하나의 계산 절차를 둡니다. 가족이라는 사실이 코드 구조에 그대로 드러납니다.
- 나머지를 문자로 바꾸는 단계를 별도 함수로 분리합니다. 여기서만 표기 규칙이 달라지므로, 나머지 계산과 섞이면 수정할 때 위험이 커집니다.
- 제도별 매개변수는 자료로 두고 계산 절차는 그대로 둡니다. 규칙이 바뀌어도 계산 코드를 건드리지 않게 됩니다.
- 공개된 예시 값으로 자체 점검을 붙여 둡니다. 알고리즘을 옮겨 적다 한 글자를 틀리는 사고는 생각보다 흔합니다.
- 검증 결과에 어느 알고리즘을 적용했는지 함께 담습니다. 같은 값이 알고리즘에 따라 다른 판정을 받을 수 있기 때문입니다.
알고리즘 이름과 매개변수는 공개된 지식이지만, 여기서 언급한 수치와 예시는 구조를 설명하기 위해 구성한 가상의 값입니다. 어떤 제도가 실제로 발급한 번호를 가리키지 않으며, 검증 통과를 번호의 진위나 사용 가능성의 근거로 삼을 수 없습니다.
다음 단계
규칙이 다른 두 제도에 같은 값을 넣어 결과가 어떻게 갈리는지 번호 검증 도구에서 확인해 보세요. 긴 번호에 mod-97 계열이 어떻게 쓰이는지 궁금하다면 IBAN 구조와 mod-97 검증이 이어집니다.