WordPress의 wptexturize 필터가 인라인 자바스크립트를 조용히 망가뜨리고 있습니다. 논리 연산자인 **&&**를 HTML 엔티티인 **&&**로 변환하여 쇼트코드 내에서 실행되는 스크립트를 깨뜨리고 있습니다.

이 문제는 일련의 계산기 쇼트코드를 유지 관리하는 한 개발자에게서 나타났습니다. 몇 주 동안 아무 문제 없이 작동하던 제출 버튼이 갑자기 응답하지 않기 시작했습니다. PHP 경고도, 콘솔 에러도 없었으며, HTML 검사 결과도 깨끗했습니다. 하지만 렌더링된 소스를 확인하자 if (!isNaN(bf) && bf > 0)라는 코드가 발견되었습니다. 단 하나의 구문 오류로 인해 전체 스크립트 블록의 실행이 차단된 것입니다.

이 필터가 문제가 되는 이유

WordPress는 브라우저에 도달하기 전, 일련의 필터를 통해 포스트 콘텐츠를 처리합니다. wptexturize는 그 필터 중 첫 번째로, 곧은 따옴표를 타이포그래피용 둥근 따옴표로 변환하고, 여러 개의 하이픈을 엠 대시(em-dash)로 교체하며, 앰퍼샌드를 정제합니다. 이 필터는 처리 대상이 코드가 아닌 산문(prose)이라고 가정합니다. 쇼트코드가 인라인 <script> 태그를 삽입하더라도 필터는 여전히 작동하며, 자바스크립트를 일반 텍스트로 취급합니다. 따라서 &&에 포함된 앰퍼샌드는 &#038;로 이스케이프되며, 브라우저는 이를 논리 AND 연산자가 아닌 일반 문자열로 해석하게 됩니다.

계산기, 폼 검증기, 인터랙티브 위젯 등 포스트 콘텐츠에 자바스크립트를 직접 삽입하는 개발자들은 이 문제에 취약합니다. 문제는 계산기에 국한되지 않습니다. &&, & 또는 이와 유사한 문자를 사용하는 모든 인라인 스크립트가 손상될 수 있습니다. 이 변환은 서버 측에서 발생하기 때문에 브라우저는 원래의 코드를 전혀 볼 수 없으며, 에러 또한 일반적인 자바스크립트 예외(exception) 형태로 나타나지 않습니다.

영향을 받는 대상과 손실

  • 사이트 소유자: 고장 난 계산기나 폼은 방문자를 짜증 나게 하고, 이탈률을 높이며, 신뢰도를 떨어뜨릴 수 있습니다.
  • 개발자: 로그나 콘솔 출력에 아무런 흔적을 남기지 않는 "유령 버그"를 잡기 위해 수 시간을 허비하게 됩니다.
  • 콘텐츠 편집자: 쇼트코드가 포함된 페이지를 편집하는 동안 자신도 모르게 기능을 망가뜨릴 수 있습니다.

그 비용은 단순히 시간뿐만이 아닙니다. 특히 가격 책정, 대출 추정 또는 건강 진단 등을 위해 맞춤형 계산기에 의존하는 사이트의 경우, 이는 곧 전환 손실로 이어질 수 있습니다.

필터가 수행하는 작업 (쉬운 설명)

  1. 곧은 따옴표 감지'"를 '스마트'한 타이포그래피용 버전으로 교체합니다.
  2. 앰퍼샌드 정리&가 이미 유효한 HTML 엔티티를 형성하고 있지 않다면 &amp;로 변환합니다.
  3. 전체 콘텐츠 문자열에 적용 – 쇼트코드에 의해 생성된 <script> 태그 내부의 내용까지 포함합니다.

필터가 &&를 만나면, 기존 HTML 엔티티의 일부가 아닌 두 개의 앰퍼샌드로 인식하여 각각을 개별적으로 이스케이프하고, 결과적으로 &#038;&#038;를 만듭니다.

코드 손상을 방지하는 방법

1. 코드가 포함된 페이지에서 필터 비활성화

