02. SQL & ORM: AI 통역사 고용하기
"데이터베이스는 한국어(Python)를 모릅니다. SQL(Structured Query Language)이라는 외국어만 할 줄 압니다. 우리는 SQL을 배우는 대신, 유능한 통역사(ORM: Object Relational Mapping)를 고용할 것입니다."
1. The Barrier: 언어의 장벽 (SQL)
여러분이 "철수 정보 좀 찾아줘"라고 파이썬으로 말해도, 데이터베이스는 알아듣지 못합니다. DB의 모국어는 SQL이기 때문입니다.
- 개발자의 고통: 파이썬 코드를 짜다가 갑자기 SQL(
SELECT * FROM...)을 섞어 쓰면 문법이 헷갈리고 오타가 나기 쉽습니다. - SQL의 생김새: 마치 기계에게 고함을 치는 것처럼 보입니다.
2. The Solution: ORM (통역사)
그래서 천재적인 개발자들이 ORM이라는 기술을 만들었습니다. 이것은 "파이썬 코드를 짜면, 알아서 SQL로 번역해주는 통역사"입니다. 우리는 그 중에서도 SQLAlchemy라는 아주 유능한 통역사를 고용할 것입니다.
이 통역사가 일하는 방식과 도구들을 먼저 알아볼까요?
sqlalchemy(통역사): 파이썬과 DB 사이를 중재하는 라이브러리 본체입니다.Base(신분증): "이 클래스는 단순한 파이썬 객체가 아니라, DB 테이블이야!"라고 표시해줍니다.Column(단어장): 이게 숫자(Integer)인지 문자(String)인지 통역사에게 알려줍니다.
이 도구들을 쓰면 대화가 이렇게 바뀝니다.
- Python:
Student.id > 20 - ORM (SQLAlchemy): (번역 중...)
SELECT * FROM student WHERE id > 20; - Database: (데이터 주섬주섬) "여기 있습니다."
🔄 전체 흐름: Frontend → ORM API → Database
아래 시퀀스 다이어그램은 사용자가 브라우저에서 요청을 보냈을 때, 데이터가 어떻게 흘러가는지를 보여줍니다.
sequenceDiagram
participant Browser as 🖥️ Frontend (Browser)
participant API as ⚙️ FastAPI (ORM)
participant DB as 🗄️ Database
Note over Browser, DB: 📖 Read (조회)
Browser->>API: GET /students
API->>DB: SELECT * FROM student
DB-->>API: [학생 데이터 목록]
API-->>Browser: JSON 응답
Note over Browser, DB: ✏️ Create (생성)
Browser->>API: POST /students (이름, 이메일)
API->>DB: INSERT INTO student ...
DB-->>API: OK (생성 완료)
API-->>Browser: 201 Created
Note over Browser, DB: 🔄 Update (수정)
Browser->>API: PUT /students/1 (새 이메일)
API->>DB: UPDATE student SET email=... WHERE id=1
DB-->>API: OK (수정 완료)
API-->>Browser: 200 OK
Note over Browser, DB: 🗑️ Delete (삭제)
Browser->>API: DELETE /students/1
API->>DB: DELETE FROM student WHERE id=1
DB-->>API: OK (삭제 완료)
API-->>Browser: 204 No Content
💡 핵심 포인트
개발자는 Python(FastAPI) 코드만 작성하면 됩니다. ORM(SQLAlchemy)이 중간에서 자동으로 SQL을 생성하여 DB와 대화합니다.
3. Setup: 파이썬으로 엑셀 표 만들기 (Model 정의)
앞 장에서 배운 Class Diagram이 여기서 빛을 발합니다.
우리가 설계한 student 테이블을 파이썬 클래스로 옮겨보겠습니다.
from sqlalchemy import Column, Integer, String
from database import Base
# 1. 파이썬 클래스 정의 (Class Diagram 구현)
class Student(Base):
__tablename__ = "student" # DB 테이블 이름 (소문자)
id = Column(Integer, primary_key=True, index=True) # 학번 (PK)
name = Column(String) # 이름
email = Column(String) # 이메일
결과
이 코드를 실행하면 DB 안에 id, name, email 칸이 있는 student 테이블이 연결됩니다.
4. 쿼리의 핵심 기술: 데이터를 지휘하기 (Querying)
"데이터베이스에 100만 명의 학생이 있어도 걱정 마세요. 우리에겐 원하는 학생만 쏙쏙 뽑아내는 쿼리(Query) 기술이 있습니다."
Step 1. CRUD: 데이터 4대 조작법
데이터베이스가 하는 일은 결국 딱 4가지입니다. 이를 CRUD라고 부르며, 수강신청 시스템의 기본입니다.
| 구분 | 영어 (CRUD) | 의미 | ORM 코드 (SQLAlchemy) | 비유 (수강신청) |
|---|---|---|---|---|
| C | Create | 생성 | db.add(student) |
신입생 입학 |
| R | Read | 조회 | db.query(Student).all() |
학생 명부 확인 |
| U | Update | 수정 | student.email = "new@..." |
이메일 변경 |
| D | Delete | 삭제 | db.delete(student) |
자퇴 처리 |
Step 2. R(조회)의 심화 기술 1: 까다로운 조건 (Filter & Like)
데이터를 찾을 때는 filter()를 사용하여 조건을 겁니다.
① 정확히 찾기 (Exact Match)
"이름이 '페이커'인 학생 찾아줘."
# SQL: SELECT * FROM student WHERE name = '페이커';
faker = db.query(Student).filter(Student.name == "페이커").first()
② 비슷하면 다 찾아오기 (Like Search)
"성이 '김'씨인 학생 다 찾아줘."
# SQL: SELECT * FROM student WHERE name LIKE '김%';
kim_students = db.query(Student).filter(Student.name.like("김%")).all()
③ 숫자 세기 (Count)
"지금 총 몇 명이 입학했지?"
Step 3. R(조회)의 심화 기술 2: 데이터 연결하기 (JOIN)
관계형 데이터베이스(RDBMS)의 꽃입니다. 따로 관리하던 '학생 명부'와 '수강 신청 내역'을 합쳐서 보는 기술입니다.
① 수강생 조회 (Join)
"페이커 학생이 신청한 수업 목록을 다 가져와."
# Student와 Enrollment를 연결
enrollments = db.query(Enrollment).join(Student).filter(Student.name == "페이커").all()
해석
이렇게 하면 student 테이블과 enrollment 테이블이 연결되어, 페이커의 수강 내역을 한 번에 볼 수 있습니다.
Step 4. 실전 기술: 정렬과 페이징 (Sort & Limit)
학생이 100만 명일 때, 한 번에 다 가져오면 서버가 뻗습니다. 스마트하게 끊어서 가져와야 합니다.
① 정렬 (Sort): 줄 세우기
- 최신순 (학번 역순):
order_by(Student.id.desc()) - 가나다순:
order_by(Student.name.asc())
② 페이징 (Limit): 끊어 읽기
- Limit: "10명만 보여줘"
- Offset: "앞에 0명은 건너뛰고"
# 1페이지 (가입 순서대로 10명)
students = db.query(Student).order_by(Student.id.asc()).limit(10).offset(0).all()
📝 요약: 쿼리 마스터 공식
- Filter (조건):
==,like()로 원하는 데이터만 남기고, - Join (연결): 흩어진 테이블을 합치고,
- Sort & Limit (정리): 보기 좋게 줄 세워서 끊는다.
이 3단계면 수강신청 시스템의 모든 데이터를 자유자재로 다룰 수 있습니다.