모바일웹에서 기상청 날씨(실황) api 가져와서 파싱해서 노출까지 자바스크립트로 만들기

<포스팅 업데이트 : 2017년 4월 11일>

다시한번 해당 내용으로 data.go.kr 문의를 보냈습니다.
원문은 https://www.data.go.kr/information/QNA_0000000000014129/qna.do 이 곳을 참고해보시면 됩니다.
결론부터 말씀드리자면 api를 제공하는 입장에서 크로스도메인은 보안상의 이유로 허용할 수 없다고 합니다.
라이브러리가 안되는건 다른 라이브러리를 사용해서든 크로스도메인을 스스로 알아서 해결하여 사용하라는 이야기입니다.
참고로 전 다른 라이브러리들을 이용해서 시도해 보았으나 이 원리가 yahoo api를 거쳐 다녀오는 형태의 라이브러리들인데 아예 yahoo api 조차에서 진행이 안되는거라 어떤 라이브러리를 써도 같습니다. ㅠ

그리고 답변 중에 '크로스도메인 같은 경우 자바스크립트 보안 정책으로 인해 웹브라우저에서 막는 내용' 이라는 이야기가 있는데요.  웹브라우저에서 막는 기능이기 때문에 어찌할 수 없다는 이야기로 해석됩니다.

결론을 말씀드리자면 현재로써는 자바스크립트로 기상청 API로 구현해낼 수 있는 방법이 없습니다.


<포스팅 업데이트 : 2017년 4월 10일>

