3장. Query Builder의 등장
Raw Query 방식에서는
SQL을 문자열로 직접 작성하고 조합해야 했다.
특히 조건이 많아질수록
문자열을 이어붙이는 방식은 빠르게 복잡해졌다.
let query = "SELECT * FROM users WHERE 1=1";
if (email) {
query += ` AND email = '${email}'`;
}
if (status) {
query += ` AND status = '${status}'`;
}
이 방식은 유연하지만,
코드의 안정성과 가독성 측면에서 부담이 커진다.
SQL을 구조적으로 다루려는 시도
이 문제를 해결하기 위해 등장한 것이
👉 Knex.js 와 같은 Query Builder 방식이다
문자열을 직접 조합하는 대신
코드 구조를 통해 SQL을 만들어가는 방식이다.
const users = await knex('users')
.where('email', email)
.andWhere('status', status);
이제 SQL은 문자열이 아니라
메서드 체이닝 형태로 표현된다.
무엇이 달라졌는가
가장 큰 변화는
👉 “SQL을 만드는 방식”이다
Raw Query에서는
- 문자열을 직접 조합했고
Query Builder에서는
- 구조를 기반으로 쿼리를 생성한다
즉,
👉 SQL 작성 방식이 “문자열 → 구조”로 바뀐다
Query Builder의 핵심 특징
이 방식은 다음과 같은 특징을 가진다.
- 메서드 체이닝 기반 쿼리 생성
- 조건을 코드로 분기 처리 가능
- 파라미터 바인딩 자동 처리
특히 중요한 점은
👉 SQL Injection을 기본적으로 방지할 수 있다는 것이다.
동적 조건 처리의 변화
1장에서 문제가 되었던 동적 조건 처리도
훨씬 자연스럽게 바뀐다.
const query = knex('users');
if (email) {
query.where('email', email);
}
if (status) {
query.where('status', status);
}
const users = await query;
문자열을 이어붙이지 않고
조건을 “추가”하는 형태로 바뀐다.
Query Builder의 장점
이 방식은 Raw Query의 여러 문제를 개선한다.
- SQL Injection 방지
- 동적 조건 처리 용이
- 코드 가독성 향상
- 쿼리 생성 로직을 구조적으로 관리 가능
특히 조건이 많은 쿼리에서
차이가 크게 드러난다.
하지만 여전히 남아있는 한계
Query Builder는 많은 문제를 해결했지만
완전히 새로운 접근 방식은 아니다.
여전히 다음과 같은 특징을 가진다.
- SQL 구조를 이해해야 한다
- 데이터베이스에 대한 의존이 남아 있다
- 복잡한 쿼리는 오히려 더 읽기 어려워질 수 있다
예를 들어 JOIN이나 서브쿼리가 많아질 경우
코드가 오히려 더 길어지기도 한다.
여전히 SQL 중심이다
중요한 점은
이 방식이 SQL을 없앤 것이 아니라
👉 SQL을 “조금 더 안전하게 만드는 것”에 가깝다는 점이다
즉,
- 사고 방식은 여전히 SQL 중심이고
- 데이터 접근 방식 자체가 바뀐 것은 아니다
다음 단계로의 흐름
개발자들은 다시 고민하게 된다.
- SQL을 계속 알아야 하는 구조가 맞는가?
- 데이터를 객체처럼 다룰 수는 없는가?
- 비즈니스 로직과 데이터 접근을 더 분리할 수는 없는가?
이 고민에서 등장한 것이
👉 객체 중심의 데이터 접근 방식
이다.