본문 바로가기
JAVA

JAVA 실습 9. 공공데이터와 Json을 이용한 항공데이터 조회하기

by 김마리님 2020. 4. 7.

공공데이터는 국가에서 제공하는 데이터들이다. 이 데이터는 다음에서 찾을 수 있다.

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

 

공공데이터포털

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

www.data.go.kr

이곳에서 항공데이터를 조회하여 가져올 것이다.

데이터는 다음과 같은 형태로 조회된다.

이 데이터를 주소로 나타내보면 다음과 같다.

위의 주소는 End Point이다. 즉, 데이터의 입구까지만 접근하는 주소이다.

? 이후에 나타나는 주소를 쿼리 스트링이라고 하는데, 이 쿼리 스트링은 일종의 질의문이다. 이 질의를 통해 데이터베이스에 상세히 접근할 수 있도록 한다.

또한, 이 데이터는 XML 형태로 제공된다.

따라서, 이 데이터를 자바에서 이용하려고 하면 Json 형태로 만들어주어야 한다. 쿼리 스트링 뒤에 타입을 붙여주자.

Json의 형태로 변화된 것이 보인다(객체의 형태)

이 주소 속 데이터를 자바 클래스로 변환하고, 값을 도출할 예정이다.

먼저, 이 Json 데이터의 클래스 원형을 만들어보자.

http://www.jsonschema2pojo.org/

불러오는 중입니다...

이 코드를 자바 새 파일로 만들어 원형 클래스로 만들어둔다.

이제, 항공데이터를 조회하도록 할 것이다.

package airplane;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import com.google.gson.Gson;

public class FlightApp {
	
	public static AirLineList getFlightInfo(String depAirportId, String arrAirportId, Integer depPlandTime){
		try {
			URL url=new URL("http://openapi.tago.go.kr/openapi/service/DmstcFlightNvgInfoService/getFlightOpratInfoList?serviceKey=uaLnSRJvnuUZqahDeBOz%2FK8rf4DSXtNmqWkueOzLButZOzzIfz4mHqWuLXwbVzwPSZ2BE736J6cX1uttigP9RA%3D%3D&numOfRows=50&depAirportId="+depAirportId+"&arrAirportId="+arrAirportId+"&depPlandTime="+depPlandTime+"&airlineId=AAR&_type=json");
			HttpURLConnection con =(HttpURLConnection)url.openConnection();
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(),"UTF-8"));
			StringBuilder sb=new StringBuilder();
			String input="";
			while((input=br.readLine())!=null) {
				System.out.println(input);
				sb.append(input);	
			}
			br.close();
			con.disconnect();
			
			Gson gson=new Gson();
			AirLineList flightInfo=gson.fromJson(sb.toString(), AirLineList.class);
			
			return flightInfo;
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static void main(String[] args) {
		String depAirportId="NAARKJJ";
		String arrAirportId="NAARKPC";
		Integer depPlandTime=20200407;
		AirLineList flightInfo=getFlightInfo(depAirportId, arrAirportId, depPlandTime);
		
		//List<Item> myItem = flightInfo.getResponse().getBody().getItems().getItem();
		
		// forEach 문 : 첨부터 끝까지 돌릴 때
		for(Item item:flightInfo.getResponse().getBody().getItems().getItem()) {
			System.out.println("항공사 : " +item.getAirlineNm());
			System.out.println("출발지 : " +item.getArrAirportNm());
			System.out.println("도착지 : " +item.getDepAirportNm());
			System.out.println("출발일시 : "+item.getArrPlandTime());
			System.out.println("이코노미 금액 : "+item.getEconomyCharge());
			System.out.println("특등석 금액 : "+item.getPrestigeCharge());
			System.out.println();
			
		}

	}
}

 

최종적으로는 매서드로 변수를 받아 변수값에 따라 쿼리값의 변화를 줄 것이기 때문에, 먼저 쿼리값에 따라 불러오는 Json 값이 변화할 수 있는 매서드, getFlightInfo를 만든다.

URL 매서드를 통해 자바에 웹페이지를 불러오고,  HttpURLConnection을 이용해 웹페이지와 자바를 연결한다.

