Cloudflare가 이메일 난독화 스크립트를 수정했습니다 (제가 계기였을 수도 있습니다)

Cloudflare 이메일 난독화 스크립트는 원래 렌더링을 차단했습니다. Cloudflare 프로덕트 매니저가 이 글을 읽고 수정을 배포했습니다. SEO와 보안 문제는 여전히 피해야 합니다.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-10-15

Cloudflare 이메일 난독화란 무엇인가?

Cloudflare 이메일 주소 난독화(Email Address Obfuscation)는 Scrape Shield 기능입니다. 페이지 내 이메일 주소를 일반 방문자에게는 그대로 보여주면서, 이메일 수집기와 봇으로부터 숨깁니다. 모든 Cloudflare 존에서 기본으로 활성화되어 있습니다.

최종 검토: Arjen Karel (2026년 4월)

2026년 4월 업데이트: Cloudflare가 문제를 해결했습니다. Cloudflare 프로덕트 매니저가 LinkedIn으로 메시지를 보내왔습니다. 이 글을 읽고 email-decode.min.js에 defer 속성을 추가했습니다. Cloudflare 공식 문서에서도 이를 확인할 수 있습니다. 해당 스크립트는 더 이상 렌더링을 차단하지 않습니다.

cloudflare email obfuscatino defer fix

defer 추가는 코드 한 줄짜리 변경입니다. 애초에 적용되지 않았던 이유는 DOMContentLoaded 전에 주소가 디코딩되어야 하는 사이트가 깨지지 않는지 확인할 필요가 있었기 때문일 것입니다. 팀의 누군가가 직접 이 작업을 해냈습니다. 인정할 것은 인정해야 합니다.

동작 방식은 간단합니다. Cloudflare 엣지 프록시가 HTML에서 이메일 주소처럼 보이는 문자열을 모두 스캔합니다. 그런 다음 각 주소를 XOR 인코딩된 16진수 문자열로 바꾸고, 브라우저에서 이를 디코딩할 email-decode.min.js라는 작은 스크립트를 삽입합니다. 이 스크립트 크기는 약 1.2 KB이며, 이제 defer로 로드되고 실행 후 DOM에서 스스로를 제거합니다.

얼마 전까지만 해도 이 스크립트는 async나 defer 없이 로드되었습니다. 렌더링을 차단했습니다. 대부분의 방문자가 알아채지도 못하고 필요로 하지도 않는 기능 때문에 렌더링을 막은 것입니다. 이 글이 원래 지적했던 문제가 바로 이것이었고, Cloudflare가 수정한 이유이기도 합니다.

cloudflare email obfuscation settings.

Cloudflare 이메일 난독화가 Core Web Vitals에 미쳤던 영향

email obfuscation network.

defer 패치 전에는 email-decode.min.js 스크립트가 render blocking 리소스로 삽입되었습니다. 브라우저는 페이지 렌더링을 계속하기 전에 이 스크립트를 다운로드하고, 파싱하고, 실행해야 했습니다. 그 결과 세 가지 문제가 발생했습니다:

1. 렌더링에 핵심적인 구간에서 네트워크 대역폭을 차지해 Largest Contentful Paint를 지연시켰습니다.
2. main thread를 차단해 Interaction to Next Paint를 '개선 필요' 영역으로 밀어낼 수 있었습니다.
3. 최대 5개의 Lighthouse 감사 경고를 발생시켰습니다: render blocking 리소스 제거, main thread의 long task 방지, JavaScript 실행 시간 단축, 중요 요청 체인 방지, 그리고 효율적인 캐시 정책으로 정적 에셋 제공.

이제 defer가 적용되어 스크립트는 HTML 파싱과 병렬로 다운로드되며, 문서 파싱이 끝난 뒤에 실행됩니다. render blocking 경고도 사라졌습니다.

수정 후에도 남아 있는 문제

main thread는 여전히 1.2 KB의 JavaScript를 파싱하고 실행해야 합니다. 데스크톱에서는 아무것도 아닙니다. 하지만 CPU가 바쁜 보급형 Android 스마트폰에서는 사소한 main thread 작업 하나하나가 INP 예산을 갉아먹습니다. 이미 마지막 50 ms의 INP 여유를 확보하기 위해 씨름하고 있다면, 이 스크립트는 대기열에 얹어지는 또 하나의 부담입니다.

더 큰 문제는 따로 있습니다. Cloudflare가 해결하지 않은 문제들입니다.

SEO 부작용

Cloudflare는 이메일 주소를 /cdn-cgi/l/email-protection#[hex]로 연결되는 링크로 대체합니다. 이 URL은 Googlebot을 포함한 크롤러에 404를 반환합니다. 그 결과 Google Search Console에 "Soft 404" 오류가 발생합니다. Ahrefs나 Screaming Frog 같은 SEO 감사 도구는 이를 깨진 내부 링크로 보고하여, 실제 크롤링 문제를 가리는 노이즈를 만듭니다. Cloudflare에서 이메일 난독화를 켜 둔 상태라면 Search Console 색인 범위 보고서에서 이런 유령 오류가 없는지 확인해 보세요.

Cloudflare 이메일 난독화는 과연 안전한가?

