ChatGPT와 MCP 앱이 이중 iframe을 사용하는 이유

📺 원본 영상: Why MCP and ChatGPT Apps Use Double Iframes — Frédéric Barthelet, Alpic 🎙️ 채널: AI Engineer 📅 정리 일자: 2026-06-16 ⚠️ Note: 본 리포트는 영상의 음성을 텍스트로 변환(STT)하여 정리한 것입니다. 화면에 표시된 자료(차트, 코드, 슬라이드 등)는 포함되지 않을 수 있습니다.


개요

MCP 호스팅 기업 Alpic의 CTO이자 공동 창업자인 Frédéric Barthelet(이하 Fred)은 ChatGPT와 같은 대화형 AI 에이전트가 서드파티 UI를 어떻게 렌더링하는지를 실제 DOM 구조 탐구에서 출발하여 이중 iframe(Double Iframe) 메커니즘에 도달하기까지의 과정을 단계별로 해부한다. 단순히 “이중 iframe을 쓴다”는 결론이 아니라, 왜 더 단순한 방법들이 하나씩 실패할 수밖에 없었는지를 Content Security Policy(CSP, 콘텐츠 보안 정책)라는 렌즈를 통해 설명하는 것이 이 강연의 핵심이다. 나아가 Alpic이 개발한 오픈소스 프레임워크 SkyBridge가 이 복잡성을 앱 개발자로부터 어떻게 추상화하는지를 라이브 데모로 보여준다.


MCP 앱과 ChatGPT 앱이란 무엇인가

MCP 앱(MCP App)과 ChatGPT 앱은 기업이 자신의 제품과 서비스를 ChatGPT나 Claude와 같은 범용 대화형 AI 에이전트 안에 노출할 수 있는 새로운 비즈니스 채널이다. Fred에 따르면 이 채널은 두 가지 핵심 속성을 갖는다. 첫 번째는 **발견 가능성(Discoverability)**으로, 앱은 스토어에서 직접 탐색될 수도 있고 대화 맥락에 따라 자동으로 불러와질 수도 있다. 두 번째이자 이 강연이 집중하는 속성은 인터랙티브 UI의 추가다. 기존의 텍스트 응답 위에 MCP 서버가 제공하거나 생성형 UI(Generative UI)로 만들어낸 시각적 인터페이스 레이어가 올라온다는 것이다.

이 UI 기능은 OpenAI가 2024년 10월 Apps SDK를 출시하며 먼저 구현했고, 이후 MCP의 첫 번째 공식 확장(MCP App Extension)으로 표준화되며 여러 클라이언트에 걸쳐 통일된 방식으로 자리잡게 되었다.


Views: 대화 안에 UI를 삽입하는 방식

대화 안에 렌더링되는 이 UI 조각들을 MCP 앱 생태계에서는 View라고 부른다. View는 항상 도구 호출(Tool Call)의 결과로서 렌더링되며, MCP 서버가 노출하는 개별 도구에 메타데이터를 첨부해 “이 도구의 결과는 특정 UI로 표시하는 것이 최적”이라고 선언할 수 있다. 호스트(ChatGPT 등)가 MCP 앱을 지원하면, 해당 도구 호출 시 연결된 View를 찾아 결과를 동적으로 렌더링한다.

View는 구조적으로 단순한 HTML 문서다. CSS를 포함할 수 있으며, 기술적으로 새로운 개념은 아니다. 중요한 점은 모든 View의 존재가 대화 시작 시점의 도구 목록 조회(Tool List Call)에서 미리 광고된다는 것이다. 호스트는 이 정보를 통해 UI 리소스를 미리 캐싱하거나, 해당 도구가 실제로 호출될 때 즉시 다운로드할 수 있다. 도구 호출이 발생하면 호스트는 새로운 iframe을 생성하고 그 안에 도구 결과를 주입해 사용자에게 동적 콘텐츠를 표시한다.

