개발 slecs

HTML escape 오류로 광고 슬롯이 조용히 깨지던 문제 수정

목차

광고 마커가 HTML escape 때문에 조용히 깨져 있었다.

Svelte 계열 템플릿이든 Astro든, set:html 같은 raw HTML 삽입 지시어를 쓸 때 큰따옴표로 내부 값을 감싸면 문자열 안의 큰따옴표가 엔터티(")로 escape 되면서 의도한 HTML이 날아간다. 오늘 수정한 게 딱 그 케이스였다.

왜 이 버그가 조용히 터지는가

set:html은 컴파일러가 속성값을 파싱하는 단계에서 따옴표 쌍을 기준으로 끊어 읽는다. 예를 들어 mobonslot 마커가 내부적으로 큰따옴표를 포함한 HTML 스니펫이라면, 아래처럼 감쌌을 때 문제가 생긴다.

<!-- ❌ 큰따옴표로 감쌀 경우 -->
<div set:html="<div class=\"mbn-slot\" data-id=\"123\"></div>" />

<!-- ✅ 백틱으로 감쌀 경우 -->
<div set:html={`<div class="mbn-slot" data-id="123"></div>`} />

큰따옴표 버전은 빌드 결과물에서 &quot;로 escape된 채 DOM에 박히거나, 아예 속성값이 중간에 잘린다. 광고 스크립트 쪽 마커는 보통 data-* 속성이나 특정 클래스명을 정밀하게 읽어서 슬롯을 초기화하는 구조라, 이 escape 하나가 광고 노출 자체를 막는다. 콘솔에는 에러가 안 뜨고, 화면에는 그냥 빈 자리만 남는다. QA에서 잡기 까다로운 이유다.

변경 범위가 넓었던 이유

파일 목록을 보면 Base.astro(레이아웃 공통), 한국어/영어 카테고리 페이지, 영어 인덱스, 영어 상세 페이지 두 개까지 총 6개 파일이다. 하나의 로직 버그라기보다 "같은 패턴을 여러 템플릿에서 복붙했는데 모두 같은 방식으로 잘못 쓰고 있었다"는 상황이다.

이런 경우 팀에서 자주 하는 실수 패턴이 있다. 첫 번째 파일에서 동작하는 것처럼 보이거나 로컬에서 대충 렌더링이 되니까, 나머지 파일에 그대로 복사한다. 그러면 버그도 같이 퍼진다. 페이지 단위로 확인하지 않으면 영어 카테고리나 결과 페이지처럼 트래픽이 상대적으로 적은 곳은 한참 뒤에야 발견된다.

파일 역할 수정 지점
Base.astro 공통 레이아웃 헤더/푸터 주변 공통 슬롯
[category].astro (ko/en) 카테고리 목록 페이지 카테고리별 광고 마커
en/index.astro 영문 메인 상단 슬롯
en/t/[slug]/index.astro 영문 상세 본문 내 삽입 슬롯
en/t/[slug]/r/[result].astro 영문 결과 결과 페이지 슬롯

회고

솔직히 이건 코드리뷰에서 잡혔어야 했다. set:html에 큰따옴표로 감싸인 HTML 리터럴이 들어오면 "이거 escape 되는 거 아닌가?" 한 번쯤 의심하는 게 맞다. Astro 문서에도 표현식 안에는 백틱이나 작은따옴표를 쓰라고 명시되어 있지는 않지만, JSX/TSX 경험이 있는 사람이라면 속성 안에 따옴표 중첩은 본능적으로 피하게 된다.

리뷰어 입장에서 이 패턴을 봤을 때 짚어줄 수 있는 체크리스트를 하나 만들어 두는 게 낫겠다는 생각이 들었다.

  • set:html 값이 따옴표 안에서 따옴표를 포함하는가?
  • raw HTML 삽입 후 실제 DOM에서 escape 여부를 개발자도구로 확인했는가?
  • 광고/외부 스크립트 연동 슬롯은 스테이징에서 실제 마커 초기화까지 확인했는가?

그리고 Base.astro처럼 레이아웃 공통 파일에 있던 버그가 하위 페이지 전체에 영향을 준다는 점도 다시 상기했다. 공통 레이아웃 변경은 항상 "이 파일 하나가 얼마나 많은 페이지에 영향을 주는가"를 먼저 생각하고 들어가야 한다. 이번엔 수정 방향으로 퍼져서 다행이지만, 반대였으면 전 페이지 광고가 한 번에 끊기는 상황이었다.

다음 PR부터는 광고 관련 raw HTML 패턴은 스크린샷이나 DOM 스냅샷을 첨부하는 쪽으로 규칙을 잡아볼 생각이다.


끝.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.