MySQL JSON 지원과 MongoDB와의 비교

Lee Jin Hyuk·2025년 9월 21일

1. MySQL JSON 지원 역사

MySQL의 JSON 지원은 MySQL 5.7.8 버전부터 시작되었다. 이는 2015년 10월 21일에 정식 출시된 MySQL 5.7의 주요 기능 중 하나이다.

-- MySQL 5.7.8 (2015년) - JSON 데이터 타입 최초 도입
-- MySQL 8.0 (2018년) - JSON 기능 대폭 향상, JSON_TABLE() 함수 추가
-- MySQL 8.0.19 이후 - 성능 최적화 및 추가 기능

MySQL JSON 지원의 핵심 특징:

  • RFC 8259 표준을 따르는 네이티브 JSON 데이터 타입
  • 텍스트 저장 대비 자동 유효성 검증
  • 최적화된 바이너리 저장 형식
  • 빠른 요소 접근을 위한 내부 인덱싱 구조

2. MySQL JSON 저장 방식

-- 테이블 생성 시 JSON 컬럼 정의
CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    details JSON
);

내부 저장 메커니즘

MySQL은 JSON 데이터를 텍스트로 저장하지 않고 최적화된 바이너리 형식으로 변환하여 저장한다.

핵심 저장 특징:

  • JSON 문서는 내부적으로 바이너리 형식으로 변환
  • 키-값 쌍의 빠른 접근을 위한 내부 인덱스 구조 생성
  • 배열 요소와 객체 속성에 대한 직접 접근 가능
  • 전체 문서를 파싱하지 않고도 특정 요소만 추출 가능

MySQL에서 JSON을 어떻게 저장하는지 자세하게 알고 싶다면 아래 글을 참고하면 좋을 것 같다.

참고: - MySQL Json 데이터 타입의 저장 구조와 성능 비교

데이터 삽입 예시

-- JSON 데이터 삽입
INSERT INTO products (name, details) VALUES 
('Laptop', '{"price": 1200, "brand": "Dell", "specs": {"ram": "16GB", "storage": "512GB SSD"}}'),
('Phone', '{"price": 800, "brand": "Samsung", "features": ["5G", "Wireless Charging"]}');

-- JSON 함수를 사용한 삽입
INSERT INTO products (name, details) VALUES 
('Tablet', JSON_OBJECT('price', 600, 'brand', 'Apple', 'color', 'Space Gray'));

저장 공간 확인

-- JSON 문서의 저장 공간 확인
SELECT 
    name,
    JSON_STORAGE_SIZE(details) AS storage_bytes,
    JSON_STORAGE_FREE(details) AS free_bytes
FROM products;

3. MySQL JSON 조회

JSON_EXTRACT() 활용

-- 기본 문법
SELECT JSON_EXTRACT(details, '$.price') AS price FROM products;

-- 단축 문법 (-> 연산자)
SELECT details->'$.price' AS price FROM products;

-- 따옴표 제거 (->> 연산자)
SELECT details->>'$.brand' AS brand FROM products;

중첩된 객체 조회

저장되어있는 JSON 구조

{
  "price": 1200,
  "brand": "Dell",
  "specs": {           
    "ram": "16GB",    
    "storage": "512GB SSD"  
  }
}
-- 중첩된 JSON 객체 조회
SELECT 
    name,
    details->'$.specs.ram' AS ram,
    details->'$.specs.storage' AS storage
FROM products 
WHERE name = 'Laptop';

배열 조회

-- 배열의 첫 번째 요소
SELECT details->'$.features[0]' AS first_feature FROM products;

-- 배열의 모든 요소
SELECT JSON_EXTRACT(details, '$.features[*]') AS all_features FROM products;

조건부 검색

-- 특정 값으로 필터링
SELECT * FROM products 
WHERE details->'$.price' > 700;

-- JSON 키 존재 확인
SELECT * FROM products 
WHERE JSON_CONTAINS_PATH(details, 'one', '$.warranty');

-- 배열에서 특정 값 검색
SELECT * FROM products 
WHERE JSON_SEARCH(details, 'one', '5G') IS NOT NULL;

4. MySQL JSON 수정

MySQL 8.0 버전 이전에는 다음과 같이 수정

-- 새로운 키-값 추가
UPDATE products 
SET details = JSON_SET(details, '$.warranty', '2 years')
WHERE name = 'Laptop';

-- 기존 값 변경
UPDATE products 
SET details = JSON_REPLACE(details, '$.price', 1100)
WHERE name = 'Laptop';

