1. MySQL Escaping - escape() 함수 vs '?' 문자
대다수의 프로그래밍 언어는 SQL Injection을 방지하기 위한 모듈이나 메소드를 제공한다.
mysql 모듈에선 이러한 escaping을 지원하는 다양한 방법을 제공하는데, 이 중 가장 대표적인 것이 바로 escape() 함수와 '?' 문자이다.
일반적으론 '?'문자를 이용해 query()함수의 2번째 인자로 배열을 넘겨주는 것이 일방적인 방법이다. 그러나 간혹 escape() 함수를 이용하는 경우가 있다. 어떤 이유에서 사용하는 것인지 예시를 통해 살펴보면서 정리하고자 한다.
아래는 npm-mysql 공식문서에서 발췌한 예시 코드이다.
https://www.npmjs.com/package/mysql#escaping-query-values
mysql
A node.js driver for mysql. It is written in JavaScript, does not require compiling, and is 100% MIT licensed.
www.npmjs.com
escape()
var userId = 'some user provided value';
var sql = 'SELECT * FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function (error, results, fields) {
if (error) throw error;
// ...
});
'?' 문자
connection.query('SELECT * FROM users WHERE id = ?', [userId], function (error, results, fields) {
if (error) throw error;
// ...
});
connection.query('UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?', ['a', 'b', 'c', userId], function (error, results, fields) {
if (error) throw error;
// ...
});
2. 예시
간단한 예시를 통해 구체적으로 살펴보도록 하자.
예를 들어 로그를 추합하여 조회하는 API가 존재한다고 상상해보자. 이때, 쿼리문 내엔 대략 이런 방식으로 SELECT 연산과 UNION 연산이 많이 들어갈 것이다.
const [ results ] = await pool.query(`
SELECT COUNT(*) AS 'total_count' FROM (
SELECT * FROM (
SELECT
...
AND a.shop_no = ${pool.escape(shop_no)}
AND a.user_no = ${pool.escape(user_no)}
) AS log1
UNION
SELECT * FROM (
SELECT
...
AND a.shop_no = ${pool.escape(shop_no)}
AND a.product_no = ${pool.escape(user_no)}
) AS log2
UNION
... // 생략
) AS total_log;`);
만약 이런 상황에서 escape()함수 대신 '?' 문자를 사용하면 어떻게 될까?
아래와 같이 2번째 인자로 넘겨줄 배열의 길이가 기하급수적으로 커질 것이다.
const [ results ] = await pool.query(`
SELECT COUNT(*) AS 'total_count' FROM (
SELECT * FROM (
SELECT
...
AND a.shop_no = ?
AND a.user_no = ?
) AS log1
UNION
SELECT * FROM (
SELECT
...
AND a.shop_no = ?
AND a.product_no = ?
) AS log2
UNION
... // 생략
) AS total_log;`,
[shop_no, user_no, shop_no, product_no, ...]); // 배열의 길이가 증가
이처럼 쿼리문이 복잡한 경우 '?'문자를 이용하면 2번째 인자로 넘겨줄 배열의 길이가 매우 길어진다. 이는 코드를 작성하는 사람 스스로가 실수를 유발하게 만들고, 다른 사람이 보았을 때 이해하기 어렵게 만든다. 이런 경우 escape()를 사용하는 것이 더 좋은 선택이다.
3. 결론
- 두 가지 방법 모두 SQL Injection을 방지하기 위함을 목적으로 한다(escaping).
- 쿼리문이 길어지고 복잡해질수록 '?' 문자를 사용하면 가독성이 떨어지고, 실수를 유발할 확률이 높아진다.
- 이때, escape() 함수를 쓰면 보다 쿼리문을 보다 명확하게 만들 수 있다.
- 어느 것이 옳고 그름의 문제가 아니다, 필요에 따라 취사선택해서 사용하면 된다.
'웹 > Node.js' 카테고리의 다른 글
[Node.js] M1에서 nvm 설치하기 (2) | 2021.08.03 |
---|---|
[Node.js] 비동기식 mysql을 사용하는 이유 (async/await) (3) | 2021.04.14 |
[Node.js] 모듈화에 사용되는 module.exports와 exports의 차이 (0) | 2021.04.13 |
[Node.js] JWT: Access Token & Refresh Token 인증 구현 (16) | 2021.04.06 |
[Node.js] MongoDB: 개념 및 기본 쿼리문 (0) | 2021.03.14 |
1. MySQL Escaping - escape() 함수 vs '?' 문자
대다수의 프로그래밍 언어는 SQL Injection을 방지하기 위한 모듈이나 메소드를 제공한다.
mysql 모듈에선 이러한 escaping을 지원하는 다양한 방법을 제공하는데, 이 중 가장 대표적인 것이 바로 escape() 함수와 '?' 문자이다.
일반적으론 '?'문자를 이용해 query()함수의 2번째 인자로 배열을 넘겨주는 것이 일방적인 방법이다. 그러나 간혹 escape() 함수를 이용하는 경우가 있다. 어떤 이유에서 사용하는 것인지 예시를 통해 살펴보면서 정리하고자 한다.
아래는 npm-mysql 공식문서에서 발췌한 예시 코드이다.
https://www.npmjs.com/package/mysql#escaping-query-values
mysql
A node.js driver for mysql. It is written in JavaScript, does not require compiling, and is 100% MIT licensed.
www.npmjs.com
escape()
var userId = 'some user provided value';
var sql = 'SELECT * FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function (error, results, fields) {
if (error) throw error;
// ...
});
'?' 문자
connection.query('SELECT * FROM users WHERE id = ?', [userId], function (error, results, fields) {
if (error) throw error;
// ...
});
connection.query('UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?', ['a', 'b', 'c', userId], function (error, results, fields) {
if (error) throw error;
// ...
});
2. 예시
간단한 예시를 통해 구체적으로 살펴보도록 하자.
예를 들어 로그를 추합하여 조회하는 API가 존재한다고 상상해보자. 이때, 쿼리문 내엔 대략 이런 방식으로 SELECT 연산과 UNION 연산이 많이 들어갈 것이다.
const [ results ] = await pool.query(`
SELECT COUNT(*) AS 'total_count' FROM (
SELECT * FROM (
SELECT
...
AND a.shop_no = ${pool.escape(shop_no)}
AND a.user_no = ${pool.escape(user_no)}
) AS log1
UNION
SELECT * FROM (
SELECT
...
AND a.shop_no = ${pool.escape(shop_no)}
AND a.product_no = ${pool.escape(user_no)}
) AS log2
UNION
... // 생략
) AS total_log;`);
만약 이런 상황에서 escape()함수 대신 '?' 문자를 사용하면 어떻게 될까?
아래와 같이 2번째 인자로 넘겨줄 배열의 길이가 기하급수적으로 커질 것이다.
const [ results ] = await pool.query(`
SELECT COUNT(*) AS 'total_count' FROM (
SELECT * FROM (
SELECT
...
AND a.shop_no = ?
AND a.user_no = ?
) AS log1
UNION
SELECT * FROM (
SELECT
...
AND a.shop_no = ?
AND a.product_no = ?
) AS log2
UNION
... // 생략
) AS total_log;`,
[shop_no, user_no, shop_no, product_no, ...]); // 배열의 길이가 증가
이처럼 쿼리문이 복잡한 경우 '?'문자를 이용하면 2번째 인자로 넘겨줄 배열의 길이가 매우 길어진다. 이는 코드를 작성하는 사람 스스로가 실수를 유발하게 만들고, 다른 사람이 보았을 때 이해하기 어렵게 만든다. 이런 경우 escape()를 사용하는 것이 더 좋은 선택이다.
3. 결론
- 두 가지 방법 모두 SQL Injection을 방지하기 위함을 목적으로 한다(escaping).
- 쿼리문이 길어지고 복잡해질수록 '?' 문자를 사용하면 가독성이 떨어지고, 실수를 유발할 확률이 높아진다.
- 이때, escape() 함수를 쓰면 보다 쿼리문을 보다 명확하게 만들 수 있다.
- 어느 것이 옳고 그름의 문제가 아니다, 필요에 따라 취사선택해서 사용하면 된다.
'웹 > Node.js' 카테고리의 다른 글
[Node.js] M1에서 nvm 설치하기 (2) | 2021.08.03 |
---|---|
[Node.js] 비동기식 mysql을 사용하는 이유 (async/await) (3) | 2021.04.14 |
[Node.js] 모듈화에 사용되는 module.exports와 exports의 차이 (0) | 2021.04.13 |
[Node.js] JWT: Access Token & Refresh Token 인증 구현 (16) | 2021.04.06 |
[Node.js] MongoDB: 개념 및 기본 쿼리문 (0) | 2021.03.14 |