데이터베이스 설계는 코드보다 먼저 결정되고, 코드보다 오래 살아남습니다.
ORM을 사용하는 프로젝트에서는 데이터베이스 설계보다는 객체 설계만 신경쓰면 된다고 여기는 경우가 많은데 스키마가 객체로 옮겨갔을 뿐 문제는 동일합니다.
잘못된 스키마는 프로젝트 내내 성가실 뿐만 아니라 시스템의 전체 수명 기간 동안 비용을 증가시킵니다.
자주 하는 실수
1. 헛점이 많은 엔티티 정의
엔티티를 제대로 파악하지 못하고 처음부터 너무 과하거나 모자라게 설계한 경우입니다.
대체로 시간에 쫓겨 도메인 지식이 부족한 상태로 설계에 들어갔을 때 발생했습니다.
분석 단계에서 시간을 충분히 들여서 고객과 요구사항을 면밀히 분석하는 수 밖에요.
2. 섣부른 인덱스 추가
슬로우 쿼리에 기계적으로 인덱스를 거는 것보다 실제 쿼리 패턴을 먼저 파악하는 것이 선행되어야 합니다. 인덱스가 많아지면 문제가 발생해서 들여다볼 때 잡음이 더 섞입니다.
3. 컬럼 타입 정리
주로 기존 DB를 활용해야하는 경우 많이 발생했습니다.
기존에 이미 사용하던 DB가 있으니 빠르게 진행하자는 압박 때문에 달렸던 경우인데요.
VARCHAR(255) 남발, DATE와 TIMESTAMP 혼용, 숫자를 문자열로 저장하는 등의 문제가 뒤늦게 드러나면 - 대개 프로젝트 중반을 넘어가서 불거집니다 - 초반에 시간을 들여 정리하고 시작했었더라면 시간을 더 절약했을텐데라는 후회가 남게 됩니다.
관계형 데이터베이스는 오랜 시간 동안 다듬어져 온 지루하지만 믿음직한 기술입니다. 이미 수많은 원칙이 있지만 실무에서 모든 원칙을 다 적용하기는 어렵죠. 그런데 비슷한 실수들을 반복하면서 원칙에 대한 자신의 기준이 만들어지는 듯합니다.
실수 끝에 정리된 원칙
- 엔티티 간 관계를 먼저 명확히 정의하고, 그 다음에 속성을 채운다
- 인덱스는 쿼리 프로파일링 결과를 보고 추가한다
- NULL 허용 여부를 명시적으로 결정한다
- 마이그레이션은 반드시 코드화하여 버전 관리한다
얼마 전까지 타입도 없는 자연어 같은 쿼리가 시대에 뒤떨어져 보인다는 소리를 종종 들었는데 이제는 LLM 붐과 함께 자연어처럼 쿼리하는 것이 최신 기술처럼 보이기도 하네요. :)