🔎
Scopes & Query Interface
재사용 가능한 쿼리를 이름 붙여 관리
Scope는 자주 사용하는 쿼리 조건을 모델에 이름 붙여 정의하는 기능입니다.
class Post < ApplicationRecord
scope :published, -> { where(status: 'published') }
scope :recent, -> { order(created_at: :desc) }
scope :by_author, ->(user) { where(user: user) }
scope :this_month, -> { where(created_at: Time.current.beginning_of_month..) }
end
사용:
Post.published # published 포스트만
Post.published.recent # 체이닝
Post.published.by_author(user).recent # 여러 scope 조합
Post.published.count # 집계와 조합
Query Interface 주요 메서드:
where— 조건 (AND)or— OR 조건not— NOT 조건order— 정렬limit/offset— 페이징includes— Eager Loadingjoins— INNER JOINleft_joins— LEFT OUTER JOINselect/pluck— 특정 컬럼만 조회
쿼리는 Lazy Loading이라 실제 데이터가 필요한 시점에만 SQL이 실행됩니다.
핵심 포인트
1
scope :name, -> { where(...) } 로 스코프 정의
2
Model.scope_name으로 호출 (클래스 메서드처럼 동작)
3
여러 scope를 체이닝하여 복잡한 쿼리 구성
4
인자가 필요한 scope: scope :by_status, ->(s) { where(status: s) }
5
default_scope는 모든 쿼리에 자동 적용 (주의해서 사용)
6
Lazy Loading: .to_a, .each, .count 등 호출 시점에 SQL 실행
장점
- ✓ 코드 재사용 (DRY)
- ✓ 가독성 향상 — 쿼리 의도가 명확
- ✓ 체이닝으로 유연한 조합
- ✓ Lazy Loading으로 불필요한 쿼리 방지
단점
- ✗ default_scope는 예상치 못한 동작 유발
- ✗ 과도한 scope는 코드 추적 어려움
- ✗ 복잡한 쿼리는 SQL이 더 명확할 수 있음
- ✗ scope 내 side effect 주의
사용 사례
상태별 필터 (published, draft)
날짜 범위 필터 (this_week, this_month)
정렬 (recent, oldest)
사용자별 필터 (by_author)