iframe 임베딩 검사

무료 온라인 iframe 체크기: 웹페이지 URL을 입력하여 X-Frame-Options 및 Content-Security-Policy(frame-ancestors) 헤더를 분석하고, iframe 임베딩 가능 여부를 확인하세요. 라이브 미리보기로 결과를 직접 검증할 수 있습니다. 검색 기록은 현재 브라우저 세션 동안에만 유지됩니다.

IFrame 임베딩 검사

:

각 줄을 동일한 헤더 검사 로직으로 처리하여 하단 세션 기록에 추가합니다. 한 번에 최대 20개의 URL만 처리하며, 대상 사이트 부하 고려하여 일부씩 순차적으로 검사합니다.

검사 완료: /
URL 결과 HTTP

실시간 미리보기

헤더 검사는 빠른 1차 확인 수단이지만, JavaScript 프레임 깨기(frame-busting) 스크립트는 감지하지 못합니다. 헤더가 '임베딩 가능'이라고 출력되는데도 미리보기가 비어 있거나 창을 벗어나거나 오류 페이지가 표시되면, 해당 페이지는 안전하게 임베딩될 수 없습니다. 최종 판단은 실시간 미리보기를 통해 내려집니다.

검사 기록 (현재 세션)

현재 탭에서만 저장(sessionStorage)되며, 탭을 닫으면 기록이 삭제됩니다. 서버에는 아무것도 전송되지 않습니다.

현재 세션에 검사 기록이 없습니다.

작동 원리

  1. 대상 URL을 입력하고 '검사하기'를 클릭하세요. 서버가 실제 iframe 요청(헤더: Sec-Fetch-Dest: iframe)으로 페이지를 가져오며 응답 헤더를 분석합니다.
  2. 결과는 X-Frame-Options(DENY/SAMEORIGIN이 프레임 사용 차단)과 Content-Security-Policy frame-ancestors(* 또는 스키마 와일드카드 패턴만 임의의 제3자 부모 도메인을 허용)에 기반합니다.
  3. 실시간 미리보기 iframe에 동일한 URL을 불러와서 헤더로는 알 수 없는 JavaScript 프레임 깨기 동작을 포함한, 브라우저의 실제 렌더링 상태를 직접 확인할 수 있습니다.

페이지 임베딩 여부는 무엇으로 결정되나요?

웹페이지가 다른 사이트의 <iframe> 내부에 표시될 수 있는지 여부는 브라우저에서 해당 페이지가 전송하는 응답 헤더를 기준으로 결정됩니다. 이 체크기는 서버 측에서 동일한 검사를 수행하여 즉시 결과를 알려드립니다.

X-Frame-Options는 전통적인 헤더입니다. DENY는 모든 페이지에서의 임베딩을 금지하고, SAMEORIGIN은 동일 출처의 페이지에만 임베딩을 허용합니다(ALLOW-FROM은 최신 브라우저에서 지원이 중단됨). 해당 헤더가 누락될 경우 기존 규칙에서는 임베딩을 차단하지 않습니다.

