
MySQL은 가장 널리 사용되고 있는 관계형 데이터베이스 관리 시스템(RDBMS, Relational DataBase Management System)이다.
MySQL 안에는 DBMS(데이터베이스 관리 시스템)이 있다.
DBMS 내부에는 여러 데이터베이스 객체(DB) 가 존재.
기본 포트는 3306.
SQL
문자열에 SQL을 직접 넣어서 실행하는 방식
EX)
SELECT name, price FROM menu;
실행 결과는 2차원 배열(레코드셋) 로 받아서 코드로 처리함.
ORM(Object Relational Mapping) 개념
SQL을 직접 쓰지 않고 클래스(객체) 로 DB 테이블을 표현.
EX)
class Menu:
name: str
price: int
이를 ORM이 SQL로 자동 변환해줌.
ORM 장점
SQL 지식이 부족해도 개발 가능 유지보수, 확장성 높음
ORM 한계
복잡한 JOIN / GROUP BY 등 고급 SQL은 어려움.
요즘 백엔드는 "FastAPI + React" 구조가 대세
ORM을 사용하는 시대이지만 SQL 기본기는 필요함
INSERT / SELECT / UPDATE / DELETE 기본 문법 꼭 알아야 함
특히 JOIN, PK/FK 이해는 필수
FastAPI는 JSON API + ORM으로 DB와 연결
Workbench에서 테이블 확인/조작 능력 필수
DB와 서버 연동 구조를 이해해야 진짜 개발자
프라이머리 키는 테이블에서 식별자 역할을 하는 컬럼이다.
특징 3가지
Unique(고유값) — 절대 중복될 수 없다.
Not Null(널 불가) — 값이 반드시 있어야 한다.
1개 또는 복합키 가능 — 여러 컬럼을 묶어서 PK로 만들 수 있음.
한국사례: PK로 주민번호를 쓰지 않는 이유
1990년 이전 출생자는 중복 주민번호 발생 사례 존재
현재는 정부 시스템이 생성하여 중복 거의 없음
PK는 변경 가능성이 없어야 하는데, 주민번호 변경 발생 가능 → 적절하지 않음
그래서 일반적으로 PK는?
id 컬럼
타입: INT
옵션: PRIMARY KEY, AUTO_INCREMENT, UNSIGNED
SQL은 크게 두 종류로 나뉜다.
CREATE
ALTER
DROP
테이블 구조나 스키마(메타 데이터)를 다룸
→ 예: CREATE TABLE ...
데이터(Data): 실제 저장되는 값 (이름, 가격 등)
메타데이터(Metadata): 데이터 구조 정보
예: 테이블의 컬럼 정보, 타입, 길이
스키마(Schema): 테이블 구조에 대한 전체 설계도
INSERT
SELECT
UPDATE
DELETE
실제 데이터 레코드를 다룸
CREATE DATABASE kakao3;
USE kakao3;
CREATE TABLE menu (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
price INT NOT NULL
);
VARCHAR(n) : 가변 길이 문자열
CHAR(n) : 고정 길이 문자열**
문자열은 반드시 작은따옴표 ' ' 사용
INSERT INTO menu VALUES (1, '라떼', 3000);
INSERT INTO menu (name, price)
VALUES ('라떼', 3000);
(autoincrement라면 id를 생략할 수 있음)
INSERT INTO menu SET
name='라떼', price=3000;
SELECT * FROM menu;
SELECT name, price FROM menu;
SELECT * FROM menu WHERE price >= 3500;
연산 의미
= 같다
!= 또는 <> 같지 않다
>, <, >=, <= 숫자 비교
AND 그리고
OR 또는
SELECT * FROM menu ORDER BY price ASC;
오름차순
SELECT * FROM menu ORDER BY price DESC;
내림차순
반드시 WHERE 절 있어야 함
안 쓰면 전부 삭제됨.
DELETE FROM menu WHERE id = 1;
UPDATE menu SET price = 6000 WHERE name = '유니짜장';
이미 생성된 테이블에 적용
ALTER TABLE menu
MODIFY id INT PRIMARY KEY AUTO_INCREMENT;
장점:id 값을 신경 안 써도 됨
중간 값이 삭제되어도 재사용하지 않음 (PK 안정성 ↑)
✔ CREATE (추가)
menu = Menu(name="우동", price=6000)
db.add(menu)
db.commit()
db.refresh(menu)
db.query(Menu).all()
db.query(Menu).filter(Menu.price > 3000).all()
db.query(Menu).order_by(Menu.price).all()
database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from dotenv import load_dotenv
import os
load_dotenv()
DATABASE_URL = "mysql+pymysql://root:00000000@localhost:3306/kakao3"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
models.py
from database import Base
from sqlalchemy import Column, Integer, String
class Menu(Base):
__tablename__ = "menu"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(50), nullable=False)
price = Column(Integer, nullable=False)
main.py
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from database import engine, Base, get_db
from models import Menu
Base.metadata.create_all(bind=engine)
app = FastAPI()
@app.get("/")
async def home():
return {"message": "Hello World"}
@app.get("/menu")
async def get_menu(db: Session = Depends(get_db)):
menu = db.query(Menu).all()
return menu
@app.post("/menu/{name}/{price}")
async def addMenu(name: str, price: int, db: Session = Depends(get_db)):
menu = Menu(name=name, price=price)
db.add(menu)
db.commit()
db.refresh(menu)
return menu