연결된 웹페이지를 BufferReader을 통해 불러온다.

while문을 통해 더이상 웹페이지에 불러올 데이터가 없을 때 까지의 반복문을 사용해 웹페이지 전체 데이터를 불러오고, BufferReader과 웹페이지와의 연결을 끊는다.

 

불러온 Json 데이터를 Gson을 이용해 AirLineList 내의 클래스 내의 원형 클래스 속에 넣는다. 이 때, 통신을 통해 들어오는 데이터는 반드시 String이기 때문에, 받아오는 데이터를 toString을 통해 문자열로 만든다.

 

메인 매서드에서는 변수를 넣고 데이터타입과 함수를 불러온다. 

이 때 item이 배열문이기 때문에, forEach문을 통해 배열의 반복문을 사용한다.

 

이 코드는 실용성에 문제가 있다.

사용자는 공항의 포트 번호와 비행기의 일련번호를 모르고, 검색기능이 없다. 

따라서, 먼저 포트번호와 비행기 번호가 입력된 데이터 파일을 만든다

 

-데이터 파일

package airplane;

import java.util.HashMap;

public class FlightInfoService {
	public static HashMap<String, String> airLineId=
			new HashMap<>();
	public static HashMap<String, String> airPortId=
			new HashMap<>();
	public static void setAirLineId() {
		airLineId.put("아시아나항공", "AAR");
		airLineId.put("에어부산", "ABL");
		airLineId.put("이스타항공", "ESR");
		airLineId.put("제주항공", "JJA");
		airLineId.put("진 에어", "JNA");
		airLineId.put("대한항공", "KAL");
		airLineId.put("티웨이항공", "TWB");
		// 추가 필요
	}
	
	public static void setAirPortId() {
		airPortId.put("무안", "NAARKJB");
		airPortId.put("광주", "NAARKJJ");
		airPortId.put("군산", "NAARKJK");
		airPortId.put("여수", "NAARKJY");
		airPortId.put("원주", "NAARKNW");
		airPortId.put("양양", "NAARKNY");
		airPortId.put("제주", "NAARKPC");
		airPortId.put("김해", "NAARKPK");
		airPortId.put("사천", "NAARKPS");
		airPortId.put("울산", "NAARKPU");
		airPortId.put("인천", "NAARKSI");
		airPortId.put("김포", "NAARKSS");
		airPortId.put("포항", "NAARKTH");
		airPortId.put("대구", "NAARKTN");
		airPortId.put("청주", "NAARKTN");
	}
}

HashMap는 key:value 한 쌍으로 엔트리에 저장한다. 따라서 데이터를 저장하는데 유용하다. 이 때, key는 중복할 수 없으니 유의하기.

 

또한 페이지가 1페이지를 넘어가면 그 값이 다 출력되지 않으므로, 값을 전체적으로 출력하는 작업도 필요하다.

이제 이것을 다시 System.in까지 받는 코드로 다시 만들어보자.

package airplane;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Scanner;

import com.google.gson.Gson;

public class FlightApp {
	
	public static int getTotalCount(String depAirportId, String arrAirportId, Long depPlandTime) {
		try {
			URL url=new URL("http://openapi.tago.go.kr/openapi/service/DmstcFlightNvgInfoService/getFlightOpratInfoList?serviceKey=uaLnSRJvnuUZqahDeBOz%2FK8rf4DSXtNmqWkueOzLButZOzzIfz4mHqWuLXwbVzwPSZ2BE736J6cX1uttigP9RA%3D%3D&numOfRows=50&pageNo=1&depAirportId="+FlightInfoService.airPortId.get(depAirportId)+"&arrAirportId="+FlightInfoService.airPortId.get(arrAirportId)+"&depPlandTime="+depPlandTime+"&airlineId=AAR&_type=json");
			HttpURLConnection con =(HttpURLConnection)url.openConnection();
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(),"UTF-8"));
			StringBuilder sb=new StringBuilder();
			String input="";
			while((input=br.readLine())!=null) {
				sb.append(input);	
				System.out.println(input);
			}
			br.close();
			con.disconnect();
			
