본문 바로가기
Develop/JPA

전기차 충전소 API 상세 정보 팝업 (4)

by ys2ys2 2024. 11. 12.

오늘도 돌아온 작업 내용 정리 시간!

 

오늘은 리스트 클릭 시 해당 지역에 마커가 찍히면서 충전소 상세정보 팝업이 뜨게 하기!

 


 

✅ 리스트 클릭 시 해당 지역 마커 + 상세정보 팝업

 

마지막까지의 작업 내용 ↓

 

마지막까지 작업 내용

 

여기에 이어서 리스트 클릭 시 카카오 지도에 마커를 전달하면서 해당 위치로 이동하게 한 후 팝업창이 나오게 구현했다.

 

 


 

리스트를 만들때 사용했던 lat, lng (위도,경도)를 이용해서 kakaomap에 전달했고 전달받은 값에 마커가 찍히게 했다.

위도와 경도 + 각종 팝업창에 띄울 필요한 값들을 생각해서 클릭 시 같이 전달하게 했다.

listItem.addEventListener("click", function () {
    const stationData = {
        name: displayName,             // 충전소명 (중복 구분 포함)
        operator: busiNm,              // 운영기관명
        contact: busiCall,             // 운영기관 연락처
        address: addr,                 // 주소
        addressDetail: addrDetail,     // 상세주소
        useTime: useTime,              // 이용 가능 시간
        output: output,                // 충전 용량
        type: type,                    // 충전기 타입 코드
        status: stat,                  // 충전기 상태 코드
        statusUpdateDate: statUpdDt,   // 상태갱신일시
        lastStart: lastTsdt,           // 마지막 충전 시작 일시
        lastEnd: lastTedt,             // 마지막 충전 종료 일시
        chargingStart: nowTsdt,        // 현재 충전 시작 일시
        note: note,                    // 충전소 안내
        limitDetail: limitDetail,      // 이용 제한 사항
        lat: lat,                      // 위도
        lng: lng                       // 경도
    };

    showStationInfoPopup(stationData);

    const selectedLocation = new kakao.maps.LatLng(lat, lng);
    map.setCenter(selectedLocation);

    const marker = new kakao.maps.Marker({
        position: selectedLocation,
        map: map
    });
});

 

마커와 함께 값 전달

 

다음으로는 상세정보 팝업을 우측에 띄우려고 했다.

 

일단 먼저 최종 결과물!

최종 팝업

 

우측에 큰 div에서 각각 항목별로 flex-direction: column;값을 주고 각 항목마다 div를 두고 조절하면서 사용했다.

 

사용하고 있는 공공데이터API에서는 충전기 타입이나, 충전기 상태 등등을 숫자로만 주고 있었기 때문에

기존에 작업할때 사용했던 값들을 그대로 받아서 쓰게 했다.

예시_

const chargerTypeMap = {
    "01": "DC차데모",
    "02": "AC완속",
    "03": "DC차데모+AC3상",
    "04": "DC콤보",
    "05": "DC차데모+DC콤보",
    "06": "DC차데모+AC3상+DC콤보",
    "07": "AC3상",
    "08": "DC콤보(완속)",
    "89": "H2"
};

const chargerStatusMap = {
    "1": { text: "사용 불가", class: "status-unavailable" },
    "2": { text: "사용 가능", class: "status-available" },
    "3": { text: "사용 중", class: "status-in-use" },
    "4": { text: "운영 중지", class: "status-out-of-service" },
    "5": { text: "점검 중", class: "status-under-maintenance" },
    "9": { text: "상태 미확인", class: "status-unknown" }
};

 

이런식으로 01에 해당하는 충전기 타입, 1에 해당하는 충전기 상태를 정의했었는데

그걸 그대로 사용하게 전역으로 정의하고

팝업창이 열릴때 값을 받을 수 있게 했다.