ChatGPT DOM에서 발견한 이중 iframe 구조

03:38 - 강연자가 ChatGPT DOM 내부를 직접 탐색하여 발견한 이중 iframe 구조 — 외부 iframe 안에 내부 iframe이 중첩된 실제 DOM 화면


문제의 출발점: ChatGPT의 Content Security Policy

이 모든 논의의 전제가 되는 개념이 바로 **Content Security Policy(CSP)**다. CSP는 서버가 HTTP 응답 헤더를 통해 브라우저에게 전달하는 지시문 모음으로, 브라우저가 무엇을 로드하고 실행해도 되는지를 명시한다. ChatGPT를 브라우저에서 열면 ChatGPT 서버는 문서와 함께 CSP 지시문을 반환하며, 이 지시문이 어떤 스크립트를 실행할 수 있는지, 어떤 스타일시트나 이미지를 다운로드할 수 있는지, 어떤 API에 연결할 수 있는지를 모두 규정한다.

Fred는 이 중 두 지시문이 이 강연의 핵심이라고 강조한다. **frame-src**는 어떤 도메인의 iframe을 문서 안에 렌더링할 수 있는지를 제어하고, **script-src**는 어떤 스크립트를 실행할 수 있는지를 제어한다. ChatGPT의 script-src는 특히 엄격한데, 모든 스크립트에 **요청마다 새로 생성되는 서명된 nonce(임시 토큰)**가 있어야만 실행을 허가한다. 이는 훌륭한 보안 기능이지만, 동시에 서드파티 앱이 JavaScript를 실행하는 것을 근본적으로 가로막는 장벽이 된다.

CSP 개념 설명 슬라이드

04:36 - Content Security Policy(CSP) 개념 설명 슬라이드 — frame-src와 script-src 지시문이 강조된 CSP 지시문 목록


시도 1: srcdoc 속성 — 같은 Origin의 함정

iframe에는 두 가지 콘텐츠 주입 방식이 있다. 하나는 외부 URL을 가리키는 src 속성이고, 다른 하나는 HTML 콘텐츠를 직접 문자열로 삽입하는 srcdoc 속성이다. 얼핏 보기에 srcdoc는 이상적인 해결책처럼 보인다. 별도 서버 없이 MCP 서버가 노출한 HTML 리소스를 그대로 iframe에 밀어넣기만 하면 되기 때문이다.

그러나 이 방식에는 치명적인 문제가 있다. srcdoc 속성으로 생성된 iframe은 부모 문서와 동일한 Origin을 공유한다. 이는 곧 ChatGPT의 엄격한 script-src CSP가 그대로 적용된다는 의미이며, nonce 서명 없이 작성된 서드파티 앱의 JavaScript는 단 한 줄도 실행될 수 없다. View 안에서 어떤 동적 동작도 불가능해지는 것이다.

src 속성과 srcdoc 속성 비교 슬라이드

06:02 - iframe의 src 속성과 srcdoc 속성 차이를 시각화한 슬라이드 — 두 방식의 동작 방식 비교


시도 2: CSP 완화 — 보안과의 거래

그렇다면 ChatGPT의 CSP를 조금 완화해 서드파티 스크립트의 실행을 허용하면 어떨까? Fred는 이 아이디어를 실험적 사고 실험으로 제시하지만, 즉각 두 번째 문제에 부딪힌다고 설명한다. srcdoc으로 생성된 iframe은 여전히 부모와 동일한 Origin을 공유하기 때문에, iframe 안에서 실행되는 서드파티 앱 스크립트가 localStorage나 쿠키에 접근할 수 있게 된다. 이 저장소들은 Origin을 기준으로 인덱싱되므로, 악의적인 앱이 ChatGPT의 localStorage를 읽어 자신의 백엔드 서버로 전송할 수 있다. OpenAI 입장에서 절대 허용할 수 없는 시나리오다.


