소프트웨어

날씨달기에 대한 단상 - 야후맵, 구글맵, 네이버맵의 연동 구현

falconer 2008. 4. 17. 09:31

어렵게 알아낸 정보을 공개해서 소개한 구글 Map 날씨 관련 글입니다.



지도 API 에 날씨 정보를 다는 것은 생각 보다 어렵습니다.

일단 저는 google 에서 제공하는 날씨 정보를 사용하였습니다.

구글에서 제공하는 API 의 주소는 다음과 같습니다.

http://www.google.com/ig/api?hl=ko&weather=seoul

위와 같이 하시면 서울의 날씨 정보를 xml 형태로 받을 수 있습니다.

hl=ko 는 보이는 태그 형태를 한글로 하겠다는 뜻이고
weather=seoul 는 해당 지역명입니다.

여기서 문제되는 것은 한국의 특정지역의 지역명을 구글에서 정의된 이름을 알아야 한다는 문제가 있습니다.

하지만 이문제를 해결하기 위해 구글에서는 몇가지 param 을 더 주고 있더군요
weather=,,,latitude_e6,longitude_e6

을 사용하시면 됩니다.

latitude_e6,longitude_e6 는 위도 와 경도를 각각 1000000 으로 곱한 값을 round 하시면 됩니다.

그럼 이제 알아 내야 하는 것은 국내의 각지역의 위도와 경도 정보가 필요하게 됩니다.

다음 정보는 제가 2일 동안 고생하면서 찾아낸 위도와 경도 정보 입니다.
Array (
    Array("안산",37.500000,126.930000),
    Array("안양",37.270000,126.980003),
    Array("부천",37.500000,126.930000),
    Array("부산",35.099998,129.029998),
    Array("청주",36.630001,127.430000),
    Array("철원",38.150001,127.319999),
    Array("춘천",37.900001,127.730003),
    Array("대구",35.880001,128.619995),
    Array("대전",36.299999,127.400001),
    Array("동두천",37.750000,127.029998),
    Array("김해",35.180000,128.929992),
    Array("고양",37.500000,126.930000),
    Array("구미",36.549999,128.720001),
    Array("군포",37.270000,126.980003),
    Array("군산",35.979999,126.699996),
    Array("광주",35.169998,126.879997),
    Array("광명",37.500000,126.930000),
    Array("경주",36.029998,129.380004),
    Array("흑산도",34.680000,125.449996),
    Array("익산",35.979999,126.699996),
    Array("일산",37.500000,126.930000),
    Array("인천",37.479999,126.629997),
    Array("제주",33.520000,126.529998),
    Array("전주",35.819999,127.150001),
    Array("진주",35.200000,128.100006),
    Array("강릉",37.750000,128.899993),
    Array("목포",34.779998,126.379997),
    Array("파주",37.549999,126.800003),
    Array("포항",36.029998,129.380004),
    Array("평택",37.080001,127.029998),
    Array("서귀포",33.229999,126.569999),
    Array("성남",37.270000,126.980003),
    Array("서울",37.500000,126.930000),
    Array("시흥",37.500000,126.930000),
    Array("송탄",37.080001,127.029998),
    Array("수원",37.270000,126.980003),
    Array("의정부",37.500000,126.930000),
    Array("울릉도",37.479999,130.899993),
    Array("울산",35.549999,129.320007),
    Array("원주",37.330001,127.949996),
    Array("용인",37.270000,126.980003),
);

해당 정보는

http://www.google.com/ig/cities?output=xml&hl=ko&country=kr

에서 찾을 수 있습니다.

하지만 해당 정보 중에서 동해라고 되어 있는 부분이 잘못된것 같더군요.

동해가 아닌 동두천 일대의 지역을 가리키고 있었습니다.

이제 해당 위도 경도 좌표와 날씨 정보을 매칭만 시키면 됩니다.

울릉도의 날씨 정보는 다음과 같습니다.

http://www.google.com/ig/api?hl=ko&weather=,,,37479999,130899993

해당 결과의 xml 에서