// 충전소 정보를 팝업에 표시하는 함수
function showStationInfoPopup(stationData) {

    // 타입과 상태 정보를 전역 매핑 객체를 사용해 변환
    const typeText = chargerTypeMap[stationData.type] || "알 수 없는 타입";
    const statusInfo = chargerStatusMap[stationData.status] || { text: "알 수 없는 상태", class: "status-unknown" };

    document.getElementById("popupType").textContent = typeText;
    document.getElementById("popupStatus").textContent = statusInfo.text; // 상태 텍스트 설정
    document.getElementById("popupStatus").className = `status-button ${statusInfo.class}`; // 상태 클래스 설정

    const formattedDate = formatDate(stationData.statusUpdateDate);


    // 로드뷰 설정을 위한 변수들
    const roadviewContainer = document.getElementById('roadview'); // 로드뷰를 표시할 div
    const roadview = new kakao.maps.Roadview(roadviewContainer); // 로드뷰 객체
    const roadviewClient = new kakao.maps.RoadviewClient(); // 좌표로부터 로드뷰 파노ID를 가져올 로드뷰 helper 객체


    // 팝업창에 데이터 설정
    document.getElementById("popupStationName").textContent = stationData.name;	//충전소 이름

    // 모든 data-value="popupOperator" 요소에 운영기관 이름 설정
    document.querySelectorAll("[data-value='popupOperator']").forEach(el => {
        el.textContent = stationData.operator || "정보 없음";
    });

    document.getElementById("popupContact").textContent = stationData.contact || "정보 없음";	//운영기관 연락처
    document.getElementById("popupAddress").textContent = stationData.address;	//충전소 주소
    //document.getElementById("popupDetailedLocation").textContent = stationData.addressDetail || "상세 주소 없음";	//충전소 상세 주소
    document.getElementById("popupUseTime").textContent = stationData.useTime || "정보 없음";	//이용 가능 시간
    document.getElementById("popupType").textContent = chargerTypeMap[stationData.type] || "알 수 없는 타입"; //충전기 타입
    document.getElementById("popupStatus").textContent = chargerStatusMap[stationData.status]?.text || "알 수 없는 상태"; //충전기 상태
    document.getElementById("popupOutput").textContent = `${stationData.output}kW` || "정보 없음";	// 충전 용량
    //document.getElementById("popupStatusUpdateDate").textContent = stationData.statusUpdateDate || "정보 없음"; //상태 갱신 일시
    //document.getElementById("popupLastStart").textContent = stationData.lastStart || "정보 없음";	// 마지막 충전 시작 일시
    //document.getElementById("popupLastEnd").textContent = stationData.lastEnd || "정보 없음";	// 마지막 충전 종료 일시
    //document.getElementById("popupChargingStart").textContent = stationData.chargingStart || "정보 없음";	// 현재 충전 시작 일시
    document.getElementById("popupNote").textContent = stationData.note || "안내 정보 없음";	//충전소 안내
    document.getElementById("popupLimitDetail").textContent = stationData.limitDetail || "제한 없음";	//이용자 제한사항

 

일단 어떤 값을 쓸지 몰라서 최대한 많은 값들을 가져오게 하고 안쓰는 값들은 주석처리로 일단 살려두기..

 

그러고 id값으로 전달하게 한 값들을 jsp요소 내에서 사용했다.

충전소 이름을 예로 들면

api에서 호출할때는 statNm이라는 값으로 받아서 statNm으로 저장하고

for (let i = 0; i < items.length; i++) {
	        const statNm = items[i].getElementsByTagName("statNm")[0].textContent;  // 충전소명

 

사용하는 공공데이터API에서는 여러개의 충전기가 있으면 그냥 동일한 이름으로 제공했기 때문에

여러개의 충전기 이름이 중복되면 뒤에 숫자를 붙여서 충전기의 개수를 표현하고 싶어서 다시 재가공했다.

// 중복된 충전소명에 번호 붙이기
if (stationNameCount[statNm]) {
    stationNameCount[statNm] += 1; // 중복 카운트 증가
} else {
    stationNameCount[statNm] = 1; // 처음 등장하는 충전소명
}

const displayName = stationNameCount[statNm] > 1 ? `${statNm} (${stationNameCount[statNm]})` : statNm;

 

이렇게 statNm으로 받아서 최종적으로 저장된 displayName으로 저장했다.

 

그러고 충전소명은 click event가 발생하면

listItem.addEventListener("click", function () {
    const stationData = {
        name: displayName,             // 충전소명 (중복 구분 포함)
        ...
    };
    
    showStationInfoPopup(stationData);

 

이렇게 name값으로 전달했고 이걸 다시 받아서 stationData로 넘겼다. 그럼 최종적으로 stationData.name!

 

이제 팝업창이 열리면 popupStationName의 id속성값에 stationData.name을 전달!

// 충전소 정보를 팝업에 표시하는 함수
function showStationInfoPopup(stationData) {
		    document.getElementById("popupStationName").textContent = stationData.name;	//충전소 이름
			...

 

<!-- 충전소 정보 팝업 -->
<div id="stationInfoPopup" class="station-info-popup">
	<button id="closePopupButton">X</button>
	<div class="real-popup">
		<div class="popupStationName">
			<span id="popupStationName"></span>
		</div>
        ...

 

이렇게 JSP 내에서 span값에 popupStationName이라는 id값을 줘서 저기서 값을 받아서 표현하게 했다.

이런식으로 나머지 값들도 하나하나 가져오기!

 

같은 방식으로 필요한 값들 다 받아서

busiNm = 운영기관명 ✅
busiCall = 운영기관 연락처 ✅
addr = 주소 ✅
useTime = 이용가능시간 ✅
chgerType = 충전기 타입 ✅
stat = 충전기 상태 ✅
statUpdDt = 상태갱신일시 ✅
lastTsdt = 마지막 충전시작일시 ✅
lastTedt = 마지막 충전종료일시 ✅
nowTsdt = 충전중 시작일시 ✅
note = 충전소 안내 ✅
limitDetail = 이용자제한 ✅

 

그대로 팝업창에 구역 나눠서 출력했다!

충전기 상태에 상태 갱신시간을 새로 추가해서 언제 갱신이 됐는지 알 수 있게 했다.

출력값

 

 


 

 

카카오 지도 API 로드뷰 사용하기

 

다음으로 한건 위치사진에 카카오 지도 api에서 제공하고 있는 로드뷰 기능을 썼다.

(참고 사이트: https://apis.map.kakao.com/web/sample/basicRoadview/ )

 

//카카오 공식 문서
var roadviewContainer = document.getElementById('roadview'); //로드뷰를 표시할 div
var roadview = new kakao.maps.Roadview(roadviewContainer); //로드뷰 객체
var roadviewClient = new kakao.maps.RoadviewClient(); //좌표로부터 로드뷰 파노ID를 가져올 로드뷰 helper객체

var position = new kakao.maps.LatLng(33.450701, 126.570667);

// 특정 위치의 좌표와 가까운 로드뷰의 panoId를 추출하여 로드뷰를 띄운다.
roadviewClient.getNearestPanoId(position, 50, function(panoId) {
    roadview.setPanoId(panoId, position); //panoId와 중심좌표를 통해 로드뷰 실행
});

 

어차피 위도,경도값은 이미 가지고 있으니까

이걸 그냥 카카오 로드뷰에 전달해서 해당 위치에 대한 로드뷰를 받아서 화면에 출력하기만 하면 됐다.

 

// 로드뷰 설정: 주어진 위도와 경도를 사용하여 로드뷰 표시
const position = new kakao.maps.LatLng(stationData.lat, stationData.lng); // 충전소의 위도와 경도
roadviewClient.getNearestPanoId(position, 50, function(panoId) {
    if (panoId) {
        roadview.setPanoId(panoId, position); // panoId와 중심좌표를 통해 로드뷰 실행
    } else {
        roadviewContainer.innerHTML = '<p>로드뷰를 사용할 수 없는 위치입니다.</p>'; // 로드뷰가 없는 경우 메시지 표시
    }
});

 

이렇게 팝업창에서 전달받고 있는 stationData.lat, stationData.lng값을 그대로 로드뷰에 전달해서 완성했다.

 

최종적으로 테스트 한번 더 해보기

테스트1

 

잘 전달받아서 출력하고 있다!

 

 


 

 

 

이제 앞으로 해야할것들

 

팝업창 나온 전기차 충전소 값을 충전소 길 찾기로 전달해서 도착지점으로 설정하기

충전소 길 찾기 스타일링

 

이러면 진짜 끝!