add_action( 'template_redirect', function () {
    if ( is_page() ) {
        remove_filter( 'the_content', 'wptexturize' );
        remove_filter( 'widget_text_content', 'wptexturize' );
    }
} );

이 스니펫은 페이지 템플릿에서만 wptexturize를 비활성화하여, 포스트 및 기타 콘텐츠 유형에 대한 타이포그래피 개선 사항은 유지합니다. 또한 인라인 스크립트의 보조적인 원인이 될 수 있는 위젯 텍스트에서도 필터를 제거합니다.

2. &&를 피하도록 로직 재작성

필터를 제거하는 것이 바람직하지 않다면, 논리 AND 연산자가 필요하지 않도록 자바스크립트를 리팩터링하십시오.

// Original
if (a && b) { … }

// Refactored
var ok = a;
if (ok) { ok = b; }
if (ok) { … }

이 방법은 코드가 몇 줄 더 추가되지만, 필터를 트리거하는 앰퍼샌드를 제거할 수 있습니다. 단순한 조건에는 효과적이지만, 복잡한 식에서는 다루기 어려워질 수 있습니다.

3. 모든 스크립트 외부화

가장 강력한 해결책은 코드를 인라인으로 삽입하는 대신 자바스크립트 파일을 인큐(enqueue)하는 것입니다.

wp_enqueue_script( 'my-calculator', get_template_directory_uri() . '/js/calculator.js', [], null, true );

인큐된 스크립트는 the_content 필터를 완전히 우회합니다. 또한 브라우저 캐싱의 이점을 누릴 수 있으며, 다른 에셋과 함께 압축(minify)하거나 번들링할 수도 있습니다.

실제 환경에서 문제 감지하기

스크립트가 명백한 에러 없이 실행을 멈춘다면, (DOM 검사기가 아닌) 페이지 소스 보기를 통해 &#038;를 검색하십시오. 만약 <script> 블록 내부에서 이를 발견했다면, 필터가 원인입니다. 브라우저가 파싱할 수 있는 문법적으로 유효한 스크립트를 아예 전달받지 못하기 때문에 콘솔에는 문제가 나타나지 않습니다.

반론: 왜 wptexturize를 유지해야 하는가?

wptexturize는 프론트엔드의 가독성을 높여줍니다. 둥근 따옴표와 적절한 대시 문자는 산문에 세련된 느낌을 주며, 많은 사이트 소유자들은 이를 타협할 수 없는 미적 요소로 간주합니다. 필터를 전역적으로 제거하면 텍스트는 타이포그래피가 적용되지 않은 가공되지 않은 상태로 되돌아갑니다.

절충안은 선택적 비활성화입니다. 코드가 있는 곳에서만 필터를 끄거나, 출력 결과가 텍스처라이징(texturizing)으로부터 안전함을 명시적으로 표시하는 커스텀 숏코드를 사용하는 것입니다. WordPress는 이미 wp_kses_post 및 기타 데이터 정화(sanitisation) 도우미를 제공하므로, 개발자는 이를 remove_filter 호출과 결합하여 두 방식의 장점을 모두 취할 수 있습니다.

다음에 주목할 점

WordPress 코어는 <script> 태그를 자동으로 제외하는 wptexturize의 변경 사항을 아직 발표하지 않았습니다. 그러한 변경 사항이 적용될 때까지 개발자는 인라인 코드를 수동으로 보호해야 합니다. 필터를 컨텍스트 인식(context-aware) 방식으로 만들기 위한 제안이 있는지 코어 개발 트래커를 계속 주시하십시오. 그동안 JavaScript를 삽입하는 모든 숏코드나 페이지 빌더 요소를 점검하고 위에서 언급한 세 가지 해결 방법 중 하나를 적용하십시오.

핵심 요약: WordPress 사이트에서 인라인 JavaScript를 실행하는 경우, wptexturize가 이를 몰래 재작성하고 있지 않은지 확인하십시오. 이스케이프 처리된 앰퍼샌드(&) 하나만으로도 전체 기능이 무력화될 수 있으며, 해결 방법은 대개 몇 줄의 PHP 코드를 추가하거나 외부 스크립트로 전환하는 것입니다.