1. 부동소수점 연산의 정밀도 한계
PHP에서 부동소수점 값을 직접 등호 연산자로 비교하는 것은 위험합니다. 예를 들어 0.1 + 0.2 === 0.3 연산은 false를 반환합니다. 이는 IEEE 754 표준이 대부분의 십진수를 유한한 이진수열로 완벽히 표현하지 못하기 때문입니다. 정확한 비교가 필요한 경우 BCMath 확장의 bccomp()를 활용해야 합니다.
$valA = 0.1 + 0.2;
$valB = 0.3;
// 직접 비교 시 false 반환
// 정확한 비교를 위한 보조 함수
function isFloatEqual($num1, $num2, $precision = 10) {
return bccomp((string)$num1, (string)$num2, $precision) === 0;
}
var_dump(isFloatEqual($valA, $valB)); // true
2. 문자열 비교 시 엄격한 연산자 사용
문자열 동등성 판별 시 == 연산자는 암시적 타입 캐스팅을 수행합니다. PHP는 비교 대상이 숫자 형식인지 검사하며, 0x 접두사의 16진수나 과학기술 표기법(1e2)까지 숫자로 해석합니다. 이로 인해 '0e123' == '0e456'과 같은 예상치 못한 true 값이 발생할 수 있습니다. 문자열의 정확한 매칭이 목적이라면 반드시 === 연산자를 사용하여 타입 변환 없이 비교해야 합니다.
3. 문자 자르기 함수의 오작동 이해
trim() 계열 함수의 두 번째 인자는 제거할 특정 문자열이 아니라, 제거 대상 문자들의 집합(character mask)으로 동작합니다. rtrim('document.txt', '.txt')를 호출하면 결과적으로 documen이 반환되며, 이는 함수가 문자열 끝에서 . 또는 t가 연속으로 나타나는 한 계속 제거하기 때문입니다. 정확한 접두사/접미사 삭제를 위해서는 정규식을 활용하는 것이 안전합니다.
function stripExactLeft($input, $pattern) {
$escaped = preg_quote($pattern, '/');
return preg_match("/^$escaped/", $input) ? substr($input, strlen($pattern)) : $input;
}
function stripExactRight($input, $pattern) {
$escaped = preg_quote($pattern, '/');
return preg_match("/$escaped\$/", $input) ? substr($input, 0, -strlen($pattern)) : $input;
}
function removeBomHeader($text) {
return preg_replace('/^\xEF\xBB\xBF/', '', $text);
}
4. 클라이언트 IP 주소의 안전한 획득
클라이언트 IP 주소를 조회하는 코드에서 HTTP_X_FORWARDED_FOR나 HTTP_CLIENT_IP 환경 변수를 우선순위로 두는 방식은 보안 취약점을 내포합니다. 이러한 값들은 HTTP 요청 헤더에서 가져오기 때문에 클라이언트나 중간 프록시가 임의로 변조할 수 있습니다. 인증이나 제한 로직에 IP를 활용할 경우 $_SERVER['REMOTE_ADDR']를 기본으로 사용하고, 필요 시 IP 형식 유효성 검사를 추가해야 합니다.
function resolveClientIp(): string {
$ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
$ip = '127.0.0.1';
}
return $ip;
}
5. 반복문 내 참조 변수의 생존 문제
foreach 문에서 배열 요소를 참조(&)하여 순회하면, 루프가 종료된 후에도 마지막 요소에 대한 참조가 유지됩니다. 이는 이후 동일한 변수명을 다른 컨텍스트에서 사용할 때 원본 배열의 데이터가 의도치 않게 변경되는 원인이 됩니다. 참조가 반드시 필요한 경우 루프 종료 후 즉시 unset()으로 참조를 해제하거나, 가능하면 값 복사 기반의 반복문을 사용하는 것이 권장됩니다.
$dataSet = ['apple', 'banana', 'cherry'];
foreach ($dataSet as &$item) {
$item = strtoupper($item);
}
unset($item); // 참조 연결 끊기
// 이후 코드에서 $item 변수 재사용 시 안전함
$item = 'new value';
print_r($dataSet); // ['APPLE', 'BANANA', 'CHERRY']로 정상 유지
6. HTML 인코딩의 완전성 및 XSS 예방
htmlspecialchars() 함수는 기본 동작상 큰따옴표만 인코딩하며 작은따옴표는 통과시킵니다. HTML 속성 값에 사용자 입력이 삽입될 경우, 작은따옴표로 인해 속성 경계가 깨지고 스크립트가 실행되는 XSS 공격이 발생하기 쉽습니다. 이를 방지하려면 두 번째 인자로 ENT_QUOTES 플래그를 명시해야 합니다. 또한 자바스크립트 템플릿이나 DOM 조작 API에 데이터 삽입 시, 문자열 리터럴 양쪽에 따옴표를 배치하거나 textContent를 활용하여 컨텍스트를 분리해야 합니다.
$userInput = $_POST['comment'] ?? '';
// 안전한 인코딩 적용
$safeOutput = htmlspecialchars(trim($userInput), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
// 위험한 방식: 속성 탈출 가능성
// element.innerHTML = '';
// 안전한 방식: 문자열 리터럴 보호 및 안전한 DOM API
element.textContent = '';
// 또는 JSON 인코딩을 통한 데이터 전달
const rawData = ;