Database Design Mistakes I Made So You Don't Have To \u2014 COD-AI.com

March 2026 · 17 min read · 4,013 words · Last Updated: March 31, 2026Advanced

💡 Key Takeaways

  • The Normalization Trap: When "Proper" Design Becomes a Performance Nightmare
  • The UUID Disaster: When "Best Practices" Destroy Your Performance
  • Ignoring Indexes: The $40,000 Query
  • The Soft Delete Catastrophe: When "Never Delete Anything" Breaks Everything

삼 년 전, 저는 제품 출시 중에 우리의 스타트업 데이터베이스가 멈추는 것을 보았습니다. 우리는 동시에 가입하려는 50,000명의 사용자가 있었고, 우리의 응답 시간은 200ms에서 47초로 불어난 상황이었습니다. 원인? 제가 이전 6개월 동안, 우리가 차고에서 단 5명일 때 저지른 데이터베이스 설계 실수들이었습니다. 그 날 밤, 우리는 180,000달러의 수익 손실을 겪었고, 시작하기도 전에 우리의 명성을 거의 망가뜨렸습니다.

💡 주요 내용

  • 정규화의 함정: "올바른" 설계가 성능 악몽이 되는 경우
  • UUID 재앙: "최고의 관행"이 성능을 파괴할 때
  • 인덱스 무시: $40,000 쿼리
  • 소프트 삭제 재앙: "절대 삭제하지 마라"가 모든 것을 망칠 때

저는 마커스 첸이고, 지난 12년 동안 데이터베이스 설계자로 일해왔습니다. 지난 7년은 특히 SaaS 기업이 제로에서 수백만 명의 사용자로 성장하는 데 도움을 주었습니다. 저는 하루에 200만 건의 거래를 처리하는 핀테크 플랫폼, 15TB의 환자 데이터를 관리하는 헬스케어 애플리케이션, 블랙 프라이데이의 트래픽 급증을 처리하는 전자상거래 사이트를 위한 시스템을 설계했습니다. 그러나 저에게 가장 가치 있는 교육은 제 경력 초기에 저지른 실수에서 배웠습니다. 그 실수들은 어떤 인증서나 교과서보다 더 많은 것을 가르쳐 주었습니다.

이 기사는 이론적 최선의 관행에 관한 것이 아닙니다. 이것은 제가 실제 생산 환경에서 저지른 구체적이고 고통스럽고 비싼 실수들과 그 뒤에 따르는 간절히 배운 교훈들에 관한 것입니다. 데이터를 저장하는 어떤 것을 만들고 있다면—주말 프로젝트든 다음 유니콘이든—이 교훈들은 여러분이 수개월의 리팩토링과 많은 불면의 밤을 절약할 수 있게 할 수 있습니다.

정규화의 함정: "올바른" 설계가 성능 악몽이 되는 경우

대학교를 갓 졸업한 저는 데이터베이스 정규화에 집착했습니다. 제3 정규형은 단순한 지침이 아니라 복음이었습니다. 제가 2013년에 물류 스타트업에 합류했을 때, 저는 정규화 원칙을 철저히 준수하여 우리의 배송 추적 시스템을 설계했습니다. 모든 데이터 조각은 자체 테이블을 가지고, 모든 관계는 완벽하게 모델링되었으며, 어디에도 중복이 없었습니다.

시스템은 학문적으로 아름다웠습니다. 그러나 재앙적으로 느리기도 했습니다.

단일 배송 세부사항을 표시하기 위해—사용자들이 매시간 수천 번 수행하는 작업이었습니다—11개의 테이블을 조인해야 했습니다. 우리의 평균 쿼리 시간은 3.2초였습니다. 추적 페이지에 대한 것이었습니다. 사용자는 페이지가 로드되기도 전에 사이트를 포기하고 있었습니다. CEO는 저를 그의 사무실로 불러들여 여전히 저를 괴롭히는 질문을 했습니다: "왜 FedEx는 즉시 로드되는데 우리의 페이지는 소포를 실제로 배송하는 것보다 더 오래 걸리느냐?"

제가 배운 것은 다음과 같습니다: 정규화는 도구이지 종교가 아닙니다. 제3 정규형은 데이터 이상을 방지하고 저장 비용을 줄이기 위해 설계되었습니다—이것은 1985년에 디스크 공간이 기가바이트당 10,000달러였을 때는 이해가 되는 문제들이었습니다. 2026년에는 저장이 사실상 무료지만, 사용자 주의 집중 시간은 밀리초 단위로 측정됩니다. 몇 킬로바이트의 중복 데이터는 느린 로드 시간으로 사용자를 잃는 것과 비교하면 사소한 비용입니다.

수정을 위해, 우리는 가장 많이 접근하는 데이터를 비정규화해야 했습니다. 우리는 여러 개의 정규화된 테이블에서 정보를 중복시킨 shipment_summary 테이블을 만들었습니다. 예, 이는 제3 정규형을 위반했습니다. 예, 동기화를 유지하기 위해 추가적인 논리가 필요했습니다. 그러나 쿼리 시간은 3.2초에서 180밀리초로 떨어졌습니다—94% 개선된 것입니다. 우리의 사용자 참여 지표는 일주일 내에 회복되었습니다.

교훈은 정규화를 완전히 버리지 말라는 것입니다. 데이터베이스 설계는 트레이드 오프에 관한 것임을 이해하는 것입니다. 일관성이 중요한 거래 데이터를 정규화하세요. 성능이 더 중요한 읽기 중심의 데이터는 비정규화하세요. 우리의 경우, 데이터 입력과 업데이트를 위해 정규화된 구조를 유지했지만, 사용자-facing 쿼리를 위해 비정규화된 뷰를 유지했습니다. 이 혼합 접근법은 데이터 무결성과 성능을 모두 제공했습니다.

