2021. 12. 7. 18:36ㆍ항해99/실전프로젝트
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. 요청 메시지 명세
- 공공데이타포털에서는 공공api를 사용하기 쉽도록 활용가이드 문서를 제공하고 있다.
- URL : http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst
- 요청 메시지 명세
- serviceKey
- pageNo
- numOfRows
- dataType=XML
- base_date
- base_time
- nx
- ny
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의 element 데이터를 string으로 바꾸는 함수이다.
- 위 함수는
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
'항해99 > 실전프로젝트' 카테고리의 다른 글
항해99 - 실전 프로젝트 06(API 제작 - JPA) (0) | 2021.12.15 |
---|---|
항해99 - 실전 프로젝트 05(스케쥴링 프로그래밍) (0) | 2021.12.13 |
항해99 - 실전 프로젝트 04(외부 API, DB에 저장하기) (0) | 2021.12.07 |
항해99-실전프로젝트 02(좋아요, 북마크) (0) | 2021.12.06 |
항해99-실전프로젝트 01 (설계) (0) | 2021.12.06 |