ORM만 쓰다가 쿼리 성능 때문에 멘붕 온 적 있나요?
SQL과 ORM은 충돌하는 기술이 아니라, 서로 보완하는 도구입니다
이 글에서는 SQL의 본질부터 ORM의 장단점, 그리고 실전에서 두 가지를 어떻게 조화롭게 사용할 수 있는지 다뤄보겠습니다
SQL (Structured Query Language)
→ 관계형 데이터베이스(RDBMS)에서 데이터를 조회하고, 삽입하고, 수정하고, 삭제하기 위한 표준 언어
-- 예: 특정 유저의 주문 목록을 날짜순으로 정렬해서 조회
SELECT * FROM orders WHERE user_id = 123 ORDER BY created_at DESC;
예시:
ORM만 사용하고 있던 프로젝트에서 느려지는 페이지가 생김.
→ 로그를 보니 WHERE 조건 없이 전체 테이블을 조회 중
→ SQL을 몰라서 원인을 찾는 데만 수 시간 소요됨
ORM은 객체(Object)와 데이터베이스 테이블(Row)을 매핑(mapping)해주는 기술임
즉, SQL을 직접 작성하지 않고도 클래스 기반으로 DB 조작 가능하게 해줌
@Entity
public class User {
@Id
private Long id;
private String name;
}
User user = userRepository.findById(1L).get();
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
# 조회
user = session.query(User).filter_by(id=1).first()
@Query(nativeQuery = true) 또는 MyBatis로 전환해서 SQL 튜닝 | 역할 | 도구 |
|---|---|
| 단순 CRUD | ORM 사용 |
| 복잡한 통계 / 집계 / JOIN | SQL 직접 작성 |
| 대시보드, 리포트 | View, Procedure + SQL |
| 동적 필터링 | Query DSL, Criteria API 등 |
// JPQL 예시
@Query("SELECT u FROM User u WHERE u.name = :name")
List<User> findByName(String name);
// Native SQL 예시
@Query(value = "SELECT * FROM users WHERE age > 30", nativeQuery = true)
List<User> findAdults();
SELECT * FROM users WHERE name = 'Kim';
session.query(User).filter_by(name="Kim").all()
둘 다 같은 동작을 하지만, SQL은 더 직접적이고 세부적인 제어가 가능함
ORM은 빠른 개발에 좋지만, 추상화된 만큼 성능을 통제하기 어려움
SELECT, JOIN, WHERE, GROUP BY, ORDER BY, LIMIT