- 이번 포스트는 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는 서버측에서 이미 콜백함수를 실행하는 코드를 반환하는 점이 다를 뿐