Window 창 크기에 따른 카카오맵 로드뷰 간의 resize 비율 조정

카카오맵 사이트의 로드뷰에서는 윈도우 화면을 줄인 후 드래그하여 resize하면 드래그 하는 동안과 마우스를 뗀 후에도 해당 화면의 비율에 맞게 1:1로 조정이 잘 되는데,
제 화면에서는 아래 사진과 같이 로드뷰가 깨집니다.
이게 전체화면일 때는 괜찮은데 윈도우 화면이 축소된 상태일 때
드래그 하는 동안 화면이 깨지고, 마우스를 떼면 잠시 후에 정상으로 돌아갑니다.
어떻게 처리해야 할지 조금 어렵네요…ㅜㅜ

아래 자바스크립트 코드 첨부합니다.

function initResizable() {
// div 요소 선택
const kakaoMap = document.querySelector(‘#kakaoMap’);
const roadview = document.querySelector(‘#roadview’);
// resizer 핸들러 요소를 선택
const resizer = document.querySelector(‘#kakaoMap .resizer’);
// 최소 사이즈 설정
const min_width = 170;
const min_height = 130;
// 최대 사이즈 설정
const max_width = window.innerWidth;
const max_height = window.innerHeight;
// 초기 너비와 높이
let original_width = 310;
let original_height = 190;
// 초기 위치 설정
let original_x = 0;
let original_y = 0;
// 마우스 초기 위치 설정
let original_mouse_x = 0;
let original_mouse_y = 0;

// 마우스 다운 이벤트 핸들러 등록
resizer.addEventListener('mousedown', function(e) {
	// 기본 이벤트 방지
	e.preventDefault();
	// resizable 이전의 요소의 현재 스타일 값을 가져와서 파싱하여 초기 값 설정
	original_width = parseFloat(getComputedStyle(kakaoMap, null).getPropertyValue('width').replace('px', ''));
	original_height = parseFloat(getComputedStyle(kakaoMap, null).getPropertyValue('height').replace('px', ''));
	// 요소의 초기 위치 설정
	original_x = kakaoMap.getBoundingClientRect().left;
	original_y = kakaoMap.getBoundingClientRect().top;
	// 초기 마우스 위치 설정
	original_mouse_x = e.pageX;
	original_mouse_y = e.pageY;
	// 마우스 이동 이벤트 리스너 등록
	window.addEventListener('mousemove', resize);
	// 마우스 업 이벤트 리스너 등록
	window.addEventListener('mouseup', stopResize);
});

// 마우스 이동 이벤트 핸들러 함수 정의
function resize(e) {
    // 새로운 너비 계산
    let width = original_width + (e.pageX - original_mouse_x);
    // 새로운 높이 계산
    let height = original_height - (e.pageY - original_mouse_y);
    
    // 너비 조정
    if (width <= min_width) {
        width = min_width;
    // 최대 넓이는 로드뷰와 1:1
    } else if (width >= max_width / 2) {
        width = max_width / 2;
    }
    // 높이 조정
    if (height <= min_height) {
        height = min_height;
    // 최상단에 닿아있을 때
    } else if (height >= max_height) {
    	// 카카오맵은 최대 높이로 설정
        height = max_height;
	    // 로드뷰 위치 조정
	    const rv_width = window.innerWidth - width;
	    roadview.style.width = rv_width + 'px';
	    roadview.style.left = width + 'px';
	// 내려와있을 때는 카카오맵에 맞추기
    } else if (height < max_height) {
    	roadview.style.width = 'auto';
    	roadview.style.left = 'auto';
    }
    kakaoMap.style.width = width + 'px';
    kakaoMap.style.height = height + 'px';
    rv.relayout();
    map.relayout();
    map.setCenter(mapWalker.walker.getPosition());
}

// 마우스 업 이벤트 핸들러 함수 정의
function stopResize() {
    // 마우스 이동 및 업 이벤트 리스너 제거
    window.removeEventListener('mousemove', resize);
    window.removeEventListener('mouseup', stopResize);
}

}

#kakaoMap {
position: absolute;
width: 310px;
height: 190px;
bottom: 0px; /* 15px /
left: 0px; /
15px */
top: auto;
border-radius: 2px;
z-index: 2;
}

#roadview.active {
width: 100%; /* roadview를 100% 너비로 설정 */
height: 100%;
position: relative;
z-index: 1;
}

로드뷰에서 사용하는 요소들이 선언한 스타일에 영향을 주고 있는지도 확인해주세요.
그리고 첨부 코드만으로는 현상 확인이 어려워서 전체 코드로 첨부 부탁드립니다.

로드뷰에 커서를 올리기 전까진 깨진 상태가 유지되고, 커서를 올리면 정상적으로 돌아오네요.
window 창 크기를 축소시켰다가 최대화 시키면 지도와 로드뷰가 window 창 내부를 꽉 채우는 게 아니라
로드뷰 오른쪽에 검은 여백이 생깁니다. resizer를 mousedown 하기 전까지 그대로구요…

function getCoord(map2dCoord){
var center = ol.proj.transform(map2dCoord, map2d.crs, ‘EPSG:4326’);
const lat = center[1];
const lon = center[0];
var S = 37.36713295859407;
var W = 127.30632201199485;
var N = 37.67029926582917;
var E = 127.84867275688543;
if ((S < lat && lat < N) && (W < lon && lon < E)){
return center;
} else {
return false;
}
};

function changeZoom(type, zoom) {
const kakaoZoomMax = 1;
const kakaoZoomMin = 8;
const ypZoomMax = 19;
const ypZoomMin = 12;
// map2D → kakaoMap
if (type === “map2D”) {
const kakaoZoom = Math.round(((zoom - ypZoomMin) / (ypZoomMax - ypZoomMin)) * (kakaoZoomMax - kakaoZoomMin) + kakaoZoomMin);
// 카카오맵의 최소 및 최대 줌 레벨 범위를 벗어나면 해당 범위로 설정
return Math.min(Math.max(kakaoZoom, kakaoZoomMax), kakaoZoomMin);
}
// kakaoMap → map2D
else if (type === “kakaoMap”) {
const ypZoom = Math.round(((zoom - kakaoZoomMin) / (kakaoZoomMax - kakaoZoomMin)) * (ypZoomMax - ypZoomMin) + ypZoomMin);
// map2D의 최소 및 최대 줌 레벨 범위를 벗어나면 해당 범위로 설정
return Math.min(Math.max(ypZoom, ypZoomMin), ypZoomMax);
}
}

function bindCoord(type){
if(type === “off”){
if($(‘#kakaoMap .MapWalker’).length > 0) {
//마커의 좌표값 얻기 {La:경도,Ma:위도}
let latlon = mapWalker.walker.getPosition();
let lat = latlon.Ma;
let lon = latlon.La;
var S = 37.36713295859407;
var W = 127.30632201199485;
var N = 37.67029926582917;
var E = 127.84867275688543;
if ((S < lat && lat < N) && (W < lon && lon < E)){
// map2D 좌표 형태로 변환
let markerCoord = ol.proj.transform([lon, lat], ‘EPSG:4326’, map2d.crs);
//지도의 줌레벨 얻기
var kakaoZoom = map.getLevel();
var ypZoom = changeZoom(“kakaoMap”, kakaoZoom);
let options = {zoom : ypZoom};
map2d.setCenter(markerCoord, options);
} else {
toastr.info(‘’, ‘지도 범위를 벗어났으므로 지도 영역을 초기화합니다.’, {timeOut: 5000});
$(‘#toast-container > div’).css({width:‘350’});
dtmap.goHome();
}
}
}
if(type === “on”){
var ypZoom = map2d.view.getZoom();
var kakaoZoom = changeZoom(“map2D”, ypZoom);
return kakaoZoom;
}
}

function setMapCenter(target) {
if(target === “kakaoMap”) {
var xy = ol.proj.transform(map2d.getCenter(), map2d.crs, ‘EPSG:4326’);
var center = new kakao.maps.LatLng(xy[1], xy[0]);
var zoom = changeZoom(“map2D”, map2d.view.getZoom());
/* getNearestPanoId(카카오 좌표, 반경(미터 단위), callback); */
rvClient.getNearestPanoId(center, 100, function(panoId) {
if (panoId === null) {
toastr.error(‘로드뷰 정보가 존재하지 않습니다.’,‘’, {timeOut: 1000});
//map.relayout();
} else {
map.setLevel(zoom);
rv.setPanoId(panoId, center);
}
});
}
if(target === “map2D”) {
const position = map.getCenter();
const lat = position.Ma;
const lon = position.La;
const center = ol.proj.transform([lon, lat], ‘EPSG:4326’, map2d.crs);
const zoom = changeZoom(“kakaoMap”, map.getLevel());
const options = {zoom: zoom};
map2d.setCenter(center, options);
map2d.map.updateSize();
}
}

function syncMapCneter(e) {
$(‘#kakaoMap’).hasClass(‘active’) ? setMapCenter(“map2D”) : setMapCenter(“kakaoMap”);
}

function toggleKakaoMap() {
var btnToggle = $(‘#btn-toggle’);
var isToggleOff = btnToggle.hasClass(‘toggle-off’);
var parent = $(‘div#roadview’).children().eq(0).children().children().eq(0)
var kakaoMap = $(‘#kakaoMap’);
if (isToggleOff) {
btnToggle.removeClass(‘toggle-off’).addClass(‘toggle-on’);
kakaoMap.addClass(‘active’);
kakaoMap.toggle(200);
} else {
btnToggle.removeClass(‘toggle-on’).addClass(‘toggle-off’);
kakaoMap.removeClass(‘active’);
kakaoMap.toggle(200);
//parent.css({width:‘inherit’,height:‘inherit’});
//parent.children().css({width:‘inherit’,height:‘inherit’});
}
}

function toggleRoadview(mapCenter, zoom) {
if(($(‘#kakaoMap’).length === 0 && $(‘#roadview’).length === 0)) {
showHideRdvwElement(“show”);
selectRoadview(mapCenter, zoom);
} else {
bindCoord(“off”);
showHideRdvwElement(“hide”);
map2d.map.un(‘moveend’, syncMapCneter);
kakao.maps.event.removeListener(map, ‘center_changed’, syncMapCneter);
map2d.map.updateSize();
}
}

function selectRoadview(center, zoom){
var kakaoMapDiv = document.getElementById(‘kakaoMap’); // 지도를 표시할 div
var roadviewDiv = document.getElementById(‘roadview’); //로드뷰를 표시할 div
rv = new kakao.maps.Roadview(roadviewDiv); //로드뷰 객체
rvClient = new kakao.maps.RoadviewClient(); //좌표로부터 로드뷰 파노라마 ID를 가져올 로드뷰 helper객체
var mapCenter = new kakao.maps.LatLng(center[1], center[0]);
var mapOption = {
center: mapCenter, // 지도의 중심좌표
level: zoom // 지도의 확대 레벨
};

// 지도를 표시할 div와  지도 옵션으로  지도를 생성합니다
map = new kakao.maps.Map(kakaoMapDiv, mapOption);
map.setMaxLevel(8);
map.addOverlayMapTypeId(kakao.maps.MapTypeId.ROADVIEW);	// 로드뷰 도로 추가

ctrlRoadview(mapCenter);

//로드뷰 toggle함수
function ctrlRoadview(position) {
	//전달받은 좌표(position)에 가까운 로드뷰의 panoId를 추출하여 로드뷰를 띄웁니다
    rvClient.getNearestPanoId(position, 50, function(panoId) {
	    if (panoId === null) {
	    	toastr.error('로드뷰 정보가 존재하지 않습니다.','', {timeOut: 1000});
	    	if($('#kakaoMap').width() === 310 && $('#kakaoMap').height() === 190) { //로드뷰 첫 실행 시
	    		return toggleRoadview();
	    	} else {
		    	//roadviewDiv.style.display = 'none'; //로드뷰를 넣은 컨테이너를 숨깁니다
			    //kakaoMapDiv.style.width = '100%';
		    	map.relayout();
	    	}
    	} else {
    		//kakaoMapDiv.style.width = '50%';
		    map.relayout(); //지도를 감싸고 있는 영역이 변경됨에 따라, 지도를 재배열합니다
		    roadviewDiv.style.display = 'block'; //로드뷰를 넣은 컨테이너를 보이게합니다
		    rv.setPanoId(panoId, position); //panoId를 통한 로드뷰 실행
		    rv.relayout(); //로드뷰를 감싸고 있는 영역이 변경됨에 따라, 로드뷰를 재배열합니다
    	}
    });
}

var startX, startY, startOverlayPoint;
function MapWalker(mapCenter){
	//커스텀 오버레이에 사용할 map walker 엘리먼트
	var content = document.createElement('div');
	var figure = document.createElement('div');
	var angleBack = document.createElement('div');

	//map walker를 구성하는 각 노드들의 class명을 지정 - style셋팅을 위해 필요
	content.className = 'MapWalker';
	figure.className = 'figure';
	angleBack.className = 'angleBack';

	content.appendChild(angleBack);
	content.appendChild(figure);

	//커스텀 오버레이 객체를 사용하여, map walker 아이콘을 생성
	var walker = new kakao.maps.CustomOverlay({
	    position: mapCenter,
	    content: content,
	    yAnchor: 1,
	});

	this.walker = walker;
	this.content = content;

    // 커스텀 오버레이에 mousedown, mouseup 이벤트를 등록합니다
    addEventHandle(this.content, 'mousedown', onMouseDown);
    addEventHandle(this.content, 'mouseup', onMouseUp);
}

//로드뷰의 pan(좌우 각도)값에 따라 map walker의 백그라운드 이미지를 변경 시키는 함수
//background로 사용할 sprite 이미지에 따라 계산 식은 달라 질 수 있음
MapWalker.prototype.setAngle = function(angle){

    var threshold = 22.5; //이미지가 변화되어야 되는(각도가 변해야되는) 임계 값
    for(var i=0; i<16; i++){ //각도에 따라 변화되는 앵글 이미지의 수가 16개
        if(angle > (threshold * i) && angle < (threshold * (i + 1))){
            //각도(pan)에 따라 아이콘의 class명을 변경
            var className = 'm' + i;
            this.content.className = this.content.className.split(' ')[0];
            this.content.className += (' ' + className);
            break;
        }
    }
};

//map walker의 위치를 가져오는 함수
MapWalker.prototype.getPosition = function() {
	return this.walker.getPosition();
};

//map walker의 위치를 변경시키는 함수
MapWalker.prototype.setPosition = function(position){
	this.walker.setPosition(position);
};

//map walker를 지도위에 올리는 함수
MapWalker.prototype.setMap = function(map){
    this.walker.setMap(map);
};

// 로드뷰가 초기화 되었을 때  map walker를 생성한다.
kakao.maps.event.addListener(rv, 'init', function() {

    // map walker를 생성한다. 생성시 지도의 중심좌표를 넘긴다.
    mapWalker = new MapWalker(mapCenter);
    mapWalker.setMap(map); // map walker를 지도에 설정한다.

    // 로드뷰가 초기화 된 후, 추가 이벤트를 등록한다.
    // 로드뷰에서 상,하,좌,우,줌인,줌아웃 이동을 할 경우 발생한다.
    // 로드뷰를 조작할 때 발생하는 값을 받아 map walker의 상태를 변경해 준다.
    kakao.maps.event.addListener(rv, 'viewpoint_changed', function(){

        // 이벤트가 발생할 때마다 로드뷰의 viewpoint값을 읽어, map walker에 반영
        var viewpoint = rv.getViewpoint();
        mapWalker.setAngle(viewpoint.pan);
    });

    // 로드뷰에서 화살표나 점프를 하였을 경우 발생한다.
    // position값이 바뀔 때마다 map walker의 상태를 변경해 준다.
    kakao.maps.event.addListener(rv, 'position_changed', function(){
        // 이벤트가 발생할 때마다 로드뷰의 position값을 읽어, map walker에 반영 
        let position = rv.getPosition();
		let lat = position.Ma;
		let lon = position.La;
        dtmap.setCenter(ol.proj.transform([lon, lat], 'EPSG:4326', map2d.crs), {});
        mapWalker.setPosition(position);
        map.setCenter(position);
    });
});

mapWalker = new MapWalker();
//지도에 클릭 이벤트를 할당합니다
kakao.maps.event.addListener(map, 'click', function(mouseEvent){
	// 현재 클릭한 부분의 좌표를 리턴 
    var position = mouseEvent.latLng;
    rvClient.getNearestPanoId(position, 30, function(panoId) {
	    if (panoId === null) {
	    	toastr.error('로드뷰 정보가 존재하지 않습니다.','', {timeOut: 1000});
	    } else{
	    	mapWalker.setPosition(position);
			ctrlRoadview(position); // 로드뷰를 토글합니다	
	    }
	});
});

// 이동,확대,축소로 인해 지도의 중심좌표가 변경될 때마다 양평맵 <-> 카카오맵 싱크 맞추기
if(($('#kakaoMap').length > 0 && $('#roadview').length > 0)) {
	kakao.maps.event.addListener(map, 'center_changed', syncMapCneter);
	map2d.map.on('moveend', syncMapCneter)
}

function onMouseDown(e) { 
    // 커스텀 오버레이를 드래그 할 때, 내부 텍스트가 영역 선택되는 현상을 막아줍니다.
    if (e.preventDefault) {
        e.preventDefault();
    } else {
        e.returnValue = false;
    }

    var proj = map.getProjection(), 
        overlayPos = mapWalker.getPosition(); // 커스텀 오버레이의 현재 위치를 가져옵니다

    // 커스텀오버레이에서 마우스 관련 이벤트가 발생해도 지도가 움직이지 않도록 합니다
    kakao.maps.event.preventMap();

    startX = e.clientX; 
    startY = e.clientY;

    // mousedown됐을 때의 커스텀 오버레이의 좌표를
    // 지도 컨테이너내 픽셀 좌표로 변환합니다 
    startOverlayPoint = proj.containerPointFromCoords(overlayPos);

    // document에 mousemove 이벤트를 등록합니다 
    addEventHandle(document, 'mousemove', onMouseMove);
}

// mouseup 했을 때 호출되는 핸들러 입니다
function onMouseUp(e) {
    // 등록된 mousemove 이벤트 핸들러를 제거합니다
    removeEventHandle(document, 'mousemove', onMouseMove);
    //이동한 마커 위치의 panoId를 가져올 수 있도록 toggleRoadview를 호출합니다.
    var position = mapWalker.getPosition();
	ctrlRoadview(position); // 로드뷰를 토글합니다
}

function onMouseMove(e) {
    // 커스텀 오버레이를 드래그 할 때, 내부 텍스트가 영역 선택되는 현상을 막아줍니다.
    if (e.preventDefault) {
        e.preventDefault();
    } else {
        e.returnValue = false;
    }

    var proj = map.getProjection(),// 지도 객체로 부터 화면픽셀좌표, 지도좌표간 변환을 위한 MapProjection 객체를 얻어옵니다 
        deltaX = startX - e.clientX, // mousedown한 픽셀좌표에서 mousemove한 좌표를 빼서 실제로 마우스가 이동된 픽셀좌표를 구합니다 
        deltaY = startY - e.clientY,
        // mousedown됐을 때의 커스텀 오버레이의 좌표에 실제로 마우스가 이동된 픽셀좌표를 반영합니다 
        newPoint = new kakao.maps.Point(startOverlayPoint.x - deltaX, startOverlayPoint.y - deltaY), 
        // 계산된 픽셀 좌표를 지도 컨테이너에 해당하는 지도 좌표로 변경합니다 
        newPos = proj.coordsFromContainerPoint(newPoint);
    
    mapWalker.setPosition(newPos);
}

// target node에 이벤트 핸들러를 등록하는 함수힙니다  
function addEventHandle(target, type, callback) {
    if (target.addEventListener) {
        target.addEventListener(type, callback);
    } else {
        target.attachEvent('on' + type, callback);
    }
}

// target node에 등록된 이벤트 핸들러를 제거하는 함수힙니다 
function removeEventHandle(target, type, callback) {
    if (target.removeEventListener) {
        target.removeEventListener(type, callback);
    } else {
        target.detachEvent('on' + type, callback);
    }
}

initResizable();

}

function initResizable() {
// div 요소 선택
const kakaoMap = document.querySelector(‘#kakaoMap’);
const roadview = document.querySelector(‘#roadview’);
// resizer 핸들러 요소를 선택
const resizer = document.querySelector(‘#kakaoMap .resizer’);
// 최소 사이즈 설정
const min_width = 170;
const min_height = 130;
// 최대 사이즈 설정
//const max_width = 2134.17;
//const max_height = 1046.67;
let max_width = window.innerWidth;
let max_height = window.innerHeight;
/** 초기 너비와 높이
* original_width = 310;
* original_height = 190;
*/
//초기 위치 설정
let original_x = 0;
let original_y = 0;
// 마우스 초기 위치 설정
let original_mouse_x = 0;
let original_mouse_y = 0;

// 마우스 다운 이벤트 핸들러 등록
resizer.addEventListener('mousedown', function(e) {
	// 기본 이벤트 방지
	e.preventDefault();
	// resizable 이전의 요소의 현재 스타일 값을 가져와서 파싱하여 초기 값 설정
	original_width = parseFloat(getComputedStyle(kakaoMap, null).getPropertyValue('width').replace('px', ''));
	original_height = parseFloat(getComputedStyle(kakaoMap, null).getPropertyValue('height').replace('px', ''));
	// 요소의 초기 위치 설정
	original_x = kakaoMap.getBoundingClientRect().left;
	original_y = kakaoMap.getBoundingClientRect().top;
	// 초기 마우스 위치 설정
	original_mouse_x = e.pageX;
	original_mouse_y = e.pageY;
	// 마우스 이동 이벤트 리스너 등록
	window.addEventListener('mousemove', resize);
	// 마우스 업 이벤트 리스너 등록
	window.addEventListener('mouseup', stopResize);
});

// 마우스 이동 이벤트 핸들러 함수 정의
function resize(e) {
    // 새로운 너비 계산
    let width = original_width + (e.pageX - original_mouse_x);
    // 새로운 높이 계산
    let height = original_height - (e.pageY - original_mouse_y);
    
    // 너비 조정
    if (width <= min_width) {
        width = min_width;
    // 최대 넓이는 로드뷰와 1:1
    } else if (width >= max_width / 2) {
        width = max_width / 2;
    }
    // 높이 조정
    if (height <= min_height) {
        height = min_height;
    // 최상단에 닿아있을 때
    } else if (height >= max_height) {
    	// 카카오맵은 최대 높이로 설정
        height = max_height;
	    // 로드뷰 위치 조정
	    const rv_width = window.innerWidth - width;
	    roadview.style.width = rv_width + 'px';
	    roadview.style.left = width + 'px';
	// 내려와있을 때는 카카오맵에 맞추기
    } else if (height < max_height) {
    	roadview.style.width = 'auto';
    	roadview.style.left = 'auto';
    }
    kakaoMap.style.width = width + 'px';
    kakaoMap.style.height = height + 'px';
    rv.relayout();
    map.relayout();
    map.setCenter(mapWalker.walker.getPosition());
}

// 마우스 업 이벤트 핸들러 함수 정의
function stopResize() {
    // 마우스 이동 및 업 이벤트 리스너 제거
    window.removeEventListener('mousemove', resize);
    window.removeEventListener('mouseup', stopResize);
}

}

// display 전환 함수
function showHideRdvwElement(display) {
if(display === “show”) {
$(‘#rightPopup.popup-panel’).removeClass(‘opened’);
$(‘#map2D’).addClass(‘split-main-map’);
$(‘

’).insertAfter($(‘#map3D’));
$(‘
’).insertAfter($(‘#map3D’));
$(‘
’).insertAfter($(‘#roadview’));
$(‘
’).insertAfter($(‘#btn-close’));
$(‘#container .logo’).hide();
$(‘#container .util-box’).hide();
$(‘#container #warningText’).hide();
$(‘#map-aside .map-control’).hide();
$(‘#map-aside .map-util’).hide();
$(‘#side .twdcvlnService’).hide();
$(‘#side #lnb’).hide();
let resizeHtml = <div class="frame"><div class="drag"><span class="resizer"></span></div></div>;
$(resizeHtml).prependTo($(‘#kakaoMap’));
} else if(display === “hide”) {
$(‘#map2D’).removeClass(‘split-main-map’);
$(‘#kakaoMap’).remove();
$(‘#roadview’).remove();
$(‘#btn-close’).remove();
$(‘#btn-toggle’).remove();
$(‘#container .logo’).show();
$(‘#container .util-box’).show();
$(‘#container #warningText’).show();
$(‘#map-aside .map-control’).show();
$(‘#map-aside .map-util’).show();
$(‘#side .twdcvlnService’).show();
$(‘#side #lnb’).show();
}
}