JSONP๋ JSON with Padding์ด๋ผ๊ณ ๋ ์๋ ค์ ธ ์์ผ๋ฉฐ CORS(Cross-Origin Resource Sharing) ์ ์ฑ ์ ์ํด ๊ฐ๋ก์ฑ์ง ์๊ณ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ ๊ธฐ์ ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ๋ธ๋ผ์ฐ์ ์์ ์ํํ๋ CORS ๊ฒ์ฌ๋ฅผ ์ฐํํ ์ ์์ต๋๋ค. ๋ด ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ๋ง์ ์ค๊ตญ ์น์ฌ์ดํธ์์๋ ์ฌ์ ํ ์ด ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
๋ถ์ธ ์ฑ๋ช ํ๊ตญ์ด ์ค๋ ฅ์ด ๋ถ์ ํ์ฌ ์ด ๊ธ์ด ๊ตฌ๊ธ ๋ฒ์ญ๊ธฐ๋ฅผ ์ฃผ๋ก ํ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ถ์ ํํ ๋ฌธ๋ฒ๊ณผ ์ดํ๊ฐ ์์์ ์์ต๋๋ค. ์ด ์ ์ํด ๋ถํ๋๋ฆฌ๋ฉฐ, ์ถํ์ ๋ค์ ๊ฒํ ํ์ฌ ์์ ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์๋๋ฆฌ์ค
์น ์ ํ๋ฆฌ์ผ์ด์
์ด www.a.com์ ํธ์คํ
๋์ด ์๊ณ JavaScript ์ฝ๋ ์ค ํ๋๊ฐ www.b.com์ ํธ์คํ
๋ ์๊ฒฉ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ค๊ณ ํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์๊ฒฉ ์๋ฒ๊ฐ * ๋๋ www.a.com์ผ๋ก ์ค์ ๋ Access-Control-Allow-Origin ํค๋๋ฅผ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ์ ์๋ตํ์ง ์์ผ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ์๋ต์ ์์ ํ๊ณ ํด์ํ ๋ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๊ณ ๊ฑฐ๋ถํฉ๋๋ค. ์์ฒญํ ๋ฐ์ดํฐ.
ํด๋ฒ
์ต์ 1: CORS ๊ตฌ์ฑ
๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฐ์ฅ ์์ ํ๊ณ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ 'Access-Control-Allow-Origin' ํค๋๊ฐ ์ ์ ํ ๋๋ฉ์ธ์ ๊ฐ๋ฆฌํค๋๋ก ์ค์ ํ์ฌ ๋ฐฑ์๋ ์๋ฒ์์ CORS๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑํ๋ ๊ฒ์ ๋๋ค. ๋ฆฌ์์ค๊ฐ Azure, GCP ๋๋ AWS์ ๊ฐ์ ํด๋ผ์ฐ๋์์ ํธ์คํ ๋๋ ๊ฒฝ์ฐ CORS๋ฅผ ํ์ฑํํ๋ ์ค์ ๋ ์์ ๊ฒ์ ๋๋ค.
์ต์ 2: JSONP ์ฌ์ฉ
JSONP์๋ ์์ ๋ ์๋ต์ ํ์ฉํ๊ธฐ ์ํด ๋ฐ๋ผ์ผ ํ๋ ํน์ ๊ท์น ์ธํธ๊ฐ ์์ต๋๋ค.
ํฌ๋งท
๋ค์์ https://a.com/sample.json์ ์์ JSON ํ์์ ์์ ๋ฐ์ดํฐ์
๋๋ค.
{
"name": "Jane",
"age": 14,
"school": "Stanford High School"
}๋ค์์ URL https://a.com/sample?callback=callback์ ์๋ JSONP ํ์์ ๋ฐ์ดํฐ์
๋๋ค.
callback({
name: 'Jane',
age: 14,
school: 'Stanford High School',
})๋ณธ์ง์ ์ผ๋ก ์ด๋ ์์ฒญ๋ ๋ฐ์ดํฐ์ ๋ํ JavaScript ํจ์ ํธ์ถ์ผ ๋ฟ์ด๋ฉฐ ํจ์ ์ด๋ฆ์ '์ฝ๋ฐฑ' ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ก ์์ ๋ ์ ์์ต๋๋ค. ์ฝ๋ฐฑ ํจ์๋ ์ฐ๋ฆฌ๊ฐ "ํจ๋ฉ(Padding)"์ด๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด https://a.com/sample?callback=cb๋ฅผ ํธ์ถํ๋ฉด ๋ฐํ๋ ๋ฐ์ดํฐ๋ cb ํจ์๋ก ๋ฌถ์
๋๋ค.
cb({
name: 'Jane',
age: 14,
school: 'Stanford High School',
})์ฃผ๋ชฉํด์ผ ํ ํ ๊ฐ์ง ์ค์ํ ์ฃผ์ ์ฌํญ์ ์ ๊ณต๋ ์ฝ๋ฐฑ ํจ์ ์ด๋ฆ์ด ๋ฌด์์ด๋ ์ ๊ณต๋ ๋ฐ์ดํฐ๋ฅผ ์๋ฏธ ์๊ฒ ์ฌ์ฉํ๋ ค๋ฉด ํจ์๊ฐ ์กด์ฌํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
Uncaught ReferenceError: <method> is not defined์ฉ๋ฒ
์์ฒญ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์์ ์ ๊ณต๋ ๋์ผํ ์ด๋ฆ์ผ๋ก JavaScript ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ์ํ๊ณ JSONP ๋ฐ์ดํฐ๊ฐ ๋ก๋๋๊ธฐ ์ ์ ํจ์๊ฐ ์ ์๋์๋์ง ํ์ธํ์ธ์.
function callback(data) {
// ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌ
console.log(data)
}HTML๋ก ์ผ์ผ์ด์ค
HTML์์๋ ๋ค์๊ณผ ๊ฐ์ด ํ์๋ฉ๋๋ค.
<!DOCTYPE html>
<html>
<head>
<title>JSONP Showcase</title>
</head>
<body>
<script type="text/javascript">
function myFunction(data) {
console.log(data)
}
</script>
<!-- ์ผ๋ฐ JavaScript์ฒ๋ผ ์คํฌ๋ฆฝํธ ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ JSONP ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ -->
<script
type="text/javascript"
src="https://a.com/mydata?callback=myFunction"
></script>
</body>
</html>์บ์ ํด์
JSONP ํธ์ถ์ <script src="https://constant-static-url">์ด ์์์ธ ๊ฒฝ์ฐ ์ต์ ํ๋ฅผ ์ํด ๋ธ๋ผ์ฐ์ ์ ์ํด ์บ์ฑ๋ฉ๋๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ ์ค๋๋ ๋ฐ์ดํฐ๋ฅผ ์บ์ฑํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ ค๋ฉด Math.random์ ์ฌ์ฉํ์ฌ ์ฝ๋ฐฑ ํจ์ ์ด๋ฆ์ ๋์ ์ผ๋ก ์์ฑํด์ผ ํฉ๋๋ค.
window.onload = function () {
var randomNum = Math.floor(100_000 * Math.random())
var functionName = 'cb_' + randomNum
window[functionName] = function (data) {
console.log(data)
}
// ์คํฌ๋ฆฝํธ ํ๊ทธ๋ฅผ ๋์ ์ผ๋ก ์์ฑํด์ผ ํฉ๋๋ค.
var newScriptTag = document.createElement('script')
newScriptTag.src = 'https://a.com/mydata?callback=' + functionName
document.body.appendChild(newScriptTag)
}์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ต์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํฉ๋๋ค.
์ฒญ์
๋ธ๋ผ์ฐ์ ์์ ์ด๋ฏธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฏ๋ก ๋์ ์ผ๋ก ์์ฑ๋ ์คํฌ๋ฆฝํธ ํ๊ทธ๋ฅผ ์ ํ์ ์ผ๋ก ์ ๊ฑฐํ ์ ์์ต๋๋ค.
window.onload = function () {
var randomNum = Math.floor(100_000 * Math.random())
var functionName = 'cb_' + randomNum
window[functionName] = function (data) {
console.log(data)
}
// ์คํฌ๋ฆฝํธ ํ๊ทธ๋ฅผ ๋์ ์ผ๋ก ์์ฑํด์ผ ํฉ๋๋ค.
var newScriptTag = document.createElement('script')
newScriptTag.id = 'script_' + functionName
newScriptTag.src = 'https://a.com/mydata?callback=' + functionName
document.body.appendChild(newScriptTag)
document.getElementById(newScriptTag.id).remove()
}์ ๋ฆฌ๋ฅผ ํตํด JSONP ํธ์ถ์ด ์ํํ๊ฒ ํ์๋ฉ๋๋ค.
์ฅ์ ๊ณผ ๋จ์
์ฅ์
- ํฌ๋ก์ค ๋๋ฉ์ธ ์์ฒญ: CORS ์ ์ฑ ์ ์ํด ์ํ๋๋ ๊ฒฝ๊ณ๋ฅผ ๋ฒ์ด๋ ์ ์์ต๋๋ค.
- ์ฌ์ฉํ๊ธฐ ์ฌ์: ๋ณต์กํ ์ค์ ์ฝ๋ ์์ด HTML์์
<script>ํ๊ทธ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. - ๋ฐ์ด๋ ๋ธ๋ผ์ฐ์ ํธํ์ฑ: ๋จ์ํ JavaScript ํจ์ ํธ์ถ์ด๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ์ง์ํฉ๋๋ค.
๋จ์
- ๋ณด์์ํ : ์ทจ์ฝํ ํน์ฑ์ผ๋ก ์ธํด ์ ์ฑ์ฝ๋์ ์ํด ์ ์ฉ๋ ์ ์์ต๋๋ค.
- ์ค๋ฅ ์ฒ๋ฆฌ ์์: ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ. ํจ์๊ฐ ์ ์๋์ง ์์๊ฑฐ๋ ์๋ฒ๊ฐ ์๋ตํ์ง ์๋ ๊ฒฝ์ฐ ํด๋น ์ค๋ฅ๋ฅผ ์ฝ์์ ํ์ํ๋ ๊ฒ ์ธ์๋ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
- ์๋ฒ์ ๋ฐ๋ผ ๋ค๋ฆ: ์๋ฒ๊ฐ JSONP ์๋ํฌ์ธํธ๋ฅผ ์ ๊ณตํ์ง ์์ผ๋ฉด JSONP๋ฅผ ์ฌ์ฉํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
- GET ์์ฒญ๋ง ์ง์: JSONP ์์ฒญ์
<script>ํ๊ทธ๋ง ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์ด๋ฏธ ์๊ณ ์์ผ๋ฏ๋ก GET ์ด์ธ์ ๋ค๋ฅธ HTTP ๋ฉ์๋๋ฅผ ์ง์ํ ๋ฐฉ๋ฒ์ ์์ต๋๋ค.