Backend/Java

UUID, 정말 안전할까?

비비빅B 2021. 11. 6. 19:15

서론

파일을 서버에 보관할 때, 파일명 변환하는 걸 java UUID를 사용해서 변환했었다. 코드 리뷰를 받던 중에 선임분이 UUID에 대한 의심을 보이셨다.

하나의 OS에 여러 앱이 가동되는 환경, 그리고 멀티스레드에서도 충돌 가능성이 없나?

단순하게 그냥 유니크한 값이라고 믿고 사용해왔던 터라 대답하지 못했다. 이번 기회에 UUID가 어떻게 유니크한 값을 생성하는지 알아보고 정리해보려 한다.


본론

고유성을 완벽하게 보장하려면 중앙관리시스템이 있어서 일련번호를 부여해 주면 간단하지만 동시다발적이고 독립적으로 개발되고 있는 시스템들의 경우 중앙관리시스템은 불가능하다.
개발주체가 스스로 이름을 짓도록 하되 고유성을 충족할 수 있는 방법이 필요하다.
이를 위하여 탄생한 것이 범용고유식별자(UUID)이며 국제기구에서 표준으로 정하고 있다.

 

UUID(Universally Unique IDentifier) 탄생 배경 자체가 분산환경 시스템에서 출발했다. 사실 이름 그대로 우주에서 고유한 키라는 뜻이기 때문에 모든 환경에서 충돌 가능성이 없는 것은 당연한 것이다. 그럼 어떻게 유니크한 값을 만들어내는 것일까? 정말 이름만 보고 믿고 사용해도 안전한 걸까?

 

결론부터 말하자면 충돌 가능성이 없는 것은 아니지만 믿고 사용해도 될만큼의 아주 극히 희박한 확률이다. 

 

 

UUID의 구성

 

550e8400-e29b-41d4-a716-446655440000

 

UUID는 총 36개 문자(32개 문자와 4개의 하이픈)로 된 8-4-4-4-12라는 5개의 그룹을 하이픈으로 구분한다.

실질적으로는 32개의 문자(16진수)로 32*4 = 128bit만으로 유니크한 값을 이룬다. 이 중에 3번째 그룹의 첫 번째 문자는 UUID 버전을 말해준다.

 

UUID v1 : 57cc83a0-3ee0-11ec-ad54-3d4a7263eeca
UUID v4 : e0f14cf7-e07c-4d12-9eb7-6360cc94770e

 

이 값을 통해 서로 다른 UUID버전으로 생성된 값끼리도 유니크한 값을 유지한다.

 

그럼 UUID 버전은 뭘까? 주로 사용하는 UUID 1과 4를 알아보자.


UUID1

 

uuid1은 시간(timestamp)과 공간(MAC 주소)을 유일성을 이용해 유니크한 값을 만들어낸다.

 

  • 60 bits of timestamp,
  • 48 bits of computer identifier,
  • 14 bits of uniquifier, and
  • six bits are fixed(version, dash)

그럼 같은 컴퓨터에서 멀티스레드 혹은 여러 애플리케이션을 가동하는 상황이면 충돌할 가능성이 있지 않을까?

그런 경우를 대비해서 Uniquifier(14bit)가 존재한다.

 

같은 컴퓨터에서 아주 아주 우연히 같은 nanosecond에 생성되더라도 14bit가 랜덤한 값으로 생성되기 때문에 충분히 안전하다. 누군가 악의적으로 맥주소와 컴퓨터 시간을 조작하지 않는 한, 정상적인 서버 환경에서는 걱정할 필요가 없다.

 

다만, UUID1으로 생성된 값이 생성시간, MAC 주소 정보를 내포하고 있기 때문에 보안의 관점에서 유의해야 한다.

또한, UUID에서 하이픈(-)을 제외한 단 하나의 값만 잘라내서 쓰더라도 유니크한 값을 보장받을 수 없다.

 


UUID4

 

uuid4는 아주 단순하다. 버전을 나타내는 문자와 variant라고 하는 포맷과 인코딩 정보를 나타내는 문자, 그리고 하이픈(-)을 제외한 128비트의 랜덤한 값을 생성한다. uuid1과는 달리 충돌 가능성은 온전히 확률적인 문제다.

이 랜덤한 값은 2^122의 경우의 수를 가진다. UUID 하나가 16 바이트기 때문에 전체 UUID를 담은 파일은 약 45 헥사 바이트다. 이는 현존하는 가장 큰 데이터베이스보다 훨씬 더 큰 수치라고 한다. 그러니 UUID를 다 써서 충돌 날 걱정할 필요는 없다.

 

혹시 UUID를 다 쓰기 전에 같은 값을 생성해 충돌 날 수 있지 않을까?

 

조사한 바에 따르면, 100년 동안 초당 10억 개의 ID를 생성해내면 그때서야 충돌할 가능성이 50%가 된다고 한다. 이는 전 세계의 사람들이 각자 6억 개의 UUID를 보유했을 때라고 한다.

 

단순히 확률적인 값으로 비유하자면, 길가다가 운석에 맞을 확률이라고 한다.

그러니 UUID를 사용하다 충돌로 서비스에 치명적인 에러가 발생했을 때는, 이미 지구는 운석에 맞아서 내가 만든 서비스를 이용할 사람들이 더이상 없다고 생각하면 걱정에서 한결 자유롭다.

 


결론

 

정상적으로 만들어지는 UUID는 어떤 환경에서도 안전하다고 믿고 쓰면 된다.

다만 확률이 존재하기는 한다는 점에서, "만약에"라는 가정에서 자유롭지는 못하다.

"그럼, UUID만 써도 안전하다고 보장하시는거죠?"

이렇게 책임소재를 분명히 하기 위해 누군가 나에게 묻는다면, 선뜻 대답하기는 힘들다. 그래서 UUID에 다른 문자열을 추가해서 사용하는 듯하다.

 


 

Universally unique identifier - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search 128-bit label used to identify information in computer systems UUID/GUID as used by UEFI variables A universally unique identifier (UUID) is a 128-bit label used for information in com

en.wikipedia.org

 

Which UUID Version Should You Use? UUID v1, v4 and v5 Explained (With Examples)

What's the difference between the different versions of UUIDs, and when should you use them? This post will describe UUID v1, v4, and v5, with examples

www.sohamkamani.com

 

GUIDs are globally unique, but substrings of GUIDs aren't

A customer needed to generate an 8-byte unique value, and their initial idea was to generate a GUID and throw away the second half, keeping the first eight bytes. They wanted to know if this was a good idea. No, it’s not a good idea.

devblogs.microsoft.com

 

범용 고유 식별자 - 위키백과, 우리 모두의 백과사전

범용 고유 식별자(汎用固有識別子, 영어: universally unique identifier, UUID)는 소프트웨어 구축에 쓰이는 식별자 표준으로, 개방 소프트웨어 재단(OSF)이 분산 컴퓨팅 환경(DCE)의 일부로 표준화하였다. U

ko.wikipedia.org

 

'Backend > Java' 카테고리의 다른 글

Session은 Controller까지만  (0) 2022.10.09
Spring Boot 2.4.x 이슈  (0) 2022.07.08
Tika로 파일 MIME 타입 검사  (0) 2021.07.24
YAML) @PropertySource에서 EnvironmentPostProcessor까지  (0) 2021.07.03
SpringBoot profile logback  (0) 2021.06.24