문자열 치환 작업은 웹 개발에서 가장 자주 마주치는 작업 중 하나다. 그런데 대부분의 개발자들은 PHP의 str_replace()만 사용하거나, str_ireplace()와의 차이를 제대로 모른 채 상황에 맞지 않는 함수를 쓰고 있다. 특히 사용자 입력값을 처리하거나 동적 콘텐츠에서 특정 단어를 치환해야 할 때, 대소문자 처리 실수로 인해 예기치 않은 결과가 나온다. 이번에는 str_replace()와 str_ireplace()의 정확한 차이, 언제 어떤 함수를 써야 하는지, 그리고 실무에서 자주 하는 실수까지 완벽하게 정리해서 소개하겠다.
str_replace()와 str_ireplace() 모두 문자열 내에서 특정 부분을 다른 문자열로 바꾸는 함수다. 핵심 차이는 대소문자 구분 여부다.
str_replace(search, replace, subject)는 대소문자를 정확히 구분해서 매칭한다. "Apple"을 찾아도 "apple"이나 "APPLE"은 바꾸지 않는다. 반면 str_ireplace(search, replace, subject)는 대소문자를 무시하고 매칭한다. "Apple", "apple", "APPLE" 모두 동일하게 취급한다.
<?php
// str_replace 예제: 대소문자 구분
$text = "I like Apple. I like apple. I like APPLE.";
$result = str_replace("apple", "orange", $text);
echo $result;
// 출력: I like Apple. I like orange. I like APPLE.
?>
위 코드에서 str_replace()는 "apple"(소문자)만 찾아서 "orange"로 바꿨다. "Apple"과 "APPLE"은 그대로 남아있다.
<?php
// str_ireplace 예제: 대소문자 무시
$text = "I like Apple. I like apple. I like APPLE.";
$result = str_ireplace("apple", "orange", $text);
echo $result;
// 출력: I like orange. I like orange. I like orange.
?>
str_ireplace()는 대소문자를 무시하고 세 개 모두를 "orange"로 바꿨다.
✓ 프로그래밍 코드나 설정값처럼 정확한 대소문자가 중요한 경우. 예를 들어 PHP 상수명 "TRUE"와 변수명 "true"를 구분해야 할 때다. ✓ 데이터베이스 컬럼명 치환. "user_id"와 "USER_ID"는 다른 컬럼일 수 있다. ✓ 사용자 입력값 정규화. 정확히 일치하는 단어만 바꿔야 할 때.
<?php
// 예제: 쿼리 문자열에서 매개변수 이름 정확히 매칭
$query = "SELECT * FROM users WHERE ID = 1 and id = 2";
// id는 중복 제거해야 하는데, ID와 id를 구분해야 함
$result = str_replace("id = 2", "", $query); // 정확히 소문자 id만 제거
echo $result;
// 출력: SELECT * FROM users WHERE ID = 1 and = 2
?>
✓ 사람이 쓴 텍스트 콘텐츠에서 단어를 바꿀 때. 문장 시작 단어는 대문자일 가능성이 높다. ✓ 검색 및 하이라이트 기능. 사용자가 "iPhone"을 검색했을 때 "iphone"이나 "IPHONE"도 찾아야 한다. ✓ 필터링이나 검열. 욕설이나 금지 단어를 제거할 때 대소문자 우회를 방지해야 한다. ✓ 사용자 친화적인 치환. 정확한 표기보다 의미가 중요할 때.
<?php
// 예제: 상품명에서 브랜드명 통일
$products = array(
"Apple iPhone 15",
"apple airpods",
"APPLE Watch"
);
// 모든 경우를 "🍎 Apple"로 통일
foreach ($products as $product) {
$result = str_ireplace("apple", "🍎 Apple", $product);
echo $result . "
";
}
// 출력:
// 🍎 Apple iPhone 15
// 🍎 Apple airpods
// 🍎 Apple Watch
?>
str_replace()와 str_ireplace() 모두 배열을 지원한다. search와 replace에 배열을 넘기면 첫 번째 요소끼리, 두 번째 요소끼리 매칭된다.
<?php
// ✗ 잘못된 코드: 배열 크기가 다르면 문제가 생김
$text = "Hello World! Goodbye World!";
$search = array("Hello", "Goodbye", "World");
$replace = array("Hi", "Bye"); // 요소 개수가 다름
$result = str_replace($search, $replace, $text);
echo $result;
// 출력: Hi World! Bye World! (World는 대응할 replace가 없어서 제거됨)
?>
<?php
// ✓ 올바른 코드: 배열 크기를 맞춤
$text = "Hello World! Goodbye World!";
$search = array("Hello", "Goodbye", "World");
$replace = array("Hi", "Bye", "Universe");
$result = str_replace($search, $replace, $text);
echo $result;
// 출력: Hi Universe! Bye Universe!
?>
배열 사용 시 주의할 점은 순서다. 앞에서 이미 바뀐 문자열을 뒤의 규칙이 또 바꿀 수 있다.
<?php
// 주의: 순서에 따라 결과가 달라짐
$text = "cat";
$search = array("cat", "ca");
$replace = array("dog", "ca-replaced");
$result = str_replace($search, $replace, $text);
echo $result; // 출력: dog ("cat" 전체가 먼저 매칭되어 "dog"으로 변경)
$text2 = "ca";
$result2 = str_replace($search, $replace, $text2);
echo $result2; // 출력: ca-replaced ("cat" 규칙은 매칭 안 되고 "ca" 규칙이 매칭됨)
?>
✗ 검색 기능에서 사용자가 "iPhone" 검색했는데 "iphone"은 못 찾음
<?php
$products = array("iphone", "iPhone", "IPHONE", "Samsung");
$search_term = "iPhone";
// ✗ 잘못된 코드
$results = array_filter($products, function($product) use ($search_term) {
return strpos($product, $search_term) !== false; // 대소문자 구분
});
print_r($results);
// 출력: Array ( [1] => iPhone ) - "iphone"과 "IPHONE"은 누락
?>
✓ 해결책은 stripos()를 써서 대소문자 무시 검색을 한다
<?php
$products = array("iphone", "iPhone", "IPHONE", "Samsung");
$search_term = "iPhone";
// ✓ 올바른 코드
$results = array_filter($products, function($product) use ($search_term) {
return stripos($product, $search_term) !== false; // 대소문자 무시
});
print_r($results);
// 출력: Array ( [0] => iphone [1] => iPhone [2] => IPHONE )
?>
✗ 사용자 ID "admin"과 일반 단어 "admin" 구분하지 못함
<?php
$text = "The admin will manage the admin panel for administrators.";
// ✗ 잘못된 코드: str_ireplace()는 모든 admin을 바꿈
$result = str_ireplace("admin", "***", $text);
echo $result;
// 출력: The *** will manage the *** panel for ***istrators.
// "administrators"의 "admin" 부분도 바뀌어서 엉망됨
?>
✓ 해결책은 정규표현식으로 단어 경계를 지정한다
<?php
$text = "The admin will manage the admin panel for administrators.";
// ✓ 올바른 코드: 단어 경계(\b)로 정확히 "admin" 단어만 매칭
$result = preg_replace("/\\badmin\\b/i", "***", $text);
echo $result;
// 출력: The *** will manage the *** panel for administrators.
// "admin" 단어만 바뀌고 "administrators"는 그대로 유지
?>
✗ str_replace() 호출했는데 원본이 안 바뀐다고 생각함
<?php
$text = "Hello World";
// ✗ 잘못된 코드: 반환값을 받지 않음
str_replace("World", "PHP", $text);
echo $text; // 출력: Hello World (원본 그대로)
?>
✓ str_replace()는 새로운 문자열을 반환하므로 반드시 변수에 저장해야 한다
<?php
$text = "Hello World";
// ✓ 올바른 코드: 반환값을 변수에 저장
$text = str_replace("World", "PHP", $text);
echo $text; // 출력: Hello PHP
?>
str_ireplace()는 내부적으로 strtolower()를 사용해서 문자열을 소문자로 변환한 후 비교한다. 따라서 대용량 텍스트에서는 str_replace()가 약간 더 빠르다. 하지만 일반적인 웹 애플리케이션에서는 차이가 무시할 수 있는 수준이다. 성능보다는 정확성이 중요하므로, 기능에 맞는 함수를 선택해야 한다.
str_replace()와 str_ireplace()는 문자열 치환이라는 같은 일을 하지만, 대소문자 처리 방식이 다르다. 프로그래밍 코드나 정확한 데이터는 str_replace()로, 사람이 쓴 텍스트나 사용자 입력은 str_ireplace()로 처리하는 것이 일반적이다. 다만 단어 경계가 중요한 경우 정규표현식 preg_replace()가 더 안전하다. 이 글의 배열 사용 방법과 실수 사례들을 참고해서 자신의 프로젝트에 맞게 적용하면, 예기치 않은 문자열 처리 버그를 크게 줄일 수 있을 것이다.