본문 바로가기
Develop/JPA

전기차 충전소 API 호출하기 (2)

by ys2ys2 2024. 11. 8.

전기차 충전소 API 호출하기 (1)에 이어서,,

 

마지막 작업으로 충전소 목록을 가져오게 했고

 

다음으로 해야 할 것들은

충전기 타입 부분 추가해서 어떤 충전기 타입인지 표시하기,

해당 지역의 모든 충전소 값들을 가져오기,

충전소 넘치는거 css하기,

리스트에 나온 충전소들 선택하면 지도에 라벨로 표시하기,

라벨 클릭시 해당 충전소에 대한 자세한 정보 팝업창으로 표시하기

 

정도로 생각하고 작업하기!

 


 

 

충전기 타입 추가, 표시

다시 공공데이터 가이드로 돌아가서 어떤 충전기 타입으로 주고 있는지 확인하기!

 

충전기 타입

 

 

 

요렇게 제공하고 있으니 각 충전기 타입의 코드에 맞게 설명부분을 업데이트 했다.

chargerTypeMap 객체에 충전기 타입 코드와 이름을 매핑했고 

chargerTypeMap 객체에서 type변수에 해당하는 값을 가져오지만,

type 키가 없는 경우 || "알 수 없는 타입" 으로 표현하게 했다.

 

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 typeText = chargerTypeMap[type] || "알 수 없는 타입";

 

이렇게 하면 api에서 값을 받아올 때 사용자들이 어떤 충전기인지 알 수 있다!

 

 

충전기 타입 추가, 표시 - 결과

 

타입 추가

 

 

검색하고 나온 결과값에 미리 설정해둔 타입에 맞게 충전기 타입이 잘 나온다!

 


 

 

충전소 결과값 스타일링

 

충전소 결과값들이 넘치는 현상이 있어서 css 수정을 했다.

 

searchbar에는 100%의 height값을 줘서 화면이 확대되거나 축소되어도 같은 크기를 유지하게 했고

충전소 검색 탭과, 충전소 길 찾기 탭이 나눠진 상태라 해당 탭을 선택하면 active가 되는데

id가 searchContent인 tab-content class가 active일때 이렇게 크기를 잡아놨다.

.tab-content.active {
    display: flex;
    margin-top: 2vh;
    height: 100%;
    flex-direction: column;
    flex: 1;
    overflow: hidden;
}

 

그러고 searchlist class에는 height 100%;, flex:1;, overflow-y: auto;, box-sizing: border-box;를 통해 높이를 잡고 해당 div 안에서 스크롤을 할 수 있게 했다.

(추후 디테일에서 스크롤 스타일을 파란색 계열 + 얇은 스크롤로 주고 싶다!)

.searchlist {
    width: auto;
    height: 100%;
    display: flex;
    flex-direction: column;
    margin-left: 2vh;
    overflow-y: auto;
    max-height: 100%;
    flex: 1;
    box-sizing: border-box;
}

 

충전소 결과값 스타일링 - 결과

 

스크롤 css

 

해당 div 안에서 스크롤이 잘 된다!

여기서 해당 지역의 충전소를 전체로 불러와서 스크롤을 할 수 있게 해야 하는건지,

페이지네이션을 줘서 1,2,3 이런식으로 페이지를 넘겨야 하는것인지 고민하고 있다.

어차피 선택해서 지도에 찍혀서 라벨로 표시되고, 충전소 정보가 뜨는거라면

사용자가 스크롤 하다가 가까운 충전소가 보였을 때 선택해서 바로 표시된다고 하면 굳이 페이지네이션이 필요없을것 같기도..

 

 


 

 

해당 지역의 모든 충전소 값들을 가져오기

 

기존에 사용하고 있던 테스트용인 numOfRows=10과 pageNo=1을 수정해야 한다.

const apiUrl = `http://apis.data.go.kr/B552584/EvCharger/getChargerInfo?serviceKey=${encodeURIComponent(apiKey)}&numOfRows=10&pageNo=1&dataType=XML&zcode=${cityCode}&zscode=${districtCode}`;

 

 

여기서 생각해본게 각각 시군구마다 충전소 갯수도 다르고, 그걸 알려주는 numOfRows나 pageNo도 모르는 상태기 때문에 어떻게 해야할지 고민이였다.

