웹 어플리케이션을 설계하다 보면 많은 Entity, Model, Table 들을 마주하게 되고 정의하게 됩니다

DB의 Table에서는 Auto Increment 기능이 있어서 개발자가 신경을 쓰지 않아도 자동 생성되는 식별자가 있습니다

이 녀석은 index 도 만들어지게 되서 검색 해서 사용하는데 문제가 없지만 DB 라는 미들웨어에 종속된 id로 DB 라는 구간을 거쳐야지만 이 값을 쓸 수 있다는 제약이 있습니다

또 숫자형의 식별자를 쓰기 때문에 문자형의 식별이나 인조키가 아닌 자연키로 쓰는 경우에도 제약이 생깁니다

하나의 데이터베이스에 모든 식별자 생성이 몰리게 되면 SPOF(single point of failure) 라는 단일 장애지점이 되어 DB가 멈춤에 따라 식별자 생성도 불가능해 집니다

즉, 식별자 생성을 데이터 생성에 의존하기 보다는 제가 해야 하는 행위(적립/사용/취소/소멸/예약 등) 에 쓰고자 하는 needs 가 있었습니다

CRM의 포인트 시스템에서는 이를 하고자 DB의 식별자와는 별개로 Point Id 를 생성하게 했는데 ksuid 라는 이름의 녀석을 사용했습니다 (2017년 6월 8일 출시)

KSUID는 K-Sortable Unique IDentifier의 약어입니다

생성시의 타임스탬프로 "자연스럽게" 정렬되도록 만들어지기로 한 것으로 UNIX sort 명령을 통해 일련의 KSUID를 실행하면 생성 시간별로 정렬됩다고 합니다

개발 당시에는 정렬이 되는 uuid 라는 요구 조건에 바로 부합되었기 때문에 큰 고민없이 도입하게 되었습니다

전체 E-Kolon 가입자 대상으로 하는 OLO 마일리지 출시를 위해 성능과 부하테스트를 하는 중 동시에 100건의 같은 Request가 왔을때 유일하게 한번만 보장하는 부분을 테스트 할 때 기존에 임직원 50%할인 포인트를 위한 기존의 2개의 포인트 타입과 새로운 타입인 OLO 마일리지간 3개의 포인트간 경합이 생겼습니다

요청하는 비즈니스로만 구분하는 경우는 각각의 클라이언트를 식별할 수 있는 식별자가 없이 막히자 말아야 하는 경우까지 막아 버릴 수 있습니다

사실 이 경우는 clientId + pointType + 주문수량 .. 등등 여러 조합을 통해 문제를 해결할 수 있지만 제가 하고자 하는 것은 지금 문제 해결이 아닌 앞으로 다른 서비스를 만들거나 현재부터 1년 뒤 10년 뒤도 문제가 안되는 해결책이 없을까에 대한 고민이 되었습니다

