문서 작업 가이드
운영 ID를 복사하지 않고 UUID v4 테스트 fixture 만들기
로컬에서 생성한 RFC 9562 UUID v4로 API·데이터베이스·event fixture를 구성하고, 형식과 관계를 검증한 뒤 값을 고정해 안전하고 결정론적인 테스트를 만듭니다.
작성 및 검수 SimpleWebUtils게시일: 검토일:
이 작업 흐름을 검증한 방법
UUID v4 생성기 검증에는 “운영 형태의 API 식별자 세 개 교체”에 적힌 정확한 입력을 사용했습니다. 정상 경로에서 “식별자 필드와 관계를 전부 매핑하기”, “제한된 배치와 정규 형식 선택하기” 단계를 실행한 뒤 생성된 값이나 파일을 문서 결과와 맞춰 봤습니다. 위험 검토 항목은 “같은 entity를 서로 다른 값으로 교체”, “충돌이 드물다는 이유로 UNIQUE 제약 제거”였습니다.
교체 ID 세 개는 모두 소문자 정규형 UUID v4를 만족하고 저장한 fixture에서 고정됐으며, 복사된 운영 식별자를 포함하지 않았습니다.
문제 상황
운영과 비슷한 fixture에는 UUID 필드가 자주 필요하지만 실제 고객·tenant·주문·trace·조직 ID를 source control, screenshot, bug report, 공유 테스트 환경에 복사하면 살아 있는 레코드와 불필요한 연결이 생깁니다. 모든 값을 123이나 임의 문자열로 바꾸는 것도 해결책이 아닙니다. 애플리케이션은 UUID 정규 문법, 버전 4와 IETF variant 비트, 안정적인 foreign-key 관계 또는 데이터베이스 UNIQUE 제약을 요구할 수 있습니다. 반대로 테스트를 실행할 때마다 새 값을 만들면 snapshot과 golden file이 비결정적으로 변합니다. 따라서 운영 식별자를 먼저 제거하고, 올바른 UUID v4를 로컬 생성하고, 같은 entity에는 같은 교체 값을 매핑하고, 문법과 관계를 검증한 뒤, 검토한 fixture를 고정해야 합니다. UUID는 비밀값이나 권한 증명이 아니므로 인증과 인가 테스트도 별도로 유지해야 합니다.
공식 출처와 표준
다음 공식 문서는 이 작업 흐름에서 다루는 형식과 보안 경계의 기준입니다. 도구별 실행 검증은 위에 별도로 기록합니다.
- RFC 9562: Universally Unique IDentifiers (UUIDs)
RFC Editor / IETF
이럴 때 사용하세요
- API 응답 fixture의 UUID primary key, foreign key, request ID 또는 event ID가 운영 레코드를 가리키지 않아야 할 때
- 데이터베이스 seed나 migration 예제에 독립적인 식별자가 필요하면서 UNIQUE·foreign-key 동작은 그대로 시험할 때
- support ticket, screenshot, log 발췌 또는 재현 묶음을 공유하기 전에 실제 tenant와 사용자 ID를 교체할 때
- contract test가 정규형 UUID v4 문법을 요구하면서 모든 실행에서 같은 기대 결과를 내야 할 때
- offline client나 분산 producer가 동기화 전에 ID를 할당하고 충돌 경로도 명시적으로 시험해야 할 때
단계
- 1단계
식별자 필드와 관계를 전부 매핑하기
UUID 필드, primary key, foreign key, correlation 필드, null 허용 여부, 표시 형식, 고유성 범위를 적습니다. 수신기가 소문자 8-4-4-4-12 정규형을 요구하는지, compact text를 허용하는지, native UUID 타입을 쓰는지 확인하고 같은 entity를 반복 참조하는 위치를 표시합니다.
- 2단계
편집 전에 운영 식별자 제거하기
정제한 복사본에서 실제 UUID, 이름, 이메일, token, 테스트에 필요 없는 payload를 먼저 삭제합니다. 운영 ID를 외부 조회 서비스에 붙여 넣지 마세요. UUID 생성기는 원본 입력 없이 새 값을 브라우저 안에서 만듭니다.
- 3단계
제한된 배치와 정규 형식 선택하기
필드 등장 횟수가 아니라 서로 다른 교체 ID 개수를 셉니다. 1~100개를 요청하고 스키마가 다르게 요구하지 않는 한 소문자 하이픈 정규형을 유지한 뒤, fixture 역할과 생성 값의 작은 매핑 표를 만듭니다.
- 4단계
UUID v4를 로컬에서 생성하기
생성기를 한 번 실행합니다. 도구는 crypto.getRandomValues()를 사용해 RFC 9562 버전 4와 IETF variant 비트를 설정하고 같은 배치의 중복을 재시도하며 Math.random()으로 대체하지 않습니다. 생성 값은 서버로 보내지 않고 전체 줄 결과를 복사하거나 내려받습니다.
- 5단계
문법·개수·관계 검증하기
출력 개수, 버전 숫자 4, variant 숫자 8·9·a·b, fixture 안의 중복 여부를 확인합니다. 같은 기존 entity의 모든 위치에는 같은 새 UUID를 넣고, 완성한 JSON이나 CSV를 실제 애플리케이션 parser로 다시 읽습니다.
- 6단계
결정론적 fixture로 고정하기
검토한 UUID를 고정 fixture 값으로 commit합니다. assertion이 난수 필드를 명시적으로 무시하거나 제어하지 않는 한 snapshot setup에서 생성기를 호출하지 마세요. 고정 ID는 diff, 실패, 기대 관계를 재현 가능하게 만듭니다.
- 7단계
제약과 인가를 별도 시험하기
운영과 같은 검증 경로로 fixture를 적재하고 데이터베이스 UNIQUE·foreign-key 제약을 유지합니다. 중복 ID, 잘못된 UUID, 누락 참조, 인가되지 않은 접근을 각각 음성 사례로 추가하세요. 올바른 UUID 자체가 권한을 주면 안 됩니다.
예시
운영 형태의 API 식별자 세 개 교체
입력
스키마: userId, organizationId, requestId는 소문자 정규형 UUID v4 문자열이어야 함; userId는 organizationId에 속함; snapshot에서 값이 고정돼야 함; 운영 ID는 남기지 않음.출력
{"userId":"3f2e2b6a-7f2c-4e3a-9a21-6e98785f4c20","organizationId":"7a6b3d94-44e3-4a70-85c0-31278f7d1b42","requestId":"b91d1c0e-6ef2-49e5-9f59-1f81d4f3be76"}흔한 실수
assertion마다 새 ID 생성
제어하지 않은 난수는 매 실행의 snapshot과 기대 payload를 바꿉니다. fixture 값은 한 번 생성해 고정하고, 운영 코드의 생성 동작을 시험해야 한다면 결정론적 UUID provider를 주입하세요.
같은 entity를 서로 다른 값으로 교체
한 organization ID가 상위 레코드와 자식 행 세 곳에 나오면 네 위치 모두 같은 교체 값이 필요합니다. 매핑 표로 foreign-key 관계가 끊어지는 것을 막으세요.
충돌이 드물다는 이유로 UNIQUE 제약 제거
UUID v4는 충돌을 극히 드물게 하지만 불가능하게 만들지는 않습니다. fixture에서도 운영 데이터를 보호하는 동일한 고유성 제약과 conflict 처리를 실행해야 합니다.
36자리 문자열이면 UUID라고 판단
길이만으로 UUID v4 문법을 증명할 수 없습니다. 16진수 그룹, 버전 4 숫자, IETF variant, 수신기가 요구하는 정규형·compact 표시를 검사하세요.
불투명한 ID를 인가로 간주
UUID는 비밀값이 아닙니다. ID를 아는 사용자가 해당 레코드에 접근할 수 있다고 가정하지 말고 허용·거부 principal을 명시해 인증과 인가를 시험하세요.
자주 묻는 질문
fixture에서 UUID를 실행 중 생성해야 하나요, 고정해야 하나요?
snapshot, 예제, golden file, 관계가 많은 fixture에는 고정 UUID를 저장하세요. 실행 중 생성은 테스트가 provider를 제어하거나 정확한 출력 대신 무작위 할당 자체를 검증할 때 적합합니다.
이름과 이메일을 지우면 운영 UUID를 복사해도 되나요?
피하는 편이 좋습니다. 식별자만으로도 fixture, log, screenshot을 실제 tenant나 레코드와 다시 연결할 수 있습니다. 새 UUID v4를 생성하고 로컬 교체 표로 관계를 보존하세요.
생성 값이 UUID v4인지 어떻게 확인하나요?
정규형이라면 8-4-4-4-12 16진수 구조, 세 번째 그룹 첫 글자 4, 네 번째 그룹 첫 글자 8·9·a·b를 확인합니다. 그런 다음 애플리케이션이 실제 쓰는 UUID library나 데이터베이스 타입으로 parse하세요.
데이터베이스 unique constraint가 여전히 필요한가요?
필요합니다. 난수 생성은 충돌 확률을 낮출 뿐 저장 규칙을 강제하지 않습니다. UNIQUE 제약을 유지하고 중복 insert가 거절될 때 애플리케이션이 처리하는 경로를 시험하세요.
UUID가 있으면 object URL이 비공개가 되나요?
아니요. UUID는 식별자이지 인가가 아닙니다. 보호된 object에는 ID 형식과 무관하게 인증, 권한 검사, 의도적인 공유 또는 만료 token 설계가 필요합니다.
생성한 fixture UUID는 외부로 전송되나요?
생성기는 Web Crypto로 로컬에서 값을 만들며 UUID를 업로드하지 않습니다. 분석에는 개수와 형식 같은 집계 설정만 포함하고 생성된 UUID text는 제외합니다.