모바일/Javascript

[Node.js] CORS 설정(Cross Domain 요청 허용)

박종명 2016. 7. 15. 21:45
728x90

웹은 기본적으로 '동일출저정책(Same Origin Policy, SOP)' 정책을  따른다.

이는 보안을 위한 기본정책으로, SOP는 하나의 출처(Origin)에서 로드된 문서나 스크립트가 다른 출처에 존재하는 리소스와 상호작용하지 못하도록 제약을 두는 것이다.

그런데, 간혹 이런 제약이 웹 응용프로그램을 만드는데 걸림돌이 되기도 한다.
Ajax 통신이 활발해 지고, 다른 사이트에 존재하는 Open API와 상호통신이 필요한 경우와 매쉬업(Mash-up)으로 새로운 2차 응용물을 개발하게 되면서.. 등등.. 이는 간혹 걸림돌이 된다.

근래 Node.JS로 서버를 만들고, Aptana Studio 자체 내장 웹서버로 몇 가지 테스트를 하고 있는데, 두 환경은 서로 다른 별도의 포트(Port)에서 웹을 동작시키기 때문에 여지없이 Cross Domain 문제가 발생한다.


호출하는 모든 웹 리소스를, Node.JS로부터 다운로드 받아서 실행하는 구조로 HTTP 서버를 구현하면 SOP 정책을 따를 수 있겠으나, 그렇지 못한 개발환경도 있을 터이고, 실제 서비스 환경에서는 더욱이 서로 다른 도메인(포트 포함)간 상호작용이 필요할 것이다.

SOP 정책을 우회하기 위해서는, 서버 측의 설정이 필요한데, 위 그림에서 친철히 안내하고 있는 것처럼 Access-Control-Allow-Origin 헤더, 즉 크로스 도메인으로 허용할 도메인 목록이 헤더로 제공되어야 한다.
이것을 CORS(Cross-Origin Resource Sharing)를 이용한 SOP 정책 우회라 한다.

Node.JS 환경에서 이 설정을 해보자.
다음과 같이, Node 기반 HTTP 서버의 응답헤더에 추가 해준다.

가장 중요한 설정은, Access-Control-Allow-Origin으로 허용할 도메인(포트)을 추가한다.
여러 도메인이 있을 경우, 중복해서 지정을 하거나 '*' 를 이용해 전체 허용도 가능하다.

var app = require("express")();

app.use(function(req, res, next) {
 res.header("Access-Control-Allow-Origin", "
http://127.0.0.1:8020");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    next();
});

app.get('/users', function(req, res) { 
 var tempUsers = [{id:'park', city:'pusan'}, {id:'kim', city:'seoul'}]; 
    res.send(tempUsers);
});

app.listen(3002);
console.log("Listening on port 3002");

참고로 127.0.0.1:8020 도메인은, 필자의 Aptana Studio가 생성한 임의 주소이다.

이렇게 설정한 후, 클라이언트에서 요청하면 요청이 성공적으로 이뤄진다.

- 이 코드가 포함된 페이지는 127.0.0.1:8020 에 호스팅되어 동작한다.
<script>
window.onload = function(){
 var xhr = new XMLHttpRequest();
 xhr.onload = function(){
  console.log(xhr.response);  
 }; 
 xhr.open("GET", "http://127.0.0.1:3002/users");
 xhr.send();
}; 
</script>

그리고 언제나 그렇듯이 확장 라이브러리도 있다.
cors라는 이름의 Node.JS 확장인데, npm을 통해 설치하고 간단히 다음처럼 사용할 수 있다. 훨씬 간편하다.

var app = require("express")();

var cors = require('cors')();
app.use(cors);

그래도 언제나 보안은 중요한 문제이니, SOP 정책에 존중하면서, 필요시 아주 제한적으로 적용하는 것을 권장함.