BioPlayground

🧬
목록으로

SQL 인젝션과 파라미터화된 쿼리

SQL 인젝션이 어떻게 작동하는지 이해하고, 파라미터화된 쿼리로 완전히 막는 방법을 배웁니다.

중급
|
7
|
검증 완료 (2026-07)
진행률0/18 (0%)

SQL 인젝션과 파라미터화된 쿼리

이 토픽을 마치면

SQL 인젝션이 어떻게 작동하는지 설명할 수 있고, 파라미터화된 쿼리로 방어하는 코드를 작성할 수 있습니다.


SQL 인젝션이란

SQL 인젝션(SQL Injection)은 사용자 입력에 SQL 코드를 삽입해서 데이터베이스를 조작하는 공격입니다. 웹 보안 공격 중 가장 오래되었고, 가장 위험하고, 아직도 가장 흔합니다.


공격이 작동하는 원리

로그인 폼을 생각해봅시다. 사용자가 이메일을 입력하면 서버에서 이렇게 처리합니다:

javascript
// ❌ 위험한 코드 — 입력을 직접 SQL에 삽입
const email = req.body.email;
const sql = `SELECT * FROM users WHERE email = '${email}'`;
connection.query(sql);

정상 입력: hoon@example.com

sql
SELECT * FROM users WHERE email = 'hoon@example.com'
-- 정상 작동

공격 입력: ' OR '1'='1

sql
SELECT * FROM users WHERE email = '' OR '1'='1'
-- '1'='1'은 항상 참 → 모든 사용자 데이터가 반환됨!

더 위험한 공격: '; DROP TABLE users; --

sql
SELECT * FROM users WHERE email = ''; DROP TABLE users; --'
-- 세미콜론으로 첫 쿼리를 끝내고, 테이블 삭제 명령을 실행
-- --는 나머지를 주석 처리

핵심: 사용자 입력이 SQL의 구조 자체를 바꿔버리는 것이 문제입니다.


방어: 파라미터화된 쿼리

파라미터화된 쿼리(Parameterized Query, Prepared Statement)는 SQL 구조와 데이터를 분리합니다.

javascript
// ✅ 안전한 코드 — 플레이스홀더 사용
const email = req.body.email;
connection.query(
  'SELECT * FROM users WHERE email = ?',
  [email]
);

공격 입력 ' OR '1'='1이 들어와도:

sql
SELECT * FROM users WHERE email = '\' OR \'1\'=\'1'
-- 전체가 하나의 문자열 값으로 처리됨. SQL 구조는 바뀌지 않음

데이터베이스 엔진이 먼저 SQL 구조를 파싱하고, 그 다음에 ? 자리에 값을 안전하게 대입합니다. 값이 아무리 이상해도 SQL 명령으로 해석되지 않습니다.


언어별 파라미터화 패턴

Node.js (mysql2)

javascript
// ? 플레이스홀더
connection.query('SELECT * FROM users WHERE id = ?', [userId]);
connection.query(
  'INSERT INTO users (name, email) VALUES (?, ?)',
  [name, email]
);

Python (sqlite3 / psycopg2)

python
# ? 플레이스홀더 (sqlite3)
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
# %s 플레이스홀더 (psycopg2 / MySQL Connector)
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

Java (JDBC)

java
PreparedStatement stmt = conn.prepareStatement(
    "SELECT * FROM users WHERE id = ?"
);
stmt.setInt(1, userId);
ResultSet rs = stmt.executeQuery();

문법은 다르지만 원리는 동일합니다: SQL과 데이터를 분리한다.


추가 방어 계층

파라미터화된 쿼리가 핵심이지만, 추가 방어 계층도 있습니다:

방법역할
파라미터화된 쿼리핵심 방어 — SQL 구조 보호
입력 유효성 검사이메일 형식, 숫자 범위 등 사전 필터
최소 권한 원칙DB 계정에 필요한 권한만 부여 (DELETE 불필요 시 제거)
ORM 사용Sequelize, Prisma 등이 내부적으로 파라미터화 적용

가장 중요한 것: 사용자 입력을 SQL 문자열에 직접 합치지 않는다. 이 한 가지 규칙만 지키면 SQL 인젝션은 발생하지 않습니다.