시스템 디자인

데이터베이스가 터진다고요? 8가지 전략으로 앱을 구원하세요

실리콘밸리 CTO가 밝히는 데이터베이스 확장의 비밀: 수직 확장부터 비정규화까지

2024.07.04 | 조회 993 |
0
|

데브필 DevPill

Top 1% 개발자로 거듭나는 성공 처방전

Introduction

여러분, 혹시 이런 악몽을 꾼 적 있나요? 여러분의 앱이 대박이 나서 사용자가 폭증했는데, 데이터베이스가 그 부하를 견디지 못하고 터져버리는 상황 말이죠. 실제로 이런 일은 스타트업계에서 흔히 일어나는 '달콤한 고민'입니다. 하지만 달콤한 만큼 위험하죠. 제때 대처하지 못하면 여러분의 꿈과 함께 서비스도 무너질 수 있으니까요.

실리콘밸리의 한 유명 스타트업 CTO는 이렇게 말합니다.

"데이터베이스 확장은 마치 롤러코스터를 타는 것과 같아요. 잘못하면 아찔하게 추락하지만, 잘 다루면 엄청난 스릴과 함께 정상에 오를 수 있죠."

그렇다면 어떻게 해야 이 위험천만한 롤러코스터를 제대로 다룰 수 있을까요? 오늘 가져온 글인 <데이터베이스를 scale-up하는 8가지 방법>에서는 데이터베이스 확장의 8가지 핵심 전략을 상세히 알아보겠습니다. 수직 확장부터 시작해 샤딩, 캐싱, 그리고 비정규화까지. 각 전략의 장단점을 파헤치고, 실제 적용 사례까지 함께 살펴볼 예정입니다.

여러분의 앱이 폭발적으로 성장할 때, 데이터베이스도 함께 성장할 수 있도록 준비하세요. 이 글을 통해 여러분은 데이터베이스 확장의 대가로 거듭날 수 있을 겁니다. 그럼, 시작해보겠습니다.


데이터베이스를 scale-up 하는 8가지 방법

사용자 정보를 저장해야 하는 애플리케이션을 개발한다고 가정해 봅시다. 앱에 수백 명의 사용자가 있을 때는 모든 데이터를 하나의 데이터베이스 서버에 보관할 수 있죠.

하지만 앱이 성장하면서 더 많은 사용자를 확보하면 더 많은 데이터를 저장해야 합니다. 증가하는 부하를 처리하기 위해 데이터베이스를 확장하지 않으면 앱 속도가 느려지고 문제가 발생할 수 있습니다.

이 글에서는 데이터베이스가 병목 현상을 일으키지 않고 애플리케이션이 최적의 성능으로 계속 작동하도록 보장하는 8가지 데이터베이스 확장 전략을 살펴보겠습니다.

1. 수직 확장(Vertical Scaling)

수직 확장은 단일 데이터베이스 서버에 더 많은 리소스(CPU, RAM, 스토리지)를 추가하는 것입니다. 작은 규모의 데이터베이스에서는 빠르고 쉬운 해결책이지만 한계가 있습니다.

  • 비용이 많이 들 수 있고
  • 확장할 수 있는 한계가 있습니다.
  • 또한 모든 것을 한 곳에 집중시키므로 단일 장애 지점이 생깁니다.

예: 소규모 전자상거래 웹사이트가 휴일 세일 기간 동안 트래픽이 증가합니다. 추가 부하를 처리하기 위해 데이터베이스 서버에 RAM을 추가하여 수직으로 확장합니다.

2. 인덱싱(Indexing) 

책 뒷부분의 색인은 모든 페이지를 넘기지 않고도 특정 정보를 빠르게 찾을 수 있게 도와줍니다. 마찬가지로 데이터베이스 인덱스는 테이블의 모든 행을 스캔하지 않고도 데이터를 훨씬 빠르게 찾을 수 있게 해줍니다.