Content-Security-Policy의 frame-ancestors는 이를 대체하는 현대적인 방식입니다. 페이지 임베딩이 허용된 출처를 나열합니다(예: frame-ancestors 'self' https://example.com). 값이 *이거나 https:와 같은 순수 스킴인 경우 모든 HTTPS 상위 문서의 임베딩을 허용하며, 그보다 제한적으로 지정하면 제삼자의 임베딩을 차단합니다.

헤더만으로 모든 상황이 판단되는 것은 아닙니다. 페이지 스크립트가 프레임 버스팅(frame-busting) 코드를 실행(top !== self 비교 및 최상위 탐색 강제)할 수 있으며, 로그인 페이지나 지역 제한 엔드포인트는 데이터센터 요청 시 다른 방식으로 동작할 수 있습니다. 따라서 모든 결과에는 실시간 미리보기가 함께 제공됩니다.

빠른 설정 가이드: 응답 헤더 구성

사이트 소유자라면 응답 헤더를 통해 직접 임베딩을 제어할 수 있습니다.

모든 페이지에서의 임베딩 차단

X-Frame-Options: DENY Content-Security-Policy: frame-ancestors 'none'

브라우저가 모든 <iframe>에서 해당 페이지를 렌더링하지 못하게 차단합니다 — 가장 강력한 클릭 재킹(clickjacking) 방어 옵션입니다.

동일 출처에서의 임베딩만 허용

X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors 'self'

스킴, 호스트, 포트가 동일한 페이지만 임베딩할 수 있으며, 외부 사이트는 차단됩니다.

특정 출처에서의 임베딩만 허용

Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com

frame-ancestors에 신뢰할 수 있는 출처를 명시하세요. 목록에 등록되지 않은 출처는 모두 차단됩니다.

모든 페이지에서의 임베딩 허용

X-Frame-Options 설정 안 함 Content-Security-Policy: frame-ancestors *

모든 사이트에서 해당 페이지를 <iframe>으로 임베딩할 수 있습니다. 보안상의 트레이드오프를 충분히 고려하십시오.

참고: CSP의 frame-ancestors는 X-Frame-Options를 대체합니다. 두 헤더가 모두 존재할 경우 CSP가 우선 적용되므로, frame-ancestors 사용을 권장합니다.

서버는 어떻게 iframe 요청임을 감지하나요?

2020년경부터 크롬 및 파이어폭스 기반 브라우저는 모든 탐색 및 서브리소스 요청에 자동으로 Fetch Metadata 요청 헤더 세트를 첨부합니다. 프레임 점검에 가장 유용한 것은 Sec-Fetch-Dest로, 요청 페이지의 별도 동의 없이도 어떤 컨텍스트에서 리소스를 호출했는지 서버에게 알려줍니다.

  • Sec-Fetch-Dest: document — 최상위 탐색(일반적인 페이지 이동, 프레임 외부)
  • Sec-Fetch-Dest: iframe — 요청이 <iframe> 요소 내부에서 로드됨
  • Sec-Fetch-Dest: frame — 레거시 <frame>(프레임셋) 내부에서 로드됨
  • Sec-Fetch-Dest: embed / object — <embed> 또는 <object> 요소 내부에서 로드됨

이 체크기는 실제 브라우저가 페이지를 임베딩할 때 보내는 것과 정확히 동일한 방식으로 `Sec-Fetch-Dest: iframe` 헤더를 포함해 자체 탐지 요청을 보냅니다. 이를 통해 해당 서버가 일반 HTTP 요청이 아닌 실제 iframe 요청에 어떻게 반응하는지 정확하게 파악할 수 있습니다.

`Sec-Fetch-Dest`는 유용한 참고 신호일 뿐, 보안 경계(security boundary)로 작용하지 않습니다. 이 헤더는 최신 브라우저에서만 자동으로 추가되며, curl이나 봇, 일부 WebView, 구형 브라우저 등 비브라우저 클라이언트는 이를 완전히 생략하거나 원하는 대로 설정할 수 있습니다. 서버는 이를 기준으로 로깅하거나 속도 제한(rate limiting)을 적용할 수는 있지만, 프레임 임베딩 안전성을 최종 결정하기 위해 이 헤더에만 의존해서는 안 됩니다. 프레임 사용 허용 여부는 여전히 `X-Frame-Options`와 CSP(`frame-ancestors`) 정책에 따라야 하며, 이는 브라우저가 요청 헤더와 무관하게 독립적으로 강제 적용합니다.

클라이언트 측에서는 특정 요청 헤더 없이도 페이지가 프레임 내부에서 실행되고 있는지 검출할 수 있습니다. 예를 들어 `window.top !== window.self` 조건을 확인하거나(동일 출처 프레임의 경우 `window.frameElement` 속성 읽기), 그 결과를 바탕으로 경고 창을 띄우거나 강제로 최상단(window.top) 페이지로 리디렉션하는 식의 대응이 가능합니다. 앞서 언급한 '프레임 깨기(frame-busting)' 기법이며, 요청 헤더 설정 여부와 상관없이 정상적으로 작동합니다.

서버 설정 예시: iframe 임베딩 차단

아래 코드 스니펫은 각 서버 또는 프레임워크에서 <iframe> 임베딩을 완전히 차단하는 설정 방법(X-Frame-Options: DENY + CSP frame-ancestors 'none')을 안내합니다. 이는 위 퀵 가이드 중에서 가장 엄격한 설정법입니다.

server {
    location / {
        add_header X-Frame-Options "DENY" always;
        add_header Content-Security-Policy "frame-ancestors 'none'" always;
    }
}
<IfModule mod_headers.c>
    Header always set X-Frame-Options "DENY"
    Header always set Content-Security-Policy "frame-ancestors 'none'"
</IfModule>
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
  next();
});
// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          { key: 'X-Frame-Options', value: 'DENY' },
          { key: 'Content-Security-Policy', value: "frame-ancestors 'none'" },
        ],
      },
    ];
  },
};
class SetFrameOptions
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);
        $response->headers->set('X-Frame-Options', 'DENY');
        $response->headers->set('Content-Security-Policy', "frame-ancestors 'none'");

        return $response;
    }
}
export default {
  async fetch(request) {
    const response = await fetch(request);
    const headers = new Headers(response.headers);
    headers.set('X-Frame-Options', 'DENY');
    headers.set('Content-Security-Policy', "frame-ancestors 'none'");
    return new Response(response.body, { status: response.status, headers });
  },
};

내 사이트나 간단한 허용 목록에서만 임베딩을 허용해야 한다면 어떻게 해야 할까요? DENY를 SAMEORIGIN으로, 'none'을 'self' 또는 명시적 출처 목록으로 교체하면 됩니다. 나머지 설정은 동일하게 유지됩니다.

주요 플랫폼 주의사항

일반적인 헤더 규칙 외에도 주요 플랫폼들마다 고유한 특수 사항이 존재합니다. 헤더 정보만으로 단순히 ‘차단됨’ 또는 ‘임베드 가능’이라고 단정 짓기 전에 꼭 확인해보시길 권장합니다.

