개발자 커뮤니티에서 주기적으로 반복되는 논쟁이 있다. ORM을 쓸 것인가, Raw SQL을 쓸 것인가. 양쪽 다 강경한 지지자들이 있고, 서로 상대방이 틀렸다고 확신한다.

객체지향 언어로 개발하다 보면 근본적인 불일치와 마주친다. 코드에서는 User 객체를 다루는데, 데이터베이스에는 users 테이블이 있다. 이 둘 사이를 연결하는 코드를 매번 작성해야 한다. ORM은 이 지루한 매핑 작업을 자동화해준다.

ORM 지지자들은 말한다. 생산성이 높다. CRUD는 코드 몇 줄이면 끝난다. 타입 안전하다. 컴파일 타임에 오류를 잡을 수 있다. 데이터베이스에 독립적이다. MySQL에서 PostgreSQL로 바꿔도 코드 수정이 거의 없다.

Raw SQL 지지자들은 말한다. 성능을 제어할 수 있다. ORM이 생성하는 쿼리가 항상 최적은 아니다. SQL은 이미 완성된 언어다. 윈도우 함수, CTE, 서브쿼리 같은 강력한 기능을 ORM으로 표현하기는 어렵다. N+1 문제 같은 함정이 없다. 디버깅이 쉽다.

사실 이 논쟁은 추상화 수준의 선택에 관한 것이다. ORM은 SQL을 몰라도 데이터베이스를 다룰 수 있게 해준다. 하지만 그 추상화에는 비용이 따른다. 추상화가 새는 순간, 결국 그 아래 계층을 이해해야 한다.

실무에서는 보통 이렇게 된다. 간단한 CRUD에는 ORM이 압도적으로 편하다. 복잡한 조회에는 Raw SQL이나 QueryDSL 같은 타입 안전한 쿼리 빌더를 쓴다. 성능이 중요한 구간에서는 무조건 SQL을 직접 튜닝한다. 배치 작업에서는 대량 데이터 처리에 ORM은 적합하지 않다.

결국 ORM이냐 SQL이냐는 잘못된 질문이다. 대부분의 프로젝트에서는 둘 다 쓴다. 상황에 맞는 도구를 선택하는 것이다.

어떤 도구를 쓰든 SQL을 알아야 한다. ORM을 쓰더라도 내부에서 어떤 쿼리가 나가는지 모르면 성능 문제를 해결할 수 없다. ORM은 SQL을 대체하는 게 아니라 SQL 위에 얹는 편의 도구다. 기초 없이 편의 도구만 쓰면 언젠가 벽에 부딪힌다.