-
실시간 날씨 open api 활용프로젝트/나날이 2023. 10. 27. 20:20
'나날이'는 날씨에 따른 옷을 추천해주는 서비스이다. 그렇기 때문에 실시간 날씨 데이터를 받아오는 것이 매우 중요하다.
open api를 검색하던 도중 Weather Forecast API라는 API를 발견해서 이걸 활용하기로 했다.
api 사이트
@Slf4j @Service @RequiredArgsConstructor public class WeatherService { public ResponseEntity<Map<String, Map<String, Object>>> weather(LocalDateTime weatherTime) throws IOException { String today = weatherTime.toString().concat("T"); today = today.substring(0, today.indexOf("T")); System.out.println("today = " + today); StringBuilder urlBuilder = new StringBuilder("https://api.open-meteo.com/v1/forecast"); // HTTPS 프로토콜 사용 urlBuilder.append("?" + URLEncoder.encode("latitude", "UTF-8") + "=" + URLEncoder.encode("37.4526", "UTF-8")); urlBuilder.append("&" + URLEncoder.encode("longitude", "UTF-8") + "=" + URLEncoder.encode("126.6517", "UTF-8")); urlBuilder.append("&" + URLEncoder.encode("hourly", "UTF-8") + "=" + URLEncoder.encode("temperature_2m,precipitation,uv_index", "UTF-8")); URL url = new URL(urlBuilder.toString()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Content-type", "application/json"); System.out.println("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 data = sb.toString(); System.out.println("API 응답 데이터: " + data); try { JSONObject jsonResponse = new JSONObject(data); JSONObject hourlyTimes = jsonResponse.getJSONObject("hourly"); JSONArray timeData = hourlyTimes.getJSONArray("time"); JSONArray temperatureData = hourlyTimes.getJSONArray("temperature_2m"); JSONArray precipitationData = hourlyTimes.getJSONArray("precipitation"); JSONArray uvIndexData = hourlyTimes.getJSONArray("uv_index"); // 날짜별 데이터를 매핑하기 위한 Map TreeMap<String, Map<String, Object>> weatherDataByDate = new TreeMap<>(); for (int i = 0; i < timeData.length(); i++) { // 이전 코드 생략 String time = timeData.getString(i); double temperature = temperatureData.getDouble(i); double precipitation = precipitationData.getDouble(i); double uvIndex = uvIndexData.getDouble(i); // 날짜 정보 추출 String date = time.replace("T", " "); // 해당 날짜에 대한 데이터 매핑 Map<String, Object> weatherData = new HashMap<>(); weatherData.put("temperature", temperature); weatherData.put("precipitation", precipitation); weatherData.put("uv_index", uvIndex); if(date.contains(today)) { weatherDataByDate.put(date, weatherData); } } List<Map.Entry<String, Map<String, Object>>> sortedList = new ArrayList<>(weatherDataByDate.entrySet()); // ResponseEntity로 매핑된 데이터 반환 return ResponseEntity.ok(weatherDataByDate); } catch (JSONException e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } }
api를 구현한 전체 코드인데 조금씩 나눠서 설명하겠다.
StringBuilder urlBuilder = new StringBuilder("https://api.open-meteo.com/v1/forecast"); // HTTPS 프로토콜 사용 urlBuilder.append("?" + URLEncoder.encode("latitude", "UTF-8") + "=" + URLEncoder.encode("37.4526", "UTF-8")); urlBuilder.append("&" + URLEncoder.encode("longitude", "UTF-8") + "=" + URLEncoder.encode("126.6517", "UTF-8")); urlBuilder.append("&" + URLEncoder.encode("hourly", "UTF-8") + "=" + URLEncoder.encode("temperature_2m,precipitation,uv_index", "UTF-8")); URL url = new URL(urlBuilder.toString()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Content-type", "application/json"); System.out.println("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 data = sb.toString(); System.out.println("API 응답 데이터: " + data);
우선 이 코드는 url을 통해서 api의 데이터를 받아오는 과정이다. 위치는 인천으로 고정했고, 실시간 날씨를 받아오는 역할을 한다.
레퍼런스를 참고해서 최대한 비슷하게 구현했다.
try { JSONObject jsonResponse = new JSONObject(data); JSONObject hourlyTimes = jsonResponse.getJSONObject("hourly"); JSONArray timeData = hourlyTimes.getJSONArray("time"); JSONArray temperatureData = hourlyTimes.getJSONArray("temperature_2m"); JSONArray precipitationData = hourlyTimes.getJSONArray("precipitation"); JSONArray uvIndexData = hourlyTimes.getJSONArray("uv_index"); // 날짜별 데이터를 매핑하기 위한 Map TreeMap<String, Map<String, Object>> weatherDataByDate = new TreeMap<>(); for (int i = 0; i < timeData.length(); i++) { // 이전 코드 생략 String time = timeData.getString(i); double temperature = temperatureData.getDouble(i); double precipitation = precipitationData.getDouble(i); double uvIndex = uvIndexData.getDouble(i); // 날짜 정보 추출 String date = time.replace("T", " "); // 해당 날짜에 대한 데이터 매핑 Map<String, Object> weatherData = new HashMap<>(); weatherData.put("temperature", temperature); weatherData.put("precipitation", precipitation); weatherData.put("uv_index", uvIndex); if(date.contains(today)) { weatherDataByDate.put(date, weatherData); } } List<Map.Entry<String, Map<String, Object>>> sortedList = new ArrayList<>(weatherDataByDate.entrySet()); // ResponseEntity로 매핑된 데이터 반환 return ResponseEntity.ok(weatherDataByDate); } catch (JSONException e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); }
그 다음은 JSON 데이터에서 원하는 값만 추출해내는 것이다. 모든 데이터를 받아오지는 않았으며 기온, 강수량, 자외선 수치만 받아왔다. 그리고 해당 날짜에 대한 값들을 반환해준다.
getJsonArray로 원하는 데이터를 고른다. (api 사이트에 많은 데이터들이 있는데 원하는 데이터 선택하면 됨)
이후에 map에 고른 데이터들을 넣어준 다음에 그 결과물들을 쭉 return 하면 아래 사진과 같이 결과들이 출력된다.
String today = weatherTime.toString().concat("T"); today = today.substring(0, today.indexOf("T")); System.out.println("today = " + today);
함수의 파라미터로 입력받은 weatherTime을 변환해주는 코드가 있는데 api에서 원하는 형식으로 변형시키기 위한 것이며 이 값으로 해당 날짜의 데이터들을 추출해낸다.
1시간 간격으로 입력한 날짜의 온도, 강수량, 자외선 수치가 나온다. 이제 이 값으로 날씨에 따른 옷을 추천하는 로직을 개발할 것이다.
날씨 관련 api들이 많았는데, 현재 날씨만 제공해주는 api도 있고 키 관리가 어려운 api도 있어서 많은 api 중에서 원하는 데이터를 잘 추출해낼 수 있는 api를 사용하는 것이 좋은 방법이다.
'프로젝트 > 나날이' 카테고리의 다른 글
나날이 백엔드 CI-CD 구축의 과정 (0) 2023.11.20 Get 요청에서는 Body로 데이터를 받으면 안된다 (0) 2023.11.17 옷 사진 데이터 설계 방식에 대한 고민 (0) 2023.10.29