플랫폼 / 시나리오 동작 상태 사유
YouTube 재생 페이지 (youtube.com/watch) 차단됨 일반 재생 URL 대신 공식 `youtube.com/embed/{id}` 플레이어 URL을 사용하세요. 기존 시청 페이지는 엄격한 프레임 임베딩 정책을 적용하고 있습니다.
Google 지도 장소 페이지 차단됨 프레임 임베딩용으로 의도된 것은 Maps Embed API iframe URL(`google.com/maps/embed`)뿐입니다.
Google/Microsoft OAuth 로그인 페이지 차단됨 2015년부터 iframe 내 자격 증명 피싱(credential phishing) 방지를 위해 의도적으로 차단했으며, 로그인 프로세스는 최상단 창(top-level window)이나 팝업에서 실행되어야 합니다.
결제 체크아웃 페이지 (Stripe Checkout, PayPal, 대다수 은행 게이트웨이) 차단됨 결제 폼의 프레임 임베딩은 고전적인 클릭재킹(clickjacking) 공격 경로이므로, 결제 처리業者는 이를 원천적으로 거부합니다.
GitHub 리포지토리/파일 페이지 차단됨 사이트 전체에 `frame-ancestors 'none'` 정책이 적용되어 있습니다. iframe 대신 REST/GraphQL API를 활용하거나 스크린샷 이미지를 사용하는 것을 권장합니다.
Notion/Google Docs ‘웹에 게시(Publish to web)’ 페이지 임베드 가능 임베딩을 명시적으로 고려하여 설계되었으며, 서비스 내에서 즉시 사용 가능한 임베드 코드를 제공합니다.
위키백과(Wikipedia) 문서 임베드 가능 기본적으로 제한적인 `X-Frame-Options` 또는 CSP 정책이 적용되지 않지만, 대규모 임베딩 전 라이선스 및 출처 표기 조건을 반드시 확인해야 합니다.

일반적인 사용 사례

  • 통합 코드 작성 전, 타사 위젯·대시보드·문서 등의 자사 제품 임베드 가능성 여부를 명확히 판단하는 데 사용됩니다.
  • 자사 사이트가 의도한 `X-Frame-Options` 또는 CSP `frame-ancestors` 정책이 정상적으로 전송되는지 검증하는 데 사용됩니다.
  • 클릭재킹 방어 디버깅: iframe 내에서 페이지가 `about:blank`로 표시되거나 접근 거부 메시지를 출력하는 원인을 파악하세요.
  • 콘텐츠 수집 또는 포털 연동 시 후보 URL을 일괄 검사하고, 세션 기록을 활용하여 결과를 재확인하세요.
  • 외부 종속성에 대한 프레임 정책 문서를 작성하여 보안 검토나 침투 테스트에 대비하세요.

자주 묻는 질문(FAQ)

"임베딩 가능"으로 진단된 페이지가 미리보기에서는 왜 빈 화면으로 나타나나요?
응답 헤더에서는 프레임 사용이 허용되더라도, 실제로는 자바스크립트 기반 프레임 차단 코드가 동작하거나 로그인/쿠키 인증이 필요해 빈 화면이 발생할 수 있습니다. 또한 방문자별로 다른 콘텐츠를 제공하기도 합니다. 따라서 실제 테스트 결과인 미리보기를 기준으로 판단하시기 바랍니다.
X-Frame-Options 또는 CSP 지시어를 우회할 수 있나요?
안 됩니다. 해당 헤더는 클릭재킹 공격으로부터 사용자를 보호하기 위해 브라우저가 직접 강제 적용하는 보안 기능입니다. 클라이언트 측 우회 방식은 불안정하며 권장되지 않습니다. 타사 콘텐츠를 임베드하려면 사이트 관리자에게 frame-ancestors 허용 목록에 본인 도메인을 등록해 달라고 요청하거나, 서비스에서 제공하는 공식 임베딩/API 기능을 이용해야 합니다.
DENY와 SAMEORIGIN은 어떻게 다른가요?
DENY는 모든 iframe(자기 도메인 페이지 포함)에서 프레임을 완전히 차단합니다. 반면 SAMEORIGIN은 프로토콜, 호스트, 포트가 동일한 페이지에서의 프레임 사용만 허용합니다.
이 도구에서 제 URL은 저장되나요?
검사 기록은 전적으로 브라우저 탭의 sessionStorage에 저장되며, 탭을 닫으면 자동으로 삭제됩니다. 검사 서버는 요청한 URL의 응답 헤더를 확인하기 위해 해당 URL에 접속하는 것 외에는 데이터를 저장하지 않습니다.
동일한 URL인데도 검사 결과가 매번 다른 경우가 있는데, 이유가 무엇인가요?
웹 사이트는 접근 경로, 리다이렉트 이동 후, User-Agent 값, 혹은 A/B 테스트 또는 WAF 방호 정책에 따라 응답 헤더를 동적으로 변경할 수 있습니다. 최신 상태를 확인하려면 반드시 새로 검사를 실행하세요.