티스토리 뷰

발생일: 2014.11.30

키워드: postMessage, message

문제:
window.postMessage()에 대한 메모이다.


해결책:

일반적으로 스크립트는 동일 근원 정책에 의해, 프로토콜, 도메인, 포트 중 어느 하나라도 다른 경우엔 다른 윈도우와 통신할 수 없다.
하지만, `window.postMessage()`를 사용하면 안전하게 오리진이 다른 윈도우와 통신할 수 있다.

아래 코드와 같이 다른 윈도우로 메시지를 보낼 수 있다.

otherWindow.postMessage(message, targetOrigin);

- otherWindow:
    - `window.open()` 의 응답으로 얻은 윈도우 객체
    - `iframe`의 `contentWindow` 프로퍼티로 가져온 윈도우 객체
    - `window.frames` 프로퍼티에서 가져온 윈도우 객체

- message: 전달할 데이터. (JSON도 가능하다)
- targetOrigin:
    - 메시지를 받을 타겟 오리진. 프로토콜, 도메인, 포트를 URL 형태로 전달한다. 
    - ‘*’ 문자열로 모든 윈도우로 전달할 수도 있지만, 악성 스크립트에서 해당 이벤트를 받을 수 있으므로 가능한 명시하는 것이 좋다.


예를 들어, 아래 코드는 `iframe`이라는 아이디를 가진 <iframe> 으로 메시지를 보낸다.

var iframeWindow = document.getElementById(‘iframe’).contentWindow;
iframeWindow.postMessage(‘hello’, ‘http://ohgyun.com');


메시지를 받을 때는, 윈도우의 ‘message’ 이벤트에 대한 핸들러를 등록하면 된다.
핸들러의 파라미터로 전달되는 이벤트 객체에는 아래 프로퍼티가 포함되어 있다.

- data: 전달받은 데이터
- origin: 메시지를 보낸 윈도우의 오리진
- source: 메지시를 보낸 윈도우의 레퍼런스. 이 레퍼런스로 다시 메시지를 보낼 수 있다.


아래 코드를 보면 이해하기 쉽다.

window.addEventListener(‘message’, function (e) {
  if (e.origin === ‘http://ohgyun.com') {
    console.log(e.data); //—> ‘hello’가 출력된다.
    e.source.postMessage(‘hi’, ‘http://ohgyun.com');
  }
});


`window.postMessage()`를 사용할 때 몇 가지 주의할 점이 있다.
- 어떤 윈도우는 `postMessage()`를 전달하고 받을 수 있기 때문에, 구현할 때에 반드시 origin을 체크해야 한다.
- 메시지를 받는 윈도우에서 에러가 발생해도, 메시지를 보낸 윈도우에서는 알 수 없다.
- 보내는 윈도우에서 `document.domain`의 속성을 변경해도, 이벤트의 `origin` 값은 변경되지 않는다.
- 메시지를 보내는 윈도우가 `javascript:`나 `data:` URL일 경우엔, 이벤트의 `origin` 속성을 해당 스크립트를 로드한 페이지이다.
- 크롬 익스텐션에서 메시지를 보내는 경우, `source`는 항상 `null`로 설정된다.


좀 더 자세한 내용은 아래 링크를 참고하면 된다.





반응형
댓글
공지사항