전혀 그렇지 않습니다. Cloudflare는 인코딩된 문자열 자체에 키가 포함된 1바이트 XOR 암호를 사용합니다. Cloudflare로 보호되는 모든 사이트가 동일한 디코딩 방식을 씁니다. 스패머 입장에서는 디코더 하나만 구현하면 이 모든 사이트에서 이메일 주소를 추출할 수 있습니다.

보안 연구원들이 입증했듯이, 이 인코딩은 손쉽게 역산할 수 있습니다. Spencer Mortensen의 2026년 난독화 연구에서는 허니팟 이메일 주소를 이용해 300곳 이상의 서로 다른 스패머를 대상으로 25가지 난독화 방식을 테스트했습니다. 단순한 CSS display:none 기법만으로도 수집기 차단율 100%를 달성했습니다. 봇으로부터 이메일 주소를 숨기자고 defer된 JavaScript까지 동원할 필요는 없습니다.

지금도 비활성화해야 하는가?

이메일 난독화가 필요 없다면(대부분의 사이트에는 필요 없습니다), 기능을 끄는 것만으로 soft 404 크롤링 오류를 없애고 main thread 작업 시간을 몇 밀리초라도 더 줄일 수 있습니다. 설정 방법은 다음과 같습니다:

1. Cloudflare 대시보드에 로그인합니다.
2. Security > Settings(이전 대시보드 레이아웃의 경우 Scrape Shield)로 이동합니다.
3. Email Address Obfuscation을 OFF로 전환합니다.

이게 전부입니다. 스크립트가 즉시 사라집니다. 전체적인 Cloudflare 성능 최적화 설정은 Core Web Vitals 통과를 위한 최적의 Cloudflare 설정을 참고하세요.

Configuration Rules로 페이지별 비활성화하기

문의 페이지에는 이메일 난독화를 적용하고 트래픽이 많은 랜딩 페이지에서는 끄고 싶다면, Configuration Rule을 사용하세요:

1. Rules > Configuration Rules로 이동합니다.
2. 새 규칙을 생성하고 이름을 지정합니다(예: "Disable email obfuscation on landing pages").
3. 일치 조건(호스트 이름, URL 경로, 또는 둘 다)을 설정합니다.
4. Email Obfuscation 설정을 추가하고 Off로 지정합니다.
5. 배포합니다.

HTML 내 개별 이메일 주소를 주석으로 감싸 예외로 둘 수도 있습니다: <!--email_off-->email@example.com<!--/email_off-->

난독화가 꼭 필요하다면: 직접 구현하세요

봇으로부터 이메일 주소를 숨겨야 한다면, 사용자가 관심을 보이기 전까지 어떤 스크립트도 전송하지 않는 훨씬 더 나은 방법이 있습니다. 가장 좋은 방법은 IntersectionObserver를 연결하고 이메일이 viewport 안으로 스크롤될 때 적시에(just-in-time) 디코딩하는 것입니다. 이는 YouTube 임베드부터 Google Maps까지 모든 작업에 사용하는 필요할 때까지 지연(defer until needed) 패턴과 동일합니다.

난독화된 이메일 만들기

여기서는 단순한 base64 인코딩을 사용했습니다. base64 인코딩은 예시일 뿐이며, 무료로 쓸 수 있는 인코딩 및 디코딩 라이브러리는 얼마든지 있습니다.
<a
 class="email-hidden"
 href="#"
 data-email="aW5mb0BleGFtcGxlLmNvbQ==">
 [email-hidden]
</a>

IntersectionObserver를 연결합니다. 다음 JavaScript 코드를 페이지 하단에 배치하세요.

<script>
const emailtag = document.querySelector('.email-hidden');
let observer = new IntersectionObserver((entries) => {
  entries.map((entry) => {
    if (entry.isIntersecting) {
      let script = document.createElement('script');
      script.onload = function () {
        emaildecode(entry.target)
      };
      script.src = 'decode-email.js';
      document.head.appendChild(script);
    }
  });
}).observe(emailtag);
</script>

이메일 디코딩 스크립트인 decode-email.js를 업로드하고, 이메일 디코딩 함수를 원하는 디코딩 라이브러리로 교체합니다.

const emaildecode = (e) => {
	let email = atob(e.dataset.email);
	e.href = 'mailto:'+email;
	e.innerHTML = email;
}

결과 확인

<a href="mailto:info@example.com">info@example.com</a>

방문자가 이메일을 viewport 안으로 스크롤할 때만 디코딩됩니다. INP 영향은 전혀 없고, Googlebot에 soft 404 오류를 유발하지도 않으며, 보안 면에서도 base64 인코딩이 Cloudflare의 XOR 암호보다 못할 것이 없습니다. 실제 방문자를 통한 개선 효과를 확인하려면 Real User Monitoring을 설정하세요. Lighthouse 점수는 디버깅에 유용하지만, Google이 순위 산정에 사용하는 것은 실제 사용자의 field data입니다.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

보고서 말고 코드를 씁니다.

1~2 스프린트 동안 팀에 합류해서 모니터링까지 세팅해둡니다. 제가 빠진 뒤에도 지표가 계속 초록으로 유지되도록.

연락 주세요
Cloudflare가 이메일 난독화 스크립트를 수정했습니다 (제가 계기였을 수도 있습니다) Core Web Vitals Cloudflare가 이메일 난독화 스크립트를 수정했습니다 (제가 계기였을 수도 있습니다)