[TIL / 데이터관리] 한 번에 여러 데이터를 MySQL에 입력하고 싶다고? SQL Injection 이 우려된다? Prepared Statements 써보자.

알락·2022년 10월 23일
0

데이터베이스

목록 보기
4/4

database banner

필요 상황

⌞ 예시) 다량의 Query문 처리

database example

장바구니에 담겨 있는 물건들을 주문하려고 한다. 클라이언트 측에서는 해당 주문 1 건을 요청하게 된다. 서버 측에서도 클라이언트의 주문을 1 건으로 저장해서 처리해야 한다. 하지만 해당 주문 건도 그렇지만 많은 주문들이 하나의 물건만 주문하는 게 아닌 여러 물건들이 같이 주문되어진다. 그래서 서버에서는 주문에 대한 중복 데이터 저장을 최소화하기 위해, 주문에 포함된 물건들의 정보는 따로 저장해두기로 하였다.
Problem pic

클라이언트의 주문 정보만 잘 전달되면 이제 서버에서 데이터베이스에 요청하는 작업만 진행해주면 된다. 주문 1 건을 저장하는 것은 문제가 없다. 하지만, 이제 해당 주문에 포함되는 품목들 정보를 저장하는 데서 비효율성을 목격하게 된다. 우리는 각 주문 품목을 저장해주기 위한 Query 요청을 꼭 서버에서 데이터베이스로 한 땀 한 땀 만들어 전해줘야 할까? 이것을 한꺼번에 데이터베이스 서버에 보내서 처리해줄 수는 없는 것일까? 나는 여러 데이터를 입력할 때 생길 서버와 데이터베이스 사이의 통신들이 비효율적이라고 생각했다.

⌞ 예시) 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의 유효성을 검사할 필요가 있다.


Prepared Statements

Query Process

우선 SQL문이 처리되는 과정은 위와 같다. 반환되는 값이 없는 INSERTUPDATE, 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가 작동하는 지에 대해서 다뤄봤다.


참고

profile
블록체인 개발 공부 중입니다, 프로그래밍 공부합시다!

0개의 댓글