시도 3: Sandbox 속성 — Origin 소거의 역설

다음으로 iframe의 sandbox 속성이 등장한다. sandbox는 iframe을 **불투명 Origin(Opaque Origin)**으로 격리시키는 속성으로, iframe이 부모와 Origin을 공유하지 않고 사실상 null Origin으로 동작하게 만든다. 이렇게 하면 앞서 언급한 localStorage나 쿠키 탈취 문제는 해결된다.

그러나 새로운 문제가 생긴다. localStorage, IndexedDB, 쿠키 같이 Origin을 기반으로 동작하는 브라우저 API가 모두 작동을 멈춘다. 이것들은 null Origin으로는 사용할 수 없기 때문이다. 그래서 개발자들은 흔히 sandbox 속성에 allow-same-origin을 추가한다. 그런데 이는 부모의 Origin을 다시 iframe 안으로 끌어들이는 것이어서, 정확히 처음의 문제로 돌아간다. sandbox 격리를 탈출할 수 있는 완벽한 조건이 복원되는 역설이 발생하는 것이다.

sandbox 속성과 allow-same-origin의 역설 도식

08:29 - sandbox 속성과 allow-same-origin의 역설을 설명하는 슬라이드 — sandbox가 오히려 취약점이 되는 구조 도식


시도 4: src 속성으로 개발자 서버 참조 — 무한 허용 목록의 문제

srcdoc 방식을 포기하고, 이번에는 앱 개발자가 자신의 서버에 View 엔드포인트를 노출하고 iframe의 src 속성으로 해당 URL을 참조하는 방식을 생각해볼 수 있다. 이 경우 iframe은 완전히 별개의 브라우징 컨텍스트로 로드되어 Origin 문제가 근본적으로 분리된다.

그러나 여기에는 ChatGPT의 frame-src CSP가 가로막고 있다. frame-src는 iframe으로 로드 허용된 도메인 목록을 명시하는데, ChatGPT 스토어에 등록될 수 있는 MCP 앱의 수는 사실상 무한하다. 새로운 앱이 출시될 때마다 OpenAI가 해당 앱의 도메인을 frame-src 목록에 추가하고 CSP를 갱신해야 한다는 것은 운영상 불가능한 요구사항이다.


시도 5: 프록시 도메인 — 호스팅 부담의 문제

그렇다면 OpenAI가 단일 프록시 도메인, 예컨대 openaiusercontent.com을 운영해 모든 앱의 HTML 리소스를 그 도메인 아래에서 서빙하는 방식은 어떨까? frame-src에 이 단일 도메인만 등록하면 모든 앱을 수용할 수 있다. 실제로 OpenAI는 이 도메인을 사용자 콘텐츠 노출에 활용하고 있다.

그러나 이 방식도 심각한 문제를 안고 있다. 첫째, OpenAI는 자신이 제어하지 않는 서드파티 코드를 자신의 도메인에서 호스팅하는 책임을 떠안게 된다. 어떤 코드인지 알 수 없는 앱들을 자사 도메인에서 실행하는 것은 보안 측면에서 매우 불리한 포지션이다. 둘째, OpenAI나 Anthropic 같은 대형 업체가 아닌 소규모 호스트라면 모든 앱의 콘텐츠를 동적으로 서빙하는 인프라를 구축하고 운영하는 데 필요한 리소스가 없을 수 있다.


최종 해결책: 이중 iframe 메커니즘의 탄생

모든 단순한 해결책이 각각의 이유로 실패한 자리에 등장하는 것이 이중 iframe(Double Iframe) 메커니즘이다. 이 구조는 앞서 나열한 모든 문제를 한꺼번에 해결하는 영리한 설계다.

