iframe은 parent html과는 독립적인 execution context를 갖고 있다. (즉, script가 따로 돌아간다.)
console에서 html을 선택할 수 있다.
iframe에서 parent와 child간의 access가 가능하기 위해서는 아래 조건이 만족 되어야 한다.
sandbox="allow-same-origin"
이어야함parent -> child 로 access 하려면 document.querySelector('iframe').contentWindow
로 접근 (contentWindow 참고)
child -> parent로 access하려면 parent
로 접근 하면 됨
아래 이미지는 codepen.io가 어떻게 front app과 통신하는지 보여주는 이미지이다.
iframe이 reload되면, iframe 자체의 html과 js로 cdpn.io와 통신한다. (iframe에서 직접적인 access가 불가능하게 하려면, 다른 domain을 써야 하므로 codepen.io가 아닌 다른 이름의 도메인(cdpn.io)를 사용한다.)
image reference: Udemy course (Typescript: The Complete Developer's Guide by Stephen Grider) |
Applies extra restrictions to the content in the frame. The value of the attribute can either be empty to apply all restrictions, or space-separated tokens to lift particular restrictions - MDN
sandbox property를 사용하면, iframe html에서 parent html에 접근하는것을 막을 수 있다.
source code | iframe DOM access blocking |
// index.html
// srcDoc은 src와 달리 request없이 사용할 수 있다.
<iframe sandbox="" srcDoc={html} />
(...생략)
const html = `<h1> Hello World! </h1>`;
위에서는 sandbox=""로 해줬기 때문에, script를 실행 시킬 수 없다. (빈 공백은 html을 load하는 것만 허락한다.)
아래처럼 sandbox="allow-scripts"로 iframe을 load하면서 script가 실행되도록 할 수 있다. 즉 sandbox는 iframe의 실행과 관련된 property이다.
const html = `
<script>
${code}
</script>
`;
return (
<div>
<textarea value={input} onChange={(e) => setInput(e.target.value)} />
<div>
<button onClick={onClick}>Submit</button>
</div>
<pre>{code}</pre>
<iframe sandbox="allow-scripts" srcDoc={html} />
</div>
);
아래 이유들은 iframe에서 parent html의 DOM에 접근을 막아야하는 이유가 될 수 있다.
import ReactDOM from 'react-dom'을 해보았다. 아래 에러가 발생하였다.
확인을 해보니, 코드가 중간에 끊겨있다? (마지막에 뜬근없이 <script>
가 있다.)
이유를 보아하니, import한 react-dom의 코드중간에 <script></script>
인 부분이 있다.
const html = `
<script>
(...)<script></script> // <--- /script 에 의해서 예상치 못한 시점에 script태그가 끊어진것, 그리고 앞에 있는 <script>가 string으로 들어간것이다.
</script>
`;
아래 이미지가 문제의 구간이다. unpkg의 react-dom 코드에서 찾아볼 수 있다.
parent와 iframe간에는 통신하는 방법이 있다.
postMessage를 이용하는 것이다.
contentWindow.postMessage(message, targetOrigin)
으로 보내고, iframe의 script에 window.addEventListener('message', callback)
을 추가하여, message를 받을 수 있다.
postMessage의 두번째 parameter는 targetOrigin으로, '*'
을 넣으면 모든 origin(parent-url)로 부터 접근을 허용하는 것임.
이 방법을 이용하면, iframe의 <script></script>
안에 직접 string으로 된 code를 넣을 필요가 없다. (iframe에서 js를 실행하기 위해서 script tag 안에 code를 직접 넣는것은 program의 crash를 만들 수 있다.)