조회수: 14

ERR_BLOCKED_BY_RESPONSE: Chrome 해결

ERR_BLOCKED_BY_RESPONSE는 COEP/CORP 정책이 교차 출처 리소스를 막은 것. COEP와 CORP 헤더를 점검하세요. 무료 HTTP 진단.

내 도메인에 이 문제가 있는지 지금 확인

무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.

문제

Chrome이 리소스 — 이미지, 스크립트, 폰트, iframe — 를 net::ERR_BLOCKED_BY_RESPONSE로 로드하지 못합니다. 뒤에 .NotSameOriginAfterDefaultedToSameOriginByCoep 같은 긴 접미사가 붙는 경우가 많죠. 헷갈리는 부분: 네트워크 탭엔 요청이 200으로 성공했다고 나오는데, 리소스는 페이지에 끝내 나타나지 않습니다.

증상

  • 콘솔에 net::ERR_BLOCKED_BY_RESPONSE 또는 점 붙은 변형(.NotSameOrigin, .NotSameOriginAfterDefaultedToSameOriginByCoep, .CorpNotSameOrigin)이 뜹니다.
  • 실패하는 리소스는 거의 항상 교차 출처 — CDN 자산, 광고, 임베드 위젯, 서드파티 호스트의 폰트입니다.
  • 응답 상태가 200 OK라 서버 오류처럼 보이지 않습니다.
  • 리소스 자체를 건드린 게 아니라 의존성 업그레이드·새 보안 헤더 미들웨어·플랫폼 기본값 변경 이후에 시작됐습니다.

이 오류의 진짜 의미

ERR_BLOCKED_BY_RESPONSE는 네트워크 실패가 아닙니다. 요청은 나갔고 응답도 돌아왔습니다. 그다음 Chrome이 페이지가 켜둔 cross-origin isolation 정책 중 하나를 적용해 그 응답이 전달돼선 안 된다고 판단하고 떨궜습니다. 차단은 성공적인 fetch 이후에 내려지는 정책 결정이고, 그래서 로드되지 않은 리소스 옆에 초록색 200이 보이는 것입니다.

거의 항상 관여하는 정책은 COEPCross-Origin-Embedder-Policy입니다. 페이지가 Cross-Origin-Embedder-Policy: require-corp를 보내면 이렇게 선언하는 셈입니다: 내가 임베드하는 모든 교차 출처 대상은 임베드되는 것에 명시적으로 동의해야 한다. 리소스가 동의하는 방법은 둘 — 임베드를 허용하는 Cross-Origin-Resource-Policy(CORP) 헤더를 달거나, CORS로 가져와지거나. 교차 출처 리소스가 둘 다 안 하면 COEP는 그것을 same-origin으로 기본 처리하고, same-origin이 아님을 확인해 차단합니다. 그 정확한 연쇄가 저 길고 긴 NotSameOriginAfterDefaultedToSameOriginByCoep가 설명하는 것입니다.

COEP와 함께 다니는 헤더가 둘 더 있습니다. COOP(Cross-Origin-Opener-Policy: same-origin)는 페이지를 자신이 여는 창, 자신을 연 창으로부터 격리합니다. CORP(Cross-Origin-Resource-Policy)는 리소스가 누가 임베드해도 되는지 말하려고 보내는 헤더입니다. COEP는 요구이고, CORP는 동의입니다. 이 오류는 그 요구가 동의한 적 없는 리소스를 만났을 때 벌어지는 일입니다.

