들어가며

최근 같은 유형의 이슈가 연달아 터졌다.

 

에러 케이스

 

부모 - 자식 관계에 있는 iframe 또는 팝업 창에서 부모창의 함수를 실행하는 경우 아래와 같은 동일한 현상이 발생하여 이슈 처리 방법에 대해 남겨본다.

부모창 함수 호출 시 발생하는 에러 화면

 

원인

부모창과 자식창의 Origin이 다르기 때문이다.

브라우저는 Same-Origin 정책을 취하므로, 스크립트가 다른 Origin으로 접근하지 못하도록 한다.

(부모창과 자식창의 프토토콜, 호스트네임, 포트 번호 동일해야 함)

 

해결 방법

Window.postMessage() 사용하기

해당 메소드는 Window 오브젝트 간 Cross-Origin 통신을 안전하게 할 수 있도록 한다.

즉, Same-Origin이 아니더라도 통신할 수 있게 한다.

 

대체로 한 window는 다른 윈도우를 참조할 수 있고, (ex. targetWindow = window.opener), targetWindow.postMessage()를 통해 다른 window에 MessageEvent를 전송할 수 있다.

 

이를 통해 이벤트를 받는 window에서 사용할 수 있다.

 

부모창에서 자식창으로 메시지 전송시

targetWindow.postMessage(message, targetOrigin, [transfer]);

// 예시
window.opener.postMessage({data: 'data_to_send'}, 'https://child.abc.net');

 

message : 다른 window에 보낼 데이터

targetOrigin : targetWindow의 origin 지정. "*" 또는 URI이어야 함.

 

자식창에서 메시지 받을 때

window.addEventListener("message", receiveMessage);

function receiveMessage(event) {
  if (event.origin !== "https://parent.abc.net") return;
  
  // 자식창이 전송한 데이터 확인
  console.log(event.data);
  
  // TODO...
  
}

 

부모창의 함수를 호출하고 싶다면?

부모창에서 자식창으로 메시지 전송시

window.parent.postMessage(
  {
    funcName: 'openStudyPlanSurveyResult',
    params: ['1', '2', '3']
  },
  '*'
);

 

자식창에서 메소드 호출 방법

회사에서 필요한 jQuery, 구식으로 짠다면

$(window).on('message', function({ originalEvent : e }) {
	if (e.origin !== "https://parent.abc.net") return;

	var data = e.data;
    
	if (!$.isEmptyObject(data) && typeof(window[data.funcName]) === 'function') {
		var execFunc = new Function('return ' + data.funcName)();
		var param1 = data.params[0];
		var param2 = data.params[1];
		var param3 = data.params[2];
		// 함수 실행
		execFunc(param1, param2, param3);
	}
});

function openStudyPlanSurveyResult(a, b, c) {
	console.log('call', a, b, c);
}

 

조금 더 모던하게 짠다면

window.addEventListener('message', (e) => {
	if (e.origin !== "https://parent.abc.net") return;
    
	if (e.data.funcName) {
		// 함수 실행
		window[e.data.funcName](
			...e.data.params
		);
	}
});

function openStudyPlanSurveyResult(a, b, c) {
	console.log('call', a, b, c);
}

 


출처

https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage

 

Window.postMessage() - Web API | MDN

window.postMessage() 메소드는 Window 오브젝트 사이에서 안전하게 cross-origin 통신을 할 수 있게 합니다. 예시로, 페이지와 생성된 팝업 간의 통신이나, 페이지와 페이지 안의 iframe 간의 통신에 사용할

developer.mozilla.org

https://velog.io/@jkas2020/CORS-iframe-%EB%B6%80%EB%AA%A8-%EC%9E%90%EC%8B%9D-%EA%B0%84-%ED%95%A8%EC%88%98%ED%98%B8%EC%B6%9C

 

[CORS] iframe 부모-자식 간 함수호출

며칠 전에 있었던 \[Vue.js] 외부 자바스크립트에서 Vue Component method 호출하기 이슈를 해결한 뒤 이어서 작업하던 중, 이번엔 상호 함수호출 중 CORS 이슈가 터졌다.포털을 구성하는 Vue.js 파일이 업

velog.io

https://stackoverflow.com/questions/25098021/securityerror-blocked-a-frame-with-origin-from-accessing-a-cross-origin-frame

 

SecurityError: Blocked a frame with origin from accessing a cross-origin frame

I am loading an <iframe> in my HTML page and trying to access the elements within it using JavaScript, but when I try to execute my code, I get the following error: SecurityError: Blocked a ...

stackoverflow.com

https://junspapa-itdev.tistory.com/55

 

서로 다른 도메인을 사용하는 부모창과 자식창(iframe) 간 데이크 통신하는 방법(크로스도메인, pos

부모창에서 iframe을 이용해서 부모창과 다른 도메인을 가진 자식창을 호출해야 하는 경우가 있습니다. 예를 들면, 내가 만든 홈페이지에 구글 애드센스나, 애드픽 등을 넣는 경우 등이 해당됩니

junspapa-itdev.tistory.com

 

'프론트엔드 > JavaScript' 카테고리의 다른 글

Scope  (0) 2020.12.26

+ Recent posts