티스토리 뷰

기상청 동네예보



.. 라던 시절도 있었죠.요즘은 기상위성들의 정밀도도 올라가고, 데이터의 축적, 기상슈퍼컴퓨터의 성능향상 등으로 일기예보의 적중률이 많이 올랐다고는 하는데요.문제는...맞을 비는 다맞고 다닌다는거...!여름의 현실은 냉혹.jpg / 손예진씨 미안요.그래서 요즘 기상청의 동네예보가 주목받고 있는데요.TV에서 오늘은 경남 일부지역에 때로 비가 오겠습니다.

...라고 하면 참 답답하죠.언덕 하나 너머 동네마다 날씨가 다른데!검색하고 있는 위치에서의 예보를 실시간으로 시간대별로 알려줍니다.

그외의 관심지역도 간단히 알아볼 수 있는데요.강수형태나 풍향까지 다양한 형태로 알려주고 있으니소나기가 내리곤하는 이런 여름철에는 꼭 체크해야 할 서비스인것 같아요!우리동네 날씨만 아니라 피서갈때도 꼭 챙겨보세요! 지역별로 읍, 면, 동 단위의 날씨를 알려줘 '우리 동네의 날씨'를 알 수 있어, 모든 시민들에게 아주 유용한 정보를 제공할 수 있을 것으로 전망되었습니다.

특히 3시간 간격으로 알 수 있어 날씨에 여파를 많이 받는, 어민 들이나 선박 해양 종사자들, 레포츠 이용자들에게도 큰 호응을 받았었다고 하네요.그런데. 이것이.. 딱딱 정확하면 참 좋으련만, 잘 맞지는 않는 다고 해요.특히 좁은 단위의 예보가 장점인 동네예보가, 게릴라성 호우, 장마 등 강수가 집중되는 여름에는 정확도가 심히 떨어져 시민들이 원성을 사고 있다고 합니다.

이렇게 기상청의 부 정확한 예측성 때문에 기상청의 신뢰도가 떨어지고 있는 요즘. 기상청의 한 관계자는 "동네예보가 실시된 후 전반적인 강수 예보의 정확성은 높아지는 추세다"며 "우리나라가 날씨 변화가 심하다는 특성을 고려한다면 선진국과 비교해도 예보의 정확도는 상당한 수준을 유지하고 있다"고 보고 했다는 데요. 날씨 변화가 심한 것은 맞지만, 정확한 정보 전달을 위해 노력해야 하는 것도 필요할 듯 하네요.특히 한 전문가는 종합적인 정보를 통해 정확성을 높일 수 있다고 했는 데요. "기상예보는 수치 예보 모델에 따라 계산해서 나오는 예측 값이므로 현실과 맞아떨어지기 어렵고 오차가 발생할 수밖에 없다"며 "이런 특성을 고려하지 않은 채 동네예보 등으로 상세히 들어가면 오히려 정확도는 낮아지고 기상예보에 대한 만족도를 떨어뜨릴 수 있다"고 언급했다고 합니다.

즉, 자세하면 자세할 수록 예측되기 힘들다는 말이네요. 자세한 지역별 정보가 유용하긴 하지만, 신뢰도는 떨어지고, 대략적이고 종합적인 정보일 수록 신뢰도가 오를 수 있는 것 같아요.. 이럴 것이면, 더 정확하게 날씨를 알려주는 것도 좋을 것 같다는 생각이..아무튼, 맞아도 너

무 안맞아 핫 이슈로 떠오른 기상청 동네예보. 열심히 일하고 계신 기상청 직원들이 들으면 속상할 이야기 지만, 정확한 정보를 통해 여러 사람에게 사랑받는 기상청이 어서 빨리 되었으면 하는 바람이네요

)?제가 여러곳에서 기상청 데이터 파싱방법을 찾아본 결과 여러방법들이 존재하고 있었습니다.

