VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
어디서나 중요한 설정
프레임워크가 무엇이든 세 가지는 반드시 참이어야 합니다:- 연결이
utf8mb4를 사용합니다. 그렇지 않으면 이모지가 전송 중에 깨집니다. utf8mb4와 이모지를 참고하세요. - Strict SQL 모드가 켜져 있습니다(MySQL 8.x의 기본값). 그래서 잘못된 데이터는 조용히 잘리는 대신 오류를 냅니다.
- 풀 크기는 의도적으로 정합니다. 모든 프레임워크는 프로세스마다 풀을 엽니다. 숫자를 고르기 전에 프로세스 수를 곱하세요. 연결 풀링을 참고하세요.
Django
- Django 문서가 권장하는, 유지 관리되는 C 드라이버인
mysqlclient를 사용하세요. - Django는 일부 제약 조건을 Python에서 흉내 냅니다. 실제 데이터베이스 제약 조건도 추가하세요(
unique=True는 실제 고유 인덱스가 되지만, 검사 제약 조건은Meta에CheckConstraint가 필요합니다). select_related()(JOIN)와prefetch_related()(두 번째 쿼리)가 N+1 도구입니다. 언제 쓰는지는 아래를 참고하세요.
Rails
database.yml의encoding: utf8mb4는 연결 문자 집합과rails db:create의 기본값을 모두 설정합니다.- ActiveRecord 유효성 검사(
validates_uniqueness_of)는 동시성 아래에서 경쟁 상태가 됩니다. 모든 고유성 검사를 실제 고유 인덱스로 뒷받침하고, 1062 중복 키 오류가 마지막 방어선이 되게 하세요. includes가 N+1 도구입니다.strict_loading모드는 지연 로딩을 오류로 바꾸어 N+1이 배포되는 대신 개발 중에 실패하게 합니다.- Rails 8.1은 이전 버전이
pool을 생성하던 자리에database.yml에max_connections를 생성합니다.pool:키는max_connections가 읽는 대체값으로 여전히 조용히 동작합니다. 둘을 서로 다른 값으로 설정하면 부팅 시 예외가 발생합니다. Rails 8이 더 이상 MySQL을 기본값으로 하지 않아 필요한--database=mysql플래그를 포함한 전체 앱은 Rails 8로 MySQL 사용하기를 참고하세요.
Prisma
- Prisma는 기본적으로 utf8mb4를 사용합니다. 주의할 설정은 URL의
connection_limit이며, 기본값이 낮습니다. prisma migrate는 스키마 드리프트에서 DDL을 생성합니다. 직접 작성한 마이그레이션과 똑같이, 프로덕션에 적용하기 전에 생성된 SQL을 읽으세요. 스키마 마이그레이션을 참고하세요.- 관계 쿼리는
include를 사용합니다. 결과를 반복하며 관계를 하나씩 접근할 때 N+1 형태가 나타납니다. - Prisma 7은 위의 연결 URL을
schema.prisma밖의 별도 설정 파일로 옮기고, 연결에 드라이버 어댑터를 요구합니다. 전체 Prisma 7 앱은 Next.js와 Prisma로 MySQL 사용하기를 참고하세요.
N+1 문제, 한 번에 정리
보편적인 ORM 성능 버그: 주문 100개를 로드한 뒤 각 주문의 고객을 지연 로드하면 ORM은 쿼리 101개를 실행합니다. 해결책은 모든 프레임워크에서 같은 아이디어입니다. 필요한 관계를 미리 선언해 ORM이 한두 개의 쿼리로 가져오게 하세요(select_related / includes / include). 탐지 도구도 보편적입니다: 개발 환경에서 쿼리 로깅을 켜고 ORM이 실제로 보내는 것을 읽거나, 프로덕션에서 슬로 쿼리 로그를 지켜보세요.
SQL로 내려가야 할 때
ORM은 CRUD에서 제값을 하고 분석에서는 그렇지 못합니다. 윈도우 함수, CTE, 대량 업서트, 다중 테이블 보고 쿼리는 그것을 표현하려 애쓰는 쿼리 빌더 체인보다 SQL에서 더 명확합니다. 모든 ORM에는 탈출구가 있습니다(Django의raw(), Rails의 find_by_sql, Prisma의 $queryRaw). 그럴 가치가 있는 5퍼센트의 쿼리에 그것을 쓰는 것은 패배가 아니라 좋은 엔지니어링입니다. 이것은 또한 VillageSQL 확장 함수가 ORM 애플리케이션에 도달하는 방법이기도 합니다: SELECT UUID_V7()이나 ai_prompt(...)는 이 탈출구 중 어느 것을 통해서든 동작합니다. ORM은 SQL을 그대로 통과시킬 뿐이기 때문입니다.
함께 보기
- Next.js와 Prisma로 MySQL 사용하기 — 설정만이 아닌, Prisma 7 위의 전체 앱
- Next.js와 Drizzle로 MySQL 사용하기 — 위에서 다루지 않은, 더 가볍고 SQL 우선인 대안 Drizzle 위의 전체 앱
- Next.js로 MySQL 사용하기 — ORM 없이 연결 설정과 쿼리 패턴
- Rails 8로 MySQL 사용하기 — Rails 8이 MySQL을 고르기 위해 필요한 스캐폴드 플래그를 포함한 전체 앱
- Laravel 12로 MySQL 사용하기 — 위에서 다루지 않은, Laravel의 Eloquent ORM 위의 전체 앱
- Go와 sqlc로 MySQL 사용하기 — 런타임 ORM 대신 생성된 타입 안전 쿼리
- 연결 풀링 — 프로세스에 걸친 풀 크기 정하기
- utf8mb4와 이모지 — 위의 모든 설정이 지정하는 문자 집합 설정
- 슬로 쿼리 로그 — ORM이 생성하는 것 잡아내기
- 스키마 마이그레이션 — ORM이 생성한 DDL을 안전하게 적용하기