current_conditions 현재의 날씨
    - condition : 날씨 상태
    - temp_f : 화씨 온도
    - temp_c : 섭씨 온도
    - humidity : 습도
    - wind_condition  : 풍향
    - icon : 날씨 아이콘 (http://www.google.com/ + icon 을 하시면 해당 날씨 아이콘을 보실수 있습니다.);
forecast_conditions 는 오늘의 날씨를 포함한 4일간의 날씨 예보입니다.
    - day_of_week : 해당 요일
    - condition : 날씨 상태
    - low : 최저기온
    - high : 최고기온
    - icon : 날씨 아이콘 (http://www.google.com/ + icon 을 하시면 해당 날씨 아이콘을 보실수 있습니다.);

위와 같이 표현되고 있습니다.

icon 을 싸이트에 맞게 커스트 마이징을 하실 경우 icon 정보를 코드로 변환을 시켜야 합니다.
제가 찾아본 결과 구글에서는 총 13종의 날씨 아이콘을 가지고 있습니다.
이는 전세계의 날씨를 여러번 돌려 본 결과 총 13종이 발견되었습니다.

$weather_icon = Array(
    '/images/weather/sunny.gif' => 102,
    '/images/weather/mostly_sunny.gif' => 103,
    '/images/weather/haze.gif' => 101,
    '/images/weather/cloudy.gif' => 104,
    '/images/weather/mostly_cloudy.gif' => 105,
    '/images/weather/rain.gif' => 106,
    '/images/weather/fog.gif' => 107,
    '/images/weather/chance_of_rain.gif' => 108,
    '/images/weather/thunderstorm.gif' => 109,
    '/images/weather/storm.gif' => 113,
    '/images/weather/chance_of_storm.gif' => 110,
    '/images/weather/snow.gif' => 112,
    '/images/weather/chance_of_snow.gif' => 111,
);

저는 이런 식으로 코드화 하였습니다.

그리고 시도를 해 보시면 아시겠지만 google 에서 데이타를 받는 속도가 그렇게 좋지가 않습니다.
하여 실시간으로 연동을 하시는 것은 권장을 하지 않습니다.

시스템에서 cron 을 돌리시는 것이 좋을 것으로 생각 됩니다.

저같은 경우 약 1000 개 지역의 날씨를 매 1시간 마다 받아와서 db 에 저장을 하고
클라이언트의 요청이 있을 경우 해당 db 쿼리에서 보여 주는 형태를 취하고 있습니다.

테스트 한 결과로는 1000개 지역의 날씨 정보를 불러 오는데 약 5분정도의 시간이 소요 되었습니다.

이렇해 한 경우 다시 문제는 이많은 지역중에서 어떤 지역의 날씨 정보를 보여 줄것인 가 하는 문제가 남게 됩니다.

즉 맵에서 어떤 날씨를 연동 시킬 것인가 하는 문제 입니다.

좁은 맵에서 이 1000개의 날씨 정보를 다 보여 주는 경우 아무른 의미가 없기 때문입니다.

하여 저는 경도와 위도, 줌레벨을 조합한 쿼리를 생각해 냈습니다.



살짝 쿼리를 보여 드리면 다음과 같습니다.

select area_name,latitude_e6, longitude_e6, round((latitude_e6 - (29840643.8998))/4915200) as latlevel, round((longitude_e6 - (102744140.625))/4915200) as lonlevel,LEAST(abs(latitude_e6 - (29840643.8998)), abs(180000000- latitude_e6 - (29840643.8998))) + LEAST(abs(longitude_e6 - (102744140.625)), abs(360000000-longitude_e6 - (102744140.625))) as dist from rainmap_weather  group by latlevel, lonlevel  order by  dist asc

select * from rainmap_weather  where concat(latitude_e6,':',longitude_e6) in ('29550000:106550000','21033333:105866667','22350000:91833333','16066667:108216667','16783333:96150000','31200000:121433333','11550000:104850000','22533333:88333333','25033333:121516667','5416667:100316667')  order by regdate desc

줌레벨은 0 이 가까울수록 세계지도에 가깝고 19에 가까울수록 상세지도입니다. 하여 줌 보정값은 다음과 같이 생성됩니다.

if ($zoom >= 19)
    $detail_level = 150;
else
    $detail_level = 150*(pow(2,(19-$zoom)));

줌은 한단계가 올라 가면 전단계의 2배로 확장됩니다.

원하시는 밀도(ex : 150)  에서 2^x 하신 것을 곱하게 되면 보정값이 나옵니다.

이 보정 값을 통해서 보여줄 지역을 group by 를 하시면 현재 맵이 보여 주고 있는 지역의 줌레벨에 맞게 날씨 정보를 추출하게 됩니다.

그리고 문제는 하나 더 있습니다. 지구가 둥글다는 이유로
경도 180 도 와 -180 도는 같은 지점입니다.

하여 order by 절에서 문제가 발생할 소지가 많이 있습니다.

저같은 경우
LEAST(abs(latitude_e6 - (29840643.8998)), abs(180000000- latitude_e6 - (29840643.8998)))
이런 쿼리로 해당 문제를 해결하였습니다.

즉 특정 위치의 경도에서  보고 있는 위치 경도를 빼서 그 값을 180 도로 테스트를 해서 작은 값을 택하도록 설계를 하였습니다.

이는 몇번 테스트를 해서 이상이 없는 것 같지만 그 로직에서 너무 복잡해서 다시 생각해 보아야 할 문제라고 생각 됩니다.

이제 날씨 정보는 다 해결하였으니 맵에 날씨 정보를 붙이는 일만 남았죠?

그건은 각각의 각 API map 에 따라서 방법이 서로 다르기 때문에 각설 하겠습니다.

참조로 혹시 필요하신 분이 있을 것 같아서 제가 찾아낸 세계 각 도시의 위성 좌표을 첨부 합니다.

참고 :
http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Google/Service/GoogleMapAPI
http://cafen.net/zblog_lib/list.html?BLOG_ID=home&TOP=blog&blog_board=27

출처 : http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=60415