인공키 UUID VS GEN KEY

roach·2021년 4월 18일
6

DB

목록 보기
2/2

DB에 기본키 위임이 추세인 이유?

  • 최근에 JPA, Spring Data JPA 와 같은 ORM 들의 강세로, Primary Key 생성 전략을 DB 에 위임하는 추세가 늘어나고 있다. 이러한 방식의 문제점은 무엇일까 가만히 생각해보니, 데이터베이스 자체의 의미론적으로 봤을때 , 별 의미없는 값이라고 생각될 수 있기 때문이다 (Entity 기준)

위임시의 장점 혹은 단점

  1. 엔티티에서 복합키를 통해 Primary Key 로 쓰기에는 Index 의 크기가 비대해질 수도 있다.
  2. DB 에 기본 생성 전략이 더 좋은 방향일 수도 있다.
  3. 쓰기 쉽다는 것도 한목하는것 같다. (제일 큰것 같다 사실)
  4. 단점은 Server-Side 에서 Repository 를 거치지 않을 경우 (Aggregate Root 혹은 부모 관계를 통해서 추가되는 경우) ID 값을 찾아오는 것이 불가능하거나, 힘들수도 있다는 것이다.

내가 Spring Data JDBC 를 어려워 한 이유

  • 사실 아직 DDD 라는 개발 패턴을 잘 이해하지 못해, 안좋게 생각하는 것일 수도 있다 parentTable_key 를 Column 에 가지고, Index 처럼 운용하던데.. 이것때문에 실상쿼리를 보면 계속해서 자식객체 INSERT 쿼리가 발사되고.. 쿼리적으로 효율적으로 바꿀까 하다가 2주라는 짧은 프로젝트니 최대한 DDD 를 경험해보자고 결심했다.
  • 디온의 리뷰대로 새로운 방향성이니 하나의 컨셉으로서 공부해보는게 좋다고 생각했다.
  • 중간에 CardRepository 를 만들까 생각했는데.. 그럼 Spring Data JDBC 를 사용하는 이유가 없고, 학습이 아닌.. 기능구현에 초점을 맞춘다고 생각해서 조원들간 처음에 약속했던대로 학습에 방향을 두는 것에 초점을 두었습니다.

내가 문제를 겪었던 점

  • React 에서 CardComponent 의 ID 를 관리하기 위해서는 ResponseData 에 ID 를 넣어줄 필요가 있다. 하지만 DB 에 키를 위임하게 되면 Server-Side 에서도 DB 를 거치기 전까지는 ID property 를 알 수 있는 방법에 한정적이므로(Aggregate Root 에 의해 관리되는 경우), ID 값을 가지게 하기 위해서는 따라서 대표적으로 아래와 같이 크게 두가지 방법론이 존재한다고 생각한다.

1. 카드 추가 (POST) 요청을 보낸 뒤 Server-Side 에서 Redirection 응답을 줘서 다시 렌더링 한뒤 GET 요청으로 카드 데이터를 받는다.

  • 1번 방식은 구현에는 쉬울 것이나, 문제는 Client 비 친화적일 수 있다는 것이다. 충분히 Axios 방식으로 동작할 수 있음에도, 이러한 방식을 선택하는 건 좋지 않다고 생각한다.

2. 카드 추가 (POST) 요청을 보낸 뒤 Server-Side 에서 CardID 를 담아준다.

  • 사실 2번 방법도 AggregateRoot 방식으로 관리되지 않는 Entity 이여서 Repository 를 사용한다면 어려운 방식은 아니다. 하지만, 나는 Column 이라는 상위 연관관계에서 Card 를 관리하는 구조이므로, Repository 를 통한 ID 값을 추적해내는게 어려웠다. 따라서 인공키 구조를 가져보는 것은 어떨까? 라는 생각을 하게 되었고, 아래와 같이 코드로 구현하게 되었다.

UUID 구조의 인공키

  • 이전에 Brian 의 Review 과정에서 UUID 를 주키로 사용했을때 장/단점을 살펴보았을때 대략적으로 검색을 통해 공부한 내용은 아래와 같았다.
    • UUID 를 주키로 놓게 되면, 주키 INDEX 가 비대해질 수 있다. UUID 는 36자리의 랜덤 난수? 를 가지게 되는데 이는 정렬하는데 어려움을 겪을 수 있을만하다고 생각한다.
    • 하지만 UUID 를 최적화된 형태로 변환하여 저장하면 효율적으로 사용이 가능하다고 보았던것 같다.
    • Server-Side 에서도 객체의 Id 를 저장하고 있을 수 있다.

인공키의 사용

  • 그래서 Entity 가 생성될때, 인공키를 사용하여 고유한 키값을 생성하고, 이를 Response 에 넣어 전달할 수 있도록 했다. 아래코드가 일단 UUID 를 생성하여 Entity 를 가지는 구조이다.
public Card(String title, String content, String author) {
        this.id = UUID.randomUUID().toString();
        this.title = title;
        this.content = content;
        this.author = author;
        this.updateDateTime = LocalDateTime.now();
    }
  • 일단 위와 같은 설계로 Entity 생성간 Key 를 가질 수 있게 됬다. 따라서 ResponseEntity 에서 Key 를 줄 수 있게 되었다.
@PostMapping()
    public ResponseEntity<?> addCard(@Validated @RequestBody Card card, @PathVariable Long id, BindingResult bindingResult) {
        final Card saveCard = columnService.addCard(id, card);
        return ResponseEntity.ok().body(new CardInfoData(id, saveCard.getId()));
    }

Response

{
    "columnId": 1,
    "cardId": "6e90cef7-cabe-440b-99b0-c2ff289a2653"
}

DB 에서 UUID 는 ?

  • 내 데이터베이스 에서는 아래와 같이 저장되어 지고 있다.

DB 테스트

  • 백만건 기준으로 수행한다. (천만건 하다가 맥북 저세상으로 보내줄 뻔했다...)
  • DB 의 제일 마지막 열에 있는 데이터를 가져올때 기준으로 수행해본다.
  • 인공키 (UUID) VS 인공키 (Auto Increment)
  • 내가 테스트를 해봤는데 천만건으로 한번 더 하면 맥북 맛탱이 갈거 같아서 1억건 정도로 하고싶은데.. 무리다 나중에 내 컴퓨터에서 해보고 여기 좋은 글이 있으니 다들 이걸 읽어보길 바란다.
  • 백만건으로 해봤는데 차이가 없다. 아마 1억건 이상은 되야하지 않을까? 근데 알게된건 적은 양의 데이터라면 충분히 UUID 를 써도 별로 성능에 문제를 주지 못한다는 것이다.
  • 그리고 효율적으로 저장하는 방법도 있으니 사실 써도 무방 할것 같다는 생각이 들었다.
    • 왜 사람들이 싸우는지 알겠다 이제야, 성능상의 큰 문제가 대규모 기업아니면 발생할 것 같지 않다.

UUID VS AUTO GENERATED KEY

연관 글

파이썬을 이용한 bulkInsert

https://velog.io/@tmdgusya/DB-Bulk-insert

profile
모든 기술에는 고민을

0개의 댓글