기상청에서 제공하는 api는 자바스크립트로 구현하기 힘든 상황입니다.
이유는 키를 이용한 호출 결과와 크로스 도메인 두 문제가 해결되지 않으면 앞으로도 해결해 나갈 수 없습니다.
크로스 도메인 문제로 data.go.kr에 문의한 결과 '다른 사용자의 경우 xdomainajax (구글 검색 참고) 라는 라이브러리를 통해 해당 내용을 해결한 사례가 있으니 참고해주시길 바랍니다.' (아마 지금 보시는 이 글인 듯합니다. 밑에 크로스 도메인을  해결할 수 있는 방법을 써놓았었거든요.

그리고 두번째는 호출입니다.  크로스 도메인을 임시로 해결하였다고 한들 ajax로 호출하고 난뒤 돌아오는 값이 이제 빈값입니다. (success 임에도 불구하구요.)  밑에 많은 분들이 댓글로 빈값이 온다 그러는데 바로 이 겁니다.  결과 값이 빈 값으로 들어옵니다.  하지만 웹으로 똑같은 호출 url을 열면 빈값이 아니라 데이터가 나오지요.  

이론적으로는 맞는데 쓸 수 없는 api 입니다.  외부에서 활용할 수 있게 api를 만들었으면 크로스도메인을 서버에서 허용해줘야하고,  url로 브라우저 접속하여 제대로 나온다고 끝이 아니라 직접 호출이 정상적으로 되는지 확인을 안하고 만들어놨다고 해놓은 상태이니 이걸 담당하는 사람도 없고 상담하시는 분도 건너 건너 이야기해 주시니 답답하네요.ㅠ


<포스팅 업데이트 : 2016년 2월 22일>

기상청에서 제공하는 api 구조가 바뀌어서 제대로 반영되지 않았던 내용을 수정하였습니다. 추가로 확인해보니 이제 새로운 api인 (신)동네예보정보조회서비스를 하나 더 제공하고 기존에 제공되어졌던 것은 (구)동네예보정보조회서비스로 변경되었습니다.  여러분께서는 지금 이 글은 구버전이므로 참고만 하시는 것을 추천드립니다.


시작하면서..

앞으로 글은 장문이 될 것 같아 역시 말이 좀 짧습니다.

기분이 나쁘시더라도 정보를 빠르게 얻어가기 위함이라 생각하시고 양해 부탁드립니다.


아무리 구글을 검색해도 기상청 날씨 API 가지고 데이터를 노출하는 것까지 나와있는 내용이 없었다.

이상하게 순수 클라이언트단에서 처리할 수 있는 자바스크립트 관련 내용이 gridx, gridy 변환, api 주소로 ajax에서 호출해오는 것까지만 나와있다.

그런데 이 다음부터 난관에 들어서게 된다.

바로 ajax로 호출하게 되면 다른 도메인에 있는 정보를 불러와야하기 때문에 보안 정책에 걸려서 불러오지 못하게 된다.

이는 역시 플러그인으로 해결할 수 있다.

그러나 기상청에서 가져온 API json 데이터의 형식이 안타깝게도 보이지 않는 공백때문에 오류가 나게 된다.

그리고 실황정보(예보 말고)를 가져오고 싶은데 대부분의 API는 동네 예보만을 가져오는 정보였다.

아래 포스팅 내용은 정답은 아니지만 그래도 최대한 기상청의 날씨 실황정보를 API를 불러와서 파싱하고 값을 노출하는 것까지 해보고자 한다.

계속 더 좋은 답이 나오면 업데이트 하도록 하겠다.

우리는 답을 찾을것이다 늘 그랬듯이..


1. 인증키 발급

일단 실황정보 API를 받기 위해 인증키를 발급 받자.

무료다.

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

위 링크로 가서 회원가입 후 활용신청하면 된다.

 

승인은 신청한지 얼마 지나지 않아 승인이 될 것이고, 마이페이지 가면 저렇게 인증키가 보이게 된다.

이렇게 비공개해야할 인증키를 공개해도 되나 생각하실까봐 미리 이야기하자면 인증키는 금방 재발급 받을 수 있다.

(포스팅이 끝나고 재발급 버튼만 누르면~ 끝!)

여튼 상세 기능 정보 보면 일일트래픽이 있다. 하루 동안 불러올 수 있는 횟수 제한이다.

어느 날씨 api가 좋고, 어느 api가 횟수가 많고 이런거 떠들라고 포스팅하려는거 아니니까 그런건 검색하면 잘 정리된 글들 많다.

다음은 코드 작성해보자.

 

2. 내 위치 값 가져오기

아래는 전부 자바스크립트 코드이니 알아서 js파일 안에 적어 넣도록 하자.

하나의 파일안에 담을 내용이지만 설명을 넣어야해서 함수별로 나눠서 쓰도록 하겠다.

function getLocation(){
	if(navigator.geolocation){
		navigator.geolocation.getCurrentPosition(locationSuccess, locationError, geo_options);
	}else{
		console.log("지오 로케이션 없음")
	}
};
// getLocation

모바일 웹브라우저의 geolocation을 이용해서 gps를 실행시키고자 한다.

gps가 없는 일반 pc 브라우저는 아마 통신사 isp 업체와 관련된 위치가 나올 것이다.

여튼 함수 설명에 지오로케이션이 있다면 값을 가져와서 locationSuccess 함수로 콜백하게 되어있다.

function locationSuccess(p){
        var latitude = p.coords.latitude,
        longitude = p.coords.longitude;
        var rs = dfs_xy_conv("toXY",latitude,longitude);
        // 위도/경도 -> 기상청 좌표x / 좌표 y 변환
        xml2jsonCurrentWth(rs.nx, rs.ny);
    }
// locationSuccess

 function locationError(error){
        var errorTypes = {
            0 : "무슨 에러냥~",
            1 : "허용 안눌렀음",
            2 : "위치가 안잡힘",
            3 : "응답시간 지남"
        };
        var errorMsg = errorTypes[error.code];
        console.log(errorMsg)
    }
    // locationError

    var geo_options = {
        enableHighAccuracy: true,
        maximumAge        : 30000,
        timeout           : 27000
    };
    // geo_options

locationSuccess 함수외에 에러와 옵션은 크게 바꿀 일이 없으니 그냥 두자.

이제 gps로 내 위치의 위도와 경도값을 가져왔는데 이걸 그대로 쓸 수 없다.

기상청은 기상청만의 위치를 나누는 면적 계산이 다르기 때문이다. (기상청 gridx, gridy 검색하면 이유를 알 수 있다.)

여튼 위 함수에서 rs는 위치 변환하여 반환받은 값을 가진다.

그런 후에 그 값을 xml2jsonCurrentWth 함수로 보낸다.

일단 rs 위치 변환 함수부터 보자.

// LCC DFS 좌표변환을 위한 기초 자료
    //
    var RE = 6371.00877; // 지구 반경(km)
    var GRID = 5.0; // 격자 간격(km)
    var SLAT1 = 30.0; // 투영 위도1(degree)
    var SLAT2 = 60.0; // 투영 위도2(degree)
    var OLON = 126.0; // 기준점 경도(degree)
    var OLAT = 38.0; // 기준점 위도(degree)
    var XO = 43; // 기준점 X좌표(GRID)
    var YO = 136; // 기1준점 Y좌표(GRID)
    //
    // LCC DFS 좌표변환 ( code : "toXY"(위경도->좌표, v1:위도, v2:경도), "toLL"(좌표->위경도,v1:x, v2:y) )
    //
function dfs_xy_conv(code, v1, v2) {
    var DEGRAD = Math.PI / 180.0;
    var RADDEG = 180.0 / Math.PI;

    var re = RE / GRID;
    var slat1 = SLAT1 * DEGRAD;
    var slat2 = SLAT2 * DEGRAD;
    var olon = OLON * DEGRAD;
    var olat = OLAT * DEGRAD;

    var 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);
    var sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
    sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;
    var ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
    ro = re * sf / Math.pow(ro, sn);
    var rs = {};
    if (code == "toXY") {

        rs['lat'] = v1;
        rs['lng'] = v2;
        var ra = Math.tan(Math.PI * 0.25 + (v1) * DEGRAD * 0.5);
        ra = re * sf / Math.pow(ra, sn);
        var theta = v2 * DEGRAD - olon;
        if (theta > Math.PI) theta -= 2.0 * Math.PI;
        if (theta < -Math.PI) theta += 2.0 * Math.PI;
        theta *= sn;
        rs['nx'] = Math.floor(ra * Math.sin(theta) + XO + 0.5);
        rs['ny'] = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5);
    }
    else {
        rs['nx'] = v1;
        rs['ny'] = v2;
        var xn = v1 - XO;
        var yn = ro - v2 + YO;
        ra = Math.sqrt(xn * xn + yn * yn);
        if (sn < 0.0) - ra;
        var alat = Math.pow((re * sf / ra), (1.0 / sn));
        alat = 2.0 * Math.atan(alat) - Math.PI * 0.5;

        if (Math.abs(xn) <= 0.0) {
            theta = 0.0;
        }
        else {
            if (Math.abs(yn) <= 0.0) {
                theta = Math.PI * 0.5;
                if (xn < 0.0) - theta;
            }
            else theta = Math.atan2(xn, yn);
        }
        var alon = theta / sn + olon;
        rs['lat'] = alat * RADDEG;
        rs['lng'] = alon * RADDEG;
    }
    return rs;
}
// dfs_xy_conv