가장 흔한 원인 3가지

  1. COEP 페이지가 CORP 헤더 없는 리소스를 임베드 - 대표 사례. 페이지가 Cross-Origin-Embedder-Policy: require-corp를 보내는데(직접 설정한 적 없이 보안 라이브러리를 통해 나가는 경우가 많습니다), Cross-Origin-Resource-Policy를 설정하지 않는 CDN에서 이미지·스크립트·폰트를 로드합니다. COEP가 그 리소스를 same-origin으로 기본 처리하고, 아니어서 Chrome이 .NotSameOriginAfterDefaultedToSameOriginByCoep로 막습니다.
  2. 임베드에 비해 너무 엄격한 CORP 헤더 - 리소스가 CORP를 보내긴 하는데, 임베드가 진짜 교차 출처인 상황에서 same-origin이나 same-site로 설정돼 있습니다. 헤더가 존재하며 능동적으로 “너는 안 돼”라고 말하는 것이고, .CorpNotSameOrigin으로 표출됩니다. 퍼스트파티용 리소스를 여러 도메인에 재사용할 때 흔합니다.
  3. 의도치 않은 기본값으로 켜진 COOP/COEP - 프레임워크 프리셋이나 호스팅 플랫폼이 SharedArrayBuffer도 정밀 타이머도 필요 없는데 격리 헤더를 내보냅니다. 이제 모든 서드파티 임베드가 아무 이득 없이 COEP를 만족시켜야 하고, 어제까지 되던 게 배포 후 깨집니다.

DechoNet으로 진단하기

  • HTTP 진단은 어떤 URL이든 정확한 응답 헤더를 보여줍니다. 당신의 페이지에 돌려 Cross-Origin-Embedder-PolicyCross-Origin-Opener-Policy를 보내는지 확인하고, 실패하는 리소스의 URL에 돌려 Cross-Origin-Resource-Policy를 보내는지 확인하세요. 그 두 답 사이의 불일치가 버그의 전부입니다.
  • SSL 진단은 리소스 호스트가 HTTPS로 깨끗이 서빙되는지 확인해, 차단으로 위장한 mixed-content나 인증서 문제를 배제합니다.

해결 체크리스트

  • 오류 문자열 전체를 읽으세요. 접미사(.NotSameOriginAfterDefaultedToSameOriginByCoep vs .CorpNotSameOrigin)가 리소스에 CORP가 아예 없는지, 아니면 너무 엄격한 CORP를 보내는지 알려줍니다.
  • 자기 페이지에 HTTP 진단을 돌리세요. Cross-Origin-Embedder-Policy: require-corp가 보이는데 SharedArrayBuffer나 performance.now() 고해상도 타이머를 실제로 안 쓴다면, 가장 간단한 해결은 COEP 전송을 멈추는 것 — 보안 미들웨어에서 제거하세요.
  • cross-origin isolation이 정말 필요하다면, 임베드하는 리소스 응답에 Cross-Origin-Resource-Policy: cross-origin을 추가하세요(당신 것이라면). 아니라면 CDN·제공업체에 추가를 요청하세요.
  • 바꿀 수 없는 서드파티 리소스라면 페이지를 Cross-Origin-Embedder-Policy: credentialless로 전환하세요. 자격증명 없는 요청에 대해 CORP 요구를 면제하므로, CORP 헤더 없는 CDN 자산이 CDN을 건드리지 않아도 로드됩니다.
  • 변경 후 두 URL에 HTTP 진단을 다시 돌려, 페이지의 요구와 리소스의 동의가 이제 맞아떨어지는지 확인하세요.

에스컬레이션 시점

  • 리소스가 당신이 통제 못 하는 CDN·SaaS에서 서빙되고 CORP 헤더를 안 보내면, Cross-Origin-Resource-Policy: cross-origin 추가를 그쪽에 에스컬레이션하세요 — 아니면 당신 쪽에서 COEP: credentialless로 옮겨 그들을 기다리지 마세요.
  • 자기 설정에서 지웠는데도 격리 헤더가 계속 나타나면, 앱 위의 프록시·WAF·호스팅 계층이 주입하는 것입니다 — 헤더가 어디서 들어오는지 보여주는 HTTP 진단 출력과 함께 그 계층 담당자에게 넘기세요.
  • 어떤 기능 때문에 cross-origin isolation이 정말 필요한데 핵심 서드파티 임베드가 CORP를 거부하고 credentialless에서도 깨진다면, 그건 헤더 조정이 아니라 아키텍처 결정(리소스를 퍼스트파티로 프록시)입니다.

관련 도구

관련 가이드

가이드 공유

[Ad] Guide Detail Inline
← 전체 가이드 보기