개발 공부용

[팀 프로젝트] 프로젝트 기록 #3 - 기상청 API를 이용해 날씨 정보 받고 저장하기(1) 본문

Project

[팀 프로젝트] 프로젝트 기록 #3 - 기상청 API를 이용해 날씨 정보 받고 저장하기(1)

솝제로 2023. 10. 5. 17:24

 

 

기상청_단기예보 ((구)_동네예보) 조회서비스

초단기실황, 초단기예보, 단기((구)동네)예보, 예보버전 정보를 조회하는 서비스입니다. 초단기실황정보는 예보 구역에 대한 대표 AWS 관측값을, 초단기예보는 예보시점부터 6시간까지의 예보를,

www.data.go.kr

 

지역별 날씨가 필요한 기능이 있어 외부 API를 활용하기로 했습니다.

제가 이용한 서비스는 공공데이터포털의 기상청 단기 예보 조회 서비스입니다. ☀️🌦️

회원가입을 하고 활용 목적을 밝히며 활용 신청을 해야 사용할 수 있습니다.

 

출처 : 공공데이터포털 https://www.data.go.kr/data/15084084/openapi.do

 

JSON, XML 중 요청 자료 형식을 선택할 수 있습니다.

단기 예보는 격자 x, y좌표가 필요하니 위 링크에서 참고 문서(활용가이드)를 다운 받아서 원하는 지역의 좌표를 확인해야 합니다.

 

 

 

Postman에서 테스트해보면 이와 같이 데이터가 잘 조회되는 것을 확인할 수 있었습니다.😊

Postman에서 테스트

 

다만 문제가 있었던 것은, 강수확률은 매 시간 데이터가 나왔는데 하루의 최저기온과 최고기온은 그렇지 않다는 점이었습니다.

제가 필요한 값이 하루의 최저기온, 최고기온과 3시간마다의 강수확률이었는데요.

일 최고기온 혹은 최저기온은 포함되는 시간대를 조회해야만 값이 나오게 됩니다. 

이 사실을 늦게 파악해서 일 최저기온과 최고기온이 조회되지 않는 줄 알고 조금 헤맸습니다.😶‍🌫️

 

 

 

따라서 일 최고기온, 일 최저기온, 3시간 간격의 강수확률을 한 번에 얻기 위해

base_time을 새벽 2시로, numOfRows를 260으로 해줬습니다. 💡

 

일 최저기온
일 최고기온

이렇게 URL을 수정하고 나니 필요한 값을 다 받아올 수 있었습니다!

 

 

 

API 요청을 보내고 데이터를 받을 수 있는 샘플 코드가 이미 있기 때문에, URL을 만들어서 데이터를 받는 코드는 참고해서 작성할 수 있었습니다.

저는 멘토님 조언 참고해서 서비스 클래스를 따로 생성해서 부분별로 나누어 메서드로 작성하였습니다.

 

    public StringBuilder makeURL(String yyyyMMdd, String nx, String ny) {
        StringBuilder urlBuilder = new StringBuilder(API_URL);
        urlBuilder.append("?" + URLEncoder.encode("ServiceKey", StandardCharsets.UTF_8) + "=" + SERVICE_KEY);
        urlBuilder.append("&" + URLEncoder.encode("pageNo", StandardCharsets.UTF_8) + "=" + URLEncoder.encode(PAGE_NO, StandardCharsets.UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("numOfRows", StandardCharsets.UTF_8) + "=" + URLEncoder.encode(NUM_OF_ROWS, StandardCharsets.UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("dataType", StandardCharsets.UTF_8) + "=" + URLEncoder.encode(DATA_TYPE, StandardCharsets.UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("base_date", StandardCharsets.UTF_8) + "=" + URLEncoder.encode(yyyyMMdd, StandardCharsets.UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("base_time", StandardCharsets.UTF_8) + "=" + URLEncoder.encode(HOUR, StandardCharsets.UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("nx", StandardCharsets.UTF_8) + "=" + URLEncoder.encode(nx, StandardCharsets.UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("ny", StandardCharsets.UTF_8) + "=" + URLEncoder.encode(ny, StandardCharsets.UTF_8));

        return urlBuilder;
    }

    public String getData(StringBuilder urlBuilder) throws IOException {
        URL url = new URL(urlBuilder.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(HttpMethod.GET.toString());
        conn.setRequestProperty("Content-type", MediaType.APPLICATION_JSON_VALUE);

        //응답 확인
        log.info("Response code: {}", conn.getResponseCode());

        //응답 데이터 읽기
        BufferedReader reader = null;
        String result = null;

        try {
            if (conn.getResponseCode() >= HttpStatus.OK.value() && conn.getResponseCode() <= HttpStatus.MULTIPLE_CHOICES.value()) {
                reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            } else {
                reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
            }

            //응답 데이터를 문자열로 변환
            StringBuilder strBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                strBuilder.append(line);
            }

            //연결 종료
            conn.disconnect();
            result = strBuilder.toString();

        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error("BufferedReader를 닫던 중 에러가 발생했습니다.");
                }
            }
        }
        return result;
    }

 

이렇게 해서 요청을 보내고 데이터를 받아올 수 있었습니다.

이제 받아온 데이터를 파싱해야 합니다.