대표적으로?1. 기상청에서 제공하는 동네코드를 알아낼 수 있는 url을 활용http://javaking75.blog.me/220091928699 [Java] ??? ???? ? ??? ?? ??? ????[??]???? (pluulove84) ??? - ??? ???? ??(?)?? : http://blog.naver.com/pluulove84/...blog.naver.com-> 단점 : 일부 지역은 포함하고있지 않아 모든 지역의 동네코드를 얻어올 수 없었습니다.

2. 기상청 RSS 활용http://www.kma.go.kr/weather/lifenindustry/sevice_rss.jspRSS > ??? > ??? > ??? ?? > ?? > ???www.kma.go.kr- 단점 : 동네 기상정보를 한 번에 한지역만 조회가가능 합니다.

3. 위도와 경도를 이용하여 GridX, GridY좌표 구해서 동네 예보가져오기 (가장  좋은 방법 같습니다.

)http://javaking75.blog.me/220089575454[JavaScript] ??? ???? ?? - ??? ( Grid XY - Lat, Lon ) : ?? ...???? http://www.kma.go.kr/weather/forecast/timeseries.jsp ???? ???? XML ??? ???...blog.naver.com* 이러한 방법들을 짬뽕하여 "지역 이름"을 하면 1. 구글 Geolocation 서비스를 이용하여 위도 경도 획득하고2. 위도, 경도를 기상청에서 만들어놓은 GridX, GridY를 구하는 공식을 이용하여 GridX,Y좌표를 구하여 동네주간예보를 가져오겠습니다.

시작!-1단계구글 Geolocation 서비스를 이용하여 "지역명"으로 위도(Longtitude),경도(Latitude) 가져오기*요청 URLhttp://maps.google.com/maps/api/geocode/json?address=지역이름ex) http://maps.google.com/maps/api/geocode/json?address=대전 서구 관저동아래처럼 크롬브라우저에다가 해당 url을 하게 되면이와 같이 JSON형태의 위치에 해당하는 정보들을 가져오게 됩니다.

[기상청 동네예보] 대체 무슨일이 있었던 걸까


여기서 필요한 정보는 location 의 "lat" , "lng" 의 정보입니다.

 * Json데이터를 손쉽게 추출하기위해서 아래 라이브러리를 사용하였습니다.

메이븐이나, 다운로드를 통해서 빌드시켜주세요http://www.mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1.1Maven Repository: com.googlecode.json-simple � json-simple � 1.1.1www.mvnrepository.com- lat, lng 좌표 가져오기1234567891011121314151617181920212223242526272829303132333435        String json;        StringBuilder sb = new StringBuilder();        double v1 = 0.0;        double v2 = 0.0;        try {            String location = "대전 서구 관저동";            String addr = "http://maps.google.com/maps/api/geocode/json?address=";            URL url = new URL(addr + URLEncoder.encode(location, "UTF-8"));            HttpURLConnection con = (HttpURLConnection) url.openConnection();            con.setConnectTimeout(10000);            con.setUseCaches(false);            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));             while (true) {                String line = br.readLine();                if (line == null)                    break;                sb.append(line);            }            br.close();            con.disconnect();        } catch (Exception e) {            System.out.println(e.getMessage());        }        json = sb.toString();        JSONObject object = (JSONObject) JSONValue.parse(json);        JSONArray array = (JSONArray) object.get("results");        for (Object o : array) {            JSONObject object2 = (JSONObject) o;            String lat = ((JSONObject) (((JSONObject) object2.get("geometry")).get("location"))).get("lat").toString();            String lng = ((JSONObject) (((JSONObject) object2.get("geometry")).get("location"))).get("lng").toString();             v1 = Double.parseDouble(lat);            v2 = Double.parseDouble(lng);        }Colored by Color Scriptercsv1, v2에 각각 위도와 경도를 저장하였습니다.