위의 ksuid 를 사용하면되지 않나? 라고 생각될 수 있지만 모든 비즈니스에 식별자를 만들지는 않아 식별자 생성 없이 유일성을 보장해야 하는 함수 들의 처리도 있었습니다 (DB에는 로직이 없고 거의 대부분이 kotlin 만들어진 로직이었습니다 - 레거시 쪽은 DB에 의존하는 SP, Query 가 많은 방식(이게 무조건 적인 단점은 아니고 일단 성능보다 코드레벨에서의 복잡도 개선이 우선 순위였고 추후 테스트를 거쳐 성능을 위해 디비에 로직이 포함됩니다)

전에 가상 면접 사례로 배우는 대규모 시스템 설계 기초 라는 책을 본 적이 있어 관련 내용을 봤었고 7장 분산 시스템을 위한 유일 ID 생성기 설계라는 파트가 있습니다

여기에 지난번 동시성 이슈 빠르게 처리하기 말미에 BillKey 에 대한 언급을 했었는데 이 책에서는 비슷하게 티켓 서버(Ticket Server) 라는 예시로 설명이 되고 있습니다 하지만 이 또한 SPOF 가 될 수 있습니다

그래서 중요한건 장애에 취약하지 않으면서 유일한 고유 식별자 생성이 되고 다변량으로 존재하는 클라이언 들이 비즈니스간 경합이 되지 않는 방식이 필요합니다 (DB에 저장하지 않아도 비즈니스의 유일성을 보장해주는 Id 이면 됩니다)

이는 가장 먼저 선행 하는 로직이 필요한 키 발급을 미리 받아서 요청 데이터 묶음을 처리 할 수 있으면 됩니다

CRM 을 하나의 플랫폼으로 바라본다면 OAuth2.0 의 프로토콜 방식을 생각해 볼 수 있습니다

OAuth 의 Authorization Code Flow 는 Access Token 을 얻기 위해 code 값을 미리 받아서 이용하고 있습니다 해당 Flow 를 Sequence Diagram 으로 보면

OAuth 2.0의 Authrization Code Grant Type Flow

아래는 PortOne(구: 아임포트) 이라는 곳의 결제 Flow 입니다

https://portone.gitbook.io/docs/auth/guide/def

 

뭔가 Authorization Code 와 위의 결제 키 라는 게 비슷하게 느껴집니다

Kolon Mall(가맹점 중 하나) 과 CRM Point 와 User 의 결제창이라는것도 비슷한 관점이 있는것 같네요

하지만 이와 같은 복잡한 구조를 가지게 되는데 아니 포인트 한번 써먹겠다고 인증 서버 수준의 구현을 따로 해야 되? 라는 논란의 여지가 있습니다

일단 ClientId 와 Client Evnet Id 라는 조합이 있기 때문에 token/billKey 발급을 위한 과정은 패스하고 추후 인증 서버를 소개할 때 다시 얘기하겠습니다

하지만 우리는 플랫폼 인증이다 하면 위와 같은 행위가 필요할 수 있다고 보고 같이 고민해주시면 좋을 것 같네요 해당 코드나 키값으로 후속 처리를 쉽게 처리할 수 있습니다 (처음이 어려우면 나중이 쉬워지는 법!!)

 

다시 고유 식별자로 넘어가면 KSUID 말고도 고유 식별자를 생성할 수 있는 방법은 어떤것이 있을까요?

가상 면접 사례로 배우는 대규모 시스템 설계 기초 에서는 UUID 와 티켓서버와 다중 마스터 복제와 마지막으로 트위터의 스노플레이크 방식이 소개 되어 있습니다 티켓 서버와 다중 마스터 복제는 Auto Increment ID 가 대상이므로 패스 합니다(관련 내용)

KSUID

  • 자연스럽게 생성 시간 순서로 정렬됩니다
  • 충돌이 없습니다
  • 단, 160bit 를 사용해서 UUID 의 128 bit 보다 큽니다
KSUID

 

 

JDK 내장된 방법

UUID (Universally Unique Identifier)

  • 컴퓨터 시스템에 저장되는 정보를 유일하게 식별하기 위한 128비트 수 입니다
  • 보편적으로 쉽게 사용할 수 있는 방법(다수의 언어거 기본적으로 제공하는 생성기) 입니다
  • 단점
    • 숫자가 아닌 값이 포함될 수 있으며 옛날 버전의 경우 시간 순으로 정렬할 수 없다
  • 하지만 UUID v6, v7, v8 에서는 타임스탬프 기반으로 정렬이 가능해서 만들어 지고 있다고 합니다
uuid v4

가상 면접 사례로 배우는 대규모 시스템 설계 기초(책)

Twitter’s Snowflake (업데이트가 안되고 있습니다)

https://en.wikipedia.org/wiki/Snowflake_ID
  • 총 64bit 를 사용합니다

도메인 주도 개발 시작하기(책 - 저자 최범균)

Nano Id

  • 엔터티의 식별자 생성 용도로 소개되었습니다
  • UUID 보다 사이즈도 작고 생성기 속도도 빠르다고 합니다
  • UUID 대안으로 더 가볍고, URL 친화적인 ID를 생성하는 라이브러리입니다
  • JavaScript 가 메인 타겟이지만, 다양한 언어 구현체도 존재하고 이 녀석은 사용하는 문자의 범위를 지정하고, 사이즈를 가변적으로 선택할 수 있다는 장점이 있습니다
nano id

그 밖에도

ULID (Universally Unique Lexicographically Sortable Identifier)

  • 이 선택지의 주요 컨셉은 UUID의 단점을 개선하는데 초점이 맞춰져 있습니다
  • UUID 128비트 구조와 호환하면서, 정렬이 가능하며, 특수문자를 포함하지 않아 URL에서 사용해도 안전합니다
https://blog.tericcabrel.com/discover-ulid-the-sortable-version-of-uuid/

 

이것 말고도 CUID 나 정말 다양하게 있는데요 (너무 많아서 소개하기는 패스~!!)

 

상황에 따라 고려할 내용들이 몇개 보였습니다

  • id 의 사이즈(용량)
  • 키 생성 시간(성능)
  • 특수문자가 사용되는지 유무(이식성 및 확장 - URL 에서 사용도 할 때)
  • 외부 노출 허용정도(보안)
  • Entity(JPA) 나 Casandra(NoSQL) 와 같은 DB에서 활용 용도 (비즈니스)

용량, 성능, 확장, 보안, 비즈니스들을 고려했을 때 단순히 조사해서는 결론을 내기 어려워서 추가로 NPM Trend 도 보았습니다

마지막으로 NPM Trend 결과 입니다 언어가 JS 방면으로 한정되겠지만 그래도 가장 인기있는 개발언어입니다

여기서 Star 수는 nano id 가 가장 많네요

https://npmtrends.com/ksuid-vs-nanoid-vs-ulid-vs-uuid

 

추가 참고 내용

 

+ Recent posts