첫 번째 iframe(외부 iframe)은 ChatGPT와는 다른 전용 도메인—ChatGPT의 frame-src에 등록된 단일 도메인—에서 제공되는 스크립트 로더를 실행한다. 이 스크립트의 내용은 모든 앱에 대해 동일하다. 단지 MCP 서버에서 실제 View 리소스(HTML)를 가져와 두 번째 iframe을 srcdoc 속성으로 초기화하는 역할만 한다. 이 로더 스크립트의 내용이 항상 동일하기 때문에 서버 인프라가 단순해진다. 또한 앱마다 서로 다른 서브도메인을 부여함으로써, 앱 간의 localStorage나 쿠키 충돌도 방지한다. Origin이 서브도메인 단위로 분리되어 앱 A가 앱 B의 데이터에 접근하는 것을 구조적으로 막는다.

두 번째 iframe(내부 iframe)은 srcdoc을 통해 실제 앱 View HTML이 로드되는 공간이다. 이 iframe은 외부 iframe의 전용 도메인을 Origin으로 가져 ChatGPT와 완전히 분리된다. 앱 개발자가 필요로 하는 JavaScript는 이 내부 iframe 안에서 자유롭게 실행된다. 여기에 더해, MCP 앱 스펙에는 앱이 자신의 CSP를 <meta> 태그 형태로 선언하는 방법이 정의되어 있으며, 이 정책은 외부 iframe 안에 올바르게 주입되어 악성 스크립트 실행이나 내부 iframe 안에서의 무단 iframe 생성을 막는 역할을 한다.

이중 iframe 메커니즘 최종 아키텍처 다이어그램

12:10 - 이중 iframe 메커니즘의 최종 아키텍처 다이어그램 — 외부 iframe(스크립트 로더 + 전용 도메인)과 내부 iframe(srcdoc + 앱 View) 구조 전체도

Fred는 이 해결책이 완전히 새로운 발명이 아님을 강조한다. 바로 Facebook이 앱 마켓플레이스를 출시했을 때 직면했던 것과 정확히 같은 문제였고, 당시에 도달한 해결책과 본질적으로 동일한 구조라는 것이다. 서드파티 UI를 자사 애플리케이션 컨텍스트 안에서 안전하게 실행하는 문제는 소셜 미디어 플랫폼 시대부터 반복되어 온 오래된 엔지니어링 과제인 셈이다.


앱 개발자가 반드시 알아야 할 것

이 이중 iframe 구조가 적용되면, 앱 개발자에게 실질적인 의무가 생긴다. Fred는 앱이 의존하는 모든 외부 도메인을 MCP 앱 스펙의 메타데이터에 명시적으로 선언해야 한다고 거듭 강조한다. 예를 들어, View에서 외부 API를 호출해 데이터를 가져오는 경우 해당 API의 도메인을 connect-src 지시문에 등록해야 하고, 외부 스크립트를 로드한다면 script-src에, 외부 이미지를 사용한다면 img-src에 각각 명시해야 한다. 이 선언이 누락되면, 앱은 개발 환경에서는 문제없이 동작하다가 프로덕션(ChatGPT 스토어)에 배포된 순간 해당 리소스 로드가 CSP에 의해 차단되어 동작을 멈추게 된다.

Fred에 따르면, CSP 설정 실수로 인한 ChatGPT 앱 스토어 제출 거절이 실제로 매우 빈번하게 발생하고 있다. 이 경험은 2016년 처음 개발을 시작하던 시절 CORS(Cross-Origin Resource Sharing) 설정을 처음 맞닥뜨리며 겪었던 좌절감과 비슷하다고 Fred는 회상한다. 새로운 규격이지만 익숙한 고통인 셈이다.


Alpic의 SkyBridge: 복잡성을 추상화하다

