다다의 개발일지 6v6

[DB] - SQL(MySQL) vs NoSQL(MongoDB) 차이점 본문

Backend/Database

[DB] - SQL(MySQL) vs NoSQL(MongoDB) 차이점

dev6v6 2025. 2. 24. 15:40

SQL과 NoSQL은 둘 다 데이터를 저장하고 관리하는 데이터베이스 시스템이다.
하지만 데이터 구조, 사용 방식, 확장성 등이 다르기 때문에 각각의 장단점이 있음

SQL (MySQL)

SQL (Structured Query Language)은 관계형 데이터베이스(RDB, Relational Database)를 다룰 때 사용함.

  • MySQL, PostgreSQL, Oracle, MSSQL 등이 대표적인 SQL 데이터베이스
  • 행/열의 생김새가 정해진 엑셀에 데이터를 저장하는 것과 유사
  • 데이터 50만 개가 적재된 상태에서, 갑자기 중간에 열을 하나 더하기는 어렵지만, 정형화되어 있는 만큼 데이터가 일관적이고 분석에 용이

Query Language란

더보기

쿼리 언어(Query Language)

쿼리(Query) = 데이터베이스에게 요청을 보내는 것
쿼리 언어(Query Language) = 데이터를 조회, 추가, 수정, 삭제 요청하는 명령어

▶ SQL (Structured Query Language)

SQL은 관계형 데이터베이스(MySQL, PostgreSQL 등)에서 데이터를 다룰 때 사용하는 쿼리 언어.

 

예제 (MySQL에서 데이터를 조회하는 SQL 쿼리)

SELECT name, age FROM users WHERE age > 20;

 

위 코드는 users 테이블에서 age가 20보다 큰 사람의 name과 age를 가져온다!

MongoDB의 NoSQL 쿼리

NoSQL 데이터베이스(MongoDB 등)도 데이터를 조회할 때 쿼리 명령을 사용하지만, SQL과 다르게 JSON 기반 명령어를 사용한다.

 

예제 (MongoDB에서 데이터를 조회하는 쿼리)

db.users.find({ age: { $gt: 20 } }, { name: 1, age: 1 });

SQL과 비슷하지만, JSON 형태의 명령어를 사용한다.

 

특징:

✔ 데이터를 테이블(table) 형태로 저장
행(row)과 열(column) 구조로 되어 있음
✔ SQL(쿼리 언어)를 사용해 데이터를 조회/추가/수정/삭제
✔ 데이터 간 관계를 설정(Join, Foreign Key) 해서 정규화 가능
✔ 정해진 스키마(고정된 데이터 구조)가 있어야 함

 

▶ JOIN과 FOREIGN KEY란?

더보기

JOIN과 FOREIGN KEY란?

SQL은 여러 개의 테이블을 서로 연결해서 사용하는 특징이 있다.

 

🔹 FOREIGN KEY (외래키)

한 테이블이 다른 테이블의 데이터를 참조할 때 사용하는 키(컬럼)
즉, 두 테이블 간 "연결(관계)"을 만드는 역할.

 

📌 예제

CREATE TABLE users (
    id INT PRIMARY KEY,  -- users 테이블의 고유 ID
    name VARCHAR(50)
);

CREATE TABLE orders (
    id INT PRIMARY KEY,  
    user_id INT,  -- users 테이블의 id를 참조하는 외래키
    product VARCHAR(100),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

여기서 orders 테이블의 user_id는 users 테이블의 id를 참조하는 FOREIGN KEY임.
즉, orders.user_id는 반드시 users.id에 있는 값만 들어갈 수 있다.

 

 

🔹 JOIN (테이블을 합치는 명령어)

두 개 이상의 테이블에서 데이터를 가져올 때 사용!

 

📌 예제 (사용자와 주문 정보를 합쳐서 가져오기)

SELECT users.name, orders.product
FROM users
JOIN orders ON users.id = orders.user_id;

 

👉 users 테이블과 orders 테이블을 user_id로 연결해서 가져오는 것!

🔹 SQL이 관계형 데이터베이스(RDB)라고 불리는 이유가 바로 이런 관계(FOREIGN KEY, JOIN)를 다루기 때문

▶ 스키마(Schema)란?

데이터베이스의 구조(형식, 규칙)를 정의한 것

더보기

스키마(Schema)란?

 

🔹 SQL (MySQL)의 스키마

MySQL 같은 관계형 데이터베이스는 스키마가 고정적이다
즉, 테이블의 컬럼(열)과 데이터 타입을 미리 정해야함

 

📌 예제 (MySQL에서 users 테이블의 스키마 정의)

CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    age INT NOT NULL
);

 

