JSONP 사용하기

SOP 문제 확인

;(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에 서버의 주소 참조하기

데이터를 가져오려는 서버의 주소를 참조한다.

var api_address = 'https://yamoo9.herokuapp.com/rest/ediya-menu'

var scriptNode = document.createElement('script')
  scriptNode.src = api_address
  console.log(scriptNode)
script에 문서를 가져오려는 url이 잘 들어갔다.

서버의 주소를 참조한 <script> 요소를 <head>의 마지막에 넣어준다.

document.head.insertAdjacentElement('beforeend', scriptNode.src)
head의 끝에 script가 잘 들어온 것을 확인

쿼리 스트링에 콜백함수 전달

쿼리 스트링(Query String)이란?

사용자가 입력 데이터를 전달하는 방법중의 하나로, url 주소에 미리 협의된 데이터를 파라미터를 통해 넘기는 것을 말한다.

  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 함수를 실행시키는 형태가 된다.

중간 정리

  var scriptNode = document.createElement('script')
  scriptNode.src = api_address + '?callback=jsonCB'

  document.head.insertAdjacentElement('beforeend', scriptNode)

  function jsonCB(data) {
    console.log(data)
  }

여기까지 진행했다면 이제 한 단계 한 단계 jsonp 방식을 사용해 본것이다. 하지만 이런 하나하나 입력하는 방식은 실무에서 사용하지 않고 대부분 헬퍼 함수를 사용한다.

헬퍼 함수

  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 함수를 제거하면서 메모리를 확보할 수 있다.

헬퍼 함수 사용하기

  // 헬퍼 함수 사용하기
  jsonp(api_address, function (data) {
    $.template(data, function (item) {
        console.log(item)
      })
  }, 10, true)
  
  // jsonp 메서드도 같이 라이브러리에 만들어져 있다
  ajax.jsonp() === jsonp() // 같은 결과가 나온다. 

고유한 함수 이름

새로 고침을 할 때마다 고유한 함수 이름이 생성이 되기 때문에 충돌 문제를 해결할 수 있다.

데이터 응답 확인

콘솔패널에서 데이터가 잘 불러온 것을 확인 할 수 있다.

Last updated

Was this helpful?