window.parent.postMessage / iframe과 부모window간 통신
현업 투입 후 첫 게시글.
배울게 정말 많고 정신도 없었다!
회사에 프로젝트가 여러 개인데 계정 관련된 통합 로그인이 따로 있다.
그 통합로그인 페이지는 iframe width100% height 100%을 사용해서 연동되어 있다.
iframe안에서 링크를 연결했는데 모든 링크가 그 iframe안에서 발생하고 만약 다시 iframe을 실행하면 또 중첩이 될 것이다.
이로 인해 없었던 스크롤이 생기는 에러가 있었다. (iframe안에 생긴 스크롤이겠지?)
처음에는 단순히 window.parent.location.href를 작성해서 부모 window의 url을 변경시켜 이동시킬 생각이었다.
하지만 iframe의 도메인과 부모 window의 도메인이 다르기 때문에 보안 문제로 에러가 발생.
이런 경우에 iframe안에서 발생한 이벤트를 부모 window객체에 안전하게 전달하기 위한 것이 바로 postMessage다.
(iframe과 관련된 상황에서만 사용하는 것은 아니고 새 window를 만들때도 사용할 수 있는 것 같다.)
https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage
문법
targetWindow.postMessage(message, targetOrigin, [transfer]);
iframe내부에서 window.parent.postMessage()로 이벤트를 보낸다.
이 글은 iframe과 관련된 내용이니 targetWindow는 iframe을 품고 있는 부모 window가 된다. (window.parent)
message는 데이터 객체이다.The structured clone algorithm을 이용해서 직렬화 한다는데... 그냥 저 알고리즘 덕분에 안전하게 객체데이터를 보낼 수 있다고 이해하면 될 것 같다.
targetOrigin은 targetWindow의 origin이다. 문자열로 들어가는데 "*"를 입력할 수 있다.
이벤트를 전송할때 targetWindow의 스키마, 호스트, 포트가 targetOrigin과 일치해야 이벤트가 전송된다.
여기서 이벤트로 치명적인 정보를 보내는 사람은 없겠지만.. 보안문제로 인해 targetOrigin을 입력한다.
"*"를 입력하면 이를 별도로 지정하지 않고 모든 url과 이벤트를 주고받게 된다.
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://example.org:8080")
return;
// ...
}
iframe을 품고있는 상위 프로젝트에서 message이벤트를 받을 수 있다.
receiveMessage에 event에 data로 iframe에서 보냈던 그 객체데이터를 받을 수 있다.
여기까지가 postMessage()의 역할이었고
이제부터는 어떤 메세지를 보내고 부모 window에서 어떤 로직을 추가하는지에 따라 다양하게 활용할 수 있다.