
배경
스크롤 랜딩과 같은 페이지를 구성하고 있는데, 이 페이지의 섹션1은 무한 재생돠는 로띠를 갖고 있고, 섹션2는 iframe으로 임베드된 유튜브 영상을 보여주고 있는 형태다.
문제
이상하게도, 처음 페이지에 들어왔을 때 safari에서 로띠가 잠깐 버벅거리는 현상이 자꾸 발생했다.
도대체 이유가 뭘까 고민하다가 아래 섹션을 처음에 숨김처리했더니 버벅이지 않는 것을 확인했다.
Lottie 동작원리
lottie-web/player/js/animation/AnimationManager.js at bede03d25d232826e0c9dca1733d542d8a7754fb · airbnb/lottie-web
Render After Effects animations natively on Web, Android and iOS, and React Native. http://airbnb.io/lottie/ - airbnb/lottie-web
github.com
Lottie는 requestAnimationFrame으로 부드러운 애니메이션을 제공한다.
따라서 버벅이는 것은 rAF가 제대로 실행되지 않는 것이라 할 수 있고, 스레드 블로킹이 발생했다는 가설을 세우게 됐다.
performance 탭으로 확인


크롬과 safari모두 스크립트 평가로 63 ~ 80ms동안 작업을 수행함을 볼 수 있다.
그런데 이 작업이 스레드를 블로킹하는가?는 여전히 의문이었다.
그래서 실험 환경을 구성해주었다.
실험
Child.html
10초뒤에 스레드를 블로킹하도록 스크립트를 구성했고, 이걸 vercel로 배포했다.
<!DOCTYPE html>
<html>
<head>
<title>Child Frame</title>
</head>
<body>
<h1>🧒 iframe 문서</h1>
<p>10초 뒤 무한 루프를 실행합니다.</p>
<script>
setTimeout(() => {
console.log("🔥 [iframe] 무한 루프 시작!");
while (true) {
// 아무 작업도 하지 않는 무한 루프
Math.random(); // Safari에서 최적화 제거 방지용
}
}, 10000); // 10초 후 실행
</script>
</body>
</html>
Parent.html
자식요소를 iframe으로 열어주는 html을 구성해주었다.
<!DOCTYPE html>
<html>
<head>
<title>Parent Page (localhost:3000)</title>
</head>
<body>
<h1>👨👧 부모 문서</h1>
<p>이 페이지는 1초마다 로그를 찍습니다.</p>
<script>
setInterval(() => {
console.log("✅ [부모] 인터벌 실행됨", new Date().toISOString());
}, 1000);
</script>
<!-- iframe은 다른 오리진의 child.html -->
<iframe src="parent.html의 주소" style="width:600px; height:200px; border:1px solid #ccc;"></iframe>
</body>
</html>
결과
사이트가 같은 경우 (localhost)
둘다 localhost로 수행한 경우에는 크롬과 safari모두 block되었다.
<!DOCTYPE html>
<html>
<head>
<title>Parent Page (localhost:3000)</title>
</head>
<body>
<h1>👨👧 부모 문서</h1>
<p>이 페이지는 1초마다 로그를 찍습니다.</p>
<script>
setInterval(() => {
console.log("✅ [부모] 인터벌 실행됨", new Date().toISOString());
}, 1000);
</script>
<!-- iframe src를 localhost의 child.html로 변경 -->
<iframe src="http://localhost:4000/child.html" style="width:600px; height:200px; border:1px solid #ccc;"></iframe>
</body>
</html>

사진처럼 스레드가 블록되어서 더이상 인터벌이 수행되지 않는다.
site가 다른 경우 (child 배포)
child.html을 vercel로 배포한뒤에 iframe으로 열었더니 크롬과 safari에서 다른 결과가 발생했다.

크롬은 스레드가 블록되지 않지만, safari는 블록된다.
결론
Chrome vs Safari
크롬은 정책상, iframe으로 사이트를 열 때 새로운 스레드를 할당한다.
https://www.chromium.org/developers/design-documents/site-isolation/#requirements
Site Isolation Design Document
Site Isolation Design Document This design document covers technical information about how Site Isolation is built. For a general overview of Site Isolation, see https://www.chromium.org/Home/chromium-security/site-isolation. Chrome's multi-process archite
www.chromium.org
하지만 사파리는 그렇지 않고, 같은 스레드를 사용해 js를 실행한다.
이로 인해서, embed된 유튜브 스크립트를 평가할때 크롬의 경우에는 블로킹이 발생하지 않고, safari는 블로킹이 발생하는 것이다.
해결
SPA의 특성을 활용해서 임베드 스크립트를 이전 페이지에서 미리 받아와서 평가하도록 만들어서 해결했다.