👉 여기서 id는 정수형, name은 50자 이하 문자열, age는 반드시 있어야 하는 정수형.
💡 스키마를 미리 정해야 하기 때문에 데이터 구조를 바꾸려면 테이블을 수정해야 함!

🔹 MySQL에서 스키마 변경이 어려운 이유

만약 새로운 컬럼이 필요하면 ALTER TABLE을 사용해서 테이블을 변경.

 

📌 예제: 새로운 필드 추가 (MySQL)

ALTER TABLE users ADD COLUMN phone VARCHAR(20);

 

👉 모든 데이터에 영향을 주기 때문에 부담이 큼!

 

 

🔹 NoSQL (MongoDB)의 스키마

MongoDB 같은 NoSQL은 스키마가 자유로워서 새로운 필드를 자유롭게 추가 가능!
즉, 컬렉션에 넣을 데이터 구조가 고정되지 않아서, 각 문서의 필드가 다를 수도 있다.

기존 데이터에 영향을 주지 않고 새로운 데이터 구조를 저장할 수 있음.

 

📌 예제 (MongoDB에 다양한 구조의 데이터 저장)

db.users.insertOne({ name: "Alice", age: 25 });
db.users.insertOne({ name: "Bob", hobbies: ["reading", "coding"] });

 

👉 Alice는 age 필드만 있고, Bob은 hobbies 필드가 있어도 문제없다!
💡 NoSQL은 스키마를 미리 정할 필요가 없기 때문에, 데이터 구조가 자주 바뀔 때 유용하다

  • 유연한 데이터 저장이 가능해서 개발 속도가 빠름
  • JSON 기반이기 때문에 직관적이고 다루기 쉬움

 

📌 예제 (MySQL 테이블 구조)

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT,
    email VARCHAR(100)
);

 

📌 데이터 삽입 (INSERT)

INSERT INTO users (name, age, email) VALUES ('Alice', 25, 'alice@example.com');

 

📌 데이터 조회 (SELECT)

SELECT * FROM users WHERE age > 20;

 

🔹 MySQL을 쓰는 이유

 JOIN, FOREIGN KEY를 이용해서 여러 테이블을 안전하게 연결 가능
✔ 데이터 중복을 최소화할 수 있음 (정규화)
✔ 트랜잭션(Transaction) 기능으로 데이터 정합성 보장 가능

 데이터 간의 관계(1:N, N:M 등)가 명확할 때는 MySQL(RDBMS)이 강력

 

 MySQL을 써야 하는 경우

  • 은행, 금융, 쇼핑몰(고객-주문), 병원(환자-진료기록)처럼 데이터 관계가 중요한 경우
  • 데이터 무결성(Integrity)이 중요하고, 잘못된 데이터가 들어가면 안 되는 경우
  • 금융, 은행, ERP 시스템 등 데이터 정합성이 중요한 경우
  • 데이터 구조가 자주 바뀌지 않는 경우
더보기

데이터 정합성(Data Integrity)이란?

데이터가 정확하고 일관성 있게 유지되는 것!
데이터가 잘못된 값으로 저장되거나, 관계가 깨지는 걸 방지하는 개념이다.

 

