SQL vs NoSQL — 무엇이 다르고 언제 무엇을 고르나
관계형(SQL)과 NoSQL의 차이를 데이터 저장 방식부터 비교하고, SQLite·Postgres·MongoDB·Firestore가 각각 어디에 속하는지, 댓글 같은 실제 기능엔 무엇이 맞는지 정리했다.
SQL vs NoSQL — 무엇이 다르고 언제 무엇을 고르나
블로그에 댓글 기능을 붙일 DB를 고를 때 "SQL이냐 NoSQL이냐"를 다시 짚게 됐다. 이름은 익숙한데 막상 "뭐가 다르냐"를 한 줄로 답하기 애매한 주제라, 기초부터 정리한다.
이름부터: NoSQL = "Not Only SQL"
- SQL = 관계형 데이터베이스(RDBMS). 데이터를 표(테이블)에 저장하고 SQL 언어로 다룬다.
- NoSQL = "SQL만 쓰는 게 아니다". 표가 아닌 다른 구조(문서·키값·그래프 등)로 저장하는 DB들의 통칭.
핵심 차이는 데이터를 어떻게 저장하느냐다.
저장 방식의 차이
SQL (관계형) — 엑셀 표처럼
컬럼이 미리 정해진 표에 행 단위로 저장한다.
comments 테이블
┌──────┬─────────────┬──────────┬─────────────┐
│ id │ author_name │ content │ created_at │
├──────┼─────────────┼──────────┼─────────────┤
│ 1 │ 홍길동 │ 안녕 │ 2026-06-21 │
│ 2 │ ㅇㅇ │ ㅋㅋ │ 2026-06-21 │
└──────┴─────────────┴──────────┴─────────────┘→ PostgreSQL, MySQL, SQLite
NoSQL (문서형) — JSON 덩어리처럼
스키마가 고정되지 않은 JSON 문서를 그대로 넣는다. 문서마다 모양이 달라도 된다.
{ "id": "abc", "author": "홍길동", "content": "안녕" }
{
"id": "def", "author": "ㅇㅇ", "content": "ㅋㅋ",
"likes": 5, // 이 문서에만 있는 필드
"replies": [{ "author": "김", "content": "ㄷㄷ" }] // 중첩 구조
}→ MongoDB, Firebase Firestore, DynamoDB
한눈에 비교
| SQL (관계형) | NoSQL (문서형) | |
|---|---|---|
| 저장 형태 | 정해진 표 | 자유로운 JSON |
| 스키마 | 미리 고정 | 유연 (문서마다 달라도 됨) |
| 관계 표현 | 테이블 간 JOIN | 중첩하거나 직접 연결 |
| 복잡한 조회 | 강력 (SQL) | 상대적으로 약함 |
| 확장 방식 | 수직(서버 키우기)에 강함 | 수평(서버 늘리기)에 강함 |
| 트랜잭션 | 강력 (ACID) | 제한적 (제품마다 다름) |
| 대표 | PostgreSQL, MySQL | MongoDB, Firestore |
"DB 없이 SQL"? — SQLite의 위치
자주 헷갈리는 지점. SQLite는 SQL 문법을 그대로 쓰지만 별도 DB 서버 프로세스가 없다. 파일 하나가 곧 DB이고, 라이브러리가 그 파일을 직접 읽고 쓴다.
일반 DB (Postgres/MySQL): 서버 프로세스가 항상 떠 있음 → 접속해서 쿼리
SQLite: 파일 하나(app.db)가 DB. 서버 없음, 라이브러리가 처리그래서 Cloudflare D1, Turso 같은 서비스가 "서버 관리 없이 SQLite를 클라우드에서" 제공한다 — "DB 없이 SQL 쓰는 느낌"에 가장 가깝다. 단, SQLite도 결국 쓰기를 받아줄 어딘가는 필요하다. 데이터를 저장할 곳이 0이면 SQL이든 NoSQL이든 불가능하다.
무엇을 언제 고르나
SQL이 유리한 경우
- 데이터 구조가 명확하고 안정적 (댓글: 이름·내용·시간·IP 등 컬럼이 뻔함)
- 관계·집계 조회가 많음 ("이 글의 댓글을 시간순으로", "같은 IP 60초 내 N개" 같은 카운트)
- 트랜잭션 정합성이 중요 (결제, 재고)
NoSQL이 유리한 경우
- 스키마가 자주 바뀌거나 문서마다 구조가 다름
- 실시간 동기화가 기본 필요 (Firestore)
- 초대규모 수평 확장이 필요 (글로벌 서비스)
실제 선택 — 댓글엔 SQL
블로그 댓글/조회수/방명록엔 SQL(PostgreSQL, Supabase)을 골랐다.
- 댓글 데이터는 컬럼이 명확해서 표 구조에 완벽히 맞는다.
- "시간순 정렬", "같은 IP 도배 카운트" 같은 집계가 SQL로 깔끔하다.
- Postgres는 표준 SQL이라 나중에 다른 DB로 이전하기도 쉽다(
pg_dump→ restore).
참고로 Firebase Firestore(NoSQL)는 무료 티어가 "용량"보다 "하루 읽기 횟수"가 먼저 걸려서, 조회가 많은 블로그엔 오히려 불리할 수 있다. 같은 무료라도 제한의 종류가 다르다.
정리
- SQL = 정해진 표 + JOIN·집계 강함 → 구조가 명확한 데이터에 적합
- NoSQL = 자유로운 JSON + 유연·실시간·초대규모 → 구조가 자주 바뀌거나 거대한 데이터에 적합
- SQLite = SQL이지만 서버 없는 파일 DB (D1·Turso가 이 계열)
- 댓글처럼 구조가 명확한 기능은 SQL이 기본값으로 무난하다
이 DB로 블로그 댓글을 어떻게 붙였는지는 정적 블로그에 동적 기능 더하기에 정리했다.
Related Posts
같이 읽으면 좋은 글
Jenkins 시리즈 ④ Controller와 Agent — 빌드는 어디서 도는가
Controller·Node·Agent·Executor의 관계, Jenkinsfile에서 무엇이 어디서 실행되는지, SSH와 Inbound(TCP·WebSocket) 연결 방식, agent 지시어와 Docker·Kubernetes 임시 Agent, 그리고 Controller 하나에서 Agent로 넘어가는 순서를 정리했다.
Jenkins 시리즈 ⑤ 배포 전략 — Recreate부터 Canary까지
버전 태그와 롤백을 전제로 Recreate·Rolling·Blue-Green·Canary를 Jenkins + docker compose 환경에서 구현하는 방법, SSH 배포와 Agent 배포의 차이, 그리고 모든 전략에 걸리는 DB 마이그레이션 문제를 정리했다.
Jenkins 시리즈 ③ GitLab 연동 — 토큰 3종, Webhook, Jenkinsfile
Jenkins와 GitLab을 잇는 Credentials와 세 가지 토큰의 방향, Job·Webhook·Secret Token 설정, 비밀값이 새지 않는 Jenkinsfile 작성법, 그리고 GitLab CI의 CI_JOB_TOKEN이 Jenkins와 어떻게 다른지까지 정리했다.