Backend
1 min read

DB 종류와 선택 기준

FE 개발자가 백엔드를 시작하며 정리한 글. 관계형/비관계형 DB의 실제 차이와, 무엇을 언제 고르는지를 의사결정 기준으로 정리합니다.

NOTE

백엔드를 거의 처음 보는 프론트엔드 개발자가 DB를 공부하며 정리한 글입니다. "DB 뭐 써야하지?"라는 질문에 답하기 전에, 종류가 왜 나뉘고 무엇을 기준으로 고르는지부터 정리했습니다.

결론부터 말을 하면 대부분의 서비스는 PostgreSQL 하나로 시작한다고 합니다. 여기서 안 되는 구체적인 이유가 생겼을 때만 다른 DB를 추가합니다. "처음부터 MongoDB", "처음부터 Redis가 메인" 같은 선택은 평균이 아니라 예외입니다.

이 글의 나머지는 그 한 문장을 풀어 쓴 것입니다. DB가 왜 종류별로 나뉘는지, 각각 무엇을 포기하고 무엇을 얻는지, 그래서 언제 디폴트를 벗어나는지를 정리합니다.

0. DB란?

DB는 데이터를 저장하고, 안전하게 보관하고, 빠르게 찾아주는 시스템입니다. 그냥 파일에 저장하면 안 되냐고 할 수 있는데, 동시에 여러 사람이 접근할 때 충돌 안 나게 하고, 데이터가 깨지지 않게 보장하고(트랜잭션), 수백만 건 중에서도 원하는 걸 빠르게 찾는(인덱스) — 이런 일들을 DB가 대신 해줍니다.

1. 관계형과 비관계형

DB는 크게 관계형(RDB, SQL)비관계형(NoSQL) 으로 나뉩니다. 흔히 "정형 / 비정형"이라고 부르는데, 이 표현은 절반만 맞습니다. 더 정확한 기준은 데이터의 구조(스키마)를 DB가 강제하느냐입니다. 이 차이가 나머지 모든 특성을 결정합니다.

관계형 (RDB)비관계형 (NoSQL)
저장 단위테이블의 행(row)문서·키값·컬럼·노드 (계열마다 다름)
스키마미리 정의, DB가 강제유연하거나 없음
관계 표현JOIN보통 애플리케이션이 처리
대표PostgreSQL, MySQL, MariaDB, SQLite, OracleMongoDB, Redis, Cassandra
언어SQL (표준화)제품마다 제각각

여기서 가장 중요한 건 마지막에서 두 번째 행입니다. 관계를 누가 책임지느냐. 관계형은 DB가 JOIN으로 처리하고, NoSQL은 대부분 애플리케이션 코드가 처리합니다. 이 책임 소재가 곧 선택의 핵심입니다.

2. 관계형 DB — 스키마, 관계, 트랜잭션

관계형 DB는 데이터를 표(테이블) 로 저장합니다. 컬럼마다 타입과 제약조건이 미리 정해져 있고, 테이블끼리 관계(foreign key) 로 엮입니다.

create table users (
  id    bigint primary key generated always as identity,
  email text not null unique
);
 
create table posts (
  id      bigint primary key generated always as identity,
  user_id bigint not null references users(id),
  title   text not null
);

posts.user_idusers.id를 참조하므로, 존재하지 않는 사용자의 글은 애초에 저장되지 않습니다. 타입이 안 맞아도, not null 컬럼을 비워도 저장이 거부됩니다. 정합성 검사를 DB가 대신 해줍니다.

관계형이 백엔드의 디폴트인 진짜 이유는 두 가지입니다.

첫째, 트랜잭션(ACID). 여러 변경을 "전부 성공 또는 전부 실패"로 묶을 수 있습니다.

begin;
  update accounts set balance = balance - 1000 where id = 1;
  update accounts set balance = balance + 1000 where id = 2;
commit;

중간에 서버가 죽어도 돈이 한쪽에서만 빠지는 일은 없습니다. 둘 다 반영되거나 둘 다 취소됩니다. 돈·재고·예약처럼 "어중간한 상태가 사고가 되는" 데이터는 이 보장이 필수입니다. ACID는 다음 네 가지의 약자입니다.

  • Atomicity(원자성): 트랜잭션은 전부 반영되거나 전부 취소된다.
  • Consistency(일관성): 제약조건을 깨는 상태로는 끝나지 않는다.
  • Isolation(격리성): 동시에 실행돼도 서로 간섭하지 않는다.
  • Durability(지속성): 커밋된 데이터는 장애가 나도 보존된다.

