본문 바로가기

비개발자의 개발 일지

현장 팀장에서 수출 ERP까지 — AI와 함께 시스템을 만든 기록

시리즈 보기
php

PHP PDO Prepared Statement — bindValue로 SQL 인젝션 차단 완전 정리

by 왕진 2026. 6. 19.
반응형

 

 

Web Development · PDO Prepared Statement

PDO Prepared Statement —
SQL 템플릿 + 바인딩으로 인젝션 차단

prepare → bindValue → execute의 3단 흐름
시작 오늘 분석할 코드
방법 1 — 이름 있는 placeholder
$sql = "INSERT INTO member (last_name, first_name, age) VALUES (:last_name, :first_name, :age)"; $stmh = $pdo->prepare($sql); $stmh->bindValue(':last_name', $_POST['last_name']); $stmh->bindValue(':first_name', $_POST['first_name']); $stmh->bindValue(':age', $_POST['age']); $stmh->execute();
방법 2 — ? placeholder
$sql = "INSERT INTO member (last_name, first_name, age) VALUES (?, ?, ?)"; $stmh = $pdo->prepare($sql); $stmh->bindValue(1, $_POST['last_name']); $stmh->bindValue(2, $_POST['first_name']); $stmh->bindValue(3, $_POST['age']); $stmh->execute();

1 SQL 인젝션이란?
※ 사용자가 입력값에 SQL 코드를 끼워 넣어 DB를 조작하는 공격. 예: '; DROP TABLE users; --
// 위험 — 문자열 결합 $sql = "SELECT * FROM users WHERE name = '" . $_POST['name'] . "'"; // 사용자가 name에 ' OR 1=1 -- 입력 시 모든 행이 노출됨

2 Prepared Statement의 원리

SQL 문장의 구조데이터를 분리해서 처리한다.

1) SQL 템플릿을 먼저 DB에 보냄 (구조 결정) 2) 데이터는 별도로 바인딩 3) DB가 데이터를 그냥 "값"으로만 취급 → SQL 코드 해석 X

인젝션이 원리적으로 불가능해진다.


3 두 가지 placeholder 비교
// 이름 있는 (named) — 권장 :last_name, :first_name bindValue(':last_name', $value) // 위치 (positional) ?, ?, ? bindValue(1, $value) // 1부터 시작 (0이 아님)

이름 있는 쪽이 가독성↑, 매개변수가 많을수록 유리.


 

반응형

 

4 짧은 형태 — execute에 바로 배열
$sql = "INSERT INTO member (last_name, first_name, age) VALUES (?, ?, ?)"; $stmh = $pdo->prepare($sql); $stmh->execute([ $_POST['last_name'], $_POST['first_name'], $_POST['age'], ]); // bindValue 3번 안 해도 됨

5 SELECT 결과 가져오기
$stmh = $pdo->prepare("SELECT * FROM member WHERE age >= ?"); $stmh->execute([20]); while ($row = $stmh->fetch(PDO::FETCH_ASSOC)) { print $row['last_name'] . " " . $row['first_name']; } // 또는 한 번에 $rows = $stmh->fetchAll(PDO::FETCH_ASSOC);

핵심 한 줄 요약

prepare()SQL 템플릿 준비
bindValue()placeholder에 값 결합
execute()DB에 실행 명령 전송
SQL 인젝션prepared로 원리적 차단
:이름named placeholder — 가독성
?positional placeholder — 짧음
execute([...])바인딩 + 실행 한 번에
반응형

댓글