동적로딩[카카오 맵 동적로딩 문제 해결]

2025. 4. 9. 22:47프론트엔드/REACT

728x90

 


📌 먼저, '동적 로딩'이란?

스크립트가 HTML에 <script>로 외부에서 불러와지고,
그 안에 있는 전역 객체(window.kakao)가 비동기적으로 생성된다는 것.

즉, React 앱이 실행될 때 window.kakao는 처음엔 존재하지 않음.
스크립트가 다운로드되고 실행된 이후에 생기기 때문에 기다려야 함.


🎯 왜 그런 일이 생길까?

우리는 보통 index.html에 이렇게 Kakao Maps SDK를 넣어요:

 

<script src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=...&libraries=services"></script>

이건 정적 HTML에 직접 삽입한 외부 스크립트

즉,

  • 브라우저는 React 앱보다 먼저 <script> 태그를 해석하고
  • 해당 JS 파일을 받아오고
  • 로딩이 끝난 후에야 window.kakao 객체가 만들어짐

하지만 이 시점은 React의 App.tsx 코드보다 늦을 수도 있어요!

그래서 React 컴포넌트 안에서 window.kakao를 바로 사용하면…

console.log(window.kakao) // ❌ undefined (초기 로딩 중일 경우)

✅ 그래서 useEffect에서 체크하는 로직이 필요한 것

useEffect(() => {
  if (window.kakao && window.kakao.maps) {
    setIsLoaded(true);
  } else {
    const interval = setInterval(() => {
      if (window.kakao && window.kakao.maps) {
        clearInterval(interval);
        setIsLoaded(true);
      }
    }, 300);
    return () => clearInterval(interval);
  }
}, []);

이 로직은 아래와 같은 역할을 해요:

단계 설명

1️⃣ useEffect 실행 컴포넌트가 마운트되면 실행됨
2️⃣ window.kakao가 있는지 확인 Kakao 스크립트 로드 완료 여부 체크
3️⃣ 없으면 setInterval로 반복 체크 매 300ms마다 다시 확인
4️⃣ 준비되면 setIsLoaded(true) Kakao API가 사용 가능한 시점 표시

📌 왜 직접 script 태그 삽입 안 하고 npm install react-kakao-maps-sdk만으로 안 될까?

  • react-kakao-maps-sdk는 Kakao 지도 SDK의 React wrapper일 뿐
  • Kakao의 실제 SDK 스크립트는 반드시 따로 <script src=...>로 불러와야 함
  • 이걸 자동으로 해주는 기능은 아직 없음

🔧 만약 script도 코드에서 자동으로 로딩하고 싶다면?

useEffect(() => {
  const script = document.createElement('script');
  script.src = "https://dapi.kakao.com/v2/maps/sdk.js?appkey=...&libraries=services";
  script.async = true;
  script.onload = () => setIsLoaded(true);
  document.head.appendChild(script);
}, []);

이렇게 하면 정말 완전 동적으로 스크립트까지도 코드에서 삽입하게 돼요.
하지만 대부분은 index.html에 고정 <script>로 넣고,
setInterval 방식으로 준비 상태만 확인하는 게 일반적이야.


✅ 정리

개념 설명

Kakao Maps SDK 외부 스크립트로 제공됨 (window.kakao)
동적 로딩 React보다 늦게 로드될 수 있음
대응 방법 useEffect + setInterval로 체크
대안 script 태그를 JS로 직접 삽입 (document.createElement)

 


💡 핵심 개념 1: React는 SPA (Single Page Application)

  • React 앱은 단 하나의 HTML 파일 (index.html)을 기반으로 전체 UI를 렌더링함
  • 이 HTML 안에 <script>로 Kakao Maps SDK를 넣었을 경우, → React 앱보다 먼저 브라우저가 해석할 수도, 못 할 수도 있음

즉, React는 JS 실행 타이밍과는 별개로 동작하므로 외부 스크립트가 완전히 로드되지 않은 상태에서도 앱이 실행될 수 있음


💡 핵심 개념 2: JS 로딩 타이밍과 DOMContentLoaded

브라우저는 보통:

  1. <head> → <body> → <script> 순으로 HTML 파싱
  2. 외부 스크립트 <script src="...">는 비동기로 다운로드됨
  3. React 앱의 main.tsx가 실행되는 시점은 스크립트 다운로드 완료보다 빠를 수 있음

따라서:

console.log(window.kakao); // ❌ undefined

💡 핵심 개념 3: React는 CSR (Client Side Rendering)

React는 서버에서 완성된 HTML을 내려주는 게 아니라,
브라우저에서 JS를 실행해서 DOM을 동적으로 그리는 방식

즉,

  1. React 앱이 실행되며 ParkingMap 컴포넌트가 렌더됨
  2. 이 시점에 window.kakao가 없으면 에러
  3. useEffect가 동작해서 “아직 Kakao가 없음”을 확인
  4. 일정 간격으로 window.kakao 존재 여부를 감시
  5. 준비되면 isLoaded = true로 바꿔서 지오코더 실행

💥 왜 setInterval로 직접 체크해야 하나?

React가 먼저 실행되는 이유는:

  • React의 JS 번들 (main.tsx)은 webpack/vite에 의해 번들링된 정적 자바스크립트
  • 반면 Kakao의 SDK는 CDN에서 다운로드되는 외부 JS
  • 로드 시점과 실행 시점이 서로 다르다 → 즉, window.kakao는 항상 존재한다고 보장할 수 없음

📌 결론

<head> 브라우저가 가장 먼저 읽음 → 빠른 로딩 가능 통과!!

 

728x90