둘째, SQL의 표준화. SQL은 표준 언어라서 PostgreSQL에서 익힌 지식이 MySQL에서도 거의 그대로 통합니다. NoSQL은 제품마다 쿼리 방식이 달라 지식 이전이 어렵습니다.

RDB · RDBMS · SQL — 용어 정리

세 단어가 자주 섞여 쓰여서 한 번 짚고 갑니다.

  • 관계형 모델 (Relational Model): 데이터를 행과 열의 테이블로 표현하고 테이블 간 관계로 잇는 이론적 모델. 1970년 E. F. Codd가 제안했고, 모든 관계형 DB의 뿌리입니다.
  • RDB (Relational Database): 그 모델을 따르는 데이터베이스, 즉 데이터 그 자체. "우리 서비스 RDB"라고 하면 저장된 테이블 묶음을 가리킵니다.
  • RDBMS (Relational Database Management System): 그 RDB를 만들고 관리하는 소프트웨어. PostgreSQL·MySQL 같은 제품이 정확히는 RDBMS입니다.
  • SQL (Structured Query Language): RDBMS와 대화하는 표준 질의 언어. "데이터를 달라 / 넣어라 / 바꿔라"를 표현하는 문법입니다.

엄밀히는 'PostgreSQL'은 RDBMS(소프트웨어)이고, 그걸로 만든 데이터 묶음이 RDB입니다. 일상에서는 둘을 구분 없이 "DB"라 부르지만, 구분해두면 정확합니다.

주요 RDBMS

이름이 많아 보여도 실제로 고르는 후보는 좁습니다. 그래도 한 번 정리해두면 어디서 이름이 나와도 안 헷갈립니다.

RDBMS라이선스특징주로 쓰는 곳
PostgreSQL오픈소스표준 준수, jsonb·배열·확장 등 기능이 가장 풍부신규 프로젝트 기본값
MySQL오픈소스 (Oracle 소유)가장 널리 쓰임, 자료가 많음전통적 웹 서비스, LAMP
MariaDB오픈소스MySQL 원작자가 만든 포크. 라이선스 걱정 없이 호환MySQL 대체
SQLite퍼블릭 도메인서버가 없는 임베디드형. 파일 하나가 곧 DB모바일·로컬·테스트·소규모
Oracle Database상용고가의 엔터프라이즈, 강력한 기능금융·대기업 기간계
SQL Server (MSSQL)상용MS 생태계와 밀착, T-SQL 방언.NET / Windows 환경
IBM Db2상용메인프레임 시절부터의 엔터프라이즈대형 금융·공공 레거시

이 표에서 성격이 가장 다른 건 SQLite입니다. 대부분의 RDBMS는 별도 서버 프로세스로 떠 있고 앱이 네트워크로 접속하지만, SQLite는 서버가 없습니다(serverless·embedded). DB가 app.db 같은 파일 하나이고, 라이브러리 형태로 앱 안에서 그 파일을 직접 읽고 씁니다. 설치·접속·관리가 필요 없어서 스마트폰 앱, 브라우저, 데스크톱 앱, 테스트 환경에 들어갑니다. 전 세계에서 가장 많이 배포된 DB이기도 합니다. 대신 여러 서버가 동시에 같은 DB에 붙는 고동시성 워크로드에는 전통적으로 약합니다.

이 표 밖에도 두 갈래가 더 있습니다.

  • 클라우드 관리형: Amazon RDS / Aurora, Google Cloud SQL, Azure SQL 등. 새 엔진이 아니라 위 RDBMS(주로 PostgreSQL·MySQL)를 클라우드가 대신 운영해주는 형태입니다. 백업·확장·장애 대응을 떠넘길 수 있습니다.
  • NewSQL (분산 SQL): CockroachDB, Google Spanner, TiDB 등. SQL과 트랜잭션(ACID)을 지키면서 NoSQL처럼 수평 확장하는 것을 목표로 합니다. 글로벌 분산 규모에서 등장합니다.

PostgreSQL과 MySQL 중 무엇을 고를지는 대부분 취향 문제입니다. 둘 다 충분히 좋습니다. 다만 PostgreSQL이 jsonb, 배열 타입, 확장(extension) 등 기능 면에서 더 풍부해서, 새 프로젝트라면 Postgres를 기본값으로 두는 경우가 많습니다.

