데이터베이스 기초집LESSON 16
ORM과 Raw SQL의 역할 분리
난이도초급 → 중급
예상 시간35분
선수지식이전 강의
16강. ORM과 Raw SQL의 역할 분리
1. 이번 강의에서 해결할 문제
모든 쿼리를 ORM 관계 탐색으로 작성하면 N+1과 복잡한 집계가 숨겨지고, 모든 것을 문자열 SQL로 작성하면 모델 변경과 타입 검증 비용이 커집니다. 쓰기 모델과 분석 조회에 맞는 도구를 선택합니다.
2. 학습 목표
3. 핵심 개념
ORM은 행을 객체로 매핑하고 관계·변경 추적을 제공해 일반 CRUD에 유리합니다. Core와 Raw SQL은 윈도 함수, CTE, DB 고유 기능, 실행 계획 최적화가 중요한 조회를 명확히 표현할 수 있습니다. 선택 기준은 취향이 아니라 쿼리 복잡도, 변경 빈도, 성능 가시성, 팀 역량입니다.
4. 단계별 예시
파일 경로: C:\dev\game-ranking-service\app\repositories\ranking.py
app/repositories/ranking.py
from sqlalchemy import Select, select, text
from sqlalchemy.orm import Session
from app.models import Player
def find_player(session: Session, player_id: int) -> Player | None:
statement: Select[tuple[Player]] = select(Player).where(Player.id == player_id)
return session.scalar(statement)
RANKING_SQL = text("""
SELECT player_id, nickname, rating,
dense_rank() OVER (ORDER BY rating DESC) AS rank_position
FROM ranking.players
WHERE deleted_at IS NULL
ORDER BY rating DESC, player_id
LIMIT :limit
""")
def get_top_ranking(session: Session, limit: int = 100):
return session.execute(RANKING_SQL, {"limit": limit}).mappings().all()
PowerShell · 테스트 실행
python -m pytest .\tests\repositories\test_ranking.py -q
5. 동작 원리
두 함수 모두 같은 요청 Session을 받아 동일한 연결·트랜잭션 경계를 사용할 수 있습니다. text()의 :limit 바인드 변수는 값을 SQL 구조와 분리합니다. Raw SQL이라고 문자열 보간을 사용하지 않으며 결과는 mappings()로 명시적인 키 기반 행으로 받습니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
MINI QUIZ
0 / 2ORM과 Raw SQL의 역할 분리 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
LESSON STATUS
16강. ORM과 Raw SQL의 역할 분리 미완료 상태학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.