SQL(MySQL)은 FOREIGN KEY, TRANSACTION(트랜잭션) 같은 기능을 통해 데이터 정합성을 보장한다

 

  • 트랜잭션(Transaction)은 데이터베이스에서 하나의 작업 단위를 의미함.
    트랜잭션은 여러 가지 작업을 하나의 묶음으로 처리해서 모두 성공하거나 모두 실패하도록 보장하는 중요한 개념임
  • 은행 시스템에서 A 계좌에서 B 계좌로 송금하는 트랜잭션 예시:
    1. A 계좌에서 100원을 출금한다.
    2. B 계좌에 100원을 입금한다.
    이 두 작업을 하나의 트랜잭션으로 묶으면, 만약 두 번째 작업인 입금이 실패하면, 첫 번째 작업인 출금도 취소되어 원래 상태로 돌아가게 됨. 즉, 트랜잭션이 완전하게 수행되거나 전혀 수행되지 않아서, 부분적인 작업이 발생하지 않게 되는 것이다.
  • 트랜잭션을 사용할 때의 장점:
    1. 데이터 무결성: 작업 중 오류가 나면 모든 작업이 취소되기 때문에 데이터가 깨지지 않음.
    2. 동시성 문제 해결: 여러 작업이 동시에 진행되더라도, 각 트랜잭션이 독립적으로 실행되므로 상호 간섭을 방지할 수 있음.
    3. 안전성 보장: 데이터베이스가 일관된 상태를 유지하도록 보장하여 안전한 데이터 변경을 할 수 있음.
    4. 지속성 (Durability):
      • 트랜잭션이 완료되면, 모든 변경 사항은 영구적으로 데이터베이스에 반영되어야 해.
      • 시스템 장애가 발생해도, 트랜잭션 완료 후의 상태는 손실되지 않음.
    1.  
  • 트랜잭션을 사용한 예시 (SQL에서)
    START TRANSACTION;  -- 트랜잭션 시작
    
    UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A';  -- A 계좌에서 100원 출금
    UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B';  -- B 계좌에 100원 입금
    
    COMMIT;  -- 트랜잭션이 성공적으로 완료되었을 때, 변경 사항을 저장
    혹은, 만약 오류가 발생하면:
    ROLLBACK; -- 트랜잭션을 취소하고, 모든 변경 사항을 원래 상태로 돌림


  • 트랜잭션이 필요한 경우
    • 금융 거래: 송금, 결제 등에서 데이터의 일관성을 보장하기 위해 사용
    • 데이터베이스에 여러 변경을 동시에 적용해야 할 때: 여러 테이블에 데이터를 수정해야 할 때, 일부만 수정되면 문제가 되므로 트랜잭션을 사용

 

📌 데이터 정합성이 깨지는 경우

예를 들어, users 테이블과 orders 테이블이 있다고 해보자.

-- users 테이블
id | name  
------------
1  | Alice  
2  | Bob  
-- orders 테이블 (user_id가 users 테이블을 참조)
id | user_id | product
----------------------
1  | 1       | Laptop
2  | 3       | Phone  <-- ❌ users 테이블에 user_id=3이 없는데 주문이 들어감!

 

👉 user_id = 3인 사용자가 users 테이블에 없는데 주문이 들어갔다면?


     MySQL은 외래키(Foreign Key)를 통해 이런 잘못된 데이터를 막을 수 있다

     -> 외래키를 사용하면  orders.user_id는 반드시 users.id에 있는 값만 들어갈 수 있다.
     트랜잭션(Transaction)을 통해 여러 작업을 하나로 묶어서 처리할 수도 있다!

 

📌 반면, MongoDB(NoSQL)는 이런 데이터 정합성을 강하게 보장하지 않아서 orders 컬렉션에서 user_id: 3이 들어가도 오류가 나지 않는다

👉 데이터 정합성이 중요한 금융/은행 시스템에서는 MySQL 같은 SQL이 적합
👉 NoSQL은 빠른 데이터 저장이 필요하지만, 정합성이 덜 중요한 경우에 적합

 

NoSQL (MongoDB)

 

NoSQL (Not Only SQL)은 비관계형 데이터베이스로, 다양한 데이터 저장 방식을 지원.

  • MongoDB, Redis, Cassandra, Firebase 등이 대표적인 NoSQL 데이터베이스.
  • 데이터 하나하나 마다 같은 필드 값들을 가질 필요가 없어 자유로운 형태의 데이터 적재에 유리한 대신, 일관성이 부족할 수 있음.

 

특징:

