← 기술 지식

기술 지식 / 소프트웨어 설계 / 상태·데이터 모델

Unicode 비교 키와 UUID·ULID의 식별 계약

표시 원문·정규화·casefold·grapheme·DB unique 의미와 시각적 유사성을 나누고 ID 충돌·시간 정렬·인가·논리 멱등성을 구분합니다.

설계 · 원리·구현·운영
기술 지식 트리

표시 문자와 Byte 표현의 차이

식별 계약은 최소한 표시값, 비교키, 내부 식별자를 세 층으로 나눕니다. 표시값은 사용자가 입력·확인하는 원문이고, 비교키는 충돌 규칙을 적용한 값이며, 내부 ID는 이름이 바뀌어도 자원을 계속 가리키는 안정된 키입니다. 한 층의 변환을 다른 층의 보안이나 권한으로 오해하지 않는 것이 출발점입니다.

é는 U+00E9 하나 또는 e+U+0301 두 code point로 표현될 수 있습니다. NFC는 이런 canonical equivalence를 맞추지만 모든 시각적 유사 문자를 합치지는 않습니다. 라틴 a와 닮은 다른 script 문자는 별도 정책 대상입니다. 표시 원문과 비교용 canonical key를 분리하면 사용자 표현과 유일성 계약을 각각 관리할 수 있습니다.

NFKC는 전각 등 compatibility 문자를 합칠 수 있어 식별 의미를 더 바꿉니다. 정규화·대소문자 case folding·locale별 규칙은 별도이며 터키어 I 같은 조건을 검사합니다. username 규칙을 비밀번호에 임의 적용하지 않습니다.

단위 e+결합 부호의 예 필요한 곳
UTF-8 bytes 둘 이상의 bytes 저장·전송 상한
code points 2 Unicode 연산
grapheme cluster 보통 사용자 눈의 한 글자 화면 커서·표시 길이

이모지 family·skin tone·ZWJ도 “문자 수”를 단순 byte 길이와 다르게 만듭니다. 최대 입력 bytes와 표시 길이를 별도로 제한합니다.

앱 비교 정책과 DB 유일성 정책

앱이 NFC+casefold를 적용한 두 이름을 같다고 보는데 DB collation은 다르게 판단하거나, 반대로 앱은 다르게 보고 DB가 같다고 판단하면 가입·로그인·검색 결과가 서로 어긋납니다. 그래서 비교 key 생성 규칙의 version과 DB unique constraint를 같은 의미로 맞추고, 두 요청이 동시에 들어올 때는 사전 조회가 아니라 최종 저장 경계에서 하나를 거절하게 합니다. 조회가 비어 있었다는 사실만으로는 두 요청 사이의 저장 경쟁을 막을 수 없으므로 사전 조회만으로 유일성을 보장하지 않습니다.

기존 이름에 새 규칙을 적용하면 서로 다른 계정이 같은 key로 충돌할 수 있습니다. 임의 병합하지 말고 충돌 목록·소유 증명·이름 변경·사용자 안내·migration을 정합니다. 혼합 script·시각적 spoofing은 허용 문자·표시·신고 정책으로 보완하며 정규화가 인증·인가를 해결하지는 않습니다.

표현과 비교와 실제 자원 권한은 분리합니다표시 원문·외부 ID. 정규화·형식·비교 정책. DB 유일성·충돌 처리. 자원 인가·논리 작업 키명시적 변환동일한 의미다른 보장 유지표시 원문·외부 ID정규화·형식·비교 정책DB 유일성·충돌 처리자원 인가·논리 작업 키
표현과 비교와 실제 자원 권한은 분리합니다 화살표는 식별 처리입니다. canonical key나 추측 어려운 ID가 있어도 실제 자원 인가와 논리 요청 중복 처리는 별도입니다.
그림을 글로 읽기
  • 표시 원문·외부 ID
  • 정규화·형식·비교 정책
  • DB 유일성·충돌 처리
  • 자원 인가·논리 작업 키
  1. 표시 원문·외부 ID → 정규화·형식·비교 정책: 명시적 변환
  2. 정규화·형식·비교 정책 → DB 유일성·충돌 처리: 동일한 의미
  3. DB 유일성·충돌 처리 → 자원 인가·논리 작업 키: 다른 보장 유지

UUID Version별 생성·정렬 의미

충분한 무작위성을 가진 UUID를 사용해도 충돌 확률을 낮출 뿐 0이라는 보장은 없으므로, DB unique와 충돌 처리를 유지합니다. UUID v4의 무작위성, 시간 성분을 갖는 다른 version, ULID의 시간+난수 구조를 서로 같은 정렬 의미로 설명하지 않습니다. 시간 정렬형 ID가 index locality에 유리할 수 있어도 같은 millisecond에 여러 노드가 만들거나 clock skew·시간 역행이 생기면 전역 인과 순서까지 보장하지 않습니다.

ULID의 monotonic 생성 범위·재시작·entropy 소진은 구현 계약을 확인합니다. 문자열의 case·encoding·DB 정렬 규칙도 맞춰야 기대 순서가 유지됩니다. 시간 성분은 생성 시각을 노출할 수 있고 집중된 마지막 index page는 쓰기 경합을 만들 수 있어 실제 엔진에서 측정합니다.

선택 기준도 분리합니다. 외부 노출 ID에는 추측 저항성과 시각 정보 노출을 검토하고, 정렬이 필요하면 생성 시각을 별도 열로 저장할지 시간 정렬형 ID를 쓸지 비교하며, 멱등성에는 ID 생성기보다 업무 요청 키를 사용합니다. UUID·ULID를 택했다고 유일성 제약과 인가 검사를 생략하지 않습니다.

ID 충돌과 중복 요청의 구분

응답을 잃은 가입 요청이 매번 새 UUID를 만들면 충돌 없이 두 레코드가 생길 수 있습니다. 이는 ID 충돌이 아니라 같은 의도의 재실행입니다. 사용자 의도에서 발급한 안정된 멱등 key·업무 unique·결과 조회를 별도로 사용합니다. 반대로 같은 인자의 의도된 두 예약은 무조건 하나로 합치지 않습니다.

URL의 ID를 추측하기 어렵게 만들어도 소유권 인가는 필요합니다. 대량 생성·재시작·시계 역행·정규화 충돌·동시 저장·표현 변환·같은 논리 요청 재시도를 시험합니다. 이 노트는 식별 설계이며 ID 구현의 충돌 확률을 실험으로 증명한 결과는 아닙니다.

예상 결과는 NFC+casefold 규칙에서 서로 다른 표현의 이름 두 개가 같은 비교키로 충돌하고, 동시에 삽입하면 DB unique 경계에서 정확히 하나만 성공하는 것입니다. 반면 같은 이름으로 의도적으로 두 예약을 만들 수 있는 업무라면 이름 unique만으로 합치지 않고 예약별 멱등키를 별도로 판단해야 합니다.

후속·관련 개념

이 개념의 확장

함께 읽을 문서

전체 기술 지식
선택 연습 · 관련 질문 2개

질문은 이해를 확인하는 보조 자료입니다. 학습 경로와 문서의 범위는 질문 수와 독립적입니다.