?2. 위도, 경도를 가지고 Gridx, Gridy 좌표 구하기위도 경도를 Gridx, Gridy좌표로 변경시켜주는 getGridxy함수의 매개변수에 이전에 얻어온 위도,경도(v1,v2)값을 넣으면됩니다.

 12345678910111213141516171819202122232425262728293031323334353637383940414243    double RE = 6371.00877; // 지구 반경(km)    double GRID = 5.0; // 격자 간격(km)    double SLAT1 = 30.0; // 투영 위도1(degree)    double SLAT2 = 60.0; // 투영 위도2(degree)    double OLON = 126.0; // 기준점 경도(degree)    double OLAT = 38.0; // 기준점 위도(degree)    double XO = 43; // 기준점 X좌표(GRID)    double YO = 136; // 기1준점 Y좌표(GRID)     public Map<String, Object> getGridxy(double v1, double v2) {         double DEGRAD = Math.PI / 180.0;        // double RADDEG = 180.0 / Math.PI;         double re = RE / GRID;        double slat1 = SLAT1 * DEGRAD;        double slat2 = SLAT2 * DEGRAD;        double olon = OLON * DEGRAD;        double olat = OLAT * DEGRAD;         double sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);        sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);        double sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);        sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;        double ro = Math.tan(Math.PI * 0.25 + olat * 0.5);        ro = re * sf / Math.pow(ro, sn);        Map<String, Object> map = new HashMap<String, Object>();        map.put("lat", v1);        map.put("lng", v1);        double ra = Math.tan(Math.PI * 0.25 + (v1) * DEGRAD * 0.5);        ra = re * sf / Math.pow(ra, sn);        double theta = v2 * DEGRAD - olon;        if (theta > Math.PI)            theta -= 2.0 * Math.PI;        if (theta < -Math.PI)            theta += 2.0 * Math.PI;        theta *= sn;         map.put("x", Math.floor(ra * Math.sin(theta) + XO + 0.5));        map.put("y", Math.floor(ro - ra * Math.cos(theta) + YO + 0.5));         return map;    }Colored by Color Scriptercs?* Map형태로 "x", "y"키 값에 각각 Gridx, Gridy값을 저장하였습니다.

 3. 위에서 얻은 Gridx,Gridy 값으로 동네 xml데이터 얻기* 요청 urlhttp://www.kma.go.kr/wid/queryDFS.jsp?gridx=x좌표&gridy=y좌표ex) http://www.kma.go.kr/wid/queryDFS.jsp?gridx=66gridy=99 (대전 서구 관저동 날씨)아래와 같은 xml데이터를 리턴합니다.

- 동네 예보 xml 태그 설명서http://www.kma.go.kr/images/weather/lifenindustry/timeseries_XML.pdf123456789101112131415161718192021222324String xml = "";        try {            // 전국 날씨정보            String addr = "http://www.kma.go.kr/wid/queryDFS.jsp?gridx=" + map.get("x") + "&gridy=" + map.get("y");            URL url = new URL(addr);            HttpURLConnection http = (HttpURLConnection) url.openConnection();            http.setConnectTimeout(10000);            http.setUseCaches(false);             BufferedReader br = new BufferedReader(new InputStreamReader(http.getInputStream()));            sb = new StringBuilder();            while (true) {                String line = br.readLine();                if (line == null)                    break;                sb.append(line);            }            xml = sb.toString();            br.close();            http.disconnect();         } catch (Exception e) {            System.out.println("다운로드에러" + e.getMessage());        }Colored by Color Scriptercs4. XML기상 정보 파싱1234567891011121314151617181920212223242526272829303132333435363738        Map<String, Object> data = new HashMap<String, Object>();        try {            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();            DocumentBuilder documentbuilder = factory.newDocumentBuilder();            InputStream is = new ByteArrayInputStream(xml.getBytes());            Document doc = documentbuilder.parse(is);            Element element = doc.getDocumentElement();             NodeList list1 = element.getElementsByTagName("data");             for (int i = 0; i < list1.getLength(); i++) {                for (Node node = list1.item(i).getFirstChild(); node != null; node = node.getNextSibling()) {                     if (node.getNodeName().equals("hour")) {                        System.out.println("----------------------------");                        data = new HashMap<String, Object>();                        data.put("hour", node.getTextContent().toString());                    }                     if (node.getNodeName().equals("temp")) {                        data.put("temp", node.getTextContent().toString());                    }                     if (node.getNodeName().equals("reh")) {                        data.put("reh", node.getTextContent().toString());                    }                     if (node.getNodeName().equals("wfEn")) {                        data.put("wfEn", node.getTextContent().toString());                        list.add(data);                    }                }            }         } catch (Exception e) {            System.out.println("파싱에러" + e.getMessage());        }        System.out.println(data);Colored by Color Scriptercs*결과?전체코드 (*JSON라이브러리만 빌드 Pass해주시면 바로 실행가능합니다.

