> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL과 PostgreSQL: 무엇을 써야 할까?

> MySQL과 PostgreSQL의 솔직한 비교: 관리형 서비스, 성능, 타입 지원, 확장성, 그리고 각각이 올바른 선택인 경우입니다.

> [card] [VillageSQL is a drop-in replacement for MySQL with extensions.](https://villagesql.com/docs/en/8.4/stable/install-server.md)
>
> All examples on this page work on VillageSQL. Install Now →

MySQL과 PostgreSQL은 둘 다 거대한 규모의 애플리케이션을 떠받치는 성숙한 오픈 소스 데이터베이스입니다. 어느 쪽도 장난감이 아니고, 어느 쪽도 명백히 더 낫지 않습니다. 둘이 가진 것은 서로 다른 기본값, 서로 다른 커뮤니티, 그리고 트레이드오프가 여러분에게 유리하게 떨어지는 서로 다른 지점입니다. 이 가이드는 여러분이 프로젝트에 맞는 결정을 내릴 수 있도록 그 트레이드오프를 솔직하게 짚어 갑니다.

## MySQL이 유리한 경향이 있는 부분

**운영의 단순함.** MySQL은 PostgreSQL보다 더 깊은 관리형 서비스 생태계를 가지고 있습니다. Amazon Aurora MySQL, Google Cloud SQL for MySQL, Amazon RDS for MySQL은 모두 수년간의 프로덕션 검증을 거친 일급 제품입니다. 운영 복잡성을 떠안지 않고 데이터베이스를 실행하고 싶다면, MySQL의 관리형 선택지는 훌륭합니다.

**기본 키 접근 속도.** InnoDB는 클러스터드 인덱스를 사용하는데, 이는 행 데이터가 기본 키 인덱스 자체 안에 존재한다는 뜻입니다. 기본 키 조회는 단일 I/O 작업으로 데이터를 가져옵니다. 힙 페치가 없습니다. 주로 키 기반 읽기인 워크로드에서는 이것이 의미 있는 이점입니다.

**극단적인 규모의 수평 확장.** Vitess는 MySQL 위에 만들어졌고, YouTube, GitHub, Shopify의 MySQL 배포 뒤에 있는 샤딩 계층입니다. Facebook은 어떤 종류의 데이터베이스도 거의 따라잡지 못한 규모로 MySQL을 운영했습니다. 수평 샤딩이 필요할 것으로 예상한다면, MySQL 생태계에는 잘 닦인 길이 있습니다.

**JSON.** MySQL 8.4의 JSON 지원은 탄탄합니다. `JSON_TABLE()`을 쓰면 JSON 배열과 객체를 관계형 데이터처럼 다룰 수 있습니다. JSONPath 연산자는 WHERE 절에서 자연스럽게 동작합니다. JSON 필드에 생성 열을 만들고 인덱스를 걸 수 있습니다. 예전 MySQL의 JSON 지원이 약했기 때문에 사람들은 여전히 이것을 과소평가합니다. 더 이상 약하지 않습니다.

**더 엄격한 기본값.** MySQL 8.4는 기본적으로 strict 모드를 활성화합니다. 조용한 데이터 잘림, 0 날짜 삽입, 0으로 나누기 오류는 데이터가 조용히 망가지는 대신 오류로 잡힙니다. 8.0 이전의 데이터 무결성 평판을 근거로 MySQL을 평가하고 있다면, 그 우려는 대부분 해소되었습니다.

## PostgreSQL이 유리한 경향이 있는 부분

**확장성.** 이것이 PostgreSQL의 가장 뚜렷한 구조적 이점입니다. pgvector, PostGIS, pg\_partman, pg\_trgm 등 데이터베이스 수준에서 타입, 인덱스 방식, 함수를 추가하는 커뮤니티 확장이 수백 개 있습니다. `CREATE EXTENSION`은 PostgreSQL에서 일급 개념이고, 그 주변 생태계는 깊습니다.

**더 풍부한 네이티브 타입.** 배열, 복합 타입, 범위 타입, hstore 등 PostgreSQL은 데이터를 모델링하는 더 넓은 어휘를 가지고 있습니다. 애플리케이션이 자연스럽게 배열이나 범위를 다룬다면, PostgreSQL은 모든 것을 자식 테이블로 정규화하거나 JSON으로 인코딩하는 대신 데이터베이스 안에 머무르게 해 줍니다.

**표준 준수.** PostgreSQL은 엣지 케이스에서 ANSI SQL을 더 가깝게 따릅니다. `RETURNING` 절, `LISTEN`/`NOTIFY`, 테이블 상속의 완전한 지원은 MySQL에는 없거나 다르게 동작하는 기능의 예입니다. 표준 준수가 프로젝트의 엄격한 요구 사항이라면, PostgreSQL이 더 안전한 선택입니다.

**부분 인덱스.** WHERE 절에 일치하는 행만 인덱싱할 수 있습니다. 행의 큰 비율이 거의 조회하지 않는 상태(예: 보관된 주문이나 소프트 삭제된 레코드)에 있을 때 중요합니다. MySQL에는 이것이 기본으로 없습니다.

**구체화 뷰.** PostgreSQL에는 필요할 때 새로 고칠 수 있는 네이티브 구체화 뷰가 있습니다. MySQL에는 없습니다. 우회책은 테이블, 저장 프로시저, 애플리케이션 수준 오케스트레이션의 조합입니다.

**전문 검색.** PostgreSQL의 `tsvector`/`tsquery` 시스템은 MySQL의 `FULLTEXT` 인덱스보다 더 유능합니다. 어간 추출, 순위 매기기, 구문 검색은 모두 PostgreSQL 쪽이 더 표현력이 높습니다.

## 기능 동등성

예전 평판 때문에 MySQL을 피해 왔다면, 그 격차 중 일부는 이미 좁혀졌습니다.

| 기능 | MySQL 8.4/9.7 | 비고 |
| :- | :- | :- |
| 윈도우 함수 | 예 | 완전 지원 |
| CTE(WITH 절) | 예 | 재귀 CTE 포함 |
| JSON | 예 | JSON\_TABLE, JSONPath, 생성 열 |
| 생성 열 | 예 | 저장형과 가상형 모두 |
| CHECK 제약 조건 | 예 | 8.0.16부터 강제 |
| 보이지 않는 인덱스 | 예 | 삭제 전에 인덱스 제거를 안전하게 시험 |
| 역할 기반 접근 제어 | 예 | |
| EXPLAIN ANALYZE | 예 | |

보이지 않는 인덱스는 특별히 언급할 가치가 있습니다. MySQL에만 있는 기능입니다. 인덱스를 보이지 않게 표시해 옵티마이저가 무시하게 하고, 쿼리 계획이 나빠지지 않는지 확인한 뒤, 안전하게 삭제할 수 있습니다. PostgreSQL에는 동등한 기능이 없습니다.

## PostgreSQL 대비 MySQL에 여전히 있는 격차

애플리케이션이 다음 중 하나라도 의존한다면, 무엇이 없는지 솔직하게 아는 것이 중요합니다:

* **배열 열 타입이 없습니다.** 자식 테이블로 정규화하거나 JSON으로 인코딩합니다.
* **부분 인덱스가 없습니다.** 흔한 우회책은 식을 가진 생성 열을 만들고 그 열에 인덱스를 거는 것입니다. 동작하지만 덜 편리합니다.
* **네이티브 구체화 뷰가 없습니다.** 테이블과 예약된 프로시저로 직접 만듭니다.
* **LISTEN/NOTIFY가 없습니다.** 데이터베이스 수준의 pub/sub이 필요하면 MySQL 바깥의 계층이 필요합니다.
* **테이블 상속이 없습니다.** PostgreSQL의 테이블 상속 모델에는 MySQL 대응물이 없습니다.
* **훨씬 작은 확장 생태계.** MySQL의 플러그인과 UDF 시스템은 존재하지만, 그 주변 커뮤니티는 PostgreSQL의 확장 생태계에 비해 얇습니다.

마지막 격차가 대부분의 개발자가 실제로 매일 체감하는 것입니다.

## VillageSQL이 격차를 메우는 부분

확장 생태계는 MySQL과 PostgreSQL 사이의 가장 구체적인 구조적 차이이며, VillageSQL이 직접 다루는 것이 바로 이것입니다. 벡터 타입, 네트워크 주소 타입(INET, CIDR, MACADDR), 암호화 함수, UUID v1\~v7, HTTP 클라이언트 함수를 PostgreSQL에서 `CREATE EXTENSION`을 실행하는 것과 같은 방식으로 설치할 수 있습니다. 서버를 수정하지 않고 그대로 들어가는 설치 가능한 번들입니다.

확장은 또한 사용자 정의 저장, 비교, 연산자 의미를 가진 새로운 열 타입을 정의할 수 있습니다. 이는 PostGIS와 pgvector가 PostgreSQL에서 사용하는 것과 같은 기능을 MySQL의 스토리지 엔진에 적용한 것입니다.

VillageSQL은 내부적으로 여전히 MySQL입니다. 복제, InnoDB 스토리지 엔진, 와이어 프로토콜, 도구 생태계 모두 그대로 유지됩니다. MySQL용으로 만든 애플리케이션은 VillageSQL과 함께 동작합니다. 바뀌는 것은 확장성 모델입니다.

## MySQL을 선택해야 할 때

* 팀이 이미 MySQL을 알고 있고 전환할 설득력 있는 이유가 없다.
* 관리형 서비스에 배포하고 Aurora, Cloud SQL, 또는 RDS를 원한다.
* 대규모에서 수평 샤딩이 필요할 것으로 예상하고 Vitess 생태계를 원한다.
* 워크로드가 읽기 중심이고 기본 키 접근 패턴이 지배적이다.

## PostgreSQL을 선택해야 할 때

* PostGIS나 pgvector가 필요하고 실행 가능한 대안이 없다.
* 애플리케이션이 정규화하기 어색한 방식으로 배열, 범위 타입, 복합 타입에 의존한다.
* 표준 준수가 여러분의 맥락에서 엄격한 요구 사항이다.
* 팀이 PostgreSQL을 잘 알고 있고 반대 방향으로 미는 마이그레이션 압력이 없다.

## 결정은 되돌릴 수 있습니다

오늘 MySQL과 PostgreSQL 사이에서 선택하는 개발자는 영구적인 약속을 하는 것이 아닙니다. 두 데이터베이스 모두 대부분의 애플리케이션을 수백만 사용자까지 무리 없이 감당할 수 있습니다. 팀이 아는 쪽, 또는 클라우드 제공업체가 가장 운영하기 쉽게 만들어 주는 쪽을 고르세요. MySQL을 택했다가 나중에 더 풍부한 확장 생태계를 바라게 된다면, 그것이 바로 [VillageSQL](https://villagesql.com/install)이 메우기 위해 만들어진 격차입니다: MySQL의 드롭인 대체품 위에서 동작하는 PostgreSQL 스타일의 확장입니다.

## 함께 보기

* [PostgreSQL에서 MySQL로 마이그레이션하기](https://villagesql.com/docs/ko/guides/postgres-to-mysql.md) — PostgreSQL 개념과 구문을 MySQL 대응물로 매핑하기
* [MySQL 인덱스의 동작 방식](https://villagesql.com/docs/ko/guides/mysql-indexes.md) — InnoDB의 클러스터드 인덱스 이해하기, 그리고 보조 인덱스를 추가해야 할 때
* [InnoDB가 데이터를 저장하는 방식](https://villagesql.com/docs/ko/guides/innodb-storage.md) — 페이지 구조, 행 형식, 디스크에서 일어나는 일
* [MySQL 데이터 타입 선택하기](https://villagesql.com/docs/ko/guides/choosing-data-types.md) — 선택한 뒤 올바른 MySQL 타입 고르기


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.