			Gson gson=new Gson();
			AirLineList flightInfo=gson.fromJson(sb.toString(), AirLineList.class);
			
			return flightInfo.getResponse().getBody().getTotalCount();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;
		
	}
	
	public static AirLineList getFlightInfo(String depAirportId, String arrAirportId, Long depPlandTime, int page){
		try {
			URL url=new URL("http://openapi.tago.go.kr/openapi/service/DmstcFlightNvgInfoService/getFlightOpratInfoList?serviceKey=uaLnSRJvnuUZqahDeBOz%2FK8rf4DSXtNmqWkueOzLButZOzzIfz4mHqWuLXwbVzwPSZ2BE736J6cX1uttigP9RA%3D%3D&numOfRows=50&pageNo="+page+"&depAirportId="+FlightInfoService.airPortId.get(depAirportId)+"&arrAirportId="+FlightInfoService.airPortId.get(arrAirportId)+"&depPlandTime="+depPlandTime+"&airlineId=AAR&_type=json");
			HttpURLConnection con =(HttpURLConnection)url.openConnection();
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(),"UTF-8"));
			StringBuilder sb=new StringBuilder();
			String input="";
			while((input=br.readLine())!=null) {
				sb.append(input);	
				System.out.println(input);
			}
			br.close();
			con.disconnect();
			
			Gson gson=new Gson();
			AirLineList flightInfo=gson.fromJson(sb.toString(), AirLineList.class);
			
			return flightInfo;
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static void main(String[] args) {
		FlightInfoService.setAirLineId();
		FlightInfoService.setAirPortId();
		
		for(String key : FlightInfoService.airPortId.keySet()) {
			System.out.print(key+" ");
		}
		System.out.println();
		System.out.println("출발지를 입력하세요.");
		
		Scanner sc=new Scanner(System.in);
		String depAirportId=sc.next();
		
		System.out.println("도착지를 입력하세요.");
		String arrAirportId=sc.next();
		
		System.out.println("출발일을 입력하세요.");
		Long depPlandTime=sc.nextLong();
		
		int page=1;
		
		int totalCount=getTotalCount(depAirportId, arrAirportId, depPlandTime);
		int count=0;
		if(totalCount%50==0) {
			count=totalCount/50;
		}else {
			count=totalCount/50+1;
		}
		
		ArrayList<AirLineList>flightInfos=new ArrayList<>();
		for (int i = 0; i < count; i++) {
			AirLineList flightInfo=getFlightInfo(depAirportId, arrAirportId, depPlandTime,page++);
			flightInfos.add(flightInfo);
		}
		
		for (AirLineList flightInfo : flightInfos) { // 3번 돌기
			
			//List<Item> myItem = flightInfo.getResponse().getBody().getItems().getItem();		
			
			//iterable(반복) 
			// forEach 문 : 첨부터 끝까지 돌릴 때
			for(Item item:flightInfo.getResponse().getBody().getItems().getItem()) {
				System.out.println("항공사 : " +item.getAirlineNm());
				System.out.println("출발지 : " +item.getArrAirportNm());
				System.out.println("도착지 : " +item.getDepAirportNm());
				System.out.println("출발일시 : "+item.getArrPlandTime());
				System.out.println("이코노미 금액 : "+item.getEconomyCharge());
				System.out.println("특등석 금액 : "+item.getPrestigeCharge());
				System.out.println();
			
		}
		
		sc.close();
			
		}

	}
}

getTotalCount 매서드를 통해 전체 페이지 역시 변수로 받는다. 

정보값이 있는 배열이 2개이므로, foreach 문을 두 번 돌려 값을 받는다. 첫 번재 foreach문은 페이지마다 회전하는 반복문, 두 번째 foreach문은 페이지 내의 데이터를 배열마다 돌리는 매서드이다.

반응형

'JAVA' 카테고리의 다른 글

16. 익명 클래스  (0) 2020.04.13
JAVA 실습 10. 공공데이터를 이용하여 코로나 공공마스크 지원 약국 주소찾기.  (0) 2020.04.10
웹과 OSI 7계층  (0) 2020.04.07
14. Json  (0) 2020.04.06
13. 입출력  (0) 2020.04.06