์นดํ…Œ๊ณ ๋ฆฌ ๋ณด๊ด€๋ฌผ: Javascript

Javascript

REST API์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋ ค๊ณ  ํ•  ๋•Œ ์š”์ฒญ ๋œ ์ž์›์— โ€˜Access-Control-Allow-Originโ€™ํ—ค๋”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ

HP Alm์˜ REST API์—์„œ ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์€ curl ์Šคํฌ๋ฆฝํŠธ์™€ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

์ด์ œ JavaScript๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ๊ณผ ๊ฐ€์ ธ ์˜ค๊ธฐ ๋ฐ ES6 (๋” ๋งŽ๊ฑฐ๋‚˜ ์ ์€)์ด ๋” ํฐ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๊ณ„์† ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

Fetch API๊ฐ€๋กœ๋“œ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์ด ์•ก์„ธ์Šค ์ œ์–ด ํ™•์ธ์„ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•จ : ์š”์ฒญ ๋œ ๋ฆฌ์†Œ์Šค์— โ€˜Access-Control-Allow-Originโ€™ํ—ค๋”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์›๋ณธ โ€˜ http://127.0.0.1:3000 โ€˜์€ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‘๋‹ต์˜ HTTP ์ƒํƒœ ์ฝ”๋“œ๋Š” 501์ž…๋‹ˆ๋‹ค. ๋ถˆํˆฌ๋ช… ํ•œ ์‘๋‹ต์ด ์‚ฌ์šฉ์ž์˜ ์š”๊ตฌ์— ๋ถ€์‘ํ•˜๋Š” ๊ฒฝ์šฐ CORS๊ฐ€ ๋น„ํ™œ์„ฑํ™” ๋œ ์ƒํƒœ์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ ์˜ค๋ ค๋ฉด ์š”์ฒญ ๋ชจ๋“œ๋ฅผ โ€˜no-corsโ€™๋กœ ์„ค์ •ํ•˜์‹ญ์‹œ์˜ค.

๋กœ์ปฌ ํ˜ธ์ŠคํŠธ ๋‚ด์—์„œ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ ์˜ค๋ ค๊ณ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์†”๋ฃจ์…˜์ด CORS๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์ดํ•ด๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ์‹ค์ œ๋กœ ๊ทธ๋ ‡๊ฒŒํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ ์–ด๋–ป๊ฒŒ ๋“  ํ—ค๋”์— ์“ฐ๋Š” ๊ฒƒ์„ ๋ฌด์‹œํ•˜๊ฑฐ๋‚˜ ๋ฌธ์ œ๊ฐ€ ๋‹ค๋ฅธ ๊ฒƒ์ž…๋‹ˆ๊นŒ?

๊ทธ๋ ‡๋‹ค๋ฉด ๊ตฌํ˜„ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚ด๊ฐ€ ์ž˜๋ชปํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ๋ถˆํ–‰ํžˆ๋„ ์„œ๋ฒ„ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ •๋ง๋กœ ์—ฌ๊ธฐ ๋ถ™์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

