mun dev

[Spring] 공공데이터 API 데이터 DB에 저장하기 본문

공부/Spring

[Spring] 공공데이터 API 데이터 DB에 저장하기

mndev 2023. 9. 28. 17:08

공공데이터를 사용해서 전기차 관련 프로젝트를 진행하기 위해서는 해당 데이터들을 DB에 저장해야 한다.

 

 

https://www.data.go.kr/

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

우선 본인이 사용하고자 하는 데이터를 검색해서 찾은 후 사용 신청을 하면된다.

신청하면 바로 사용이 가능하고  API키는 복사해서 호출시 넣으면 된다.

API마다 필수 request값이 있으니 해당 API 문서를 잘 참고하는 것이 중요하다!

 

 

나는 xml로 반환되는 데이터들을 DB에 저장할 것이기 때문에

우선, DataService 에 해당 메서드를 추가해준다.

public void callApiAndSaveData(String apiKey,String addr) throws IOException {
        String apiUrl = "https://apis.data.go.kr/B552584/EvCharger/getChargerInfo";
        String serviceKey = apiKey; // 본인이 발급 받은 api키 
        String pageNo = "1";
        String numOfRows = "41291"; //41291
        String zcode = addr;

        StringBuilder urlBuilder = new StringBuilder(apiUrl);
        urlBuilder.append("?" + URLEncoder.encode("serviceKey", "UTF-8") + "=" + serviceKey);
        urlBuilder.append("&" + URLEncoder.encode("pageNo", "UTF-8") + "=" + URLEncoder.encode(pageNo, "UTF-8"));
        urlBuilder.append("&" + URLEncoder.encode("numOfRows", "UTF-8") + "=" + URLEncoder.encode(numOfRows, "UTF-8"));
        urlBuilder.append("&" + URLEncoder.encode("zcode", "UTF-8") + "=" + URLEncoder.encode(zcode, "UTF-8"));

        URL url = new URL(urlBuilder.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-type", "application/json");
        log.info("Response code: " + conn.getResponseCode());

        BufferedReader rd;
        if (conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
            rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        } else {
            rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        }

        StringBuilder sb = new StringBuilder();
        String line;

        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }

        rd.close();
        conn.disconnect();

        String xml = sb.toString();
        Map<String, DataSave> result = new HashMap<>();
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(DataSave.class); // JAXB Context 생성
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();  // Unmarshaller Object 생성
            DataSave apiResponse = (DataSave) unmarshaller.unmarshal(new StringReader(xml)); // unmarshall 메서드 호출
            result.put("response", apiResponse);

            if (apiResponse.getBody() != null && apiResponse.getBody().getItems() != null) {
                List<DataSave.Body.Items.Item> itemList = apiResponse.getBody().getItems().getItem();
                List<Data> datas = itemList.stream()
                        .map(this::convertToEntity)
                        .collect(Collectors.toList());
                dataRepository.saveAll(datas);
            }
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

 

 

DataSave엔티티

xml로 되어 있는 데이터들을 변환하는 역할을 해주는 엔티티이다.

    @Getter
    @Setter
    @XmlRootElement(name = "body")
    public static class Body {

        private Items items;
        private String pageNo;
        private String numOfRows;
        private String zcode;

        @Getter
        @Setter
        @XmlRootElement(name = "items")
        public static class Items {

            private List<Item> item;

            @Getter
            @Setter
            @XmlRootElement(name = "item")
            public static class Item {

                private String statNm; // 충전소명
                private String statId; // 충전소 ID
                private String chgerId; // 충전기 ID
                private String chgerType; // 충전기 타입
                private String addr; // 소재지 도로명 주소
                private String lat; // 위도
                private String lng; // 경도
                private String useTime; // 이용 가능 시간
                private String busiId; // 기관 ID
                private String busiNm; // 운영기관명
                private String busiCall; // 관리업체 전화번호
                private String stat; // 충전기 상태
                private String statUpdDt; // 상태 갱신 일시
                private String powerType; // 충전기 용량
                private String zcode; // 지역코드
                private String zscode; // 지역상세코드
                private String parkingFree; // 주차료무료 여부
                private String note; // 충전소 안내
            }
        }
    }
}

 

Data엔티티

변환해서 저장되는 엔티티, DB의 각 컬럼들이 되는 부분이다.

@Entity(name="home")
@lombok.Data
@AllArgsConstructor
@NoArgsConstructor // 기본 생성자 추가
public class Data {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String statNm; // 충전소명
    private String statId; // 충전소 ID
    private String chgerId; // 충전기 ID
    private String chgerType; // 충전기 타입
    private String addr; // 소재지 도로명 주소
    private String lat; // 위도
    private String lng; // 경도
    private String useTime; // 이용 가능 시간
    private String busiId; // 기관 ID
    private String busiNm; // 운영기관명
    private String busiCall; // 관리업체 전화번호
    private String stat; // 충전기 상태
    private String statUpdDt; // 상태 갱신 일시
    private String powerType; // 충전기 용량
    private String zcode; // 지역코드
    private String zscode; // 지역상코드
    private String parkingFree; // 주차료무료 여부
    private String note; // 충전소 안내
}

 

이후 DataService 부분에 변환해서 저장되는 메서드를 추가해준다.

  public Data convertToEntity(DataSave.Body.Items.Item response){
        Data datas=new Data();
        datas.setStatNm(response.getStatNm());
        datas.setStatId(response.getStatId());
        datas.setChgerId(response.getChgerId());
        datas.setChgerType(response.getChgerType());
        datas.setAddr(response.getAddr());
        datas.setLat(response.getLat());
        datas.setLng(response.getLng());
        datas.setUseTime(response.getUseTime());
        datas.setBusiId(response.getBusiId());
        datas.setBusiCall(response.getBusiCall());
        datas.setStat("2"); // 충전대기 상태로 초기화
        datas.setStatUpdDt(response.getStatUpdDt());
        datas.setPowerType(response.getPowerType());
        datas.setZcode(response.getZcode());
        datas.setZscode(response.getZscode());
        datas.setParkingFree(response.getParkingFree());
        datas.setNote(response.getNote());

        dataRepository.save(datas);
        return datas;
    }

 

BaseData

프로젝트 실행시 API를 호출하여 지역별 전기차 데이터들을 저장한다.

 

@Slf4j
@Configuration
@Profile({"dev"})
public class BaseData {

    @Value("${data.apiKey}")
    private String apiKey;

    @Bean
    CommandLineRunner initData(
            DataService dataService
    ){
        return new CommandLineRunner() {
            @Override
            @Transactional
            public void run(String... args) throws Exception {
                String addr[]={"11","26","27","28","29","30","31","36","41","43",
                        "44","45","46","47","48","50","51"};
                for(int i=0; i<addr.length; i++){
                    dataService.callApiAndSaveData(apiKey,addr[i]);
                }
                log.info("BASE_DATA SUCCESS!");
            }
        };
    }
}

 

 

이렇게 BASE_DATA SUCCESS가 떴다면 저장이 완료됐다. 이제 이 데이터들을 사용해서 기능 구현을 시작하면 된다.