React와 iframe 사이 postMessage 통신을 실제로 구현해본 이야기
iframe에서 react로 메세지 보내기
#React #Iframe
React 앱을 운영하다 보면, iframe을 써야 하는 상황이 생각보다 자주 생긴다. 특히 기존에 JS로 따로 구현된 페이지, 게임 콘텐츠, 외부 위젯 등을 삽입해야 할 때 iframe은 거의 유일한 선택지다. 내가 진행하고 있는 프로젝트에도 게임 콘텐츠가 들어가는데, 이 게임은 HTML, CSS, JS로 구성된 독립형 구조였다. React 내부에 바로 붙일 수 있는 구조가 아니라서 결국 iframe으로 감싸서 띄우는 방식으로 처리하게 됐다. 그런데 문제는 거기서 끝이 아니었다. 단순히 보여주기만 하면 되겠지만, 실제로는 게임이 끝난 뒤 부모인 React에게 완료 신호를 보내거나, React 쪽에서 게임 내부로 데이터를 전달해야 하는 상황이 계속 생겼다. 이번 글에서는 이렇게 iframe과 React 사이에서 메시지를 주고받는 방식 을 어떻게 구성했는지, 그리고 이 방식이 왜 임시방편으로는 유용하지만 장기적으로는 추천되지 않는지 까지 정리해본다. 언제 쓰냐면? React 앱 안에 외부 HTML (예: 게임, 외부 콘텐츠 등)을 iframe으로 삽입했을 때 iframe에서 사용자 행동(예: 미션 완료, 버튼 클릭)을 React로 전달해야 할 때 React에서 iframe으로 상태 변경이나 명령(예: 시작, 정지 등)을 내려야 할 때 React → iframe으로 메시지 보내기 iframe → React로 메시지 받기 iframe 내부에서 메세지 받기 iframe 내부에서 메시지 보내기 주의할 점 postMessage의 두 번째 인자 (targetOrigin)는 무조건 정확한 주소 여야 한다. ' * '로 하면 보안상 위험함. 양쪽 모두 origin 체크 를 해야 예기치 않은 메시지 수신을 막을 수 있다. 보낼 수 있는 데이터는 객체 형태 ({ type: '...', payload: ... })로 구조화하는 것이 좋다. 메시지 종류가 많아지면 switch-case나 별도 핸들러로 정리하자. 왜 이 방식이 이상적인 해결책은 아닐까? iframe + postMessage 조합은 꽤 강력하고 유용한 수단이지만, 다음과 같은 한계도 있다 1. 보안 이슈 서로 다른 도메인 간 통신이기 때문에 targetOrigin을 정확히 설정하지 않으면 XSS 공격에 취약 해질 수 있다. 무조건 정확한 origin을 명시해야 한다. 2. 상태 동기화 어려움 부모와 iframe이 각각 다른 상태를 갖고 있기 때문에 동기화를 하기 위해선 메시지를 계속 보내고 받아야 한다. 구조가 커질수록 유지보수가 복잡해진다. 3. postMessage 디버깅이 불편 console.log만으로 흐름을 추적해야 하고, 타입 안정성도 보장되지 않는다. 단방향 prop이나 hook 기반 설계에 익숙한 React 개발자에게는 번거로운 방식이다. 4. 일시적인 연결 구조에 불과함 iframe으로 통신하는 구조는 임시방편일 뿐, 결국은 React로 완전히 옮기거나 외부 콘텐츠를 라이브러리 형태로 끌어오는 게 더 자연스럽다. 왜 이렇게 구현했는가? 이 방식이 최선은 아니라는 건 알지만, 내가 맡은 프로젝트의 구조상 iframe 방식이 현실적인 선택지 였다. 기존 게임은 Webpack으로 번들링된 독립형 HTML/JS 구조였고 React 내부로 통합할 수 없는 구조였으며 프로젝트 일정상 전체 구조를 갈아엎는 것은 불가능했다 그래서 React에서 iframe을 이용해 게임을 띄우고, postMessage로 통신만 주고받는 식으로 구현했다. 또 React 쪽에서 type: "react" 메시지를 먼저 보내고 iframe 내부에서 그걸 받은 후에야 부모에게 메시지를 보내도록 제한을 걸었다. 운영 서버에 올리더라도 iframe이 무조건 메시지를 보내는 걸 방지하기 위함이었다. 마무리 iframe과 postMessage는 완벽한 구조는 아니지만, 때로는 현실적으로 가장 실용적인 선택이 된다. 특히 기존 외부 콘텐츠나 독립된 페이지를 마이그레이션하는 과도기 단계에서는, 기능을 빠르게 붙이고 시스템을 유지하면서 점진적으로 React로 옮길 수 있는 좋은 징검다리가 되어준다. 이번 프로젝트에서도 이 구조 덕분에 기존 콘텐츠와 React 앱을 유연하게 연결할 수 있었고, 전체 시스템을 안정적으로 유지하면서 필요한 기능을 빠르게 개발할 수 있었다. 물론 궁극적으로는 iframe 없이 React 내부에서 모든 UI와 상태를 통합하는 구조가 이상적이다. 하지만 현실적인 제약 속에서도 어떤 방식이 현재 가장 적합한지 판단하고, 그것을 안정적으로 구현해내는 것도 중요한 개발자의 역량이라고 생각한다.