function performSignIn() {

  let headers = new Headers();

  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');

  headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
  headers.append('Access-Control-Allow-Credentials', 'true');

  headers.append('GET', 'POST', 'OPTIONS');

  headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

  fetch(sign_in, {
      //mode: 'no-cors',
      credentials: 'include',
      method: 'POST',
      headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

Chrome์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Chrome CORS ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•ด ๋ณด์•˜์ง€๋งŒ ๋‹ค๋ฅธ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

์š”์ฒญ์˜ ์ž๊ฒฉ ์ฆ๋ช… ๋ชจ๋“œ๊ฐ€ โ€˜includeโ€™์ธ ๊ฒฝ์šฐ ์‘๋‹ต์˜ โ€˜Access-Control-Allow-Originโ€™ํ—ค๋” ๊ฐ’์ด ์™€์ผ๋“œ ์นด๋“œ โ€˜*โ€™๊ฐ€ ์•„๋‹ˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์›๋ณธ โ€˜ http://127.0.0.1:3000 โ€˜์€ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. XMLHttpRequest์— ์˜ํ•ด ์‹œ์ž‘๋œ ์š”์ฒญ์˜ ์ž๊ฒฉ ์ฆ๋ช… ๋ชจ๋“œ๋Š” withCredentials ์†์„ฑ์— ์˜ํ•ด ์ œ์–ด๋ฉ๋‹ˆ๋‹ค.



๋‹ต๋ณ€

์ด ๋‹ต๋ณ€์€ ๋งŽ์€ ๊ทผ๊ฑฐ๋ฅผ ๋‹ค๋ฃจ๋ฏ€๋กœ ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

  • CORS ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ โ€œNo Access-Control-Allow-Origin headerโ€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•
  • CORS ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๋ฅผ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š” โ€œ์•ก์„ธ์Šค ์ œ์–ด โ€“ ํ—ˆ์šฉ โ€“ ์›์‚ฐ์ง€ ํ—ค๋”๋Š” ์™€์ผ๋“œ ์นด๋“œ๊ฐ€ ์•„๋‹ˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹คโ€ ๋ฌธ์ œ

CORS ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ โ€œNo Access-Control-Allow-Origin headerโ€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

ํ”„๋ก ํŠธ ์—”๋“œ JavaScript ์ฝ”๋“œ๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์„œ๋ฒ„๋ฅผ ์ œ์–ดํ•˜์ง€ ์•Š๊ณ  ํ•ด๋‹น ์„œ๋ฒ„์˜ ์‘๋‹ต ๋ฌธ์ œ๊ฐ€ ํ•„์š”ํ•œ Access-Control-Allow-Originํ—ค๋” ๊ฐ€ ๋ถ€์กฑํ•œ ๊ฒฝ์šฐ ์—๋„ ์š”์ฒญ์„ ํ†ตํ•ด ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CORS ํ”„๋ก์‹œ. ์ž‘๋™ ๋ฐฉ์‹์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ๋จผ์ € CORS ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

const url = "https://example.com"; // site that doesnโ€™t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Canโ€™t access " + url + " response. Blocked by browser?"))

catch๋ธ”๋ก์— ๋„๋‹ฌ ํ•˜๋Š” ์ด์œ ๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด๋‹น ์ฝ”๋“œ๊ฐ€์—์„œ ์˜ค๋Š” ์‘๋‹ต์— ์•ก์„ธ์Šคํ•˜์ง€ ๋ชปํ•˜๊ฒŒํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค https://example.com. ๊ทธ๋ฆฌ๊ณ  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ทธ๋ ‡๊ฒŒํ•˜๋Š” ์ด์œ ๋Š” Access-Control-Allow-Origin์‘๋‹ต ํ—ค๋”์— ์‘๋‹ต์ด ์—†๊ธฐ ๋•Œ๋ฌธ ์ž…๋‹ˆ๋‹ค.

์ด์ œ ์ •ํ™•ํžˆ ๋™์ผํ•œ ์˜ˆ์ด์ง€๋งŒ CORS ํ”„๋ก์‹œ๊ฐ€ ์ถ”๊ฐ€ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesnโ€™t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Canโ€™t access " + url + " response. Blocked by browser?"))

์ฐธ๊ณ  : https://cors-anywhere.herokuapp.com์„ ๋‹ค์šด๋กœ๋“œ ํ•  ๋•Œ ๋‹ค์šด๋˜์—ˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•  ์ˆ˜์—†๋Š” ๊ฒฝ์šฐ 2-3 ๋ถ„๋งŒ์— Heroku์— ์ž์ฒด CORS Anywhere ์„œ๋ฒ„๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋ž˜๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

์œ„์˜ ๋‘ ๋ฒˆ์งธ ์ฝ”๋“œ ์Šค ๋‹ˆํŽซ์€ ์š”์ฒญ URL์„ ๊ฐ€์ ธ ์™€์„œ ํ”„๋ก์‹œ URL์„ ์ ‘๋‘์‚ฌ๋กœ ์‚ฌ์šฉ ํ•˜์—ฌ https://cors-anywhere.herokuapp.com/https://example.com์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‘๋‹ต์— ์„ฑ๊ณต์ ์œผ๋กœ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค . ํ•ด๋‹น ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์— ์š”์ฒญ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค https://example.com.
  2. ์—์„œ ์‘๋‹ต์„๋ฐ›์Šต๋‹ˆ๋‹ค https://example.com.
  3. Access-Control-Allow-Origin์‘๋‹ต์— ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค .
  4. ์ถ”๊ฐ€ ๋œ ํ—ค๋”์™€ ํ•จ๊ป˜ ํ•ด๋‹น ์‘๋‹ต์„ ์š”์ฒญ ํ”„๋ก ํŠธ ์—”๋“œ ์ฝ”๋“œ๋กœ ๋‹ค์‹œ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ธŒ๋ผ์šฐ์ €๋Š” ํ”„๋ก ํŠธ ์—”๋“œ ์ฝ”๋“œ๊ฐ€ ์‘๋‹ต์— ์•ก์„ธ์Šค ํ•  ์ˆ˜์žˆ๊ฒŒํ•ฉ๋‹ˆ๋‹ค. Access-Control-Allow-Origin์‘๋‹ต ํ—ค๋”๊ฐ€ ์žˆ๋Š” ์‘๋‹ต์ด ๋ธŒ๋ผ์šฐ์ €์— ํ‘œ์‹œ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค .

https://github.com/Robโ€“W/cors-anywhere/์˜ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž์‹ ์˜ ํ”„๋ก์‹œ๋ฅผ ์‰ฝ๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .
5 ๊ฐœ์˜ ๋ช…๋ น์œผ๋กœ ๋ง ๊ทธ๋Œ€๋กœ 2-3 ๋ถ„๋งŒ์— Heroku์— ์ž์‹ ์˜ ํ”„๋ก์‹œ๋ฅผ ์‰ฝ๊ฒŒ ๋ฐฐํฌ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master

ํ•ด๋‹น ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด https://cryptic-headland-94862.herokuapp.com/ ๊ณผ ๊ฐ™์€ ์ž์ฒด CORS Anywhere ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค . ๋”ฐ๋ผ์„œ ์š”์ฒญ URL ์•ž์— ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์ด์ง€ https://cors-anywhere.herokuapp.com๋ง๊ณ  ๋Œ€์‹  ์ž์‹ ์˜ ์ธ์Šคํ„ด์Šค URL๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์ด์‹ญ์‹œ์˜ค . ์˜ˆ๋ฅผ ๋“ค์–ด, https://cryptic-headland-94862.herokuapp.com/https://example.com .

๋”ฐ๋ผ์„œ https://cors-anywhere.herokuapp.com์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋‹ค์šด๋˜์–ด ์žˆ์Œ์„ ๋ฐœ๊ฒฌ ํ•œ ๊ฒฝ์šฐ (์•„์ง ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ) Heroku ๊ณ„์ •์„ ๊ฐ€์ ธ ์™€์„œ 2๋ฅผ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค. ๋˜๋Š” 3 ๋ถ„ ๋™์•ˆ ์œ„ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ Heroku์— ์ž์‹ ์˜ CORS Anywhere ์„œ๋ฒ„๋ฅผ ๋ฐฐํฌํ•˜์‹ญ์‹œ์˜ค.

์ž์ฒด์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋“  https://cors-anywhere.herokuapp.com ๋˜๋Š” ๊ธฐํƒ€ ๊ฐœ๋ฐฉํ˜• ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋“  ์ƒ๊ด€์—†์ด์ด ์†”๋ฃจ์…˜์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ CORS ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ OPTIONS์š”์ฒญ ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํŠธ๋ฆฌ๊ฑฐ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํ”„๋ก์‹œ๋Š” ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ Access-Control-Allow-Headers๋ฐ Access-Control-Allow-Methodsํ—ค๋”๋ฅผ ๋‹ค์‹œ ๋ณด๋ƒ…๋‹ˆ๋‹ค .


CORS ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๋ฅผ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•

๋ฌธ์ œ์˜ ์ฝ”๋“œ๋Š” Authorizationํ—ค๋”๋ฅผ ์ „์†กํ•˜๊ธฐ ๋•Œ๋ฌธ์— CORS ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค .

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

๊ทธ๊ฒƒ ์—†์ด๋„ Content-Type: application/jsonํ—ค๋”๋Š” ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์—‡ โ€œํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธโ€์ˆ˜๋‹จ : ๋ธŒ๋ผ์šฐ์ €๊ฐ€๋ฅผ ์‹œ๋„ํ•˜๊ธฐ ์ „์— POST๋ฌธ์ œ์˜ ์ฝ”๋“œ์—์„œ, ๊ทธ๊ฒƒ์€ ๋จผ์ € ๋ณด๋‚ด๋“œ๋ฆฝ๋‹ˆ๋‹ค OPTIONS์„œ๋ฒ„์— ์š”์ฒญ์„ โ€“ ํฌ๋กœ์Šค ๊ธฐ์› ์ˆ˜์‹ ์— ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉ ์ค‘๋‹จ ๋œ ๊ฒฝ์šฐ ๊ฒฐ์ • POSTํฌํ•จ Authorizationํ•˜๊ณ  Content-Type: application/jsonํ—ค๋”๋ฅผ.

์ž‘์€ curl ์Šคํฌ๋ฆฝํŠธ์™€ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ „์†ก curlํ•˜๋Š” ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ OPTIONS์š”์ฒญ์„ ์—๋ฎฌ๋ ˆ์ดํŠธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค .

curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
    -H 'Access-Control-Request-Method: POST' \
    -H 'Access-Control-Request-Headers: Content-Type, Authorization' \
    "https://the.sign_in.url"

โ€ฆ https://the.sign_in.url์‹ค์ œ sign_inURL์ด ๋ฌด์—‡์ด๋“  ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค .

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด๋‹น OPTIONS์š”์ฒญ ์—์„œ ํ™•์ธํ•ด์•ผํ•˜๋Š” ์‘๋‹ต ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ—ค๋”๊ฐ€ ํฌํ•จ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Access-Control-Allow-Origin:  http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization

๊ฒฝ์šฐ OPTIONS์‘๋‹ต์ด ๊ทธ ํ—ค๋”๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š”, ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ฐ”๋กœ ๊ฑฐ๊ธฐ ์ค‘์ง€, ์‹ฌ์ง€์–ด ๋ณด๋‚ดํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค POST์š”์ฒญ์„. ๋˜ํ•œ ์‘๋‹ต์˜ HTTP ์ƒํƒœ ์ฝ”๋“œ๋Š” 2xx (์ผ๋ฐ˜์ ์œผ๋กœ 200 ๋˜๋Š” 204) ์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ƒํƒœ ์ฝ”๋“œ ์ธ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฐ”๋กœ ์ค‘์ง€๋ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ์˜ ์„œ๋ฒ„ OPTIONS๊ฐ€ 501 ์ƒํƒœ ์ฝ”๋“œ๋กœ ์š”์ฒญ์— ์‘๋‹ตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ์ง€์›์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์„ ์˜๋ฏธ OPTIONSํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์„œ๋ฒ„๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 405 โ€œMethod not allowedโ€์ƒํƒœ ์ฝ”๋“œ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ POST์„œ๋ฒ„ OPTIONS๊ฐ€ 405 ๋˜๋Š” 501 ๋˜๋Š” 200 ๋˜๋Š” 204 ์ด์™ธ์˜ ๋‹ค๋ฅธ ์š”์ฒญ์œผ๋กœ ํ•ด๋‹น ์š”์ฒญ์— ์‘๋‹ต ํ•˜๊ฑฐ๋‚˜ ํ•„์š”ํ•œ ์‘๋‹ต์œผ๋กœ ์‘๋‹ตํ•˜์ง€ ์•Š์œผ๋ฉด ํ”„๋ŸฐํŠธ ์—”๋“œ JavaScript ์ฝ”๋“œ์—์„œ ํ•ด๋‹น ์„œ๋ฒ„๋กœ ์ง์ ‘ ์š”์ฒญ ์„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ—ค๋”.

๋ฌธ์ œ์˜ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๋ฅผ ์œ ๋ฐœํ•˜์ง€ ์•Š๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์„œ๋ฒ„๊ฐ€ Authorization์š”์ฒญ ํ—ค๋”๋ฅผ ์š”๊ตฌํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  POST์š”์ฒญ ๋ณธ๋ฌธ์— ๋‚ด์žฅ ๋œ ์ธ์ฆ ๋ฐ์ดํ„ฐ ๋˜๋Š” ์ฟผ๋ฆฌ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ์˜์กด ํ•˜๋Š” ๊ฒฝ์šฐ
  • ์„œ๋ฒ„์— POST๋ณธ๋ฌธ์— Content-Type: application/json๋ฏธ๋””์–ด ์œ ํ˜• ์ด ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ ๋Œ€์‹  JSON ๋ฐ์ดํ„ฐ ๊ฐ’ ์„ ๊ฐ–๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜ (๋˜๋Š” ๊ธฐํƒ€)๋ฅผ ์‚ฌ์šฉ ํ•˜์—ฌ POST๋ณธ๋ฌธ์„ ์ˆ˜๋ฝ ํ•œ ๊ฒฝ์šฐapplication/x-www-form-urlencodedjson

์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š” โ€œ์•ก์„ธ์Šค ์ œ์–ด โ€“ ํ—ˆ์šฉ โ€“ ์›์‚ฐ์ง€ ํ—ค๋”๋Š” ์™€์ผ๋“œ ์นด๋“œ๊ฐ€ ์•„๋‹ˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹คโ€ ๋ฌธ์ œ

๋‹ค๋ฅธ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

์š”์ฒญ์˜ ์ž๊ฒฉ ์ฆ๋ช… ๋ชจ๋“œ๊ฐ€ โ€˜includeโ€™์ธ ๊ฒฝ์šฐ ์‘๋‹ต์˜ โ€˜Access-Control-Allow-Originโ€™ํ—ค๋” ๊ฐ’์ด ์™€์ผ๋“œ ์นด๋“œ โ€˜*โ€™๊ฐ€ ์•„๋‹ˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์›๋ณธ โ€˜ http://127.0.0.1:3000 โ€˜์€ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. XMLHttpRequest์— ์˜ํ•ด ์‹œ์ž‘๋œ ์š”์ฒญ์˜ ์ž๊ฒฉ ์ฆ๋ช… ๋ชจ๋“œ๋Š” withCredentials ์†์„ฑ์— ์˜ํ•ด ์ œ์–ด๋ฉ๋‹ˆ๋‹ค.

์ž๊ฒฉ ์ฆ๋ช…์ด ํฌํ•จ ๋œ ์š”์ฒญ์˜ ๊ฒฝ์šฐ Access-Control-Allow-Origin์‘๋‹ต ํ—ค๋” ๊ฐ’์ด ์ธ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ”„๋ŸฐํŠธ ์—”๋“œ JavaScript ์ฝ”๋“œ๊ฐ€ ์‘๋‹ต์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค *. ๋Œ€์‹ ์ด ๊ฒฝ์šฐ์˜ ๊ฐ’์€ ํ”„๋ก ํŠธ ์—”๋“œ ์ฝ”๋“œ์˜ ์›์ ๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค http://127.0.0.1:3000.

์ฐธ์กฐ ์ž๊ฒฉ์žˆ๋Š” ์š”์ฒญ๊ณผ ์™€์ผ๋“œ ์นด๋“œ MDN์ด HTTP ์•ก์„ธ์Šค ์ œ์–ด (CORS) ๊ธฐ์‚ฌ๋ฅผ.

์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์„œ๋ฒ„๋ฅผ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๊ฒฝ์šฐ์ด ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ Origin์š”์ฒญ ํ—ค๋” ์˜ ๊ฐ’์„ ๊ฐ€์ ธ ์™€์„œ Access-Control-Allow-Origin์‘๋‹ต ํ—ค๋” ์˜ ๊ฐ’์œผ๋กœ ์—์ฝ” / ๋ฐ˜์˜ํ•˜๋Š” ์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, nginx์˜ ๊ฒฝ์šฐ :

add_header Access-Control-Allow-Origin $http_origin

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ํ•˜๋‚˜์˜ ์˜ˆ์ผ๋ฟ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ (์›น) ์„œ๋ฒ„ ์‹œ์Šคํ…œ์€ ์›์  ๊ฐ’์„ ๋ฐ˜ํ–ฅํ•˜๋Š” ์œ ์‚ฌํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


Chrome์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ทธ Chrome CORS ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

Chrome CORS ํ”Œ๋Ÿฌ๊ทธ์ธ Access-Control-Allow-Origin: *์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ณด๋Š” ์‘๋‹ต์— ํ—ค๋”๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค . ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๋” ๋˜‘๋˜‘ํ•˜๋‹ค๋ฉด, ๊ฐ€์งœ Access-Control-Allow-Origin์‘๋‹ต ํ—ค๋” ์˜ ๊ฐ’์„ ํ”„๋ก ํŠธ ์—”๋“œ JavaScript ์ฝ”๋“œ์˜ ์‹ค์ œ ์›์ ์œผ๋กœ ์„ค์ •ํ•˜๋ฉด http://127.0.0.1:3000๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ…Œ์ŠคํŠธ์—๋„ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์‚ฐ๋งŒ์ž…๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‘๋‹ต์„ ํ•„ํ„ฐ๋งํ•˜์ง€ ์•Š๊ณ  ์„œ๋ฒ„์—์„œ ์–ด๋–ค ์‘๋‹ต์„ ์–ป๋Š” ์ง€ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด curl -H์œ„์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค .


fetch(โ€ฆ)์งˆ๋ฌธ ์˜ ์š”์ฒญ์— ๋Œ€ํ•œ ํ”„๋ก ํŠธ ์—”๋“œ JavaScript ์ฝ”๋“œ๊นŒ์ง€ :

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');

๊ทธ ์ค„์„ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค. Access-Control-Allow-*ํ—ค๋”๋Š” ์‘๋‹ต ํ—ค๋”. ๋‹น์‹ ์€ ์š”์ฒญ์— ๊ทธ๋“ค์„ ๋ณด๋‚ด๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์œ ์ผํ•œ ํšจ๊ณผ๋Š” ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.


๋‹ต๋ณ€

์ด ์˜ค๋ฅ˜๋Š” ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ํฌํ•จํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ URL๊ณผ ์„œ๋ฒ„ URL์ด ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ต์ฐจ ์ถœ์ฒ˜ ์ž์› ๊ณต์œ  ์ธ CORS์— ๋Œ€ํ•ด ์„œ๋น„์Šค๋ฅผ ํ™œ์„ฑํ™”ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Spring REST ์„œ๋น„์Šค๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฒฝ์šฐ Spring Framework ์˜ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ CORS ์ง€์›์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .

Node.js ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋น„์Šค๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฒฝ์šฐ

  1. Node.js ์„œ๋ฒ„๋ฅผ ์ค‘์ง€ํ•˜์‹ญ์‹œ์˜ค.
  2. npm install cors --save
  3. server.js์— ๋‹ค์Œ ์ค„์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

    var cors = require('cors')
    
    app.use(cors()) // Use this after the variable declaration

๋‹ต๋ณ€

ํ”„๋ก ํŠธ ์—”๋“œ์—์„œ ์š”์ฒญ ํ—ค๋” ๋กœ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค .

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');

์ด๋Ÿฌํ•œ ํ—ค๋”๋Š” ์š”์ฒญ์ด ์•„๋‹Œ response ์— ์†ํ•ฉ๋‹ˆ๋‹ค . ๋”ฐ๋ผ์„œ ๋ผ์ธ์„ ํฌํ•จํ•˜์—ฌ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค .

headers.append('GET', 'POST', 'OPTIONS');

๊ท€ํ•˜์˜ ์š”์ฒญ์— โ€˜Content-Type : application / jsonโ€™์ด ์žˆ์—ˆ์œผ๋ฏ€๋กœ CORS ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ OPTIONS ๋ฉ”์†Œ๋“œ๋กœ ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ CORS ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.
๋”ฐ๋ผ์„œ ๋ฐฑ์—”๋“œ ์—์„œ๋Š” ๋‹ค์Œ์„ ํฌํ•จํ•˜๋Š” ์‘๋‹ต ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ์ด ํ”„๋ฆฌ ํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Access-Control-Allow-Origin : http://localhost:3000
Access-Control-Allow-Credentials : true
Access-Control-Allow-Methods : GET, POST, OPTIONS
Access-Control-Allow-Headers : Origin, Content-Type, Accept

๋ฌผ๋ก  ์‹ค์ œ ๊ตฌ๋ฌธ์€ ๋ฐฑ์—”๋“œ์— ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

ํ”„๋ŸฐํŠธ ์—”๋“œ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

function performSignIn() {
    let headers = new Headers();

    headers.append('Content-Type', 'application/json');
    headers.append('Accept', 'application/json');
    headers.append('Authorization', 'Basic ' + base64.encode(username + ":" +  password));
    headers.append('Origin','http://localhost:3000');

    fetch(sign_in, {
        mode: 'cors',
        credentials: 'include',
        method: 'POST',
        headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

๋‹ต๋ณ€

๋‚ด ๊ฒฝ์šฐ์—๋Š” ์•„๋ž˜ ์†”๋ฃจ์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋ŸฐํŠธ ์—”๋“œ ๋˜๋Š” ์•ต๊ทค๋Ÿฌ

post(
    this.serverUrl, dataObjToPost,
    {
      headers: new HttpHeaders({
           'Content-Type':  'application/json',
         })
    }
)

๋ฐฑ์—”๋“œ (PHP๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค)

header("Access-Control-Allow-Origin: http://localhost:4200");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header("Access-Control-Allow-Headers: Content-Type, Authorization");

$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
print_r($request);

๋‹ต๋ณ€

CORS ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌโ€œ ํ—ค๋” ์—†์Œ โ€๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๊ด€ํ•œ 2 ์„ผํŠธAccess-Control-Allow-Origin

๋ฐฑ์—”๋“œ์—์„œ PHP๋กœ ์ž‘์—…ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด โ€œCORS ํ”„๋ก์‹œโ€๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

  1. ๋‹ค์Œ ๋‚ด์šฉ์œผ๋กœ โ€˜no-cors.phpโ€™๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    $URL = $_GET['url'];
    echo json_encode(file_get_contents($URL));
    die();

  2. ํ”„๋ก ํŠธ ์—”๋“œ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ดํ•˜์‹ญ์‹œ์˜ค.

    fetch('https://example.com/no-cors.php' + '?url=' + url)
    .then(response=>{*/Handle Response/*})


๋‹ต๋ณ€

์ด๊ฒƒ์„ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค :

credentials: 'include',

๋‹ต๋ณ€

์‚ฌ์šฉํ•˜๋Š” dataType: 'jsonp'๋‚  ์œ„ํ•ด ์ผํ–ˆ์Šต๋‹ˆ๋‹ค.

   async function get_ajax_data(){
       var _reprojected_lat_lng = await $.ajax({
                                type: 'GET',
                                dataType: 'jsonp',
                                data: {},
                                url: _reprojection_url,
                                error: function (jqXHR, textStatus, errorThrown) {
                                    console.log(jqXHR)
                                },
                                success: function (data) {
                                    console.log(data);

                                    // note: data is already json type, you
                                    //       just specify dataType: jsonp
                                    return data;
                                }
                            });


 } // function               

์ด ๊ธ€์€ Javascript ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๋ถ„๋ฅ˜๋˜์—ˆ๊ณ  ๋‹˜์— ์˜ํ•ด ์— ์ž‘์„ฑ๋์Šต๋‹ˆ๋‹ค.