아무 생각없이 numOfRows를 1000으로 잡고 pageNo도 1000으로 하면 한 번의 호출에 너무 많은 데이터를 가져오게 되고, 응답 시간이 길어지고 그런 상황이 분명히 생기기 때문에

해당 시군구에 있는 pageNo을 순회하면서 각 페이지에 해당하는 값들만 가져오게 했다.

 

async function fetchAllChargers(cityCode, districtCode, apiKey) {
    const allItems = []; // 아이템 담을 배열
    let pageNo = 1; // 페이지 번호 초기화
    const numOfRows = 100; // 100개씩 데이터 줘
    let hasMoreData = true; // 데이터 더 있어?

    while (hasMoreData) {
        // API 호출 URL에서 pageNo와 numOfRows로 페이지당 데이터를 요청
        const apiUrl = `http://apis.data.go.kr/B552584/EvCharger/getChargerInfo?serviceKey=${encodeURIComponent(apiKey)}&numOfRows=${numOfRows}&pageNo=${pageNo}&dataType=XML&zcode=${cityCode}&zscode=${districtCode}`;
        try {
            const response = await fetch(apiUrl);
            if (!response.ok) throw new Error("API 호출 오류");

            const data = await response.text();
            const parser = new DOMParser();
            const xmlDoc = parser.parseFromString(data, "application/xml");
            const items = xmlDoc.getElementsByTagName("item");

            // items의 데이터를 allItems 배열에 추가
            for (let i = 0; i < items.length; i++) {
                allItems.push(items[i]);
            }

            // 데이터가 100개 미만? 다음 페이지 X
            if (items.length < numOfRows) {
                hasMoreData = false; // 데이터 없으면 loop 끝
            } else {
                pageNo++; // 다음 페이지 ++
            }
        } catch (error) {
            console.error("API 호출 오류:", error);
            hasMoreData = false;
        }
    }
    return allItems;
}

 

이렇게 하고 테스트 해봤는데.. 

 

결과값이 너무 많다

 

충전소가 별로 없을것 같은곳으로 했는데도 결과값이 너무 많아서 스크롤하기 힘들었다...

(전기차 충전소 누가 없다고 했어.. 엄청 많잖아..)

 

 


 

 

 

그냥 페이지네이션으로 해서 각각의 페이지에 해당하는 충전소가 표시되게 해야할 것 같아서 다시 수정!

 

일단 페이지 번호를 1로 시작하게 하고

한 페이지에 표시할 충전소를 30개로 설정했다.

총 페이지 수는 api 호출 후에 데이터 개수에 따라 계산되니까 일단 1로 설정

const numOfRows = 30; // 표시할 결과 개수
let currentPage = 1; // 현재 페이지 번호
let totalPage = 1; // 총 페이지 수

 

 

setupPagination을 통해 총 페이지 수에 따라 페이지 버튼을 만들었고

for문으로 각 페이지 번호에 해당하는 버튼을 만들고 그 버튼을 누르면 해당 페이지 번호에 맞는 데이터를 가져오는

fetchChargersByPage 함수가 실행되게 했다.

그러고 페이지네이션 버튼을 담을 div를 하나 만들어주고 테스트!

 

function setupPagination() {
    const paginationContainer = document.getElementById("pagination");
    paginationContainer.innerHTML = "";

    for (let i = 1; i <= totalPage; i++) {
        const pageButton = document.createElement("button");
        pageButton.textContent = i;
        pageButton.className = "page-button";
        if (i === currentPage) pageButton.classList.add("active");

        pageButton.addEventListener("click", function () {
            currentPage = i; 
            fetchChargersByPage(currentPage);
        });

        paginationContainer.appendChild(pageButton);
    }
}

 

 

 

 

해당 지역의 모든 충전소 값들을 가져오기 - 결과

 

 

페이지네이션 버튼

 

제주도가 전기차 충전소가 가장 많다고 해서 찍어봤는데.. 제주시만  30개씩 가져오는 값에 187개면.. 5610개..?

 

일단 해당하는 버튼 누를때 마다 해당 페이지에 대한 충전소 결과가 잘 나오고 있으니까 이걸 스타일링을 해야할 것 같다.

1~10까지의 버튼 후 다음을 누르면 11~20까지 목록이 나오게 하는것도 깔끔할 것 같아서.. 그렇게 할 예정!

 

 

다 하고 또 업뎃해야지~~