SOP 문제 확인
Copy ;( function (global , $ , ajax) {
'use strict'
var api_address = 'https://yamoo9.herokuapp.com/rest/ediya-menu'
// SOP 문제 발생!
// Ajax 비동기 호출
ajax .get (api_address) .then ( function (data) {
console .log (data)
})
})(window , Dom , ajax)
Access to XMLHttpRequest at 'https://yamoo9.herokuapp.com/rest/ediya-menu ' from origin 'http://127.0.0.1:60400 ' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
포트 넘버가 달라서 XMLHttpRequest 객체로 접근이 불가능 하다는 오류 메세지를 확인 할 수 있다.
실습하기
이번에는 ajax 방식이 아닌 jsonp 방식을 사용해 SOP문제를 해결한다.
script에 서버의 주소 참조하기
데이터를 가져오려는 서버의 주소를 참조한다.
Copy var api_address = 'https://yamoo9.herokuapp.com/rest/ediya-menu'
var scriptNode = document .createElement ( 'script' )
scriptNode .src = api_address
console .log (scriptNode)
head에 서버 주소 넣기
서버의 주소를 참조한 <script>
요소를 <head>
의 마지막에 넣어준다.
Copy document . head .insertAdjacentElement ( 'beforeend' , scriptNode .src)
쿼리 스트링에 콜백함수 전달
Copy var scriptNode = document .createElement ( 'script' )
scriptNode .src = api_address + '?callback=jsonCB'
document . head .insertAdjacentElement ( 'beforeend' , scriptNode)
function jsonCB (data) {
console .log (data)
}
해석 → typrof jsonCB의 값이 function이라면 jsonCB로 내부의 것을 실행!
실제 json 방법이 아닌 jsonp 방법을 사용해서 동적으로 스크립트를 추가하고 url 주소 뒤에 쿼리 스트링이 추가 되면서 입력해둔 callback 함수를 실행시키는 형태가 된다.
중간 정리
Copy var scriptNode = document .createElement ( 'script' )
scriptNode .src = api_address + '?callback=jsonCB'
document . head .insertAdjacentElement ( 'beforeend' , scriptNode)
function jsonCB (data) {
console .log (data)
}
여기까지 진행했다면 이제 한 단계 한 단계 jsonp 방식을 사용해 본것이다. 하지만 이런 하나하나 입력하는 방식은 실무에서 사용하지 않고 대부분 헬퍼 함수를 사용한다.
헬퍼 함수
Copy function jsonp (url , callback , time_limit , log) {
var unique_id = Math .floor ( Math .random () * 100000 )
var jsonpCb = 'jsonpCb_' + unique_id
var s = document .createElement ( 'script' )
s .src = url + '?callback=' + jsonpCb
document . head .insertAdjacentElement ( 'beforeend' , s)
window[jsonpCb] = callback
s .remove ? s .remove () : s . parentNode .removeChild (s)
window .setTimeout ( function () {
log &&
console .info ( 'JSONP 콜백함수: ' + jsonpCb + '를 전역에서 제거했습니다.' )
delete window[jsonpCb]
} , (time_limit || 3 ) * 1000 )
}
time_limit
time_limit은 설정한 시간이 지나면 전역에 있던 callback 함수는 사라지게 된다. (기본값 2초)
이는 전역을 오염시킨 callback 함수를 제거하면서 메모리를 확보할 수 있다.
헬퍼 함수 사용하기
Copy // 헬퍼 함수 사용하기
jsonp (api_address , function (data) {
$ .template (data , function (item) {
console .log (item)
})
} , 10 , true )
// jsonp 메서드도 같이 라이브러리에 만들어져 있다
ajax .jsonp () === jsonp () // 같은 결과가 나온다.
고유한 함수 이름
새로 고침을 할 때마다 고유한 함수 이름이 생성이 되기 때문에 충돌 문제를 해결할 수 있다.
데이터 응답 확인