항해99-실전프로젝트 03(공공데이타포털 api 사용하기)

2021. 12. 7. 18:36항해99/실전프로젝트

728x90

 

E-R 다이어그램

  • e-r 다이어그램이 나타내고 있는 날씨, 천문 데이터 엔티티 정보들은 모두 외부 api를 통해서 데이터를 가져와야 한다.
  • 그렇기 때문에 백엔드에서 외부 api를 사용하여 데이터를 가져와보자

 

백엔드 서버에서 외부 api를 사용하여 데이터를 가져오는 이유

더보기

일단 프론트 서버의 주 업무는 클라이언트에게 화면을 보여주고 랜더링 하는 것이다.

또한 데이터를 관리, 보관 하는 것은 백엔드 업무이기에

백엔드에서 외부 api를 가져오고 도메인 설계에 맞게 가공하여 db에 저장하기로 했다.

 

공공데이타포털

  • 날씨 데이터 혹은 천문 데이터는 공공데이터 포털에서 제공하는 api를 사용하였다.
  • https://www.data.go.kr
 

공공데이터 포털

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

www.data.go.kr

 

1) 기상청 오픈 API 활용신청

데이터 찾기 -> "기상청 단기" 검색

 

  • 일단 해당 api에 활용신청을 해야한다.
  • 간단한 신청서를 작성하고 나면 마이페이지에서 해당 api를 볼 수 있다.

2) 기상청 api key 확인

  • api에 일반 인증키를 받은 것을 알 수 있다.
  • 이제 이 api를 사용하기 위해서 어떤 query문을 날려야 하는지 알아야 한다.

※rest api인 경우 url, method 방식, 필수 parameter를 알아야 사용가능하다.

 

3) 요청, 응답 메시지 명세

3-1. 요청 메시지 명세

3-2) 각 지역의 좌표값

  • 위의 요청 메시지의 명세 중 nx, ny는 예보지역의 위경도 좌표다
  • 해당하는 지역의 예보를 받기 위해서는 지역 정보를 위경도 좌표를 바꿔주는 작업이 필요하다.
  • 해당 작업은 후 소스코드 보기에서 작성하겠다.

3-2. 응답 메시지 명세

  • 위의 request param 들을 call back url에 붙여서 넣어주고 응답 메시지를 본다면
  • url :
    • http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst
    • ?serviceKey={개인 서비스키}
    • &pageNo=1&numOfRows=1000&dataType=XML&base_date=20211207&base_time=0800&nx=55&ny=127
  • response data

  • 위의 데이터를 얻을 수 있다.
  • 각 <item></item> 속성안에는 <category>에 해당하는 정보들이 들어가 있다.

  • <category> 데이터의 의미

  • 즉 강수확률을 얻기위해서는 <category> 안에 있는 POP라는 <item> 을 찾아서
  • xml파일을 자바 객체로 만든 후에 이를 DB에 저장해야한다.

4) 전체적인 구조

  • 전체적으로는 가이드 문서에 맞게 url을 맞추어 api를 요청하게된다.
  • 받아온 데이터는 자바 DTO 객체에 맞추어 형변환 혹은 데이터 슬라이스한다.
  • 이렇게 자바 DTO로 형변환하여 위의 데이터를 이용하여 프로그래밍 할 수 있다.

5) 소스코드

5-1) 지역 좌표 enum 작업

  • 위의 nx, ny는 해당하는 도시의 위치좌표를 넣어줘야한다.
  • 도시의 위치좌표는 공공데이터포탈에서 가이드 문서에 들어 있으며
  • 이를 자바 프로젝트에 사용하기 위해서 enum으로 잘랐다.
@Getter
@AllArgsConstructor
public enum WeatherCity {
    서울("서울",60,127),
    부산("부산",97,74),
    대구("대구",89,90),
    인천("인천",54,124),
    광주("광주",57,74),
    대전("대전",67,101),
    울산("울산",101,84),
    세종("세종",66,103),
    수원("수원",60,121),
    성남("성남",63,124),
    의정부("의정부",61, 130),
    안양("안양",59,123),
    부천("부천",56,125),
    광명("광명",58,125),
	......
}

5-2) api를 사용하여 데이터 가져오기

  • 다행히 데이터 공공 포털에서는 데이터를 가져 올 수 있는 자바 코드를 전부 준비되어있다.
  • 위 코드를 조금수정한다.
@Component
@Slf4j
public class WeatherApi {
    private final String apiKey = "my service key";