3. NoSQL — "관계형이 아닌 것" 네 가지

NoSQL은 단일 제품군이 아닙니다. "관계형이 아니다"라는 부정형으로 묶인 네 계열입니다. 각각 해결하는 문제가 다릅니다.

3-1. 문서형 (Document) — MongoDB

JSON 같은 문서를 통째로 저장합니다. 한 문서 안에 중첩 구조를 그대로 담을 수 있습니다.

{
  _id: "p1",
  title: "글 제목",
  author: { name: "geon", email: "..." },
  tags: ["db", "nosql"],
  comments: [{ user: "a", text: "..." }]
}

강점: 스키마가 자주 바뀌거나, 한 덩어리를 통째로 읽고 쓰는 데이터(상품 카탈로그, CMS 콘텐츠)에 잘 맞습니다. JOIN 없이 문서 하나만 읽으면 끝납니다.

약점: 관계가 많은 데이터에 약합니다. 위 예시에서 author 정보가 바뀌면, 그 사람이 쓴 모든 문서를 찾아 고쳐야 합니다. 관계형이라면 users 한 행만 바꾸면 끝날 일입니다.

3-2. 키-값 (Key-Value) — Redis

key → value 단순 구조입니다. 보통 메모리에 올려두기 때문에 매우 빠릅니다.

INCR  visits:2026-05-28      # 카운터 1 증가
SET   session:abc123  "..."  # 세션 저장
EXPIRE session:abc123  3600  # 1시간 뒤 자동 삭제

용도: 캐시, 세션, 토큰, 실시간 순위표, 간단한 큐. 실무에서 가장 많이 쓰는 NoSQL은 사실 MongoDB가 아니라 Redis입니다. 단, Redis는 관계형 DB를 대체하지 않습니다. 메인 DB 앞단에 캐시로 같이 둡니다.

3-3. 컬럼형 (Wide-column) — Cassandra, ScyllaDB

행마다 컬럼이 달라도 되는 분산 저장소입니다. 여러 서버에 데이터를 쪼개 담아 초당 수만 건 이상의 쓰기를 감당합니다.

용도: IoT 센서 데이터, 대규모 이벤트 로그처럼 쓰기량이 폭발적인 경우. 개인·소규모 서비스에서는 거의 만날 일이 없습니다. 이런 DB가 필요하다는 건 이미 트래픽이 그 정도 규모라는 뜻입니다.

3-4. 그래프 (Graph) — Neo4j

노드(데이터)와 엣지(관계) 자체를 1급 시민으로 저장합니다. "친구의 친구의 친구" 같은 다단계 관계 탐색이 관계형보다 훨씬 빠릅니다.

용도: 소셜 네트워크, 추천 시스템, 경로 탐색, 부정거래 탐지. 관계 자체가 핵심 데이터인 도메인에 씁니다.

4. "정형 vs 비정형"이라는 말의 함정

블로그를 쓰며 가장 짚고 싶었던 지점입니다. "NoSQL은 스키마가 없어서 자유롭다"는 설명은 오해를 부릅니다.

스키마가 없다는 건 데이터 정합성 책임이 DB에서 애플리케이션 코드로 넘어온다는 뜻입니다. MongoDB에 아무 모양이나 넣을 수 있다는 건, 뒤집으면 필드가 있는지·타입이 맞는지를 내 코드가 매번 확인해야 한다는 의미입니다.

그래서 현실에서 MongoDB는 보통 Mongoose 같은 도구로 애플리케이션 단에서 스키마를 다시 강제해서 씁니다. 결국 스키마는 어딘가에는 필요합니다. 차이는 "DB가 강제하느냐, 내 코드가 강제하느냐"일 뿐입니다.

PostgreSQL은 jsonb 타입으로 비정형 데이터도 잘 다룹니다. "정형 데이터 90% + 비정형 일부"라면 MongoDB를 따로 두지 말고 Postgres 한 곳에서 해결하는 편이 낫습니다. DB를 두 개 운영하는 비용이 생각보다 큽니다. 이것도 "디폴트가 Postgres"인 이유 중 하나입니다.

5. 정규화 vs 비정규화 — 설계 철학의 차이