이 문제를 개발자들이 직접 겪지 않도록 Alpic이 구축한 것이 오픈소스 프레임워크 SkyBridge다. SkyBridge는 공식 MCP Apps SDK의 상위 집합(Superset)으로, 여러 기능을 제공한다. MCP 서버와 앱 View 사이의 **엔드-투-엔드 타입 안전성(End-to-End Type Safety)**을 보장하고, 특정 호스트(Claude 또는 ChatGPT)에서만 지원되는 비표준 API에 대한 폴리필(Polyfill)을 제공하며, 특히 개발 환경에서의 편의 기능을 다수 포함한다.

라이브 데모에서 Fred는 SkyBridge로 생성한 Magic 8-Ball 예제 앱을 보여준다. 이 앱에는 질문에 대한 답변을 생성하는 MCP 도구와 질문·답변을 표시하는 View가 포함되어 있다. SkyBridge 서버를 시작하면 브라우저에서 **개발자 도구(Dev Tool)**에 접근할 수 있는데, 이 도구는 노출된 도구 목록을 좌측에 표시하고 각 도구를 직접 실행하면서 연결된 View가 인스펙터 안에서 라이브로 렌더링되는 것을 확인할 수 있도록 한다.

SkyBridge 개발자 도구 인터페이스

17:32 - SkyBridge 개발자 도구 인터페이스 — 좌측 도구 목록, 우측 View 인스펙터가 함께 표시된 화면

그 중 Fred가 특별히 소개하는 기능이 **CSP 인스펙터(CSP Inspector)**다. 이 도구는 개발자가 메타데이터에 선언한 도메인과 View가 실제로 접근하는 모든 도메인을 비교 분석해, 누락된 도메인이 있으면 즉시 경고를 표시한다. 데모에서 Fred는 코드베이스에 외부 IP 위치 API 호출을 추가하고, 메타데이터에 해당 도메인을 등록하지 않은 상태에서 인스펙터가 곧바로 이를 누락 항목으로 표시하는 것을 보여준다. 해당 도메인을 메타데이터에 추가하면 인스펙터가 초록색으로 바뀌며 검증을 통과한다. 프로덕션 배포 전에 CSP 설정 오류를 로컬 개발 환경에서 잡아낼 수 있는 것이다.

CSP 인스펙터 작동 화면

18:24 - CSP 인스펙터 작동 화면 — 누락된 외부 도메인이 경고로 표시된 상태와 메타데이터 추가 후 초록색으로 전환된 상태 비교


마무리

ChatGPT와 Claude 같은 범용 대화형 AI에 서드파티 인터랙티브 UI를 안전하게 삽입하는 문제는 단순해 보이지만, Content Security Policy라는 브라우저 보안 체계와 정면으로 충돌하는 복잡한 엔지니어링 과제다. srcdoc은 같은 Origin의 함정에, CSP 완화는 데이터 탈취 위험에, sandbox는 Origin 의존 API의 작동 불능에, 프록시 도메인은 인프라 부담과 보안 책임에 막혔다. 이중 iframe은 이 모든 실패의 교훈을 종합한 해결책이며, 그 유효성은 이미 Facebook 앱 마켓플레이스가 십 년 전에 증명한 것이다.

앱 개발자 입장에서는 이 구조의 존재를 이해하고, 자신의 앱이 의존하는 모든 외부 리소스 도메인을 MCP 앱 메타데이터에 빠짐없이 선언하는 것이 스토어 제출 거절을 피하는 가장 중요한 실천 사항이다. SkyBridge의 CSP 인스펙터는 이 과정을 자동화하고 시각화하여, 개발자가 CORS 시절의 시행착오를 반복하지 않도록 돕는다.


📚 출처 및 참고

구분내용
원본 영상Why MCP and ChatGPT Apps Use Double Iframes — Frédéric Barthelet, Alpic
채널AI Engineer
강연자Frédéric Barthelet (CTO & Co-founder, Alpic)
리포트 작성2026-06-16
작성 방식YouTube 영상 STT 변환 후 에디팅

💬 본 리포트는 영상 내용을 바탕으로 재구성되었습니다. 정확한 내용은 원본 영상을 참조해 주세요.