[기상청 동네예보] 세상에나..



)* 클래스파일과 라이브러리파일 첨부해두었습니다.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLEncoder;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map; import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory; import org.json.simple.JSONArray;import org.json.simple.JSONObject;import org.json.simple.JSONValue;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList; public class WeatherMain {     public static void main(String[] args) {        List<Map<String,Object>> list = getXml("대전 서구 관저동");        for(Map<String,Object> map : list){            System.out.println(map);        }    }            public static List<Map<String, Object>> getXml(String locate) {         List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();                String location=locate;        String json="";        StringBuilder sb = new StringBuilder();        double v1 = 0.0;        double v2 = 0.0;        try {                        String addr = "http://maps.google.com/maps/api/geocode/json?address=";            URL url = new URL(addr + URLEncoder.encode(location, "UTF-8"));            HttpURLConnection con = (HttpURLConnection) url.openConnection();            con.setConnectTimeout(10000);            con.setUseCaches(false);            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));             while (true) {                String line = br.readLine();                if (line == null)                    break;                sb.append(line);            }            br.close();            con.disconnect();        } catch (Exception e) {            System.out.println(e.getMessage());        }        json = sb.toString();        JSONObject object = (JSONObject) JSONValue.parse(json);        JSONArray array = (JSONArray) object.get("results");        for (Object o : array) {            JSONObject object2 = (JSONObject) o;            String lat = ((JSONObject) (((JSONObject) object2.get("geometry")).get("location"))).get("lat").toString();            String lng = ((JSONObject) (((JSONObject) object2.get("geometry")).get("location"))).get("lng").toString();             v1 = Double.parseDouble(lat);            v2 = Double.parseDouble(lng);        }                //위에서 얻은 위도 경도를 가지고 GridX,GridY좌표를 구합니다.

        Map<String, Object> map = getGridxy(v1, v2);                String xml = "";        //GridX, GridY좌표를 가지고 XML데이터를 가져옵니다.

        try {            // 전국 날씨정보            String addr = "http://www.kma.go.kr/wid/queryDFS.jsp?gridx=" + map.get("x") + "&gridy=" + map.get("y");            URL url = new URL(addr);            HttpURLConnection http = (HttpURLConnection) url.openConnection();            http.setConnectTimeout(10000);            http.setUseCaches(false);             BufferedReader br = new BufferedReader(new InputStreamReader(http.getInputStream()));            sb = new StringBuilder();            while (true) {                String line = br.readLine();                if (line == null)                    break;                sb.append(line);            }            xml = sb.toString();            br.close();            http.disconnect();         } catch (Exception e) {            System.out.println("다운로드에러" + e.getMessage());         }         Map<String, Object> data = new HashMap<String, Object>();        //위에서 추출한 XML데이터를 파싱해봅시다.

        try {            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();            DocumentBuilder documentbuilder = factory.newDocumentBuilder();            InputStream is = new ByteArrayInputStream(xml.getBytes());            Document doc = documentbuilder.parse(is);            Element element = doc.getDocumentElement();             NodeList list1 = element.getElementsByTagName("data");             for (int i = 0; i < list1.getLength(); i++) {                for (Node node = list1.item(i).getFirstChild(); node != null; node = node.getNextSibling()) {                     if (node.getNodeName().equals("hour")) { //시간                        data = new HashMap<String, Object>();                        data.put("hour", node.getTextContent().toString());                    }                     if (node.getNodeName().equals("temp")) { //온도                        data.put("temp", node.getTextContent().toString());                    }                     if (node.getNodeName().equals("reh")) { //습도                        data.put("reh", node.getTextContent().toString());                    }                     if (node.getNodeName().equals("wfEn")) { //날씨 정보                        data.put("wfEn", node.getTextContent().toString());                        list.add(data);                    }                }            }         } catch (Exception e) {            System.out.println("파싱에러" + e.getMessage());        }         return list;    }       public static Map<String, Object> getGridxy(double v1, double v2) {        double RE = 6371.00877; // 지구 반경(km)        double GRID = 5.0; // 격자 간격(km)        double SLAT1 = 30.0; // 투영 위도1(degree)        double SLAT2 = 60.0; // 투영 위도2(degree)        double OLON = 126.0; // 기준점 경도(degree)        double OLAT = 38.0; // 기준점 위도(degree)        double XO = 43; // 기준점 X좌표(GRID)        double YO = 136; // 기1준점 Y좌표(GRID)        double DEGRAD = Math.PI / 180.0;        // double RADDEG = 180.0 / Math.PI;         double re = RE / GRID;        double slat1 = SLAT1 * DEGRAD;        double slat2 = SLAT2 * DEGRAD;        double olon = OLON * DEGRAD;        double olat = OLAT * DEGRAD;         double sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);        sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);        double sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);        sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;        double ro = Math.tan(Math.PI * 0.25 + olat * 0.5);        ro = re * sf / Math.pow(ro, sn);        Map<String, Object> map = new HashMap<String, Object>();               double ra = Math.tan(Math.PI * 0.25 + (v1) * DEGRAD * 0.5);        ra = re * sf / Math.pow(ra, sn);        double theta = v2 * DEGRAD - olon;        if (theta > Math.PI)            theta -= 2.0 * Math.PI;        if (theta < -Math.PI)            theta += 2.0 * Math.PI;        theta *= sn        map.put("lat", v1);       map.put("lng", v2);        map.put("x", (int)Math.floor(ra * Math.sin(theta) + XO + 0.5));        map.put("y", (int)Math.floor(ro - ra * Math.cos(theta) + YO + 0.5));         return map;    } } Colored by Color Scriptercs?최종 결과??좌표값으로 동네 주소 값얻기http://maps.google.com/maps/api/geocode/json?latlng=37,126maps.google.com 지역별로 읍, 면, 동 단위의 날씨를 알려줘 '우리 동네의 날씨'를 알 수 있어, 모든 시민들에게 아주 유용한 정보를 제공할 수 있을 것으로 전망되었습니다.

특히 3시간 간격으로 알 수 있어 날씨에 여파를 많이 받는, 어민 들이나 선박 해양 종사자들, 레포츠 이용자들에게도 큰 호응을 받았었다고 하네요.그런데. 이것이.. 딱딱 정확하면 참 좋으련만, 잘 맞지는 않는 다고 해요.특히 좁은 단위의 예보가 장점인 동네예보가, 게릴라성 호우, 장마 등 강수가 집중되는 여름에는 정확도가 심히 떨어져 시민들이 원성을 사고 있다고 합니다.

이렇게 기상청의 부 정확한 예측성 때문에 기상청의 신뢰도가 떨어지고 있는 요즘. 기상청의 한 관계자는 "동네예보가 실시된 후 전반적인 강수 예보의 정확성은 높아지는 추세다"며 "우리나라가 날씨 변화가 심하다는 특성을 고려한다면 선진국과 비교해도 예보의 정확도는 상당한 수준을 유지하고 있다"고 보고 했다는 데요. 날씨 변화가 심한 것은 맞지만, 정확한 정보 전달을 위해 노력해야 하는 것도 필요할 듯 하네요.특히 한 전문가는 종합적인 정보를 통해 정확성을 높일 수 있다고 했는 데요. "기상예보는 수치 예보 모델에 따라 계산해서 나오는 예측 값이므로 현실과 맞아떨어지기 어렵고 오차가 발생할 수밖에 없다"며 "이런 특성을 고려하지 않은 채 동네예보 등으로 상세히 들어가면 오히려 정확도는 낮아지고 기상예보에 대한 만족도를 떨어뜨릴 수 있다"고 언급했다고 합니다.

즉, 자세하면 자세할 수록 예측되기 힘들다는 말이네요. 자세한 지역별 정보가 유용하긴 하지만, 신뢰도는 떨어지고, 대략적이고 종합적인 정보일 수록 신뢰도가 오를 수 있는 것 같아요.. 이럴 것이면, 더 정확하게 날씨를 알려주는 것도 좋을 것 같다는 생각이..아무튼, 맞아도 너

무 안맞아 핫 이슈로 떠오른 기상청 동네예보. 열심히 일하고 계신 기상청 직원들이 들으면 속상할 이야기 지만, 정확한 정보를 통해 여러 사람에게 사랑받는 기상청이 어서 빨리 되었으면 하는 바람이네요

그리고 우리지역 철원은 역시나 눈의 고장답게

내린 눈으로 눈세상이 펼쳐졌어요.쌓인 눈가득한 풍경이 참 아름답니만

눈으로 길이 미끄러우니 운전 시, 보행 시 유의하세요!그리고 기상청에서 제공하는 기상청 동네예보도 필히 확인하도록 해요 그리고 언제 어떻게 변할지 모르는 날씨이다 보니기상예보에 귀를 쫑긋

세우시고 적절히 대처하셔야해요.그리고 날씨정보를 빠르게 확인 할 수 있는 곳이 있는데요.기상청 동네예보에서 여러분이 계신 지역의 날씨상황을 빠르게 알 수 있답니다.

기상청 동네예보는 기상청에서 제공하는 날씨를 안내하고 있어요.현재의 날씨 및 기온, 풍향, 풍속, 습도, 1시간 강수량과앞서 약 2시간 후의 기상예보도 알 수 있어요.문자 및 음성예보도 제공하고 있으니일기예보에 촉각을 세우시어 이동시 꼭 참고하시도록 하세요!http://www.kma.go.kr/weather/forecast/timeseries.jsp△기상청 동네예보철원군청에서 바라본 철원시내 풍경과 철원군청의 옥상이에요.눈으로 가득

한 철원군을 보니 눈이 맑아지는 기분이네요.소복히 쌓여 발자국을 남기는 재미도 있지요.이렇게 아름다운 눈,아름답게 감상만 할수는 없잖아요

?철원 곳곳에 눈이 많이 내려 길이 미끄러워요.그러니 보행 시 운전 시 꼭 안전에 유의하셔야 햅니다.

겨울철에는 차량에 스노우타이어를 장착하셔야하고보행 시에는 주머니에 손을 넣고 걸으시는걸 자제하셔야해요!감기 걸리지 않도록 따듯하게 옷을 입는것도 잊지마시고요.그럼 건강한 하루 되세요

go.kr/weather/forecast/timeseries.jsp??http://www.kma.go.kr/weather/forecast/timeseries.jsp??? > ???? > ???? > ??�?? > ?? > ???www.kma.go.kr
공유하기 링크
TAG
, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
댓글
댓글쓰기 폼