관계형과 문서형의 차이는 결국 정규화(normalization) 에 대한 태도 차이로 좁혀집니다.

  • 정규화 (관계형의 기본): 데이터를 중복 없이 잘게 쪼개고 관계로 잇는다. 사용자 정보는 users에 한 번만 둔다. 수정이 쉽고 정합성이 보장된다. 대신 읽을 때 JOIN이 필요하다.
  • 비정규화 (문서형의 기본): 함께 읽히는 데이터를 한 문서에 미리 합쳐 둔다. 읽기가 빠르다. 대신 같은 데이터가 여러 곳에 중복되어, 수정 시 전부 고쳐야 한다.

핵심 트레이드오프는 읽기와 쓰기 중 무엇을 최적화하느냐입니다.

  • 데이터를 자주 수정하고 정합성이 중요하다 → 정규화(관계형)
  • 데이터를 한 번 쓰고 자주, 통째로 읽는다 → 비정규화(문서형)

대부분의 일반적인 웹 서비스는 수정과 정합성이 더 중요하기 때문에 관계형이 기본값이 됩니다.

6. 선택 기준 — 질문 네 개

순서대로 자문하면 대부분 결론이 나옵니다.

Q1. 데이터끼리 관계가 있고 정합성이 중요한가? (주문-회원-상품, 결제, 잔액) → 관계형(PostgreSQL). 트랜잭션이 필요한 데이터는 무조건 여기입니다.

Q2. 빠른 임시 저장·조회가 목적인가? (캐시, 세션, 토큰, 실시간 랭킹) → Redis. 메인 DB를 대체하는 게 아니라 앞단에 추가합니다.

Q3. 데이터 모양이 자주 바뀌고, 한 문서를 통째로 다루는가? (속성이 제각각인 카탈로그, CMS) → MongoDB(문서형). 단, Postgres jsonb로 먼저 가능한지 따져봅니다.

Q4. 쓰기량이 초당 수만 건 이상으로 폭발적인가? (센서, 대규모 로그) → Cassandra 등 컬럼형. 소규모에서는 해당 없음.

개인·소규모 서비스 결론: 99% PostgreSQL 하나. 캐시가 필요해지면 Redis 추가. 이걸로 충분합니다. 위 표의 나머지는 "그 규모에 도달했을 때" 다시 보면 됩니다.

7. 한 발 더 — 스케일과 일관성

NoSQL이 등장한 역사적 배경을 알면 선택 기준이 더 또렷해집니다.

수직 확장 vs 수평 확장. 관계형 DB는 전통적으로 수직 확장(한 서버의 CPU·메모리를 키우는 방식)에 강합니다. 한계가 분명합니다. 반면 NoSQL은 처음부터 수평 확장(서버 여러 대에 데이터를 쪼개 분산)을 염두에 두고 설계됐습니다. 트래픽이 한 서버로 감당 안 되는 규모에서 NoSQL이 유리해지는 지점입니다.

ACID vs BASE. 데이터를 여러 서버에 분산하면 트랜잭션을 유지하기 어려워집니다. 그래서 많은 NoSQL은 ACID 대신 BASE(Basically Available, Soft state, Eventually consistent)를 택합니다. "지금 당장은 서버마다 값이 다를 수 있지만, 시간이 지나면 결국 같아진다"는 모델입니다. 이를 최종 일관성(eventual consistency) 이라 합니다.

이 차이가 중요한 이유: 은행 잔액을 최종 일관성에 맡길 수는 없습니다. 방금 입금한 돈이 "잠시 후 반영"되면 안 됩니다. 반대로 SNS의 좋아요 수는 1~2초 늦게 반영돼도 아무 문제 없습니다. 데이터의 성격이 일관성 모델을 결정합니다.

다만 최근에는 경계가 흐려졌습니다. MongoDB도 트랜잭션을 지원하고, PostgreSQL도 확장으로 수평 분산이 가능합니다. "관계형=ACID, NoSQL=BASE"는 출발점일 뿐 절대 규칙이 아닙니다.

8. 결론

  • DB는 스키마를 DB가 강제하느냐로 갈린다. 그 차이가 정합성·관계·확장 특성을 모두 결정한다.
  • NoSQL은 한 덩어리가 아니라 문서·키값·컬럼·그래프 네 계열이고, 각각 푸는 문제가 다르다.
  • "스키마가 없다"는 자유가 아니라 정합성 책임이 코드로 넘어온다는 뜻이다.
  • 관계+정합성이면 관계형, 캐시면 Redis, 그 외는 구체적 이유가 생겼을 때 추가한다.
  • 개인·소규모는 PostgreSQL + (필요 시) Redis면 충분하다.

Comments