매우 길다.

진짜 길다.

그냥 복사 붙여넣기 해서 쓰자.

기상청에서 만든 코드라서 활용하기만 하면 된다.

궁금하면 구글 검색하면 친절히 설명을 쓴 글들이 있다. (다시 말해 본인은 포스팅 제목과 관련된 설명만 작성 중이다.)

이제 위치 변환된 값으로 api 정보를 가져와보자.

 

3. 위치에 맞는 실황 정보 API 불러오기

function xml2jsonCurrentWth(nx, ny){
    var today = new Date();
    var dd = today.getDate();
    var mm = today.getMonth()+1;
    var yyyy = today.getFullYear();
    var hours = today.getHours();
    var minutes = today.getMinutes();
    console.log("time " + minutes)

    if(minutes < 30){
        // 30분보다 작으면 한시간 전 값
        hours = hours - 1;
        if(hours < 0){
            // 자정 이전은 전날로 계산
            today.setDate(today.getDate() - 1);
            dd = today.getDate();
            mm = today.getMonth()+1;
            yyyy = today.getFullYear();
            hours = 23;
        }
    }
    if(hours<10) {
        hours='0'+hours
    }
    if(mm<10) {
        mm='0'+mm
    }
    if(dd<10) {
        dd='0'+dd
    } 

    var _nx = nx,
    _ny = ny,
    apikey = "Emz8CfMLIHnIeD7Hl6qDBtzOB5Mpt3Sgh8G9ol07R4yzQ3ffyNDX%2BTdekwX6KD2utTd7q8UbAik%2B8pgk7w3bug%3D%3D",
    today = yyyy+""+mm+""+dd,
    basetime = hours + "00",
    fileName = "http://newsky2.kma.go.kr/service/SecndSrtpdFrcstInfoService/ForecastGrib";
    fileName += "?ServiceKey=" + apikey;
    fileName += "&base_date=" + today;
    fileName += "&base_time=" + basetime;
    fileName += "&nx=" + _nx + "&ny=" + _ny;
    fileName += "&pageNo=1&numOfRows=6";
    fileName += "&_type=json";

    $.ajax({
        url: fileName,
        type: 'GET',
        cache: false,
        success: function(data) {
            var myXML = rplLine(data.responseText);
            var indexS = myXML.indexOf('"body":{"items":{'),
                indexE = myXML.indexOf("}]}"),
                result = myXML;
//                result = myXML.substring(indexS, indexE);
            var jsonObj = $.parseJSON('[' + result + ']'),
                rainsnow = jsonObj[0].response.body.items.item[0].obsrValue,
                sky = jsonObj[0].response.body.items.item[4].obsrValue,
                temp = jsonObj[0].response.body.items.item[5].obsrValue;
                var contentText = document.getElementById('content');
            contentText.innerHTML = "하늘 상태 : " + sky + " / 눈 비 상태 : " + rainsnow + " / 온도 : " + temp;
        },
        error:function(request,status,error){
            alert("다시 시도해주세요.\n" + "code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error);
        }
        });

}
// xml2jsonCurrentWth

function rplLine(value){
    if (value != null && value != "") {
        return value.replace(/\n/g, "\\n");
    }else{
        return value;
    }
}
// rplLine

위 코드 중 apikey 에 이전에 발급받은 인증키를 넣으면 된다.

날짜와 시간은 실황 조회 api를 접근할 때 입력해야하기 때문에 초반부에 넣었다.

또한 이 실황 조회가 항상 현재 시간 기준으로 조회 될 수 있는게 아니다.

발표시간이 따로 있다.

또 발표시간도 매 정각마다이긴 한데 또 조회 기준 시간도 다르다.

이게 참 복잡한데 예를 들자면,

오후 3시 29분에 조회를 하면 2시 발표된 걸 불러와야하고,

오후 3시 31분에 조회를 하면 3시에 발표된 걸 불러와야한다.

발표정각을 기준으로 한시간 단위이지만 조회30분을 기준으로 한시간 단위다.

왜인지 궁금하면 기상청에 물어보면 된다.

여튼 만약에 위 예제대로 3시 29분에 3시 발표된 걸 불러오려고 하면 없는 데이터로 나온다.

그걸 대비하기 위에 위 코드에 알아서 계산되게 코드 짜놓았다.

그러니 그냥 인증키만 수정해서 쓰면된다.

 

4. 가져온 데이터 손보기

Ajax 호출 후 success 안에는 가져온 데이터에 빈공간엔터로 인해 생기는 오류를 대비해서 rplLine 함수를 통해 변환 작업을 거친다.

변환작업을 거치면 기상청 api안에 숨어있는 안보이는 빈공간을 오류없이 변환해 준다.

다시 변환된 텍스트를 $.parseJSON을 통해 json 형식으로 값을 변환하게 된다.

  • rainsnow : 없음(0), 비(1), 비/눈(2), 눈(3)
  • sky : 맑음(1), 구름조금(2), 구름많음(3), 흐림(4)
  • temp : 온도

가져온 눈또는 비 상태 (rainsnow) 와 하늘 상태 (sky), 온도(temp)를 이쁘게 사용자 화면에 뿌려주면 된다.

html에 id가 contentText 인 요소안에 값이 노출될 것이다.

여기까지 완성되었다면 getLocation함수를 실행시키는 것으로 모든 코드가 작동되게 해보자.

getLocation();

 

5. 크로스 도메인 해결

결과화면이 뿌듯하게 나오나 싶었다.

깔끔하게 작동된다면 더 바랄 것이 없겠지만 아마 크로스 도메인 때문에 아래와 같은 콘솔 메시지를 보게 될 것이다.

뭐라 떠드는지 몰라도 No 'Access-Control-Allow-Origin' header is present on the requested resource. 이 글만 봐도 접근할 수 없단다.

바로 도메인이 다른 곳의 파일을 불러올 때 보안에 문제가 생기기 때문에 막아버린 현상인데 그럼 ajax로 호출할 때  dataType: "jsonp" 로 하면 가능하다라고 생각할 것이다.

물론 이론상으로는 jsonp로 다른 도메인 파일 가져올 수 있다.

그런데 jsonp로 기상청 api가 안불러와진다.

그래서 본인이 ajax 호출하는 코드에  // dataType: "jsonp", 이렇게 주석처리해서 작동안되게 해놨다.

도전해보고 싶은 사람은 해봐도 좋다. (성공하면 피드백 좀... ㅠㅠ)

여튼 답은 플러그인이다.

에 아래 코드 입력하고 파일을 업로드한다.

<script type="text/javascript" src="./js/jquery.xdomainajax.js"></script>

해당 플러그인 파일은 http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/ 이 곳에 받을 수 있다.

이제 작동해보자.

본인은 값을 활용하여 이미지가 노출되게 하였다.

여기에 발표시간도 노출하고 그외 api에서 제공해주는 다른 값들도 넣어주면 된다.

기상청에서 api 다운받을 때 가이드 문서 있다.

그 문서에 엄청 많은 정보를 제공해주고 있으니 활용해보면 좋을 것 같다.


예제 파일

http://werty.co.kr/blog/labfile/weatherSample/

샘플 압축 파일


마치면서

기상청 api는 불안한 점이 많다.

api를 제공하는 서버가 접속이 안되는 경우가 빈번하게 발생하기 때문이다.

서버에서 정상으로 호출되는 경우는 이렇게 값이 잘 나오게 된다.

그러나 가끔 이렇게 호출되지 않고 엄하게 서버 오류 메세지가 나오게 된다.

어느 API를 쓰는지는 본인의 몫이다.

Subscribe
Notify of
guest

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.

39 댓글
Oldest
Newest
Inline Feedbacks
View all comments
니삼
니삼
9 years ago

이런 방법도 있지만 누간가 인증키를 탈취하여 일일 트래픽을 다 날려버린다거나 하는 악용이 될 수 도 있을까 싶어요. 잘읽고 갑니다 🙂

mynain
mynain
9 years ago
Reply to  니삼

저도 그 생각을 해보긴 했어요~ 남의 인증키로 트래픽 뺏어가면 어쩔까봐~ 해결방법은 여러가지가 있겠지만 이번에는 제목만큼 내용을 알아보려는 과정이였습니다.
정보들을 검색해보면 다들 ajax로 가져오면 된다라고만 나와있고 실제로 어떤 오류가 나오고, 어떻게 문제 해결을 하고, 어떻게 최종 출력을 하는지는 안나와있더라구요.

유재석
유재석
9 years ago

안녕하세요 저는 마이크로소프트웨어의 유재석 기자입니다. 이 포스팅의 링크와 앞 문단 일부를 인용해서 마소 페이지에 공유해도 될지 궁금해서 이렇게 댓글을 답니다..! 다음은 예시 링크입니다. https://www.imaso.co.kr/news/article_view.php?article_idx=20150217090845

mynain
mynain
9 years ago
Reply to  유재석

쓰셔도 되긴 하는데 어필이 너무 개인적이여서 ... 손 많이 보셔야할 것 같아요;;
가시적으로 퍼블리싱 하기전에 어떤 내용인지 한번 볼 수 있을까요?

유재석
유재석
9 years ago
Reply to  mynain

감사합니다. 제목은 이고요. 내용은 다음과 같은 형식으로 게재됩니다.

모바일웹에서 API를 통해 기상청 날씨 데이터를 노출하는 과정을 담은 포스팅을 소개합니다. 아래 링크를 통해 확인할 수 있습니다.

모바일웹에서 기상청 날씨(실황) api 가져와서 파싱해서 노출까지 자바스크립트로 만들기(하이퍼링크) - 아무리 구글을 검색해도 기상청 날씨 API 가지고 데이터를 노출하는 것까지 나와있는 내용이 없었다. 이상하게 순수 클라이언트단에서 처리할 수 있는 자바스크립트 관련 내용이 gridx, gridy 변환, api 주소로 ajax에서 호출해오는 것까지만 나와있다. 그런데 이 다음부터 난관에 들어서게 된다. 바로 ajax로 호출하게 되면 다른 도메인에 있는 정보를 불러와야하기 때문에 보안 정책에 걸려서 불러오지 못하게 된다. 이는 역시 플러그인으로 해결할 수 있다. 그러나 기상청에서 가져온 API json 데이터의 형식이 안타깝게도 보이지 않는 공백때문에 오류가 나게 된다.

mynain
mynain
9 years ago
Reply to  유재석

네넹~ 혹시 중간 중간에 읽는 분들께 불쾌감 줄 수 있는 단어나 문맥이 있을지도 모르니 한번 검토하시고 활용하시면 될 것 같습니다.
감사합니다.

유재석
유재석
9 years ago
Reply to  mynain

옙! 원문 포스팅으로 유입되게 하는 것이 목적인 글이라서요. 필자님의 개인적인 의견이 반영됐다는 점을 기사 안에 추가해놓겠습니다. 좋은 글 공유 허락해주셔서 감사합니다 ^^!

유재석
유재석
9 years ago
Reply to  유재석

기사는 다음과 같이 올라왔습니다~ 추가, 수정할 부분 있으시면 제 이메일주소 yoojs@imaso.co.kr 로 말씀해주세요! https://www.imaso.co.kr/news/article_view.php?article_idx=20150224103359

mynain
mynain
9 years ago
Reply to  유재석

저 역시 공유해주셔서 감사합니다.
많은 분들께 도움되었으면 좋겠습니다 ^^

권선중
권선중
8 years ago

기상청 데이터는 콜백함수를 제공해주지 않기때문에 jsonp로 값을 가져올수가 없습니다.. 그렇타고하여 json은 크로스도메인차단으로 가져올수없죠..

그래서 아래와 같은 식으로 하면됩니다..

test.php (저는 PHP를 사용하기때문에)

<?php
$url = 'http://newsky2.kma.go.kr/service/SecndSrtpdFrcstInfoService/ForecastGrib '
.'?ServiceKey=API키'
.'&today='.$_GET['today']
.'&base_date='.$_GET['base_date']
.'&base_time='.$_GET['base_time']
.'&nx='.$_GET['nx']
.'&ny='.$_GET['ny']
.'&pageNo='.$_GET['pageNo']
.'&numOfRows='.$_GET['numOfRows']
.'&_type='.$_GET['_type'];

//echo $url.'';
echo "jsonCallback(".curl($url).")"; // 가지고 온값에 콜백값을 추가해서 뿌려줌
function curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$g = curl_exec($ch);
curl_close($ch);
return $g;
}
?>

