Home
>
DB
>
๐พ[Database] Primary Key ์์ฑ ์ ๋ต - ์ ๋ํฌ ๋ฌธ์์ด ๋๋ ์ซ์
Database
Primary Key
DBMS
โ๐พ[Database] Primary Key ์์ฑ ์ ๋ต - ์ ๋ํฌ ๋ฌธ์์ด ๋๋ ์ซ์โ
๐ Intro.
PK(Primary Key)๋ฅผ ๋จ์ํ AUTO_INCREMENT๊ฐ ์๋, ๊ณ ์ ํ ๋ฌธ์์ด(UUID) ๋๋ ์ซ์(Snowflake, Nano ID ๋ฑ)๋ก ์์ฑํ๋ ๋ฐฉ์์
๋๋ค.
์ด ๋ฐฉ์์ ๋ถ์ฐ ์์คํ
, ๋์ฉ๋ ํธ๋ํฝ ์ฒ๋ฆฌ, ๋ณด์์ฑ ๊ฐํ ๋ฑ์ ์ด์ ๋ก ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค.
โ
1๏ธโฃ โ์ ๋ํฌ ๋ฌธ์์ด ๋๋ ์ซ์โ PK ๋ฐฉ์์ด ํ์ํ ์ด์ .
๊ธฐ์กด์ AUTO_INCREMENT PK๋ ๋จ์ํ 1์ฉ ์ฆ๊ฐ ํ๋ ๋ฐฉ์์ด๋ฏ๋ก:
1. ๋ณด์์ ์ทจ์ฝ โ ๊ณต๊ฒฉ์๊ฐ ID๋ฅผ ์์ํ ์ ์์(/articles/1, /articles/2 โฆ).
2. ๋ค์ค ์๋ฒ(์ค๋ฉ) ํ๊ฒฝ์์ ์ถฉ๋ ๋ฐ์ ๊ฐ๋ฅ โ ๊ฐ ์๋ฒ์์ ๋
๋ฆฝ์ ์ธ ID ์์ฑ์ด ์ด๋ ค์.
3. ๋ฐ์ดํฐ ๋ง์ด๊ทธ๋ ์ด์
์ ์ถฉ๋ ๊ฐ๋ฅ์ฑ โ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ๋ฐ์ดํฐ๋ฅผ ์ฎ๊ธธ ๋ ID๊ฐ ๊ฒน์น ์ ์์.
์์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, UUID, Snowflake, Nano ID ๋ฑ ์ ์ฌ์ฉํ์ฌ ๊ณ ์ ํ ๋ฌธ์์ด ๋๋ ์ซ์๋ก PK๋ฅผ ์์ฑ ํ๋ ๋ฐฉ์์ด ๋ฑ์ฅํ์ต๋๋ค.
โ
2๏ธโฃ ์ ๋ํฌ ๋ฌธ์์ด ๋๋ ์ซ์๋ฅผ ์ด์ฉํ PK ์์ฑ ์ ๋ต.
์ ๋ต
์์
๊ธธ์ด
ํน์ง
UUID(Universally Unique Identifier)
550e8400-e29b-41d4-a716-446655440000
36์
์ ์ธ๊ณ์ ์ผ๋ก ์ ์ผํ ๋ฌธ์์ด, ์๋๊ฐ ๋๋ฆด ์ ์์
Snowflake(Twitter ID ๋ฐฉ์)
146789123456789012
19์
์๊ฐ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ, ๊ณ ์ ์ฑ ๋ณด์ฅ, ์ฑ๋ฅ ์ต์ ํ
Nano ID
V1StGXR8_Z5jdHi6B-myT
21์
๋๋ค ๋ฌธ์์ด, URL-safe, ์งง๊ณ ์ถฉ๋ ํ๋ฅ ์ด ๋ฎ์
KSUID(K-Sortable Unique ID)
0ujsswThIGTUYm2K8FjOOfXtY1K
27์
์๊ฐ ์ ๋ ฌ ๊ฐ๋ฅ, UUID๋ณด๋ค ์งง๊ณ ์ฝ๊ธฐ ์ฌ์
โ
3๏ธโฃ UUID(Universally Unique Identifier)
๐ UUID๋?
128๋นํธ์ ๊ณ ์ ํ ๋ฌธ์์ด์ ์์ฑํ๋ ์๊ณ ๋ฆฌ์ฆ.
์ ์ธ๊ณ์ ์ผ๋ก ์ ์ผํ ๊ฐ์ ๋ง๋ค ์ ์์.
๋๋ค์ฑ์ด ๊ฐํ์ฌ ์ถฉ๋ ํ๋ฅ ์ด ๋งค์ฐ ๋ฎ์.
๊ธธ์ด๊ฐ ๊ธธ์ด(36์) ์ธ๋ฑ์ฑ ์ฑ๋ฅ์ด ์ ํ๋ ์ ์์.
๐ ๏ธ UUID๋ฅผ PK๋ก ์ฌ์ฉํ๋ MySQL ํ
์ด๋ธ ์์ .
CREATE TABLE article (
article_id CHAR ( 36 ) PRIMARY KEY , -- UUID ์ฌ์ฉ
title VARCHAR ( 255 ) NOT NULL ,
content TEXT NOT NULL ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
๐ Spring Boot JPA์์ UUID ์ ์ฉ.
import jakarta.persistence.* ;
import lombok.Getter ;
import lombok.NoArgsConstructor ;
import org.hibernate.annotations.GenericGenerator ;
import java.util.UUID ;
@Getter
@NoArgsConstructor
@Entity
@Table ( name = "article" )
public class Article {
@Id
@GeneratedValue ( generator = "UUID" )
@GenericGenerator ( name = "UUID" , strategy = "org.hibernate.id.UUIDGenerator" )
@Column ( name = "article_id" , updatable = false , nullable = false , length = 36 )
private String articleId ;
private String title ;
private String content ;
}
โ
UUID๋ฅผ ์๋์ผ๋ก ์์ฑํ์ฌ PK๋ก ์ฌ์ฉ
โ
JPA์์ @GeneratedValue(generator = โUUIDโ)๋ฅผ ์ฌ์ฉ
โ
DB์๋ CHAR(36)๋ก ์ ์ฅ
๐ Snowflake๋?
Twitter์์ ๊ณ ์ ํ ์ซ์ ID๋ฅผ ๋น ๋ฅด๊ฒ ์์ฑํ๊ธฐ ์ํด ๊ฐ๋ฐํ ์๊ณ ๋ฆฌ์ฆ.
64๋นํธ ์ ์ (19์๋ฆฌ)๋ฅผ ์ฌ์ฉํ์ฌ ์๊ฐ ์ ๋ ฌ ๊ฐ๋ฅ.
์ฑ๋ฅ ์ต์ ํ & ID ์ถฉ๋ ์์.
๋ถ์ฐ ์์คํ
(์ฌ๋ฌ ์๋ฒ)์์ ์ฌ์ฉ ๊ฐ๋ฅ.
๐ ๏ธ MySQL ํ
์ด๋ธ ์์ (Snowflake).
CREATE TABLE article (
article_id BIGINT PRIMARY KEY , -- Snowflake ID ์ฌ์ฉ
title VARCHAR ( 255 ) NOT NULL ,
content TEXT NOT NULL ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
๐ Spring Boot์์ Snowflake ์ ์ฉ.
import java.time.Instant ;
public class Snowflake {
private static final Long EPOCH = 1640995200000L ; // 2022-01-01 ๊ธฐ์ค
private static final Long MACHINE_ID = 1L ;
private static final Long SEQUENCE_BITS = 12L ;
private Long lastTimestamp = - 1L ;
private Long sequence = 0L ;
public synchronized Long nextId () {
Long timestamp = Instant . now (). toEpochMilli ();
if ( timestamp == lastTimestamp ) {
sequence = ( sequence + 1 ) & (( 1 << SEQUENCE_BITS ) - 1 );
if ( sequence == 0 ) {
while ( timestamp <= lastTimestamp ) {
timestamp = Instant . now (). toEpochMilli ();
}
}
} else {
sequence = 0 ;
}
lastTimestamp = timestamp ;
return (( timestamp - EPOCH )) << ( 64 - 41 ) | ( MACHINE_ID << ( 64 - 41 - 10 )) | sequence ;
}
}
โ
UUID๋ณด๋ค ์งง์ ์ซ์(BIGINT)๋ก ๊ณ ์ ํ ID ์์ฑ.
โ
๋ ์ง ๊ธฐ๋ฐ์ด๋ฏ๋ก ์ ๋ ฌ ๊ฐ๋ฅ (์ต๊ทผ ๋ฐ์ดํฐ ์กฐํ ์ ์ ๋ฆฌ).
โ
์๋ฒ๊ฐ ์ฌ๋ฌ ๊ฐ์ฌ๋ ์ค๋ณต๋์ง ์์.
โ
5๏ธโฃ Nano ID (๊ฐ๋ณ๊ณ ์งง์ ๋๋ค ๋ฌธ์์ด)
๐ Nano ID๋?
UUID๋ณด๋ค ์งง๊ณ ์ฑ๋ฅ์ด ๋น ๋ฅธ ID ์์ฑ๊ธฐ.
URL-safe (URL์ ์ฌ์ฉ ๊ฐ๋ฅ).
๋๋ค์ฑ์ผ๋ก ์ธํด ์ถฉ๋ ํ๋ฅ ์ด ๋ฎ์.
์๋ฐ์คํฌ๋ฆฝํธ ํ๊ฒฝ์์๋ ์ฌ์ฉ ๊ฐ๋ฅ.
๐ ๏ธ MySQL ํ
์ด๋ธ ์์ (Nano ID)
CREATE TABLE article (
article_id VARCHAR ( 21 ) PRIMARY KEY , -- Nano ID ์ฌ์ฉ
title VARCHAR ( 255 ) NOT NULL ,
content TEXT NOT NULL .
created_at TIME
)
VARCHAR(21) โ Nano ID๋ ๊ธฐ๋ณธ์ ์ผ๋ก 21์ ๊ธธ์ด๋ฅผ ๊ฐ์ง๋ฏ๋ก ํ
์ด๋ธ์์๋ VARCHAR(21)๋ก ์ค์ .
๐ Spring Boot์์ Nano ID ์ ์ฉ.
Java์์๋ Nano ID ๋ผ์ด๋ธ๋ฌ๋ฆฌ(com.aventrix.jnanoid)๋ฅผ ์ฌ์ฉํ์ฌ Nano ID๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
1๏ธโฃ Maven ๋๋ Gradle์ Nano ID ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
<dependency>
<groupId> com.aventrix.jnanoid</groupId>
<artifactId> jnanoid</artifactId>
<version> 2.0.0</version>
</dependency>
implementation 'com.aventrix.jnanoid:jnanoid:2.0.0'
2๏ธโฃ Entity์์ Nano ID๋ฅผ ์ฌ์ฉํ์ฌ Primary Key ์ค์ .
import jakarta.persistence.* ;
import lombok.Getter ;
import lombok.NoArgsConstructor ;
import org.hibernate.annotations.GenericGenerator ;
import org.hibernate.annotations.Parameter ;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils ;
@Getter
@NoArgsConstructor
@Entity
@Table ( name = "article" )
public class Article {
@Id
@Column ( name = "article_id" , updatable = false , nullable = false , length = 21 )
private String articleId ;
private String title ;
private String content ;
@PrePersist
public void generateId () {
this . articleId = NanoIdUtils . randomNanoId (); // Nano ID ์์ฑ
}
}
โ
Nano ID ๋ฐฉ์์ ์ฅ์ .
1. UUID๋ณด๋ค ์งง์(21์) โ ์ฑ๋ฅ ์ต์ ํ
2. ๋๋คํ ๊ฐ์ด๋ฏ๋ก ๋ณด์์ฑ ์ฐ์ (ID ์์ธก ๋ถ๊ฐ๋ฅ)
3. URL-safe โ URL์์ ์์ ํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ
4. ์๋ฒ ๋ถ๋ด์ด ์ ๊ณ , ๋น ๋ฅธ ์๋๋ก ์์ฑ ๊ฐ๋ฅ
โ Nano ID ๋ฐฉ์์ ๋จ์ .
1. UUID๋ณด๋ค ์ถฉ๋ ํ๋ฅ ์ด ๋์ง๋ง, ์ถฉ๋ถํ ๋ฎ์ ์์ค.
2. ์ ๋ ฌ์ด ์ด๋ ค์ โ ์๊ฐ ๊ธฐ๋ฐ์ด ์๋๋ฏ๋ก ์ต๊ทผ ๋ฐ์ดํฐ ์ ๋ ฌ์ด ํ์ํ ๊ฒฝ์ฐ ์ ํฉํ์ง ์์.