JPA에서는 아래와 같이 Entity를 설계할 때, @Id 어노테이션으로 해당 프로퍼티가 Database에서 PK가 되는 것을 명시하고, @GeneratedValue 를 통해 어떻게 PK를 생성할 건지 생성 전략을 명시하고 있다.
@Entity
public class Entity {
@Id @GeneratedValue(strategy = IDENTITY)
private Long id;
}
IDENTITY 전략을 사용하면, MySQL의 Auto Increment 생성 전략으로 ID를 생성할 수 있다.
그 외에 TABLE, SEQUENCE, UUID, AUTO 의 전략으로 ID를 설계할 수 있다.

하지만 Auto Increment 전략을 사용하면, 기본적으로 data가 새롭게 생성될 때 id가 1씩 증가하기 때문에, 숫자가 매우 단순하게 구성되어 있다.
따라서 예를 들어 게시글을 새롭게 작성했는데, 게시글을 조회하는 URL이 ~/posts/10 인 경우에는 해당 게시글이 10번째 게시글이구나! 라고 쉽게 예측할 수 있게 된다.
게시글의 경우는 민감한 정보가 아닐 수 있지만, 민감한 정보에 대해서는 pk로 id가 쉽게 유추되는 경우에는 위험한 상황이 발생할 수 있다.
위 상황처럼, url에 다른 값을 넣으면서 다른 리소스에 접근하는 시도를 해볼 수 있기 때문이다.
따라서 조금 더 복잡하게 or 랜덤하게 PK 혹은 Unique key를 생성할 수 있다. 그 중 하나가 UUID이다.
UUID (Universally Unique Identity)
UUID에 대한 설명은 RFC 4122에서 확인할 수 있다.
RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace
RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace
This specification defines a Uniform Resource Name namespace for UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier). A UUID is 128 bits long, and can guarantee uniqueness across space and time. UUIDs were originally use
datatracker.ietf.org
UUID는 아래와 같이 선언하여 생성할 수 있다.
@Entity
public class TestEntity {
@Id @GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
}
보통 프로젝트에서 S3에 올릴 정적 파일의 id를 설정할 때, UUID를 많이 활용했다.
하지만 UUID 자체가 문자열 길이가 길어지기 때문에, 조금 더 줄여서 만들 수 있는 방법에 대해서 고민하게 된다. (아무래도 128bit 길이가 부담스러울 수 있으니 …) 대표적으로 쿠폰 번호나 초대 코드, 인증 코드 등을 만들 때 이런 고민을 하게되는데 …
이 때 쉽게 생각할 수 있는 방법으로, 0 ~ 9까지 숫자를 사용해서 Random한 숫자를 만드는 것이다.
103429 이런식으로 0~9까지 각 자리마다 random하게 한 숫자를 뽑아 숫자를 구성할 수 있다. 하지만 이 때 생각해볼 수 있는 점은 내가 설계한 ID가 겹치지는 않을까? 라는 점이다.
이와 관련해서 … 간단하게 확인해볼 수 있는 방법이 있다.
Nano ID CC
zelark.github.io
예를들어, 0~9까지 숫자로, 6글자로 random string을 만들었을 때, 초당 1번씩 id를 만드는 경우
2시간 정도에 한 번 씩 충돌 가능성이 생기게 된다. (birthday problem 기반으로 계산)

따라서 PK 설계 혹은 고유키를 생성하는 경우에 이런 부분을 잘 고려하여 설계해야합니다.
아래는 유튜브 URL 예시입니다.
https://www.youtube.com/watch?v=BoVpTSsTuVQ
그렇다고 무조건 복잡하게 값을 생성하는 것도 좋은 방법은 아닙니다. 서비스 관점에서도 이러한 값을 생각할 필요가 있습니다. 예를 들어, 서비스에 쿠폰 번호를 만든다고 가정해보겠습니다.
우리 서비스에 인기가 많아서 쿠폰 발급량이 많은데 이 때 쿠폰 번호가 aB123Cd-123vfg-23dasd-as2fefef-adwdwdwd 라고 한다면, 복사/붙여넣기가 가능하다면 괜찮지만 불가능한 상황에서는 저 값을 입력하기에 매우 불편하고, 사용자 입장에서도 보기 좋은 코드는 아니겠죠?
따라서 키 설계는 서비스적으로도 고려해야할 대상이라고 생각합니다.
Database를 설계하는 것이 매우 중요하기 때문에 만약 서비스 개발을 하면서, 이러한 PK나 고유키를 설계해야하는 상황이 온다면, 이후에 개발 측면과 서비스를 측면하는 점에서 잘 고려해서 결정해야 하는 것이 중요한 것 같다.
'Spring' 카테고리의 다른 글
| [Smeem] Presentation Layer <-> Application Layer DTO 리팩토링 (0) | 2024.03.22 |
|---|---|
| [Spring] RestDocs 기반으로 API 문서 작성해보기 (0) | 2024.03.16 |
| [Study] Test Code Study 정리 (1) (1) | 2024.02.27 |
| [Spring] AWS EC2에 Spring Boot Project 배포하기. (0) | 2023.06.05 |
| [Spring Boot] Spring Boot로 HTTP API 설계하기 (2) | 2023.05.10 |