동적로딩[카카오 맵 동적로딩 문제 해결]
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
브라우저는 보통:
- <head> → <body> → <script> 순으로 HTML 파싱
- 외부 스크립트 <script src="...">는 비동기로 다운로드됨
- React 앱의 main.tsx가 실행되는 시점은 스크립트 다운로드 완료보다 빠를 수 있음
따라서:
console.log(window.kakao); // ❌ undefined
💡 핵심 개념 3: React는 CSR (Client Side Rendering)
React는 서버에서 완성된 HTML을 내려주는 게 아니라,
브라우저에서 JS를 실행해서 DOM을 동적으로 그리는 방식
즉,
- React 앱이 실행되며 ParkingMap 컴포넌트가 렌더됨
- 이 시점에 window.kakao가 없으면 에러
- useEffect가 동작해서 “아직 Kakao가 없음”을 확인
- 일정 간격으로 window.kakao 존재 여부를 감시
- 준비되면 isLoaded = true로 바꿔서 지오코더 실행
💥 왜 setInterval로 직접 체크해야 하나?
React가 먼저 실행되는 이유는:
- React의 JS 번들 (main.tsx)은 webpack/vite에 의해 번들링된 정적 자바스크립트
- 반면 Kakao의 SDK는 CDN에서 다운로드되는 외부 JS
- 로드 시점과 실행 시점이 서로 다르다 → 즉, window.kakao는 항상 존재한다고 보장할 수 없음
📌 결론
<head> 브라우저가 가장 먼저 읽음 → 빠른 로딩 가능 통과!!
728x90
'프론트엔드 > REACT' 카테고리의 다른 글
| s3이미지 업로드 후 리뷰 완성! (0) | 2025.05.01 |
|---|---|
| 컴포넌트 인터페이스와 Props (0) | 2025.04.01 |
| React와 Chart.js로 구현하는 레이더 차트: RadarChart 컴포넌트 분석[FC] (0) | 2025.04.01 |
| QRReader 컴포넌트[FC] (0) | 2025.04.01 |
| [CATSPOT]층별 학교 강의실 구조 설정 & 시간표 연동 BA2 페이지 구현기 (0) | 2025.03.27 |