[20211230] JSONP

JSONP(JSON with Padding)에 대해 알아보자.

JSONP?

JSONP는 cross-domain 이슈없이 JSON data를 보내는 방법이다. JSONP는 data를 XMLHttpRequest가 아닌 script 태그를 이용해서 요청한다.

다른 도메인으로 부터 파일을 요청하면 cross-domain policy 때문에 문제(cors 에러)가 발생할 수 있음. 하지만, script 태그로 외부 script를 요청할 때는 똑같은 문제가 발생하지 않음.

JSONP는 cors가 발생하지 않는 script 태그를 이용한다.

코드로 보는 JSONP

간략하게 코드로 JSONP이 어떻게 동작하는지 알아보자. 코드는 client와 server 로직이 섞여있다. 코드의 원본은 jsoup guide gist by shreyansb를 참고하였다.

### (client)step 1. <head> 삽입할 script 태그를  작성한다.
### script 태그에는 가져올 데이터의 url을 포함하고,
### 해당 url에는 callback 인자가 있음을 유의한다.
### ex) var url = http://server-url/filename?lat=12.34&lon=45.67&callback=deal_with_request
load_jsonp_script = function (url) {
  // jsonp 요청을 위한 url을 만든다.
  var e = document.createElement("script");
  e.setAttribute("language", "javascript");
  e.setAttribute("type", "text/javascript");
  e.setAttribute("src", url);
  var parent = document.head;
  parent.appendChild(e);
};

### (client)step 2. <head>  script 태그가 생성된다.
<html>
    <head>
        <script language='javascript' type='text/javascript'
          src='http://splitmyri.de/cofi?lat=12.34&lon=45.67&callback=deal_with_request'>
        </s>
    </head>
    <body>
    </body>
</html>

### (server)step 3. server는 GET 요청을 받는다.
### 요청에 대한 응답으로 callback함수로 감싸진 json 데이터를 반환한다.
def get(self):
    callback = self.get_argument('callback', None)
    resp_data = {'name':'asha'}
    if callback:
        resp_str = str(callback) + '(' + simplejson.dumps(resp_data) + ');'
        self.write(resp_str)
    else:
        self.write(resp_data)

### (client)step 4.  다음 html은 아래와 같이 보인다.
<html>
    <head>
        <script language='javascript' type='text/javascript'
          src='http://splitmyri.de/cofi?lat=12.34&lon=45.67&callback=deal_with_request'>
            deal_with_request({'name':'asha'});
        </script>
    </head>
    <body>
    </body>
</html>

### step 5. <script> 태그 내부의 함수는 json data를 인자로 호출될 것이다.
deal_with_response = function(resp) {
    console.log(resp); // {'name':'asha'} 가 console에 출력됨.
};

위의 코드에서 보는 것처럼 JSONP를 사용하기 위해서는 해당 서버에서 JSONP를 지원해줘야 한다.

JSONP의 다른 용도와 오해

JSON 문자열로만 가득 채워진 파일을 <script src=”…”> 태그로 읽어 들이면 제대로 동작하지 않음.
그래서 보통 JSONP 방식으로 해결할 수 있었음.

하지만, 이는 JSON 파일의 문제가 아니라 JSON 파일을 잘못 해석해서 발생하는 문제임.

JSON 파일의 내용이 {“kukucorn”: 99} 라고 하자.

JavaScript 엔진이 JSON 파일의 내용을 해석을 하게되는데, 이를 객체로 받아들이지 않고 코드 블록으로 해석을 해버린다.
그래서 “kukucorn”이 객체의 키가 아닌 코드 블록에 존재하는 레이블로 해석이 되어 버린다.
그리고 레이블은 ““로 감싸면 에러를 발생하기 때문에 위의 경우 에러가 발생하는 것이다.

이를 JSONP를 사용해서 JSON을 함수의 인자로 넘김으로써 코드 블록이 아닌 객체 리터럴로 해석할 수 있게 해준 것이었다.


출처

W3School JSONP jsoup guide gist by shreyansb