부모창에서 iframe을 이용해서 부모창과 다른 도메인을 가진 자식창을 호출해야 하는 경우가 있습니다.
예를 들면, 내가 만든 홈페이지에 구글 애드센스나, 애드픽 등을 넣는 경우 등이 해당됩니다.
아래와 같은 구조가 되는 거죠.
부모창에서 다른 도메인을 가진 iframe 페이지 표시하는 방법
일반적으로 부모창에 서로 다른 도메인을 가진 iframe을 추가하게 되면 아래와 같이 에러가 발생하면서 자식창이 화면에 표시가 안됩니다.
에러 메세지 : Refused to display 'http://localhost:8181/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
같은 도메인에서만 호출을 허용하도록 설정이 되어 있기 때문입니다.
그래서 아래와 같이 다른 도메인에서 호출해도 화면에 표시가 되도록 iframe 서버의 로직을 수정합니다.
처음엔 부모창의 서버 로직을 수정해야 하는 줄 알았는데 자식창의 서버 로직을 수정해야 했습니다.
//iframe src URL 호출하는 JAVA 로직
@RequestMapping(value = "/iframe.do")
public String iframe(Model model, HttpServletResponse response) throws Exception {
//... 처리 로직...
//http://abc.com : 부모창 도메인
response.setHeader("X-Frame-Options", "ALLOW-FROM http://abc.com");
return "jspPage";
}
저는 특정 URL에 대해서만 허용하기 위해 위와 같이 처리했는데, 자식창의 모든 URL에 대해서 설정을 변경하려면 서버에서 환경설정을 변경하면 됩니다. ('X-Frame-Options' to 'sameorigin'. 으로 구글 검색하면 관련된 내용이 많이 나옵니다. )
서로 다른 도메인인 부모창과 자식창간 함수 호출(데이터 통신)하는 방법
위와 같이 처리하니 다음으로 부모창과 자식창간 함수를 호출하는 문제가 발생했습니다.
당연히 서로 도메인이 다르기 때문에 아래와 같은 에러메세지가 뿜어 나오네요.
//일반적으로 iframe의 함수를 호출하는 방법
var iframe = document.getElementById('child_iframe').contentWindow;
iframe.childFunction();
에러메세지 : Uncaught DOMException: Blocked a frame with origin "http://localhost:8001" from accessing a cross-origin frame.
직접 함수를 호출하는 방법이 없기 때문에 다른 방법을 이용해야 합니다.
바로 window.postMessage() 입니다.
자식창에서 부모창으로 데이터를 전달하는 방법
targetWindow.postMessage(message, targetOrigin, [transfer]);
window.onload = function() {
console.log('child load');
//targetWindow.postMessage(message, targetOrigin, [transfer]);
window.parent.postMessage({ childData : 'test data' }, 'http://abc.com');
//모든 도메인에 대해서 허용하고자 하는 경우 targetOrigin(두번째인자) 인자를 '*'로 작성
//보안을 위해 추천하지 않음
//window.parent.postMessage({ childData : 'test data' }, '*');
};
자식창이 보낸 데이터를 부모창이 받아서 활용하는 방법
window.addEventListener('message', function(e) {}); 를 이용
window.addEventListener('message', function(e) {
console.log('parent message');
console.log(e.data); // { childData : 'test data' }
console.log("e.origin : " + e.origin); //http://123.com(자식창 도메인)
if(e.data.childData === 'test data'){
...처리 로직 (부모창 함수 호출)
}
});
부모창에서 자식창으로 데이터를 보내는 방법도 동일합니다.
function sendMessageIframe(){
var iframe = document.getElementById('child_iframe').contentWindow;
iframe.postMessage({ parentData : 'test parent data', 'http://123.com');
}
자식창에서는 아래와 같이 부모창이 보낸 데이터를 활용할 수 있습니다.
window.addEventListener('message', function(e) {
console.log('child message');
console.log(e.data); // { parentData : 'test parent data' }
console.log("e.origin : " + e.origin); //http://abc.com(부모창 도메인)
if(e.data.parentData === 'test parent data'){
...처리 로직 (자식창 함수 호출)
}
});
좀 더 자세한 설명은 아래 링크를 참고하시기 바랍니다.
https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage
https://developer.mozilla.org/ko/docs/Web/Events/message
'Javascript & Jquery' 카테고리의 다른 글
[Javascript] HTML5 Web Storage 를 언제 사용해야 할까? (cookie 대신 활용한 사례) (0) | 2019.05.16 |
---|---|
서버작업 없이 엑셀파일 내용을 JSON으로 변환해서 활용하는 예제(HTML5 FileReader + Javascript SheetJS) (0) | 2019.05.09 |
[Javascript] 재귀함수 실제 적용한 예제. 사용자가 입력한 여러 키워드를 조합하는 기능 (0) | 2019.04.23 |
[jquery] li 태그의 data 속성을 이용해서 정렬하는 방법(jquery sort() 함수 사용) (0) | 2019.04.22 |
[Javascript] 객체(Object) 생성, 프로퍼티(key, value) 접근하는 다양한 방법 (0) | 2019.04.19 |