📍 공공데이터(Open Data)
공공기관에서 사용할 목적으로 처리된 자료 또는 정보
🔑 OpenAPI 방식
🔑 데이터 포맷 종류
🔑 공공데이터 OpenAPI를 사용하기 위한 절차
1. https://www.data.go.kr/ 로그인
2. 사용하고자 하는 공공데이터 조회 -> 신청 (참고자료 - 직업훈련)
3. 마이페이지 -> 데이터 활용 -> Open API -> 활용신청 현황!
인증키 : 마이페이지 -> 데이터 활용 -> Open API -> 인증키 발급 현황
상세설명 -> 요청변수 참고(필수)
미리보기(확인) -> 요청 주소 확인
📍 HttpUrlConnection 객체 사용 절차
- 요청할 주소를 전달해서 java.net.URL 객체 생성하기
- 생성된 URL 객체를 가지고 HttpUrlConnection 객체 얻어내기
- 요청 시 필요한 Header 설정하기
- 해당 OpenAPI 서버로 요청 보낸 후 입력 스트림을 통해 응답데이터 받기
- 다 사용한 스트림 객체 반납하기
(gson 라이브러리 사용)
package com.kh.opendata.run;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.kh.opendata.model.vo.Air;
public class AirPollutionJavaAppRun {
// 발급받은 인증키 변수 처리
public static final String SERVICEKEY ="인증키";
public static void main(String[] args) throws IOException {
// UnsupportedEncodingException의 부모로 예외처리
// OpenAPI 서버로 요청하고자 하는 url 작성
String url = "http://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty";
url += "?serviceKey=" + SERVICEKEY; // 서비스키가 제대로 부여되지 않았을 경우 => SERVICE_KEY_IS_NOT_REGISTERED_ERROR
url += "&sidoName=" + URLEncoder.encode("서울", "UTF-8");
url += "&returnType=json";
// System.out.println(url);
// ** HTTPURLConnection 객체를 활용해서 OpenAPI 요청 절차 **
// 1. 요청할 주소를 전달해서 java.net.URL 객체 생성하기
URL requestUrl = new URL(url);
// 2. 생성된 URL 객체를가지고 HttpUrlConnection 객체 얻어내기
HttpURLConnection urlConn = (HttpURLConnection)requestUrl.openConnection(); // 다운캐스팅
// 3. 요청 시 필요한 Header 설정하기
urlConn.setRequestMethod("GET");
// 4. 해당 OpenAPI 서버로 요청 보낸 후 입력 스트림을 통해 응답데이터 받기
BufferedReader br = new BufferedReader(new InputStreamReader( urlConn.getInputStream() ));
String responseText="";
String line;
while((line=br.readLine()) != null) { // 한 줄씩 읽어 올 데이터가 있는 동안 반복
// System.out.println(line);
responseText += line;
}
// System.out.println(responseText);
/* JSON 형태
{
"response":
{
"body":
{
"totalCount":40,
"items":
[
{
"so2Grade":"1",
"coFlag":null,
"khaiValue":"52",
"so2Value":"0.003",
"coValue":"0.5",
"pm10Flag":null,
"o3Grade":"1",
"pm10Value":"15",
"khaiGrade":"2",
"sidoName":"서울",
"no2Flag":null,
"no2Grade":"2",
"o3Flag":null,
"so2Flag":null,
"dataTime":"2023-08-23 14:00",
"coGrade":"1",
"no2Value":"0.032",
"stationName":"정릉로",
"pm10Grade":"1",
"o3Value":"0.029"
},
{
"so2Grade":"1",
"coFlag":null,
"khaiValue":"-",
"so2Value":"0.002",
"coValue":"0.5",
"pm10Flag":null,
"o3Grade":"2",
"pm10Value":"3",
"khaiGrade":null,
"sidoName":"서울",
"no2Flag":null,
"no2Grade":"1",
"o3Flag":null,
"so2Flag":null,
"dataTime":"2023-08-23 14:00",
"coGrade":"1",
"no2Value":"0.013",
"stationName":"도봉구",
"pm10Grade":"1",
"o3Value":"0.039"
}, ...
]
}
}
}
*/
// JSONObject, JsonArray 이용해서 파싱할 수 있음(gson 라이브러리)
// json 데이터를 원하는 데이터만 추출하여 VO에 담기
// 응답 데이터 text를 JsonObject화 시키는 작업(파싱)
JsonObject totalObj = JsonParser.parseString(responseText).getAsJsonObject();
// System.out.println("total : " + totalObj);
// response 속성에 접근
JsonObject responseObj = totalObj.getAsJsonObject("response");
// System.out.println("responseObj : " + responseObj);
// body 속성 접근
JsonObject bodyObj = responseObj.getAsJsonObject("body");
// System.out.println("bodyObj : " + bodyObj);
// totalCount 속성 접근
int totalCount = bodyObj.get("totalCount").getAsInt();
// System.out.println("totalCount : " + totalCount);
// items(JsonArray 형태) 속성 접근
JsonArray itemArr = bodyObj.getAsJsonArray("items");
// System.out.println("itemArr : " + itemArr);
// items에 담겨있는 item 객체 하나씩 추출
ArrayList<Air> list = new ArrayList<Air>();
// length 아니고 size
for(int i = 0; i<itemArr.size(); i++) {
JsonObject item = itemArr.get(i).getAsJsonObject(); // 배열이 아니라 객체라서 get 사용 !! itemArr[i] 사용 불가
// System.out.println(item);
Air air = new Air();
air.setStationName(item.get("stationName").getAsString());
air.setDataTime(item.get("dataTime").getAsString());
air.setKhaiValue(item.get("khaiValue").getAsString());
air.setPm10Value(item.get("pm10Value").getAsString());
air.setSo2Value(item.get("so2Value").getAsString());
air.setCoValue(item.get("coValue").getAsString());
air.setNo2Value(item.get("no2Value").getAsString());
air.setO3Value(item.get("o3Value").getAsString());
list.add(air);
}
// System.out.println("list : "+list);
// list에 담긴 VO 객체 확인
for(Air a : list) {
System.out.println(a);
}
// 5. 다 사용한 스트림 객체 반납하기
br.close();
urlConn.disconnect();
}
}
📍 비동기식으로 웹 애플리케이션에 적용하고자 할 때의 절차
- Jsp에서 현재 웹 애플리케이션 서버로 ajax 요청
- Controller에서 요청 받기 (이때 요청 시 전달값이 있다면 기록)
- HttpURLConnection 객체 활용해서 OpenAPI서버에 요청하여 응답데이터 받기
- 3번 과정에서의 응답데이터를 Client에게 다시 응답
- Client측에서 돌려받은 응답데이터를 가지고 파싱 작업 후 웹 페이지에 시각화 하기
<h1>실시간 대기오염 정보</h1>
지역 :
<select id="location">
<option>서울</option>
<option>부산</option>
<option>대전</option>
</select>
<button id="btn1">해당 지역 대기 오염 정보</button>
<br>
<br>
<table border="1" id="result1">
<thead>
<tr>
<th>측정소명</th>
<th>측정일시</th>
<th>통합대기환경수치</th>
<th>미세먼지농도</th>
<th>아황산가스농도</th>
<th>일산화탄소농도</th>
<th>이산화탄소농도</th>
<th>오존농도</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
$(function(){
$("#btn1").click(function(){
/* JSON 형식으로 응답받을 떄
$.ajax({
url : "air",
data : {location : $("#location").val()},
success : function(data){
// console.log(data);
// console.log(data.response.body.items);
const itemArr = data.response.body.items;
let value = "";
for(let item of itemArr){
console.log(item);
value += "<tr>"
+ "<td>" + item.stationName + "</td>"
+ "<td>" + item.dataTime + "</td>"
+ "<td>" + item.khaiValue + "</td>"
+ "<td>" + item.pm10Value + "</td>"
+ "<td>" + item.so2Value + "</td>"
+ "<td>" + item.coValue + "</td>"
+ "<td>" + item.no2Value + "</td>"
+ "<td>" + item.o3Value + "</td>"
+"</tr>"
}
$("#result1 > tbody").html(value);
}, error : function(){
console.log("통신실패");
}
})
*/
// @RequestMapping(value = "air", produces = "application/json; charset=UTF-8")
@ResponseBody
public String airMethod(String location) throws IOException {
String url = "http://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty";
url += "?serviceKey=" + SERVICEKEY; // 서비스키 추가
url += "&sidoName=" + URLEncoder.encode( location , "UTF-8"); // 지역명 추가(한글이 들어가면 인코딩 처리해야 함)
url += "&returnType=json"; // 리턴타입
url += "&numOfRows=2";
// 1. 작성된 url 정보를 넣어서 URL 객체 생성
URL requestUrl = new URL(url);
// 2. 생성된 URL 객체로 URLConnection 생성
HttpURLConnection urlConn = (HttpURLConnection)requestUrl.openConnection();
// 3. 요청 시 필요한 Header 생성
urlConn.setRequestMethod("GET");
// 4. 해당 OpenAPI 서버로 요청 후 입력스트림을 통해서 응답데이터 읽어오기
BufferedReader br = new BufferedReader( new InputStreamReader( urlConn.getInputStream()));
String line;
String responseText="";
while((line = br.readLine()) != null) {
responseText += line;
}
// 5. 다 사용한 스트림 반납 및 연결 해제
br.close();
urlConn.disconnect();
System.out.println(responseText);
return responseText;
}
$.ajax({
url : "air",
data : {location : $("#location").val()},
success : function(result){
console.log(result);
// $("요소명").find(매개변수)
// - 기준이 되는 요소의 하위 요소들 중 특정 요소를 찾을 때 사용
// - html, xml은 같은 markup language이기 때문에 사용 가능하다
// console.log($(result).find("item"));
// xml 형식의 응답데이터를 받았을 때
// 1. 넘겨받은 데이터를 $() 제이쿼리화 시킨 후
// 응답데이터 안에 실제 데이터가 담겨있는 요소 선택
const itemArr = $(result).find("item");
// 2. 반복문을 통해 실제 데이터가 담긴 요소들에 접근해서 동적으로 요소 만들기
let value;
itemArr.each(function(index, item){
// console.log(item);
console.log($(item).find("o3Value").text());
console.log(item);
value += "<tr>"
+ "<td>" + $(item).find("stationName").text() + "</td>"
+ "<td>" + $(item).find("dataTime").text() + "</td>"
+ "<td>" + $(item).find("khaiValue").text() + "</td>"
+ "<td>" + $(item).find("pm10Value").text() + "</td>"
+ "<td>" + $(item).find("so2Value").text() + "</td>"
+ "<td>" + $(item).find("coValue").text() + "</td>"
+ "<td>" + $(item).find("no2Value").text() + "</td>"
+ "<td>" + $(item).find("o3Value").text() + "</td>"
+"</tr>"
});
// 3. 동적으로 만들어낸 요소를 화면에 출력
$("#result1 > tbody").html(value);
},
error : function(){console.log("통신 실패")}
})
})
})
@GetMapping(value="air", produces = "text/xml; charset=UTF-8")
@ResponseBody
public String airPollution(String location) throws IOException {
// 필요한 url 가져오기
String url = "http://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty";
url += "?serviceKey=" + SERVICEKEY;
url += "&sidoName=" + URLEncoder.encode( location , "UTF-8");
url += "&returnType=xml";
url += "&numOfRows=5";
// URL 객체 생성
URL requestUrl = new URL(url);
// URL Connection 생성
HttpURLConnection urlConn = (HttpURLConnection)requestUrl.openConnection();
// Header 생성
urlConn.setRequestMethod("GET");
// 스트림 생성
BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
// 데이터 읽어서 저장
String responseText = "";
String line;
while((line=br.readLine()) != null) {
responseText += line;
}
// 자원 반납
br.close();
urlConn.disconnect();
System.out.println(responseText);
return responseText;
}
<h1>실시간 지진해일 긴급 대피장소</h1>
<button id="btn2">실시간 지진해일 긴급 대피장소 정보</button>
<br><br>
<table border="1" id="result2">
<thead>
<tr>
<th>시도명</th>
<th>시군구명</th>
<th>대피지구명</th>
<th>대피장소명</th>
<th>주소</th>
<th>경도</th>
<th>위도</th>
<th>수용가능인원수</th>
<th>대피소 분류명</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
$(function(){
$("#btn2").click(function(){
$.ajax({
url : "shelter",
success : function(data){
console.log(data);
const list = $(data).find("row");
// console.log(list)
let value;
list.each(function(index, item){
value += "<tr>"
+ "<td>" + $(item).find("sido_name").text() + "</td>"
+ "<td>" + $(item).find("sigungu_name").text() + "</td>"
+ "<td>" + $(item).find("remarks").text() + "</td>"
+ "<td>" + $(item).find("shel_nm").text() + "</td>"
+ "<td>" + $(item).find("address").text() + "</td>"
+ "<td>" + $(item).find("lon").text() + "</td>"
+ "<td>" + $(item).find("lat").text() + "</td>"
+ "<td>" + $(item).find("shel_av").text() + "</td>"
+ "<td>" + $(item).find("shel_div_type").text() + "</td>"
+"</tr>"
})
$("#result2 > tbody").html(value);
},
error : function(){
console.log("통신 장애")
}
})
})
})
</script>
// xml형식으로 지진해일 대피소 OpenAPI 활용하기
@GetMapping(value="shelter", produces = "text/xml; charset=UTF-8")
@ResponseBody
public String shelterList() throws IOException {
String url = "https://apis.data.go.kr/1741000/TsunamiShelter3/getTsunamiShelter1List";
url += "?ServiceKey=" + SERVICEKEY;
url += "&pageNo=2";
url += "&numOfRows=100";
url += "&type=xml";
URL requestUrl = new URL(url);
HttpURLConnection urlConn = (HttpURLConnection)requestUrl.openConnection();
urlConn.setRequestMethod("GET");
BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
String responseText = "";
String line;
while((line=br.readLine()) != null) {
responseText += line;
}
br.close();
urlConn.disconnect();
System.out.println(responseText);
return responseText;
}