콘텐츠로 이동

02. SQL & ORM: AI 통역사 고용하기

"데이터베이스는 한국어(Python)를 모릅니다. SQL(Structured Query Language)이라는 외국어만 할 줄 압니다. 우리는 SQL을 배우는 대신, 유능한 통역사(ORM: Object Relational Mapping)를 고용할 것입니다."

1. The Barrier: 언어의 장벽 (SQL)

여러분이 "철수 정보 좀 찾아줘"라고 파이썬으로 말해도, 데이터베이스는 알아듣지 못합니다. DB의 모국어는 SQL이기 때문입니다.

  • 개발자의 고통: 파이썬 코드를 짜다가 갑자기 SQL(SELECT * FROM...)을 섞어 쓰면 문법이 헷갈리고 오타가 나기 쉽습니다.
  • SQL의 생김새: 마치 기계에게 고함을 치는 것처럼 보입니다.
-- SQL: 20살 넘는 사람 다 내놔!
SELECT * FROM users WHERE age > 20;

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()

"성이 '김'씨인 학생 다 찾아줘."

# SQL: SELECT * FROM student WHERE name LIKE '김%';
kim_students = db.query(Student).filter(Student.name.like("김%")).all()

③ 숫자 세기 (Count)

"지금 총 몇 명이 입학했지?"

# SQL: SELECT COUNT(*) FROM student;
total_count = db.query(Student).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()

📝 요약: 쿼리 마스터 공식

  1. Filter (조건): ==, like()로 원하는 데이터만 남기고,
  2. Join (연결): 흩어진 테이블을 합치고,
  3. Sort & Limit (정리): 보기 좋게 줄 세워서 끊는다.

이 3단계면 수강신청 시스템의 모든 데이터를 자유자재로 다룰 수 있습니다.