-- 키 제거
UPDATE products 
SET details = JSON_REMOVE(details, '$.color')
WHERE name = 'Tablet';

🚀 JSON 부분 업데이트 최적화 (MySQL 8.0+)

참고로 MySQL 8.0부터는 JSON 부분 업데이트(Partial Update) 최적화가 도입되었다. 이는 큰 JSON 문서에서 작은 부분만 수정할 때 성능을 대폭 향상 시키는 이점이 있다.

기존 방식 (MySQL 5.7):

  • JSON 문서를 수정할 때마다 전체 문서를 다시 작성
  • 10MB 문서에서 1바이트만 바꿔도 10MB 전체를 새로 씀

새로운 방식 (MySQL 8.0+):

  • 변경된 부분만 디스크에 기록
  • 바이너리 로그에도 패치 정보만 저장 (조건 설정 시)
-- 부분 업데이트 조건을 만족하는 예시
-- ✅ 동일한 컬럼에서 읽고 쓰기
UPDATE products 
SET details = JSON_SET(details, '$.last_updated', NOW())
WHERE id = 1;

-- ✅ 여러 JSON 함수 조합 가능
UPDATE products 
SET details = JSON_SET(
    JSON_REPLACE(details, '$.price', 999),
    '$.updated_at', NOW()
)
WHERE id = 1;

-- ❌ 부분 업데이트 불가능한 경우 (다른 컬럼)
UPDATE products 
SET details = JSON_SET(other_column, '$.price', 999)  -- 다른 컬럼 참조
WHERE id = 1;

5. MySQL JSON 인덱싱

JSON 컬럼에 직접 인덱스를 생성할 수는 없지만, 가상 컬럼을 활용하여 인덱싱할 수 있다.

-- 가상 컬럼 생성 및 인덱싱
ALTER TABLE products 
ADD COLUMN price_virtual DECIMAL(10,2) 
GENERATED ALWAYS AS (details->'$.price') STORED;

CREATE INDEX idx_price ON products(price_virtual);

-- 인덱스를 활용한 빠른 검색
SELECT * FROM products WHERE price_virtual > 700;

6. MySQL 8.0 + 추가된 기능

위에서 잠깐 언급했던 부분 업데이트도 눈에 띄는 변화라고 생각하는데 가장 눈에 들어왔던것은 JSON_TABLE() 이다. 이는 JSON을 관계형 테이블로 변환시켜주는 함수이다.

-- JSON_TABLE(): JSON을 관계형 테이블로 변환
SELECT j.* 
FROM products,
JSON_TABLE(details, '$.features[*]' 
    COLUMNS (
        feature VARCHAR(50) PATH '$'
    )
) AS j
WHERE name = 'Phone';

7. MySQL vs MongoDB

MySQL JSON에 대한 여러 정보를 찾아보던 중 기존 JSON을 저장하던 대표적인 MongoDB를 그럼 이제 쓰지 않아도 되는건지 어떤 차이가 있는건지 궁금해서 찾아봣다.

MySQL JSON의 강점:

  • 관계형 데이터와 JSON의 조합 시 우수한 성능
  • 복잡한 JOIN 연산에서 뛰어난 최적화
  • ACID 트랜잭션 완벽 지원
  • 성숙한 쿼리 옵티마이저

MongoDB의 강점:

  • 대용량 비구조화 데이터 처리에 최적화
  • 수평 확장(Sharding) 기본 지원
  • 문서 전체 조회 시 빠른 성능
  • 스키마 변경에 대한 높은 유연성

그럼 언제 어떤 것을 사용하면 좋을까?

MySQL JSON 추천 상황

이런 경우에 MySQL JSON을 선택하면 좋을 것 같다.

  1. 기존 관계형 환경에서 일부 유연성이 필요한 경우
  2. ACID 트랜잭션이 중요한 금융, 전자상거래 시스템
  3. 복잡한 관계형 쿼리와 JSON을 함께 사용해야 하는 경우
  4. 기존 MySQL 인프라를 유지하면서 JSON 기능 추가

MongoDB 추천 상황

이런 경우에 MongoDB를 선택하면 좋을 것 같다.

  1. 스키마가 자주 변경되는 빠른 개발 환경
  2. 대용량 비구조화 데이터 (로그, IoT, 소셜 미디어)
  3. 수평 확장이 필수인 대규모 서비스
  4. 실시간 분석이나 콘텐츠 관리 시스템

참고자료

0개의 댓글