인덱스는 보통 가장 자주 쿼리되는 열에 생성되어 읽기 요청을 더 빠르게 만들지만, 과도한 인덱싱은 오버헤드로 인해 쓰기 성능을 저하시킬 수 있습니다. 또한, 인덱스를 과도하게 생성하면 그만큼 추가적인 정보를 많이 저장하게 되니 가용 가능한 용량도 줄어듭니다. 보통 인덱스가 차지하는 용량은 10~15%를 적정선으로 생각합니다. 인덱스가 그 이상을 차지한다면 과도하게 쓰고 있지는 않은지 고려해볼 필요가 있습니다. 

3. 샤딩(Sharding) 

하나의 머신은 한정된 양의 데이터만 저장할 수 있습니다. 더 많은 사람들이 애플리케이션을 사용할수록 공간이 부족해지고 속도가 느려질 것입니다. 이를 방지하기 위해 데이터를 더 작은 조각(샤드)으로 나누어 다른 서버에 저장할 수 있습니다. 이 과정을 데이터베이스 샤딩이라고 합니다.

이렇게 데이터를 분산시키면 확장이 더 쉬워지고 더 많은 사용자를 처리할 수 있습니다.

4. 수직 분할(Vertical Partitioning) 

일부 열이 다른 열보다 더 자주 접근되는 상황에서는 데이터베이스 테이블을 더 작은 테이블로 나누어 각각 원래 테이블의 열의 부분집합을 포함하도록 하는 것이 좋습니다.

이렇게 하면 쿼리 중에 읽는 데이터의 양을 줄일 수 있어 특정 접근 패턴에 대한 성능을 향상시킬 수 있습니다.

예: 전자상거래 애플리케이션에서 제품 테이블을 다음과 같이 나눌 수 있습니다:

자주 접근하는 데이터(ID, 이름, 가격, 카테고리)가 있는 "core_product" 테이블

덜 자주 접근하는 데이터(설명, 명세)가 있는 "product_details" 테이블

큰 바이너리 데이터(이미지, 비디오)가 있는 "product_media" 테이블

5. 캐싱(Caching) 

거의 모든 주요 애플리케이션에서 일부 데이터는 다른 데이터보다 더 자주 접근됩니다.

예를 들면:

  • 블로그 앱에서는 일부 글이 다른 글보다 더 자주 읽힙니다.
  • 소셜 미디어 앱에서는 일부 사용자가 다른 사용자보다 플랫폼을 더 자주 사용합니다.
  • 스트리밍 플랫폼에서는 일부 영화가 다른 영화보다 더 자주 시청됩니다.

이런 자주 접근되는 데이터를 더 빠른 저장소 계층에 저장하면 접근 속도를 높이고 데이터베이스의 부하를 줄일 수 있습니다.

이를 캐싱이라고 하며, 자주 접근되는 데이터에 대한 쿼리 속도를 높이기 위한 인기 있는 선택입니다.

6. 복제(Replication) 

데이터베이스 서버가 한 지역에만 있다면 다른 지역의 사용자들은 더 높은 지연 시간을 경험할 수 있습니다. 이를 해결하기 위해 주 데이터베이스를 다른 지역에 복제하고 읽기 요청을 로컬에서 처리할 수 있습니다. 이 과정을 데이터베이스 복제라고 합니다.

간단히 말해, 데이터베이스 복제는 읽기 성능을 향상시키고 고가용성과 재해 복구를 보장하기 위해 여러 서버나 위치에 데이터베이스의 복사본(복제본)을 만들고 유지하는 것입니다. (역자 주: 서비스의 도메인에 따라 다르지만, 일반적으로 읽기 요청이 쓰기 요청보다 훨씬 많은 경우가 다수이기 때문에, 복제를 통해 큰 성능 향상을 기대할 수 있습니다.)

이러한 복제본(slave)들은 원본 데이터베이스(master)와 동기화되어 데이터 일관성을 보장합니다.

복제 유형:

  • 동기식 복제: 주 데이터베이스에 대한 변경사항이 즉시 모든 복제본에 복제된 후에야 트랜잭션이 완료된 것으로 간주됩니다. 이는 강력한 데이터 일관성을 보장하지만 추가적인 오버헤드로 인해 성능에 영향을 줄 수 있습니다.
  • 비동기식 복제: 주 데이터베이스에 대한 변경사항이 약간의 지연 시간을 두고 복제본에 복제됩니다. 이는 더 나은 성능을 제공하지만 주 데이터베이스와 복제본 간의 잠재적인 데이터 불일치(복제 지연이라고 알려진)라는 trade-off가 있습니다.

