본문 바로가기

IT정리/java

[카카오 지도 API] 2개 이상의 지도 추가 시 랜더링 에러 삽질기

카카오 지도 API 활용 중 발생한 에러와 해결 과정

카카오 지도 API를 활용하여 여러 개의 지도를 탭 형태로 전환하며 표시하려고 할 때 발생한 문제와 이를 해결한 과정을 공유한다.

기존의 카카도 지도API 소스코드는 다음과 같다.

// 스크립트 동적 로드
const script = document.createElement('script');
script.src = 'https://dapi.kakao.com/v2/maps/sdk.js?appkey=[MY_APP_KEY]&autoload=false'; 
document.head.appendChild(script);

script.onload = () => {
    window.kakao.maps.load(() => {
        const maps = [
            {
                id: 'map1',
                center: new window.kakao.maps.LatLng(33.450701, 126.570667),
                positions: [
                    { title: '카카오', latlng: new window.kakao.maps.LatLng(33.450705, 126.570677) },
                    { title: '근린공원', latlng: new window.kakao.maps.LatLng(33.451393, 126.570738) }
                ]
            },
            {
                id: 'map2',
                center: new window.kakao.maps.LatLng(33.450701, 124.570667),
                positions: [
                    { title: '카카오', latlng: new window.kakao.maps.LatLng(33.450705, 126.570677) },
                    { title: '근린공원', latlng: new window.kakao.maps.LatLng(33.451393, 126.570738) }
                ]
            },
            {
                id: 'map3',
                center: new window.kakao.maps.LatLng(33.450701, 123.570667),
                positions: [
                    { title: '카카오', latlng: new window.kakao.maps.LatLng(33.450705, 126.570677) },
                    { title: '근린공원', latlng: new window.kakao.maps.LatLng(33.451393, 126.570738) }
                ]
            }
        ];
	// 지도 객체를 저장할 배열
	const mapIndex = [];
        maps.forEach(({ id, center, positions }) => {
            const container = document.getElementById(id);
            const options = { center, level: 3 };
            const map = new window.kakao.maps.Map(container, options);
	    // 생성된 지도 객체를 maps 배열에 저장
	    mapIndex.push(map);

            positions.forEach(position => {
                const marker = new window.kakao.maps.Marker({
                    map,
                    position: position.latlng,
                    title: position.title
                });

                const infowindow = new window.kakao.maps.InfoWindow({
                    content: '<div style="padding:5px;">'+position.title+'</div>'
                });

                infowindow.open(map, marker);
            });
        });
    });
};

문제 상황

  1. 여러 지도 표시 및 탭 전환 구현
    • HTML 페이지에서 탭 형태로 여러 개의 지도를 전환하여 표시했다.
    • 각 탭 클릭 시, 해당 탭과 연결된 지도가 표시되고 나머지는 숨기도록 구현했다.
  2. 발생한 에러
    • 초기 구현 시 아래와 같은 소스코드를 사용했다. 그러나 탭 전환 시 리렌더링 문제가 발생하여 지도가 정상적으로 표시되지 않았다.
    • 지도 컨테이너가 display: none 상태였다가 다시 display: block으로 변경된 후, 지도 크기를 재계산하지 못해 에러가 발생한 것으로 보인다.

 

해결 과정

문제 원인

  • 카카오 지도 API는 지도 컨테이너가 display: none 상태에서 크기를 제대로 계산하지 못한다.
  • relayout 메서드를 호출해서 컨테이너 크기를 재계산한다.
  • 지도 중심 좌표도 다시 설정(setCenter())해서 설정한대로 지도가 표출되도록 한다.

해결 방법

다음은 문제를 해결한 카카도 지도API 소스코드다.

// 스크립트 동적 로드
const script = document.createElement('script');
script.src = 'https://dapi.kakao.com/v2/maps/sdk.js?appkey=[MY_APP_KEY]&autoload=false';  
document.head.appendChild(script);

script.onload = () => {
    window.kakao.maps.load(() => {
        const maps = [
            {
                id: 'map1',
                center: new window.kakao.maps.LatLng(33.450701, 126.570667),
                positions: [
                    { title: '카카오', latlng: new window.kakao.maps.LatLng(33.450705, 126.570677) },
                    { title: '근린공원', latlng: new window.kakao.maps.LatLng(33.451393, 126.570738) }
                ]
            },
            {
                id: 'map2',
                center: new window.kakao.maps.LatLng(33.450701, 124.570667),
                positions: [
                    { title: '카카오', latlng: new window.kakao.maps.LatLng(33.450705, 126.570677) },
                    { title: '근린공원', latlng: new window.kakao.maps.LatLng(33.451393, 126.570738) }
                ]
            },
            {
                id: 'map3',
                center: new window.kakao.maps.LatLng(33.450701, 123.570667),
                positions: [
                    { title: '카카오', latlng: new window.kakao.maps.LatLng(33.450705, 126.570677) },
                    { title: '근린공원', latlng: new window.kakao.maps.LatLng(33.451393, 126.570738) }
                ]
            }
        ];

        // 지도 객체를 저장할 배열
        const mapIndex = [];

        // 지도 생성 및 초기화
        maps.forEach(({ id, center, positions }) => {
            const container = document.getElementById(id);
            const options = { center, level: 3 };
            const map = new window.kakao.maps.Map(container, options);

            // 생성된 지도 객체를 배열에 저장
            mapIndex.push(map);

            // 마커 및 인포윈도우 생성
            positions.forEach(position => {
                const marker = new window.kakao.maps.Marker({
                    map,
                    position: position.latlng,
                    title: position.title
                });

                const infowindow = new window.kakao.maps.InfoWindow({
                    content: <div style="padding:5px;">${position.title}</div>
                });

                infowindow.open(map, marker);
            });

            // 초기 지도 크기 재조정 및 중심 설정
            map.relayout(); // 컨테이너 크기 재계산
            map.setCenter(center); // 중심 좌표 설정
        });

        // 탭 클릭 이벤트 추가
        document.querySelectorAll('.tabChange li a').forEach((tab, index) => {
            tab.addEventListener('click', () => {
                // 모든 지도 컨테이너 숨기기
                maps.forEach(({ id }) => {
                    document.getElementById(id).style.display = 'none';
                });

                // 클릭된 탭의 지도 컨테이너 표시
                const selectedContainer = document.getElementById(maps[index].id);
                selectedContainer.style.display = 'block';

                // 해당 지도 크기 재조정 및 중심 좌표 재설정
                if (mapIndex[index]) {
                    mapIndex[index].relayout(); // 크기 재계산
                    mapIndex[index].setCenter(maps[index].center); // 중심 좌표 재설정
                }
            });
        });
    });
};

추가된 부분은 탭 클릭 이벤트 시 탭의 지도 컨테이너를 보여주면서 해당 탭의 지도의 크기 재조정 및 중심 좌표를 재설정 한 것이다.

 

해결 포인트 정리

  1. relayout 사용
    • 지도 컨테이너가 display: none 상태에서 다시 표시될 때, relayout() 메서드를 호출하여 컨테이너 크기를 재계산한다.
  2. setCenter 호출
    • 크기 재계산 후 중심 좌표를 다시 설정하여 지도가 정상적으로 표시되도록 보장한다.