[FAQ] 지도/로컬 API 문의 전 꼭 읽어 주세요.
react-native webview로 kakaomap을 구현하고 있습니다.
android 환경에서는 정상적으로 그려지는데 ios환경에선 지도 load를 못하고 있는거 같습니다.
import {View, Text, StyleSheet} from 'react-native';
import WebView, {WebViewMessageEvent} from 'react-native-webview';
import {KAKAO_API_KEY} from '../../utils/consts';
import {useState} from 'react';
interface KakaoMapProps {
lat?: string;
lng?: string;
address: string;
addressDetail?: string;
companyName: string;
height?: number;
onTouchStart?: () => void;
onTouchEnd?: () => void;
}
const KakaoMap: React.FunctionComponent<KakaoMapProps> = ({
lat,
lng,
address,
addressDetail,
companyName,
height = 400,
onTouchStart,
onTouchEnd,
}) => {
// 주소 전체 텍스트를 미리 만들기
const fullAddress = addressDetail ? `${address} ${addressDetail}` : address;
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<script type="text/javascript" src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=${KAKAO_API_KEY}&libraries=services"></script>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
touch-action: none;
}
#map {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
touch-action: none;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const initMap = async () => {
try {
const container = document.getElementById('map');
let position;
if ('${lat}' && '${lng}') {
position = new kakao.maps.LatLng(${lat || 0}, ${lng || 0});
} else {
try {
const geocoder = new kakao.maps.services.Geocoder();
const result = await new Promise((resolve, reject) => {
geocoder.addressSearch('${address}', (results, status) => {
if (status === kakao.maps.services.Status.OK && results?.[0]) {
resolve(results[0]);
} else {
reject(new Error('Geocoding failed'));
}
});
});
position = new kakao.maps.LatLng(result.y, result.x);
} catch (error) {
position = new kakao.maps.LatLng(37.5666805, 126.9784147);
}
}
const options = {
center: position,
level: 3,
draggable: true,
zoomable: true,
};
const map = new kakao.maps.Map(container, options);
const marker = new kakao.maps.Marker({
position: options.center
});
marker.setMap(map);
const content = \`
<div style="
padding: 8px 12px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
font-size: 14px;
font-weight: 500;
max-width: 200px;
word-break: keep-all;
text-align: center;
border: 1px solid rgba(0,0,0,0.1);
position: relative;
transform: translateY(-42px);
">
${companyName}
<div style="
position: absolute;
bottom: -5px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-top: 8px solid white;
filter: drop-shadow(0 2px 2px rgba(0,0,0,0.1));
"></div>
</div>
\`;
const customOverlay = new kakao.maps.CustomOverlay({
content: content,
position: options.center,
yAnchor: 1
});
customOverlay.setMap(map);
} catch (error) {
console.error(error);
}
};
document.addEventListener('DOMContentLoaded', initMap);
</script>
</body>
</html>
`;
return (
<View style={styles.container}>
{/* 위치 아이콘과 회사명 헤더 */}
<View style={styles.companyHeader}>
<View style={styles.locationIconContainer}>
<View style={styles.locationIcon} />
</View>
<Text style={styles.companyName} numberOfLines={1} ellipsizeMode="tail">
{companyName}
</Text>
</View>
{/* 지도 영역 */}
<View
style={{
height,
width: '100%',
marginVertical: 0,
borderRadius: 0,
overflow: 'hidden',
backgroundColor: '#f5f5f5',
}}
onTouchStart={onTouchStart}
onTouchEnd={onTouchEnd}>
<WebView
source={{html: htmlContent}}
style={{flex: 1}}
// scrollEnabled={false}
// bounces={false}
// showsHorizontalScrollIndicator={false}
// showsVerticalScrollIndicator={false}
// javaScriptEnabled={true}
/>
</View>
{/* 주소 표시 카드 */}
<View style={styles.addressCard}>
<Text style={styles.addressText} numberOfLines={2}>
{fullAddress}
</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
marginVertical: 15,
borderRadius: 12,
overflow: 'hidden',
backgroundColor: 'white',
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
companyHeader: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: 'white',
borderBottomWidth: 1,
borderBottomColor: '#f0f0f0',
},
locationIconContainer: {
width: 28,
height: 28,
borderRadius: 14,
backgroundColor: '#fdf5f9',
alignItems: 'center',
justifyContent: 'center',
marginRight: 12,
shadowColor: '#E8588C',
shadowOffset: {width: 0, height: 0},
shadowOpacity: 0.2,
shadowRadius: 6,
elevation: 3,
borderWidth: 1,
borderColor: '#f9e0eb',
},
locationIcon: {
width: 12,
height: 12,
borderRadius: 6,
backgroundColor: '#E8588C', // 핑크색
shadowColor: '#E8588C',
shadowOffset: {width: 0, height: 0},
shadowOpacity: 0.6,
shadowRadius: 4,
elevation: 4,
},
companyName: {
fontSize: 16,
fontWeight: '600',
color: '#333',
flex: 1,
},
addressCard: {
width: '100%',
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: 'white',
borderTopWidth: 1,
borderTopColor: '#f0f0f0',
},
addressText: {
width: '100%',
fontSize: 15,
color: '#333',
fontWeight: '400',
flexWrap: 'wrap',
flexShrink: 1,
lineHeight: 22,
},
});
export default KakaoMap;
inpo.plist에서 설정도 알맞게 잘 한거 같은데 어디 설정을 좀더 해줘야 할까요?
undefined is not a constructor (evaluating 'new kakao.maps.LatLng
로그찍어보면 이런 에러가 나오는거 같습니다.