본문 바로가기

자바 심화/TIL

데이터베이스 PK 타입 및 페이지네이션 관련 의사 결정

개요

팀 프로젝트로 음식 주문관리 애플리케이션을 개발하게 되었고, 설계 조건에 따라 DB를 설계하던 중 PK와 관련된 문제를 직면하게 되었고 팀원과 의사결정을 하게 되었다.

 

데이터베이스 PK 타입 의사 결정

프로젝트 DB 설계 조건

  • 테이블 명명 규칙: 모든 테이블에 p_ 접두사 사용
  • UUID 사용: 모든 주요 엔티티의 식별자는 UUID를 사용 (유저는 예외)
  • Audit 필드: 모든 테이블에 created_at, created_by, updated_at, updated_by, deleted_at, deleted_by 필드를 추가하여 데이터 감사 로그 기록
  • ERD 설계: 엔티티 간의 관계를 명확히 하는 ERD(Entity-Relationship Diagram) 작성

 

초기 DB 설계(ERD)

  • 설계 초기에는 p_user 테이블을 제외한 모든 테이블의 PK 값을 UUID 타입의 값으로 설정했다.

 

피드백

  • PK 는 UUID 컬럼으로 두셨는데, 아이디 체계가 변경이 될 수도 있겠죠~ 그럼 PK 의 컬럼 타입을 varchar로 바꿔야하는데, 이때 DB 가 잠깐 다운될 수도 있어요! 그래서 보통 PK 는 bigint 타입의 auto increment 로 두고, UUID 컬럼은 유니크 값으로 두기도 합니다. 참고하세요!

튜터님의 피드백을 수용하여 PK 값을 String 타입으로 변경하고 프로젝트를 시작했다.

 

DB 테이블 PK 타입 관련 의사 결정 과정

팀원 의견

팀원 A

  • 현재 데이터베이스 테이블의 PK 타입은 varchar, 값은 UUID로 PK 타입을 varchar로 지정한 이유는 추후 PK 생성 방식의 변경을 대비해 확장성을 고려했기 때문입니다(PK의 타입 변경 작업보다 PK 값을 변경하는 작업이 DB에 부담이 덜 할 것이라고 생각).

팀원 B

  • 튜터님의 피드백 내용에서 PK는 보통 bigint 타입의 auto increment로 두고, UUID 컬럼은 유니크 값으로 둔다라는 의견처럼 PK 값을 auto increment로 생성한 것을 사용하고 UUID 값을 유니크 값으로 설정해 외부 노출되도록 하는 것이 좋을 것 같다.

 

각 방식의 장점

PK 값이 정수 타입일 때

  • auto_increment의 경우 PK를 클러스터링 인덱스로 사용하는 DB의 경우 데이터가 디스크에 PK 기준으로 정렬되어 저장 되기에 정렬된 데이터를 가져와야 하며, 디스크 I/O가 발생하는 쿼리 작업에 효율적이다.

PK 값이 UUID(varchar)일 때

  • 전역적으로 고유한 식별자이므로 여러 데이터베이스 인스턴스에서 데이터가 생성되거나, 복제 및 통합이 이루어져도 충돌을 방지할 수 있다.
  • 따라서 분산 환경에서 데이터를 통합하거나 병합할 때 매우 유리하며, auto_increment 방식에서 발생할 수 있는 주요 도메인 데이터 개수 추적과 같은 문제 방지 가능

 

최종 의사 결정

auto_increment와 UUID의 이점을 모두 가져갈 수 있도록 PK는 bigint auto_increment로 두어 클러스터링 인덱스로 활용 가능하도록 하고, UUID는 유니크 키로 두어 외부로 노출되는 외부 식별자 역할을 담당하도록 DB 설계 수정

 

페이지네이션 처리 방식 의사 결정

의사 결정 과정

의견

팀원 A

  • 구현이 쉬운 오프셋 방식으로 할 경우 대용량 데이터를 처리할 때 성능이 저하될 우려가 있으므로 커서 방식을 도입하는데 페이징 기준이 되는 Key 값을 어떻게 처리할 지 논의가 필요하다.

팀원 B

  • 커서 기반 페이지네이션은 페이징을 위해 키 값을 기준으로 데이터를 가져옴
  • 기준이 되는 키 값을 비교 연산자를 통해 가져오기에 정렬 가능한 컬럼이어야 함
  • 기준이 되는 키 값은 성능을 위해 인덱싱 되어야 함
  • 보통 정수형 PK(auto_increment)를 통해 데이터를 페이징함
  • 커서 기반 페이지네이션 적용 시 UUID를 통해 PK를 찾아 해당 PK + (PK + size)까지 데이터를 가져온다. 

팀원 C

  • order by 조건이 있는 경우 복합 인덱스를 사용하여 페이지네이션할 수 있다.
  • 서비스가 확장 됨에 다라 인덱스가 너무 커지지 않을지? 거의 사용되지 않는 정렬 조건은 인덱스를 걸어놓지 않아도 되지 않을까?

최종 의사 결정

cursor 기반 페이지네이션을 사용한다.

  • 데이터를 순차적으로 조회하지 않아도 되기 때문에 성능상의 이점이 있다.
  • offset 기반과 달리, 데이터가 생성 및 삭제될 때 중복이나 누락되는 상황이 적어진다.

추가적으로 고려해 볼 사항

  • 다른 정렬 조건이 들어올 때, cursor 값을 어떻게 선정하면 좋을지?
  • 복합 인덱스를 사용해야 하는지?
  • 정렬 조건이 많아진다면 인덱스가 많아지는 것은 아닌지?
  • cursor 기반 페이지네이션 적용 범위 : admin과 관련된 기능에서 모든 정보를 한 눈에 보려면 cursor 기반보다 offset이 좋은 거 같다.

 

팀원과 의사 결정을 통해 느낀 점

  • 혼자서 개발할 때와는 다르게 여러 사람의 관점을 통해 더 좋은 방식으로 개선해 갈 수 있어서 좋았다.
  • 내가 모르는 부분을 팀원을 통해 배우게 되었고, 의견을 나누며 단순히 이 방법으로 하라고 해서 했다가 아닌 A 방법이 B 방법에 비해 이런 장, 단점이 있고 프로젝트 요구 사항을 토대로 어떤 방법을 쓰는 것이 더 좋을지 정할 수 있는 점이 좋았다.
  • 프로젝트를 진행할 때 팀원과 개발 관련된 커뮤니케이션 능력을 기를 수 있어서 좋았다.

'자바 심화 > TIL' 카테고리의 다른 글

클린 코드 1  (2) 2024.11.19
페이지네이션 Offset vs Cursor  (2) 2024.11.18
결제 기능 구현  (0) 2024.11.16
PostgreSQL 기초  (1) 2024.11.14
아키텍처(Architecture)  (0) 2024.11.12