✔ 데이터를 JSON 형태의 문서(document) 로 저장
스키마(고정된 구조) 없이 유연한 데이터 저장 가능
✔ 관계를 강제하지 않고, 중첩된 데이터 저장 가능 (Embed)
✔ 수평 확장(서버 추가)하기 쉬움
대량의 데이터를 빠르게 처리할 수 있음

 

📌 예제 (MongoDB 문서 구조)

{
  "_id": ObjectId("507f1f77bcf86cd799439011"),
  "name": "Alice",
  "age": 25,
  "email": "alice@example.com",
  "hobbies": ["reading", "coding"],
  "address": { "city": "Seoul", "country": "Korea" }
}

 

📌 데이터 삽입 (INSERT)

db.users.insertOne({
  name: "Alice",
  age: 25,
  email: "alice@example.com"
});

 

📌 데이터 조회 (FIND)

db.users.find({ age: { $gt: 20 } });

 

🔹 NoSQL을 쓰는 경우

✔ 관계형 데이터가 적거나, 하나의 문서(document) 안에 모든 정보를 포함할 수 있을 때
✔ 데이터를 빠르게 저장하고 읽어야 할 때 (대용량 데이터)
✔ 스키마를 유연하게 변경하고 싶을 때

 

👉 orders 컬렉션에 user 정보를 직접 포함해서 저장! (JOIN이 필요 없음)
👉 한 번에 데이터를 불러올 수 있어서 성능이 좋다

 

 NoSQL을 써야 하는 경우

  • SNS(게시글-댓글), 실시간 데이터 처리(채팅, 로그), IoT, 빅데이터
  • 관계가 복잡하지 않고, 한 문서에 데이터를 통째로 저장하는 게 효율적인 경우
  • 데이터 구조가 자주 바뀌는 경우
  • 수평 확장이 필요한 경우

확장성

🔹 MySQL은 수직 확장이 일반적 ( 한 대의 서버 성능을 높이는 것 (RAM, CPU 추가 등) )

MySQL 같은 관계형 데이터베이스는 JOIN, 트랜잭션 등이 필요하기 때문에 한 대의 강력한 서버에서 처리하는 경우가 많다.

✔ 한 개의 중앙 서버가 모든 데이터를 관리해야 해서 분산이 어려움!
✔ 여러 개의 서버에 나눠 저장하면 JOIN이 어렵고, 속도가 느려질 수 있음.

🔹 MongoDB는 수평 확장이 쉬움! ( 서버 여러 대를 추가해서 성능을 높이는 것 )

MongoDB는 데이터를 여러 서버에 나눠 저장(Sharding) 할 수 있다.

 JOIN이 필요 없고, 데이터가 독립적이라 여러 서버에 분산이 가능!
✔ 새로운 서버를 추가하는 것만으로 성능을 쉽게 높일 수 있음.

클라우드 환경에서 확장성이 뛰어남

 

📌 예제: Sharding(샤딩)

sh.enableSharding("myDatabase")  # 데이터베이스를 샤딩 가능하게 설정

 

👉 이렇게 하면 여러 서버에 데이터를 나눠서 저장할 수 있다!

 

 

SQL vs NoSQL 차이점 비교

  SQL (MySQL) NoSQL (MongoDB)
데이터 구조 테이블 (행과 열) 문서(JSON)
스키마(구조) 고정된 스키마 필요 유연한 구조
확장성 수직 확장 (서버 성능 업그레이드) 수평 확장 (서버 여러 개 추가)
관계(Relationships) 여러 테이블을 연결 (Join) 중첩된 데이터 저장 가능 (Embed)
속도 복잡한 쿼리 처리에 강함 빠른 데이터 읽기/쓰기 처리
적용 분야 금융, ERP, 전자상거래 등 빅데이터, 실시간 처리, 로그, SNS 등
데이터 정합성 강력한 정합성 보장 (Foreign Key, Transaction) 정합성이 약함 (빠른 성능 중심)

 

👉 SQL(MySQL) = 관계형 데이터, 데이터 정합성이 중요한 경우
👉 NoSQL(MongoDB) = 대량의 데이터를 빠르게 저장하고, 유연한 구조가 필요한 경우