이렇케 json값을 가져옵니다..

그리고 이걸 제공해주신 소스페이지에서 다시 불러오면 OK...

fileName = "test.php?";
fileName += "base_date=" + today;
fileName += "&base_time=" + basetime;
fileName += "&nx=" + _nx + "&ny=" + _ny;
fileName += "&pageNo=1&numOfRows=6";
fileName += "&_type=json";
fileName += "&callback=callback";

$.ajax({
url: fileName,
type: 'GET',
async: false,
jsonpCallback: 'jsonCallback', //콜백 값..
contentType: "application/json",
dataType: 'jsonp',
success: function(data) {

값을 가져오는거는
var rainsnow = data.response.body.items.item[0].obsrValue;

이렇케 하니 잘됩니다..

mynain
mynain
8 years ago
Reply to  권선중

php 방법을 이용해서 가져오는 방법을 공유해주셔서 감사합니다~
나중에 다시 활용하게 될 때 써볼께요!

김장환
김장환
8 years ago

저 코드에 인증키 값만 수정해서 실행 했는데

자바 스크립트 실행이 제대로 안됩는데.. 다른것도 수정해 줘야 하나요?

mynain
mynain
8 years ago
Reply to  김장환

console.log로 어떻게 오류나는지 확인을 해주세요~

박용준
박용준
8 years ago

정보 감사합니다. 다만 인증키 바꾸고 해당 코드 사용해보니 다음과 같은 에러가 납니다. Uncaught SyntaxError: Unexpected token <m.parseJSON @ jquery-latest.min.js:4$.ajax.success @ contents.js:168(anonymous function) @ jquery.xdomainajax.js:58j @ jquery-latest.min.js:2k.fireWith @ jquery-latest.min.js:2x @ jquery-latest.min.js:4b.onload.b.onreadystatechange @ jquery-latest.min.js:4

KWD
KWD
8 years ago
Reply to  박용준

이건 문법 에러로 나오는거 보니 코드가 바뀌었거나 아니면 임포트 시키는 파일에 문제가 있을 수 있습니다. ajax로 불러오실 때 콘솔로 data가 불러와지는지 확인부터 하셔야할 것 같습니다.

박용준
박용준
8 years ago
Reply to  KWD

답변 주셔서 감사합니다. 오늘 다시 건드려보니 이런 에러 메세지가 나네요.
XMLHttpRequest cannot load http://newsky2.kma.go.kr/service/SecndSrtpdFrcstInfoService/ForecastGrib?Se…base_time=1100&nx=98&ny=75&pageNo=1&numOfRows=6&_type=json&_=1455849793004. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

박용준
박용준
8 years ago
Reply to  박용준

아, 이제보니 크로스 도메인.js 파일에 문제가 있는 것 같습니다. 해당 파일 경로를 추가하면 처음에 적은 것과 같은 에러 메세지가 뜨고, 경로가 없으면 방금 댓글단 것과 같은 에러가 나는군요. 포스팅하신 곳에서 크로스 도메인 파일을 받을 수 없어서, 따로 구글링해서 구했는데 이쪽 파일에 문제가 있나봅니다.

KWD
KWD
8 years ago
Reply to  박용준

헛! 정보 감사합니다. 나중에 다시 확인해봐야겠습니다.

박용준
박용준
8 years ago
Reply to  KWD

2개의 크로스도메인.js 파일을 찾았는데, 두 파일의 차이가 아래와 같더군요. query = 'select * from xml where url="{URL}"'; ->인식 못함
'select * from html where url="{URL}" and xpath="*"'; -> 인식하는데 문법 에러. 어떻게 고쳐야할지 감을 못 잡겠습니다

KWD
KWD
8 years ago
Reply to  박용준

주말에 시간나면 다시한번 체크해볼께요~

박용준
박용준
8 years ago
Reply to  KWD

ㅎㅎ 감사합니다. 하나하나 콘솔 찍어서 문제 위치를 거의 다 파악했어요. result값을 콘솔 찍으니까 <h라고 뜨고 그 부분이 에러 시작점인데, 혹시 정상 출력되는 글자가 어떻게 되야하는지 알 수 있을까요? 혹시 인가요?

werty
werty
8 years ago
Reply to  박용준

내용 수정해서 올려놓았습니다. 예제 파일도 서버에 업로드하였습니다.
안되었던 이유는 기성청에서 제공해주는 결과 화면 구조를 바꾸었었네요.
그걸 좀 다시 맞춰 넣었습니다.

박용준
박용준
8 years ago
Reply to  KWD

콘솔로 data를 찍어보니 다음과 같이 뜨네요. Object {responseText: "{"response":{"header":{"respons...":"SERVICE ACCESS DENIED ERROR."}}}"} 상세 데이터값도 요청날짜랑 요청 코드만 제대로 찍히고 마찬가지입니다. 이건 기상청 경로나 코드가 바뀐 건가요?

박용준
박용준
8 years ago
Reply to  KWD

data를 console로 찍어본 결과 지금 기상청에서 받아오는 주소가 바뀌어있단 걸 발견해서 해당 부분 수정했습니다. 이제 data는 다 정상으로 받아오는데, 앞서 말씀드린 문법 에러 메세지는 계속 일어나네요. 역시 크로스도메인.js가 잘못된걸까요?

유병문
유병문
7 years ago

ajax에서 data.responseText 정보가 null로 나오는데 무슨 문제 일까요 ㅜ 예제파일 js도 전부 사용했습니다.

naminsik
naminsik
7 years ago
Reply to  유병문

혹시 테스트 어떤 환경에서 하셨나요? https 가 아닌 웹사이트나 로컬호스트에서 할 경우 테스트가 안되실 꺼예요. http://bongsunga.com/blog/3294 참고해보세용~

유병문
유병문
7 years ago
Reply to  naminsik

이클립스 사용해서 로컬호스트 쓰고 있습니다. fileName 직접 열어 보니까 위치 받아와서 웹에서 날씨 정보는 잘 나오는데 로컬호스트 문제일까요?

naminsik
naminsik
7 years ago
Reply to  유병문

구 날씨 예보가 폐기되고 신 날씨 예보로 나와서 해보려고 하는데 인증키가 주소로 접속하면 정상 작동되지만 ajax 크로스도메인까지 해결해도 인증키 전달이 정확히 되지 않아 무용지물인 API로 되었습니다.
그간 패치방법을 강구하느라 시간을 좀 보냈는데 결과적으로는 이제 방법이 없습니다. ㅠㅠ

유병문
유병문
7 years ago
Reply to  naminsik

PHP로 해보니까 간단하게 되네요ㅎㅎ 답글 감사합니다.

naminsik
naminsik
7 years ago
Reply to  유병문

해결하셨다니 다행이네요.
이제 단순히 자바스크립트로만 만들긴 힘들 것 같습니다. ㅎㅎ

박문배
박문배
7 years ago

샘플파일을 받아서 키값 변경후 서버에서 실행시켰는데요.
msg.responseText 값을 찍어보면 아무것도 안나오는데 어떤거 때문에 그런건지 알수 있을가요?
ajax url을 확인해보면
{"response":{"header":{"resultCode":"0000","resultMsg":"OK"},"body":{"items":{"item":[{"baseDate":20170223,"base 이렇게 데이터가 나옵니다.

naminsik
naminsik
7 years ago
Reply to  박문배

기상청 개발 관련 코드를 확인해봤는데 인증키값이 명확하게 기상청으로 보내지지 않더라구요. 그래서 상태를 문의하니 이 포스팅을 보았는지 크로스 도메인 우회하는 방법이 있다고 해보라고 권해주더군요 ㅠㅠ

박문배
박문배
7 years ago
Reply to  naminsik

답변 감사합니다.
위의 샘플화면을 보면 지역명이 중구 / 명동 이렇게 나오는데.
현재위치의 지역명은 어떻게 가져온것인지 궁금합니다.
샘플 파일에는 없는듯 한데..

naminsik
naminsik
7 years ago
Reply to  박문배

http://bongsunga.com/blog/3390
여기에 포스팅해서 올려놓았습니다~

강소희
강소희
6 years ago

안녕하세요. 이제 이 포스트에 있는 소스는 사용하지 못하는건가요..???

강소희
강소희
6 years ago
Reply to  강소희

현재로써는 자바스크립트로 기상청 API로 구현해낼 수 있는 방법이 없습니다. 라는 문구때문에 여쭙니다ㅠ 만약에 안되면 다른 API로 갈아타려고 합니다.

naminsik
naminsik
6 years ago
Reply to  강소희

네. 기상청에서 API 보안을 풀어주지 않는 이상은 사용이 불가능하고, 기상청에서도 php, asp와 같은 백사이드 언어를 이용해서 api를 접근하라고 권장하고 있습니다.
다른 api로 전환해주세요~

강소희
강소희
6 years ago
Reply to  naminsik

띠로리...감사합니다....정부에서 공개하는 api인데도 사용을 할 수 없다는게 참...이상할따름이네요. 덕분에 시간을 좀 벌었습니다..

naminsik
naminsik
6 years ago
Reply to  강소희

이 것이 바로 정부의 반쪽짜리 기술이란 ㅠㅠ 아쉬운 정보죠.
힘내시고 만드는거 잘되시길 바래요~

TOP