7. 구체화된 뷰(Materialized Views) 

일부 데이터베이스 쿼리는 복잡하고 실행하는 데 오랜 시간이 걸릴 수 있습니다. 이러한 쿼리가 자주 실행되면 애플리케이션의 성능이 저하될 수 있습니다. 하지만 이러한 복잡하고 빈번한 쿼리의 결과를 미리 계산하고 저장한다면 어떨까요? 이것이 구체화된 뷰의 아이디어입니다.(역자 주: 성능 및 효율성 향상을 위해 쿼리 결과를 주기적으로 캐시하는 미리 계산된 뷰라고 생각하시면 됩니다.)

구체화된 뷰는 복잡한 쿼리의 결과를 미리 계산하여 디스크에 저장한 결과 집합입니다. 즉석에서 계산되는 가상의 일반 뷰와 달리, 구체화된 뷰는 결과를 물리적으로 저장하여 빠른 검색을 위해 즉시 사용할 수 있게 합니다. 이는 복잡하고 리소스 집약적인 작업의 쿼리 성능을 크게 향상시킵니다.

예시: 

전자상거래 플랫폼에서 날짜와 제품별로 판매 데이터를 집계하는 일일 판매 보고서를 생성해야 합니다. 이 보고서는 경영진이 비즈니스 결정을 내리기 위해 자주 접근합니다.

구체화된 뷰 생성:

새로 고침 일정 설정:

8. 데이터 비정규화(Data Denormalization) 

일부 데이터베이스 쿼리는 여러 테이블과 복잡한 조인을 포함할 수 있습니다. 이러한 쿼리는 큰 테이블에서 실행될 때 종종 느리고 애플리케이션을 느리게 만들 수 있습니다.

이를 피하기 위해 복잡한 조인의 필요성을 줄이기 위해 여러 테이블을 하나로 결합하여 중복성을 추가할 수 있습니다. 이를 데이터 비정규화라고 합니다. 이는 읽기 성능을 최적화하기 위해 의도적으로 데이터베이스에 중복성을 도입하여 테이블을 결합하거나 중복 데이터를 추가하는 과정입니다.

예시: 

소셜 미디어 플랫폼이 사용자, 게시물, 댓글, 좋아요에 대해 별도의 테이블로 정규화된 데이터베이스 스키마를 가지고 있습니다.

정규화된 스키마:

이 플랫폼은 사용자 프로필과 관련 게시물 및 댓글에 대해 높은 읽기 트래픽을 경험하므로 게시물과 댓글을 user_profiles 테이블 내에 JSON 배열로 저장합니다.

비정규화된 스키마:

이러한 각 전략은 복잡성, 일관성, 성능 측면에서 고유한 trade-off를 가집니다. 최선의 접근 방식은 종종 애플리케이션의 특정 요구 사항과 제약 조건에 맞춰 이러한 기술들을 조합하는 것입니다.

 


Top 1% 개발자로 거듭나는 확실한 처방전, 데브필입니다.

 

 

다가올 뉴스레터가 궁금하신가요?

지금 구독해서 새로운 레터를 받아보세요

이번 뉴스레터 어떠셨나요?

데브필 DevPill 님에게 ☕️ 커피와 ✉️ 쪽지를 보내보세요!

댓글

의견을 남겨주세요

확인
의견이 있으신가요? 제일 먼저 댓글을 달아보세요 !
© 2024 데브필 DevPill

Top 1% 개발자로 거듭나는 성공 처방전

뉴스레터 문의dev.redpill@gmail.com

자주 묻는 질문 서비스 소개서 오류 및 기능 관련 제보

서비스 이용 문의admin@team.maily.so

메일리 사업자 정보

메일리 (대표자: 이한결) | 사업자번호: 717-47-00705 | 서울 서초구 강남대로53길 8, 8층 11-7호

이용약관 | 개인정보처리방침 | 정기결제 이용약관