1언제 필요해?
- 사용자/주문/상품 같은 정형 데이터를 저장할 때
- 데이터 간 관계가 중요할 때 (사용자 - 주문 - 상품)
- 복잡한 조회가 필요할 때 (JOIN, GROUP BY, 집계)
- 트랜잭션 보장이 필요할 때 (결제, 재고 관리)
2주요 서비스
PostgreSQL
무료, 가장 인기오픈소스. JSON, 전문검색, 확장 기능이 풍부합니다. 대부분의 신규 프로젝트에 추천됩니다.
MySQL
무료, 레거시 많음오랜 역사와 거대한 생태계. WordPress, 기존 시스템에서 많이 사용됩니다.
Supabase
PostgreSQL 관리형PostgreSQL 기반의 BaaS. 인증, 스토리지, 실시간 기능을 함께 제공합니다.
PlanetScale
MySQL 관리형MySQL 호환. 브랜칭으로 스키마 변경을 안전하게 관리합니다.
3비용
- PostgreSQL / MySQL - 자체 설치 시 무료 (서버 비용은 별도)
- Supabase - 무료 티어 500MB 스토리지, 월 50K API 요청
- PlanetScale - 무료 티어 5GB 스토리지, 월 1B 행 읽기
4연결 예제
FastAPI + asyncpg (Python)
app/database.py
# app/database.py
import asyncpg
from contextlib import asynccontextmanager
DATABASE_URL = "postgresql://user:password@localhost:5432/mydb"
pool = None
async def init_db():
global pool
pool = await asyncpg.create_pool(DATABASE_URL)
async def close_db():
await pool.close()
async def get_connection():
async with pool.acquire() as conn:
yield connapp/main.py
# app/main.py
from fastapi import FastAPI, Depends
from app.database import init_db, close_db, get_connection
app = FastAPI()
@app.on_event("startup")
async def startup():
await init_db()
@app.on_event("shutdown")
async def shutdown():
await close_db()
@app.get("/users")
async def get_users():
async with pool.acquire() as conn:
rows = await conn.fetch("SELECT id, name, email FROM users")
return [dict(r) for r in rows]
@app.post("/users")
async def create_user(name: str, email: str):
async with pool.acquire() as conn:
row = await conn.fetchrow(
"INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
name, email
)
return dict(row)Hono + postgres.js (TypeScript)
src/db.ts
// src/db.ts
import postgres from 'postgres';
const sql = postgres('postgresql://user:password@localhost:5432/mydb');
export default sql;src/index.ts
// src/index.ts
import { Hono } from 'hono';
import sql from './db';
const app = new Hono();
app.get('/users', async (c) => {
const users = await sql`SELECT id, name, email FROM users`;
return c.json(users);
});
app.post('/users', async (c) => {
const { name, email } = await c.req.json();
const [user] = await sql`
INSERT INTO users (name, email)
VALUES (${name}, ${email})
RETURNING *
`;
return c.json(user, 201);
});
export default app;ORM을 사용하면 더 편합니다
실제 프로젝트에서는 SQL을 직접 쓰기보다 SQLAlchemy(Python)나 Drizzle ORM(TypeScript)을 사용하는 것이 일반적입니다.