본문으로 바로가기

JSONP

category JavaScript 2021. 6. 6. 02:26

Jsonp

  • 웹 브라우저에서 실행되는 JavaScript는 동일 출처 정책에 따라 XMLHttpRequest 등의 직접적인 HTTP 통신을 이용해 외부 출처에서 데이터를 받아오는 것이 불가능하지만, HTML script 요소는 외부 출처로부터 조회된 내용을 실행하는 것이 허용되어 있다.
  • JSONP는 동일-출처 정책을 우회하는 데이터의 공유를 가능하게 한다.
  • 상속 비보안 문제로 인해 JSONP는 CORS로 대체되고 있다.

참고 위키백과

쇼핑하우 fetch 요청해보기

// 쇼핑하우에 검색어에 'abc'라고 입력했을때 url

'https://suggest-bar.daum.net/suggest?limit=10&mode=json&code=utf_in_out&q=abc&id=shoppinghow_suggest'

image

  • 요러한 데이터가 나온다
  • 이제 이것을 fetch로 요청해보자!
fetch('https://suggest-bar.daum.net/suggest?limit=10&mode=json&code=utf_in_out&q=abc&id=shoppinghow_suggest')
  .then(data => data.json())
  .then(data => console.log(data));

image

  • 😎 짠! 하고 에러가 나왔다
  • CORS 문제라고 한다
  • Jsonp 로 바꿀차례인것 같다

쇼핑하우 Jsonp 요청하기

  • javascript 는 동일 출처 정책을 따르지만
  • HTML script 요소는 외부 출처로부터 조회된 내용을 실행하는 것이 허용되어 있다.
  • JSONP는 이러한 웹 브라우저의 특성을 이용해, JSON 데이터를 클라이언트가 지정한 콜백 함수를 호출하는 유효한 JavaScript 문법으로 감싸 클라이언트에 전송한다.
 <script>
 function parseResponse(data) { 
   console.log(data)
 }
 </script> 
 <script 
   src="https://suggest-bar.daum.net/suggest?
   callback=parseResponse&limit=10&mode=json&code=utf_in_out&q=abc&id=shoppinghow_suggest">
 </script>
  • 클라이언트가 'parseResponse'라는 함수를 JSONP 요청의 콜백 함수로 지정하였다고 하면, 다음과 같은 HTML 태그가 문서에 삽입된다.



image

  • 위의 html 코드의 결과는 이렇게 데이터가 나오는 것을 확인할 수 있다

 

js 코드에서는 어떻게?

 function requestJsonp(word) {
   const script = document.createElement('script');
   script.src = https://suggest-bar.daum.net/suggest?
     callback=responseJsonpData&amp;limit=10&amp;mode=json&amp;code=utf_in_out&amp;q=${word}&amp;id=shoppinghow_suggest;
   document.body.append(script);
 } 
 
 function responseJsonpData(data) {
   console.log(data) 
 } 
 requestJsonp('abc');
  • 이런식으로 responseJsonpData를 callback의 인자로 넣어주었다

 

function requestJsonp(word, callback) {
  const script = document.createElement('script');
  script.src = https://suggest-bar.daum.net/suggest?
    callback=${callback.name}&amp;limit=10&amp;mode=json&amp;code=utf_in_out&amp;q=${word}&amp;id=shoppinghow_suggest;
  document.body.append(script);
}

function responseJsonpData(data) {
console.log(data);
}

requestJsonp('abc', responseJsonpData);
  • 이렇게 해도 동일하게 작동한다
  • 이렇게 해서 사용하면 된다~ (~ ̄▽ ̄)~




Webpack 사용 시 문제점

  • webpack으로 js소스를 번들링하여 하나의 js 파일만 사용하고 있었는데
  • 위와 동일하게 했음에도 불구하고 문제가

image

  • 요렇게 나온다
    (위의 코드는 jsonp.js파일을 html에서 번들링하지 않고 따로 불러서 사용했었다)
  • 분명 responseJsonpData 함수를 선언해 두었는데 찾지 못한다고 한다

image

  • Source 탭에서 디버깅을 해본결과 responseJsonpData는 존재하고 있었다!! 왜 못찾는거지??

 

  • 그후로 삽질 ⛏⚒🛠🔨🪓🏹🗡⚔💣⌛⏳⌚⏰⏱⏲...

 

결과

  • webpack의 변수 유효범위는 해당파일안에서만 접근 가능하다
  • ▼ 이미지는 아메리카노로 입력했을때 생성된 script

image

  • Jsonp가 동작하게 하기 위해서는 script를 새로 생성해야 하는데 새로 생성한 스크립트에서는 접근을 할 수가 없는 것이었다!! 🎊
  • 그래서 함수를 전역으로 이동시켜야 한다

https://stackoverflow.com/questions/40759250/why-webpack-use-jsonp-to-get-chunk-script

window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) { }
  • jsonp를 사용하는 코드는 window 전역객체를 사용하는 코드가 보이던데 이런식으로 사용해야하나보다..

 

내 코드 수정

function requestJsonp(word, callbackName) { 
  const script = document.createElement('script'); 
  script.src = https://suggest-bar.daum.net/suggest?
    callback=${callbackName}&amp;limit=10&amp;mode=json&amp;code=utf_in_out&amp;q=${word}&amp;id=shoppinghow_suggest;
  document.body.append(script);
} 

window['responseJsonpData'] = function (data) {
  console.log(data);
} 

requestJsonp('abc', 'responseJsonpData');
  • 이런식으로 해결~ 어쩔 수 없는 전역 함수인 것 같다 (~ ̄▽ ̄)~