메뉴추가하면

http://127.0.0.1:8000/menu 들어갔을때 추가됨
1. database.py — 데이터베이스 연결 & 세션 관리
DATABASE_URL
MySQL에 접속하기 위한 URL.
mysql+pymysql://user:password@host:port/dbname 형식이며 여기서는 kakao3 데이터베이스를 사용한다.
engine
SQLAlchemy가 실제 DB와 통신하기 위한 핵심 객체.
연결 풀 관리
SQL 실행
ORM과 DB를 연결하는 다리 역할
SessionLocal
트랜잭션 단위 작업을 위한 DB 세션 생성기.
autocommit=False 덕분에 원하는 시점에 db.commit()을 명시적으로 호출해야 한다.
이 설정은 의도치 않은 DB 변경을 막기 때문에 프로덕션 기본 설정이다.
Base = declarative_base()
모든 모델 클래스(Menu 등)의 부모 클래스.
모델을 선언하려면 이 Base를 반드시 상속해야 SQLAlchemy가 테이블로 인식한다.
get_db() — FastAPI 의존성 주입(DI)용
FastAPI에서 DB 세션을 관리하는 표준 패턴.
FastAPI는 이 함수를 호출해
요청 시작 → 세션 열고
요청 끝 → 세션 자동 종료
하는 과정을 깔끔하게 처리할 수 있다.
2.models.py
Menu 클래스 = menu 테이블
ORM에서는 클래스 = 테이블
속성 = 컬럼
컬럼 설명
컬럼 타입 설명
id Integer, PK 기본키, 자동 증가
name String(50) 메뉴 이름
price Integer 가격
SQLAlchemy는 이 클래스를 기반으로 실제 MySQL 테이블 구조를 자동으로 생성한다.
3. main.py
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from database import engine, Base, get_db
from models import Menu
Base.metadata.create_all(bind=engine)
app = FastAPI()
Base.metadata.create_all(bind=engine)
모델(Menu) 정의를 바탕으로 DB에 테이블을 자동 생성한다.
3-1. 기본 라우트
@app.get("/")
async def home():
return {"message": "Hello World"}
잘됐는지 확인해볼려고 만든 기본 엔드포인트.
3-2. 메뉴 전체 조회 API
@app.get("/menu")
async def get_menu(db: Session = Depends(get_db)):
menu = db.query(Menu).all()
return menu
db: Session = Depends(get_db)
→ 요청마다 새로운 DB 세션을 자동으로 주입받는다.
db.query(Menu).all()
SELECT * FROM menu 실행
ORM 객체를 JSON 형태로 반환
FastAPI가 자동으로 ORM 객체를 dict로 바꿔준다.
3-3. 메뉴 추가 API
@app.post("/menu/{name}/{price}")
async def addMenu(name: str, price: int, db: Session = Depends(get_db)):
menu = Menu(name=name, price=price)
db.add(menu)
db.commit()
db.refresh(menu)
return menu