장바구니에 담겨 있는 물건들을 주문하려고 한다. 클라이언트 측에서는 해당 주문 1 건을 요청하게 된다. 서버 측에서도 클라이언트의 주문을 1 건으로 저장해서 처리해야 한다. 하지만 해당 주문 건도 그렇지만 많은 주문들이 하나의 물건만 주문하는 게 아닌 여러 물건들이 같이 주문되어진다. 그래서 서버에서는 주문에 대한 중복 데이터 저장을 최소화하기 위해, 주문에 포함된 물건들의 정보는 따로 저장해두기로 하였다.
클라이언트의 주문 정보만 잘 전달되면 이제 서버에서 데이터베이스에 요청하는 작업만 진행해주면 된다. 주문 1 건을 저장하는 것은 문제가 없다. 하지만, 이제 해당 주문에 포함되는 품목들 정보를 저장하는 데서 비효율성을 목격하게 된다. 우리는 각 주문 품목을 저장해주기 위한 Query
요청을 꼭 서버에서 데이터베이스로 한 땀 한 땀 만들어 전해줘야 할까? 이것을 한꺼번에 데이터베이스 서버에 보내서 처리해줄 수는 없는 것일까? 나는 여러 데이터를 입력할 때 생길 서버와 데이터베이스 사이의 통신들이 비효율적이라고 생각했다.
혹시 다음 과 같이 생 Query
문을 생성해서 요청을 보낼 때 다음과 같은 경우에 해당하는 사람이 있을 수 있다.
const userId = anyInsertValue();
const queryString = `SELECT * FROM USERS WHERE id = ${userId} ;`
db.query(queryString (err, res)=>{ ...생략 })
위와 같은 상황에서 Query
문에 다른 조치를 취하지 않으면 SQL Injection
공격에 취약하게 된다. userId
의 값이 1234 OR 1=1
로 들어오면 원치 않던 정보들까지 조회하게 만든다. 이런 상황에서는 userId
의 유효성을 검사할 필요가 있다.
우선 SQL문이 처리되는 과정은 위와 같다. 반환되는 값이 없는 INSERT
나 UPDATE
, DELETE
같은 경우는 FETCH의 과정이 생략된다. 보통의 Statements
같은 경우는 위와 같이 처리 된다.
Prepared Statementes
를 사용하게 되는 경우, 처음 한 번 Query
가 잘 작성되어 있는지만 확인한 후에 이후 실행에서는 Parse
단계가 생략된다.
Prepared Statementes
는 일반적인 Statements
와 다르게 Query
문 중에 ?
(Question Mark)가 들어가 있는게 특징이다.
// Prepared Statementes 예시
SELECT * FROM USERS WHERE id = ? AND name = ?;
MySQL
에서는 Prepared Statements
가 다음과 같이 작동한다.
// Prepared Statement 선언
mysql > PREPARE stmt1 FROM "SELECT * FROM USERS WHERE id = ? AND name = ?;";
// ?와 대응될 변수 선언
mysql > SET @a = 1;
mysql > SET @b = "AlRock";
// Prepared Statement 실행
mysql > EXCUTE stmt1 USING @a, @b;
// Prepared Statement 할당 해제
mysql > DEALLOCATE PREPARE stmt1;
이렇게 MySQL
에서 어떻게 Prepared Statments
가 작동하는 지에 대해서 다뤄봤다.