오늘날 스타트업과 상담할 때, 저는 같은 실수를 반복해서 봅니다. 데이터베이스 과정을 갓 졸업한 주니어 개발자들은 모든 것을 과도하게 정규화합니다. 그들은 이론적으로는 완벽하지만, 실제로는 사용 불가능한 시스템을 만듭니다. 제 경험 법칙: 일반 쿼리가 세 개 이상의 조인을 요구하면, 아마도 그 사용 사례에 대해 과도하게 정규화된 것입니다. 이론적 순수함이 아니라 실제 접근 패턴을 위해 설계하세요.

UUID 재앙: "최고의 관행"이 성능을 파괴할 때

2016년, 저는 소셜 미디어 분석 플랫폼을 구축하고 있었습니다. 우리는 글로벌로 확장할 것을 기대했기 때문에, UUID를 기본 키로 사용하기로 하는 것처럼 보이는 스마트한 결정을 내렸습니다. 읽은 모든 기사는 분산 시스템에 대해 UUID를 추천했습니다. UUID는 전 세계적으로 고유하며, 나열 공격을 방지하고, 클라이언트 측에서 ID를 생성할 수 있게 해줍니다. 무엇이 잘못될 수 있겠습니까?

"정규화는 도구이지 종교가 아니다. 이론적 순수함을 실제 성능보다 우선시하는 순간, 당신은 이미 전투에서 지고 있는 것이다."

모든 것이 결국 그렇게 되었습니다.

출시 후 6개월 만에, 200만 사용자가 있고 500만 레코드를 보유한 우리의 데이터베이스 성능은 신비롭게 저하되고 있었습니다. 빠르셔야 할 쿼리가 몇 초가 걸리고 있었습니다. 우리의 데이터베이스 크기는 340GB로 불어났습니다—데이터 양이 제안하는 것보다 훨씬 큰 사이즈였습니다. 가장 우려스러운 것은, 초기에 비해 삽입 성능이 60%나 떨어졌다는 것이었습니다. 더 강력한 하드웨어로 업그레이드했음에도 불구하고 말입니다.

문제는 인덱스 단편화였습니다. UUID는 무작위이므로, 각 삽입은 B-트리 인덱스의 무작위 위치로 이동합니다. 자동 증가 정수로, 새로운 레코드는 인덱스의 끝에 추가되는 빠른 작업입니다. UUID에서는 데이터베이스가 인덱스 페이지를 계속 분할하고 재균형하도록 만들며, 이는 대규모 단편화를 초래했습니다. 우리의 인덱스는 본래보다 3.2배 더 컸고, 모든 쿼리는 이 비대해진 단편 구조를 통과해야 했습니다.

성능의 영향은 파괴적이었습니다. 우리의 기본 키 인덱스만 47GB였고—실제 데이터는 12GB 뿐입니다. 인덱스 유지 관리는 우리의 데이터베이스 CPU 시간의 40%를 소비하고 있었습니다. 더 나쁜 것은, 무작위 I/O 패턴이 있어 우리가 캐시를 효과적으로 사용할 수 없었다는 것입니다. 순차적 ID의 경우, 최근에 삽입된 레코드는 함께 접근될 가능성이 높습니다. UUID의 경우, 모든 접근이 본질적으로 무작위이므로 캐시 적중률을 파괴했습니다.

우리는 결국 하이브리드 접근법으로 마이그레이션했습니다: 내부적으로 순차적 ID, 외부 API를 위한 별도의 UUID 열. 이 마이그레이션은 신중한 계획과 실행에 3주가 걸렸으며, 그 동안 두 시스템을 동시에 유지해야 했습니다. 우리는 약 85,000달러의 엔지니어링 시간과 인프라 비용이 들었습니다. 성능 개선은 즉각적이고 극적이었습니다—삽입 성능은 240% 증가하고, 쿼리 시간은 55% 감소했으며, 데이터베이스 크기는 재인덱스 후 30% 감소했습니다.

여기서의 교훈은 미묘합니다. UUID가 본질적으로 나쁜 것은 아닙니다—단지 비용이 비쌉니다. 정말로 분산 ID 생성을 필요로 하거나 ID 예측 가능성이 보안 문제인 다중 테넌트 시스템을 구축하는 경우, UUID는 그 비용을 가치 있게 만들 수 있습니다. 그러나 대부분의 애플리케이션, 특히 초기 단계에서는 순차적 ID가 훨씬 더 효율적입니다. 나중에 외부 식별자가 필요하다면 UUID 열을 추가할 수 있습니다. "최고의 실천"이라고 하여 UUID로 시작하는 것은 화물 숭배 공학에 불과합니다.

C

Written by the Cod-AI Team

Our editorial team specializes in software development and programming. We research, test, and write in-depth guides to help you work smarter with the right tools.

Share This Article

Twitter LinkedIn Reddit HN

Related Tools

JSON Formatter & Beautifier - Free Online Tool Help Center — cod-ai.com How to Generate Hash Values — Free Guide

Related Articles

How to Debug Faster: Strategies That Actually Work JavaScript Minifier: Complete Guide to Minifying JS Code Regex Cheat Sheet 2026: Patterns Every Developer Needs — cod-ai.com

Put this into practice

Try Our Free Tools →