본문 바로가기
Spring/JPA

[Spring/JPA] Entity 에서 UUID vs AutoIncrement

by windy7271 2024. 7. 1.
728x90
반응형

Entity를 작성하면  보통 95%의 사람들은 Auto Increment를 쓴다.

 

이로인해 많지는 않지만 문제가 생기는데

  1. 외부에서 해당 시스템 PK를 예측하기 쉬워져서 SQL Injection 문제
  2. Sequence, auto_increment는 중앙 집중식으로 값을 생성하는 방식이므로 DB에 의존적이게 되어 확장성이 제한되는 문제
  3. 서비스 폭풍성장 시, ID 고갈되는 문제 (BIGINT 최댓값은 4,294,967,295 이고, unsigned BIGINT라면 18,446,744,073,709,551,615)
  4. 데이터베이스 변경의 어려움
  5. DB가 2대 이상일 때 중복 문제

 

이런 문제를 해결하고자 나온게 UUID 값을 PK로 설정하는것이다.

 

UUID는 범용 고유 식별자라는 뜻으로 128bit의 긴 고유값을 PK로 사용한다.

중복될 확률은 운석맞을 확률과 같아 중복문제는 거의 안 생긴다고 보면 된다.

 

UUID 의 장점

  • 보안, 키 값이 외부 노출될 일 없음
  • 레코드 간 고유성을 보장한다.

ex ) 티스토리 https://windy7271.tistory.com/post/1

이렇게 하면 털릴 가능성 높다.

 

하지만 UUID를 사용한다면.

https://www.youtube.com/watch?v=pDVjGxjjk5o

watch 뒤에 암호처럼 생긴다.

 

그러면 UUID가 제일 좋을까 ??

아니다.

트래픽이 많지않고, 데이터가 수백만, 수천만 생기지 않을 서비스라면 auto 하거나 uuid를 pk로 해도 된다.

UUID를 랜덤하게 생성하되 이 값을 sequencial 하게 생성해서 사용하기도 한다.

 

UUID

장점

  1. 전역 고유성: UUID는 전 세계에서 유일하기 때문에 여러 데이터베이스나 시스템 간에 충돌 없이 데이터를 병합하거나 동기화할 수 있다..
  2. 보안성: 순차적인 숫자가 아닌 랜덤하게 생성되므로 내부 데이터베이스 구조를 추론하기 어렵다.
  3. 분산 시스템에 적합: 여러 서버에서 동시에 생성할 수 있으며, 중복의 위험 없이 고유성을 보장한다.
  4. 무중단 마이그레이션: 기존 데이터베이스에서 다른 데이터베이스로 데이터를 옮길 때 고유성을 유지할 수 있다.

단점

  1. 공간 낭비: UUID는 128비트(16바이트) 크기로, 4바이트인 일반적인 Auto PK 보다 메모리와 저장 공간을 더 많이 차지한다.
  2. 인덱스 성능 저하: 랜덤하게 생성되므로 인덱스 정렬이 어려워져 검색 성능이 저하될 수 있다..
  3. 가독성: 사람이 읽고 관리하기 어렵다.

Auto Increment 장단점

장점

  1. 간단한 사용: 설정과 사용이 매우 간단하며 자동으로 증가하므로 중복될 염려가 없다
  2. 저장 공간 효율성: 일반적으로 4바이트의 int형을 사용하여 저장 공간을 절약할 수 있다.
  3. 빠른 인덱싱: 순차적으로 증가하므로 인덱스 정렬이 용이하고, 검색 성능이 우수하다.
  4. 가독성

단점

  1. 전역 고유성 부족: 단일 데이터베이스 내에서는 고유하지만 여러 시스템 간 병합 시 중복 가능
  2. 보안 취약성: 연속된 숫자이므로 데이터베이스 구조나 크기를 쉽게 추측 가능
  3. 데이터 마이그레이션 어려움: 다른 데이터베이스로 데이터를 옮길 때 고유성을 유지하기 어렵다.

대기업의 데이터베이스 설계 경향

대기업들은 일반적으로 다음과 같은 방식을 사용한다.

  1. 혼합 사용: 각 상황에 맞게 UUID와 auto increment를 혼용하여 사용한다. 주요 사용자 계정 등 외부 노출이 가능한 데이터는 UUID를 사용하고, 내부 관리용 데이터는 auto increment를 사용한다.
  2. 분산 시스템: 여러 서버나 데이터센터에 걸쳐 데이터베이스를 운영할 경우, UUID의 전역 고유성을 이용하여 데이터 충돌을 방지한다.
  3. 샤딩(Sharding): 데이터베이스를 여러 파티션으로 나누어 저장하는 샤딩 기법을 사용할 때, UUID를 사용하여 각 샤드 간의 고유성을 유지한다.
  4. 복합 키 사용: 여러 필드를 조합한 복합 키를 사용하여 고유성을 확보하는 경우도 있습니다. 예를 들어, 특정 필드와 auto increment를 조합하여 복합 키를 구성한다.

결론적으로, 대기업들은 데이터베이스 설계 시 데이터의 특성과 사용 시나리오를 고려하여 UUID와 auto increment를 적절히 조합하여 사용한다.

 

사용 방법

@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.createUser(user.getName(), user.getEmail());
        return ResponseEntity.ok(createdUser);
    }

    @GetMapping("/{uuid}")
    public ResponseEntity<User> getUserByUuid(@PathVariable String uuid) {
        Optional<User> user = userService.getUserByUuid(uuid);
        return user.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
    }
}
@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User createUser(String name, String email) {
        User user = new User(name, email);
        return userRepository.save(user);  // 내부적으로 id를 사용하여 저장
    }

    public Optional<User> getUserByUuid(String uuid) {
        return userRepository.findByUuid(uuid);  // 외부에서 UUID를 사용하여 조회
    }
}

 

  • 애플리케이션 내부용 키로는 자동증가 pk, 외부에 공개할 키로는 uuid를 사용하는 것을 권장한다.
    • 애플리케이션 내부에서 자동증가 pk를 사용하면 성능과 저장 장소 측면에서 이점이 있다.
    • 만약 식별 값이 외부로 노출될 수도 있는 서비스라면 UUID로 데이터를 식별하는 것이 좋다.
    • 어떤 이유로든(외부 노출 등) UUID가 손상된다면 UUID를 변경해야 한다. PK를 변경하는 작업은 매우 값비싼데, UUID가 PK와 별개로 사용되는 경우 UUID를 변경하는 작업은 훨씬 저렴하다.

중복되더라도 자동 증가 열(기술 키)에 기본 키를 생성하여 데이터베이스 내에서 일관성을 유지하고, 설계 단계에서 문제가 발생한 경우 "기본 키"가 변경되도록 허용하는 것이다. 또한 다른 테이블의 외래 키 제약 조건에 의해 키가 지정되는 경우 소비되는 공간을 줄이고 후보 키를 null이 아닌 고유하게 만든다.

 

만약 UUID가 손상되면 이를 변경해야 한다. PK 변경에는 비용이 많이 들고 부작용이 많을 수 있다. UUID가 PK와 분리된 경우 해당 변경으로 인한 결과가 훨씬 적다

반응형

댓글