🧐 TIL

[백엔드 기본 개념 정리] 데이터베이스

백엔드의 핵심 요소, 데이터베이스

이번 포스트에서는 데이터베이스에 대해 다뤄보려고 한다. 사실, 데이터베이스는 비개발자들도 대부분 이해하고 많이 사용하기 때문에 개념 자체는 익숙하지만 여기서는 단순한 저장소로서의 데이터베이스 보다는 백엔드를 구성하는 요소로서 데이터베이스가 왜 반드시 필요하고 핵심적인지를 알아보자.

백엔드와 데이터베이스의 관계

백엔드 어플리케이션은 크게 세 가지 일을 한다.

  1. 데이터를 받아서
  2. 가공하고
  3. 다시 저장하거나 전달한다. 웹 서비스를 만든다는 건 결국 데이터를 다루는 일로, 이전 포스트에서 설명한 개념들은 모두 데이터와 연관이 있었다. 프로토콜은 위 세 가지 중 데이터를 어떻게 보내고 받을 것인가에 대한 규칙을 정립한 것이고, 웹서버나 WAS는 데이터의 전달과 가공을 담당하는 프로그램들이었다.

그리고 위 세 가지 중 마지막으로 남은 일이 데이터를 잘 보관하는 것이다.

여기서 중요한 포인트는 데이터를 “잘” 보관해야 한다는 것이다. 단순한 저장소의 역할만 필요하다면 굳이 데이터베이스를 사용하지 않고 파일 시스템을 사용한다거나 스프레드시트에 저장을 해도 될 것이다. 그러나 백엔드에서 데이터를 다룰 때는 단순히 CRUD(Create, Read, Update, Delete)만 잘된다고 끝이 아니다. 요청에 따라 정확한 데이터를 빠르게 반환하는 것이 중요하기 때문에 데이터베이스 시스템이 사용되는 것이며 DB를 어떻게 활용하는지가 곧 시스템의 안정성과 직결된다.

즉, 데이터베이스는 단순 저장소를 넘어 시스템의 신뢰성을 떠받치는 핵심 인프라에 가깝다.

안정적인 DB 운영을 위한 요소

무결성 (Integrity)

무결성은 데이터에 결함이 없도록 정확성, 일관성, 완전성, 유효성을 유지하는 것을 말한다.

  • 정확성(Accuracy): 데이터가 현실 세계의 실제 값과 일치하고 중복이나 누락이 없는 것
  • 일관성(Consistency): 데이터가 어떤 연산을 수행하더라도 그 결과가 모순 없이 일관된 상태를 유지하는 것
  • 완전성(Completeness): 데이터의 누락이 없이 의도된 목적을 달성하기에 충분한 상태를 갖는 것
  • 유효성(Validity): 데이터가 특정 규칙이나 제약 조건에 따라 올바른 형식과 범위를 가지는 것 RDB에서 컬럼 타입과 속성을 지정하고 primary key, foreign key를 사용하는 것, 정규화를 하거나 데이터 조작을 위한 일련의 동작을 트랜잭션(transaction)이라는 단위로 묶는 것 등이 모두 무결성을 지키기 위한 방법들이다.

동시성 (Concurrency)

웹 서비스에서 데이터에 대한 접근은 여러 사용자에 의해 동시에 일어날 수 있다. 예를 들어, 재고가 하나 남은 상품을 한 사용자가 주문하는 동안 다른 사용자도 같은 상품을 주문할 수 있고 이 때 DB는 누가 먼저 주문을 했는가를 판단해야 한다.

이렇듯 동시에 일어나는 데이터의 조회, 수정을 안전하게 다룰 수 있도록 동시성 제어(concurrency control)가 필요하다. 동시성 제어를 위해서는 아래와 같은 방법들이 사용된다.

  • 락 (Lock) — 데이터 접근을 막아 다른 트랜잭션에 의한 수정을 방지한다.
  • 격리 수준 (Isolation Level) — 동시에 일어나는 트랜잭션들을 어느 수준까지 격리시킬 것인가를 결정한다.

확장성 (Scalability)

서비스가 커지면서 트래픽이 증가하고 데이터가 늘어나더라도 DB를 안정적으로 운영할 수 있어야 한다.

  • 수직 확장 (Vertical Scaling, Scale-up) — 데이터베이스 서버 스펙을 높이는 것으로 간단하지만 한계가 존재한다.
  • 수평 확장 (Horizontal Scaling, Scale-out) — 데이터베이스 서버를 여러대로 분산한다. 단, 여러대의 DB에 데이터를 어떻게 저장할 것인지 전략이 필요하다.
    • Master-Replica: 읽기용 DB, 쓰기용 DB를 분리해서 부하를 분산한다.
    • Sharding: 데이터를 여러대의 DB에 각각 분할한다.

성능 (Performance)

처리 속도를 단순히 빠르게 하는 것이 아니라 다양한 작업을 하더라도 일정한 성능을 유지할 수 있도록 하는 것이 핵심이다.

  • 인덱싱(Indexing): 색인 같은 자료구조를 만들어 데이터 검색 속도를 높이는 것
  • 캐싱(Caching): 자주 조회되는 데이터를 캐시에 저장하여 DB 부하를 줄이고 조회 속도를 높이는 것
  • 쿼리 최적화(Query Optimization): 쿼리 구조를 개선하여 처리 속도를 높이고 리소스 사용을 줄이는 것

장애 대비

디스크 고장, 네트워크 분리, 잘못된 마이그레이션 등 언제든 장애가 발생할 수 있는 것을 고려하여 데이터의 손실에 대비한다.

  • 백업(Backup): 주기적으로 dump 또는 snapshot 저장
  • 복제(Replication): Master–Replica 구조로 장애 시 자동 전환
  • 모니터링(Monitoring): CPU, 쿼리 시간, slow query log 추적
  • 복구 전략(Recovery Strategy): 자동 복구 절차 마련, RPO(복구 지점 목표), RTO(복구 시간 목표) 정의