    public List<WeatherApiDto2> getWeather(WeatherCity weatherCity) throws IOException, ParserConfigurationException, SAXException {

        List<String> date = getCurrentTime();

        StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst"); /*URL*/
        urlBuilder.append("?" + URLEncoder.encode("serviceKey","UTF-8") + "="+apiKey); /*Service Key*/
        urlBuilder.append("&" + URLEncoder.encode("pageNo","UTF-8") + "=" + URLEncoder.encode("1", "UTF-8")); /*페이지번호*/
        urlBuilder.append("&" + URLEncoder.encode("numOfRows","UTF-8") + "=" + URLEncoder.encode("300", "UTF-8")); /*한 페이지 결과 수*/
        urlBuilder.append("&" + URLEncoder.encode("dataType","UTF-8") + "=" + URLEncoder.encode("XML", "UTF-8")); /*요청자료형식(XML/JSON) Default: XML*/
        urlBuilder.append("&" + URLEncoder.encode("base_date","UTF-8") + "=" + URLEncoder.encode(date.get(0), "UTF-8")); /*‘21년 6월 28일발표*/
        urlBuilder.append("&" + URLEncoder.encode("base_time","UTF-8") + "=" + URLEncoder.encode("0800", "UTF-8")); /*05시 발표*/  //3시간 단위
        urlBuilder.append("&" + URLEncoder.encode("nx","UTF-8") + "=" + URLEncoder.encode(weatherCity.getX().toString(), "UTF-8")); /*예보지점의 X 좌표값*/
        urlBuilder.append("&" + URLEncoder.encode("ny","UTF-8") + "=" + URLEncoder.encode(weatherCity.getY().toString(), "UTF-8")); /*예보지점의 Y 좌표값*/
        log.info("urlBuilder.toString() = " + urlBuilder.toString());

        DocumentBuilderFactory dbFactoty = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactoty.newDocumentBuilder();
        Document doc = dBuilder.parse(urlBuilder.toString());
    }
}
  • WeatherApi 클래스를 만들고 데이터 가져올 method인 getWeather를 만들었다.
  • 위 클래스는 후에 AutoWried를 위해서 @Component를 통해서 spring bean으로 등록해 두었다.
  • nx, ny 부분은 파라미터로 받은 weatherCity enum class 를 통하여 선택된 도시의 좌표값을 가져온다.

5-3) response data 가져오기

  • 위의 api의 response data 타입은 xml 타입이기에 이를 자르는 함수가 필요하다
    private static String getTagValue(String tag, Element eElement) {
        NodeList nlList = eElement.getElementsByTagName(tag).item(0).getChildNodes();
        Node nValue = (Node) nlList.item(0);
        if(nValue == null)
            return null;
        return nValue.getNodeValue();
    }

xml data를 dto 객체로 변경하기

@Getter
@Setter
@AllArgsConstructor
@ToString
public class WeatherApiDto {
    private String baseDate;
    private String baseTime;
    private String category;
    private String fcstDate;
    private String fcstTime;
    private String fcstValue;
}
  • 이렇게 잘라온 data는 일단 weatherApiDto 클래스를 만들어 저장한다.
 if (getTagValue("category",eElement).equals(POP.getName())){
                    WeatherApiDto weatherApiDto = new WeatherApiDto(
                            getTagValue("baseDate", eElement),
                            getTagValue("baseTime", eElement),
                            POP.getKorName(),
                            getTagValue("fcstDate", eElement),
                            getTagValue("fcstTime", eElement),
                            getTagValue("fcstValue", eElement)
                    );
                    weatherApiDtoList.add(weatherApiDto);
                }
  • 위 코드를 통해서 강수확률 데이터를 찾아서 weatherAPiDto 객체 형식으로 저장한다.

5-4) 확인하기

public static void main(String[] args) throws IOException, ParserConfigurationException, SAXException {
        WeatherApi weatherApi = new WeatherApi();
        for (WeatherCity value : WeatherCity.values()) {
            List<WeatherApiDto2> weather = weatherApi.getWeather(value);
            for (WeatherApiDto2 weatherApiDto2 : weather) {
                log.info("weatherApiDto2 = {}", weatherApiDto2);
            }
        }

    }
  • class 내 main method를 통해서 가져온 data의 log를 찍어볼 수 있다.

6)마무리

위처럼 하나의 외부 api를 가져온 일련의 과정을 포스팅하였다.

가장 중요한 점은 아무래도 api 문서에 맡게 요청 메시지를 잘 작성하고

응답 메시지 또한 형식에 맡게 잘 받아서 객체로 바꾸는 작업을 가장 신경 썼었다.

 

다음 포스팅에서는 이런 형식으로 가져온 api들을 하나의

또 다른 class로 묶어서 DB에 저장해 보겠다.

 

깃허브 : https://github.com/salmon2/StarProject

 

GitHub - salmon2/StarProject

Contribute to salmon2/StarProject development by creating an account on GitHub.

github.com

프로젝트 홈페이지 : https://stellakorea.co.kr/

 

별보러가지않을래?

캠핑 차박하실때 불멍만 즐기셨나요? 이제는 별도 구경해보세요! 별이 잘보이는 장소,날씨 정보보시고 나만의 캠핑,차박 장소도 공유 해보세요!

stellakorea.co.kr