본문 바로가기

Node.js

Node.js - CORS (Cross-Origin Resource Sharing)

CORS를 제대로 이해해 보자.

 

 

Access-Control-Allow-Origin

Access-Control-Allow-Origin 에러는 Access-Control-Allow-Origin이라는 헤더가 없다는 내용의 에러이다. 브라우저와 서버의 도메인이 일치하지 않으면 기본적으로 요청이 차단이 된다. 이 현상은 브라우저에서 서버로 요청을 보낼 때 만 발생을 하고, 서버에서 서버로 요청을 보낼 때는 발생하지 않는다.

 

위 로그는 실제 Access-Control-Allow-Origin 에러가 뜨는 경우이다.

보면 토큰의 Method가 POST 대신 OPTIONS로 표시되는 것을 볼 수 있다. OPTIONS 메서드는 실제 요청을 보내기 전 서버가 이 도메인을 허용하는지 체크하는 역할을 한다.

 

CORS 문제를 해결하기 위해서는 응답 헤더에 Access-Control-Allow-Origin 헤더를 넣어야 한다. 이 헤더는 클라이언트 도메인의 요청을 허락하겠다는 뜻을 가지고 있다. res.set 메서드로 직접 넣어도 좋지만, npm에는 편하게 설치할 수 있는 패키지가 있다. 바로 cors이다.

 

응답 헤더의 조작을 위해선 클라이언트 사이드가 아니라 API 서버에서 바꿔야 한다. 응답은 API 서버가 보내는 것이기 때문이다.

 

cors 모듈을 설치하고 사용해보자.

 

const cors = require('cors');

...

router.use(cors({
    credentials: true
}));

 

위와 같이 사용해주면 모든 라우터에 적용이된다. 이제 응답에 Access-Control-Allow-Origin 헤더가 추가되어 나간다. credentials: true 라는 옵션은 다른 도메인 간에 쿠키 공유를 허락하는 옵션이다. 서버 간 도메인이 다른 경우 이 옵션을 활성화하지 않으면 로그인되지 않을 수 있다. 참고로 axios에서도 도메인이 다른데, 쿠키를 공유해야 하는 경우 withCredentials: true 옵션으로 요청을 보내야 한다.

 

위 사항을 적용하고 다시 클라이언트 사이드에서 응답 헤더를 보면,

 

Access-Control-Allow-Origin이 *로 되어있는데, 이는 모든 클라이언트의 요청을 허용한다는 뜻이다. Access-Control-Allow-Credentials도 true로 되어있는데, 이는 위에서 credentials: true 옵션을 넣어주었기 때문이다.

 

프록시 서버

CORS 문제를 해결하는 또 다른 방법으로 프록시 (대리인) 서버를 사용하는 것이 있다. 서버에서 서버로 요청을 보낼 때는 CORS 문제가 발생하지 않는다는 것을 이요한 방법이다.

 

프록시 서버는 브라우저와 도메인이 같은 서버를 만든 후, 브라우저에서는 API 서버 대신 프록시 서버에 요청을 보낸다. 그 후, 프록시 서버에서 요청을 받아 다시 API 서버로 요청을 보낸다. 서버-서버 간의 요청이므로 CORS 문제가 발생하지 않는다.

 

프록시 서버는 직접 구현할 수도 있다. 그러나 http-proxy-middleware 같은 패키지를 사용하면 쉽게 익스프레스와 연동할 수 있다.

 

 

출처

Node.js 교과서 개정 2판 - 길벗, 조현영