일반적으로 스크립트는 동일 근원 정책에 의해, 프로토콜, 도메인, 포트 중 어느 하나라도 다른 경우엔 다른 윈도우와 통신할 수 없습니다.
하지만, window.postMessage()를 사용하면 안전하게 서로 다른 도메인을 가진 다른 윈도우와 통신할 수 있게 됩니다.
간단한 예제코드는 아래와 같습니다.
otherWindow.postMessage(message, targetOrigin);
otherWindow:
- window.open() 의 응답으로 얻은 윈도우 객체
- iframe 의 contentWindow 프로퍼티로 가져온 윈도우 객체
- window.frames 프로퍼티에서 가져온 윈도우 객체
message:
- 전달할 데이터 (JSON도 가능하다)
targetOrigin:
- 메시지를 받을 타겟 오리진. 프로토콜, 도메인, 포트를 URL 형태로 전달한다.
"*" 문자열로 모든 윈도우로 전달할 수도 있지만, 악성 스크립트에서 해당 이벤트를 받을 수 있으므로 가능한 명시하는 것이 좋습니다.
예를 들어, 아래 코드는 example 이라는 아이디를 가진 <iframe>으로 데이터를 보내는 예제입니다.
<iframe id="example" src="https://other-domain.com/receive.html"></iframe> <script type="text/javascript"> var iframeWindow = document.getElementById("example").contentWindow; iframeWindow.postMessage("hello world!","https://other-domain.com"); </script>
받는 측에서는 윈도우의 message 이벤트를 통해 데이터를 받을 수 있습니다.
위의 예제코드상으로 https://other-domain.com/receive.html 파일에 작성되어야 하는 내용입니다.
<script type="text/javascript"> window.addEventListener("message", function (e) { if (e.origin === "https://domain.com") { // 위의 예제 코드가 작성된 곳의 도메인주소 console.log(e.data); // "hello world!" 가 출력된다. e.source.postMessage("hi", "https://domain.com"); // e 객체를 활용하여, 메시지를 보낸 곳으로 다시 메시지를 보낼 수 있다. } }); </script>
window.postMessage()를 사용할 때 몇 가지 주의할 점이 있습니다.
1. 메시지를 받는 윈도우에서 에러가 발생해도, 메시지를 보낸 윈도우에서는 알 수 없다.
2. 보내는 윈도우에서 "document.domain"의 속성을 변경해도, 이벤트의 "origin" 값은 변경되지 않는다.
3. 메시지를 보내는 윈도우가 "javascript:"나 "data:" URL일 경우엔, 이벤트의 "origin" 속성을 해당 스크립트를 로드한 페이지이다.
4. 크롬 익스텐션에서 메시지를 보내는 경우, "source"는 항상 null로 설정된다.
좀 더 자세한 내용은 아래 링크를 참고하면 되며,
https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage
postMessage 브라우져별 지원여부는 아래 링크를 참고하시면 됩니다.
https://caniuse.com/#search=postMessage