• Home
  • About
    • Jiwon Jeong photo

      Jiwon Jeong

      끊임없이 배우며 성장하는 엔지니어

    • Learn More
    • Email
    • Github
  • Posts
    • All Posts
    • All Tags
    • All Categories
  • Projects

JSONP 사용법

01 May 2021

Reading time ~3 minutes

  • 이번 포스트는 http://dev.epiloum.net/1311 에서 참조함을 명시합니다.

JSONP 기본원리

  • 한 웹페이지에서 도메인이 다른 웹페이지로 데이터를 요청할 때 사용하는 자바스크립트 개발 방법론
  • 웹 브라우저는 도메인이 다른 웹 페이지로는 Ajax 등의 방법으로 접근하지 못하게 제한 : 동일출처원칙(Same-origin policy)
  • JSONP는 바로 이러한 경우에 동일출처원칙을 회피하는 일종의 편법
  • type 값은 무조건 GET으로 고정해야함

예제코드 개요

  • 회원명부에서 이름으로 검색하는 웹페이지를 작성하고자 함
  • 메인 웹 서버에는 a.epiloum.net 도메인이 연결되어 있는데 반해, 회원명부 DB는 b.epiloum.net 도메인에 연결된 서버에 있음
  • 일출처원칙으로 인하여 일반적인 방법으로는 a.epiloum.net의 웹페이지가 b.epiloum.net에 있는 웹페이지를 호출할 수는 없음
  • 한가지 해결방법은, a.epiloum.net에서 b.epiloum.net의 DB를 접근할 수 있도록 접근권한을 조정하는 것

클라이언트측 예제코드

<!DOCTYPE html>
<html lang="ko">
<head>
<title>JSONP Sample Code</title>
<meta charset="utf-8">
<script type="text/javascript">

function find()
{
    var j = document.createElement('script');
    var s = encodeURIComponent(document.getElementById('str').value);
    var u = 'http://b.epiloum.net/find.php?callback=loadList&s=' + s;
  
    j.setAttribute('src', u);
    j.setAttribute('type', 'text/javascript');
    document.getElementsByTagName('body')[0].appendChild(j);
 
    return false;
}
 
function loadList(arr)
{
    var o = document.getElementById('list');
    var l;
  
    while(o.childNodes.length)
    {
        o.removeChild(o.lastChild);
    }
  
    for(var i=0; i<arr.length; i++)
    {
        l = document.createElement('li');
        l.appendChild(document.createTextNode(arr[i]));
        o.appendChild(l);
    }
}
</script>
</head>
<body>
<input id="str" type="text" size="50" />
<input id="btn" type="button" value="입력" onclick="return find()" />
<ul id="list"></ul>
</body>
</html>
  • 텍스트 입력란에 적당한 텍스트를 입력하고 버튼을 누르면, find()라는 자바스크립트 함수가 실행.
  • 이 함수는 새로운 script 요소를 생성하여 body 요소 아래에 추가하는 역할
  • 여기서 중요한 것은 url 속성인데, URL의 도메인이 현재 도메인과는 다른 b.epiloum.net임을 확인
  • callback이라는 파라메터에는 “loadList”라는 문자열이 들어가 있는데, 이것과 같은 이름을 가진 loadList()라는 함수가 있다는 점을 기억
  • s라는 파라메터에는 사용자가 텍스트 입력란에 타이핑한 값이 들어가게 됨
  • 위 예제코드 어디에서도 호출하는 부분이 없는 loadList() 함수가 있습니다. 이 함수는 인자로 받은 배열의 내용을 ul id=”list” 요소 아래에 표시하는 역할

서버측 예제코드

<?
// Send HTTP Header
header('Content-Type:application/javascript');
 
// Connect to DB
$dbi = mysql_connect('localhost', '****', '****');
mysql_select_db('****', $dbi);
mysql_query('SET NAMES utf8', $dbi);
 
// DB Search
$sql = 'SELECT name FROM member WHERE ';
$sql .= 'name LIKE "%' . mysql_real_escape_string($_GET['s']) . '%"';
$res = mysql_query($sql, $dbi);
$dat = array();
 
while($v = mysql_fetch_assoc($res))
{
    $dat[] = $v['name'];
}
 
// Output
echo $_GET['callback'] . '(' . json_encode($dat) . ')';
?>
  • 회원명부를 담고 있는 member 테이블에서, 이름에 해당하는 name 필드에 검색어가 포함된 레코드를 LIKE 문을 사용해 검색
  • 검색어는 GET 파라메터 s를 통해 입력받음
  • 검색한 결과는 PHP 변수인 $dat에 배열로 담아둠
  • GET 파라메터 callback을 통해 전달받은 이름의 함수를 호출하는 자바스크립트 코드를 출력하고 있는 것
  • 함수의 인자로, 회원명부에서 검색한 결과를 담은 배열이 들어감.

예제코드 실행 결과

  • 검색화면 웹페이지에서 “john”을 입력하고 버튼을 클릭하면, 아래와 같은 script 요소가 생성되었을 것
<script src=”http://b.epiloum.net/find.php?callback=loadList&s=john”></script>
  • 이렇게 호출된 find.php 파일은 아래와 같이 callback 파라메터로 전달받은 이름인 loadList() 함수를 실행하는 스크립트를 출력
loadList([“John Miller”,”John C. Potter”])
  • <ul id=”list”> 요소 아래에 John이라는 단어로 검색한 결과가 목록으로 보이게됨

JQuery를 사용하여 쉽게 AJax 처리하기!

<!DOCTYPE html>
<html lang="ko">
<head>
<title>JSONP Sample Code</title>
<meta charset="utf-8">
<script type="text/javascript">

function find()
{  
    var s = encodeURIComponent(document.getElementById('str').value);
     
    $.ajax({
        dataType: "jsonp",
        url: "http://b.epiloum.net/find.php",
        type: "GET",
        data: {'s':s},
        success: function(data){
            loadList(data);
        }
    });
  
    return false;
}
 
function loadList(arr)
{
    var o = document.getElementById('list');
    var l;
  
    while(o.childNodes.length)
    {
        o.removeChild(o.lastChild);
    }
  
    for(var i=0; i<arr.length; i++)
    {
        l = document.createElement('li');
        l.appendChild(document.createTextNode(arr[i]));
        o.appendChild(l);
    }
}
</script>
</head>
<body>
<input id="str" type="text" size="50" />
<input id="btn" type="button" value="입력" onclick="return find()" />
<ul id="list"></ul>
</body>
</html>
  • Ajax와 다른 점은 단지 dataType 값을 “jsonp”로 놓았다는 것 뿐.
  • 위 예제코드를 실행해보면 success 함수가 콜백함수의 역할을 하게 되는 것

JSONP 작동구조

  • 데이터를 요청할 페이지(클라이언트)에, 데이터를 받아 처리할 콜백 함수를 먼저 준비해놓음. 그 후에 script 요소를 생성하여, 데이터 요청함
  • 데이터 요청을 받은 페이지(서버)에서는 콜백 함수를 실행하는 스크립트를 출력합니다. 이 때 callback 함수의 인자에는 요청받은 데이터가 들어가게 됨

일반적인 JSON 데이터 요청 AJax와의 차이점

  • Ajax는 데이터 만을 일단 responseText 속성으로 가져온 후, XMLHttpRequest 객체에서 onreadystatechange 속성에 담긴 콜백함수를 실행
  • JSONP는 서버측에서 이미 콜백함수를 실행하는 코드를 반환하는 점이 다를 뿐


WebProgramming Share Tweet +1