[ SOP ]
- CORS를 이해하기 전에 먼저 SOP에 대해 알아 보자.
- SOP는 same origin policy의 약자로 같은 origin끼리만 통신을 허용하는 것을 의미한다.
- 여기서 Origin이란 url의 구성요소 중에서 proptocol, host, port를 합친 부분을 의미한다.
- 예를 들어 네이버 스포츠에 들어가 보면 url이
https://sports.news.naver.com/news?oid=343&aid=0000122713 이렇게 되어 있는 것을 확인할 수 있다.
- 여기서 https부터 com까지가 Origin이다.(포트번호는 생략이 되어있는 상태이다) Origin만 같다면 그 뒷 부분이 달라도 같은 출처로 인식 된다.
[ SOP가 왜 필요하지? ]
- 예를들어 우리가 네이버라는 웹 사이트롤 볼 수 있는 이유는 네이버의 서버에서 데이터를 보내 줬기 때문이다. 그런데 만약에 악의적인 누군가가 나인척을 하고 데이터를 요청하여 내 정보를 가져 가면 안되기 때문에 SOP라는 정책이 있는 것이다.
[ CORS? ]
- CORS는 Cross Origin Resource Sharing의 약자다.
- 직역 해 보면 "교차 출처 자원 공유"라는 긍정적인 의미이다. 즉, CORS 에러가 발생을 했다는 것은 SOP정책으로 인해 접근할 수 없으니 접근 하고 싶다면 CORS정책을 따르게 만들어라는 의미이다.
[ CORS 에러 동작 원리 ]
- 먼저 Origin을 비교해서 다른 Origin이면 Cors 에러를 띄우는 주체는 브라우저다.
- 따라서 브라우저가 어떻게 Cors에러를 발생시키는지 알아 보자.
- 먼저 첫번째로 클라이언트에서 HTTP 프로토콜을 이용하여 서버에 요청을 보내게 될 것인데, 이때 브라우저는 request 헤더에 현재 Origin을 넣어서 보내게 된다.
- 요청을 받은 서버는 응답 헤더에 전달받은 Origin을 Access-Control-Allow-Origin이라는 필드에 넣어서 보내 주게 된다.
- 이렇게 데이터를 전달 받은 브라우저는 자신이 보냈던 Origin과 Access-Control-Allow-Origin에 담긴 Origin을 비교해서 같으면 통과 시키고, 다르면 Cors 에러를 발생시킨다.
[ CORS에러 해결 방법 ]
- CORS 에러의 해결 방법은 크게 2가지로 볼 수 있다.
- 첫번째는 서버에서 허용할 Origin을 지정해 주는 방법
- 두번째는 Proxy 서버를 이용하는 방법이다.
1. 서버에서 CORS 에러 해결
- 서버에서 Access-Control-Allow-Origin의 헤더에 허용할 Origin을 담아서 응답하면 된다.
// 이렇게 해주면 locoalhost:3000포트에서 온 요청에 대한 응답에 브라우저가 접근할 수 있다.
Access-Control-Allow-Origin : https://localhost:3000
// 접근을 허용할 http 메서드도 지정할 수 있다.
Access-Control-Request-Methods : GET, POST, PUT, DELETE
// 클라이언트 요청에서 쿠키에 담긴 어떤 정보를 함께 보내줘야 한다면, 즉 credentials가 include일 때 요청에 대한 응답을 할 수 있는지를 나타낸다.
Access-Control-Allow-Credentials : true
const Server = http.createServer((req, res) => {
//😀 허용할 HTTP 메서드 지정
response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
//😀 허용할 Origin 지정
response.setHeader('Access-Control-Allow-origin', 'https://localhost:3000');
//😀 클라이언트와 서버 간에 쿠키 주고받기 허용
response.setHeader('Access-Control-Allow-Credentials', 'true');
//😀 상태 코드 보내기
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end('ok');
});
2. Proxy 서버 이용 하기
- CORS 에러는 브라우저에서 response를 차단 하여 발생하는 오류 이기 때문에, 서버와 서버사이의 요청과 응답에 대해서는 발생하지 않는다.
- 따라서 클라이언트, 즉 브라우저와 도메인이 같은 Proxy서버를 만들어서 브라우저는 Proxy서버에 Api요청을 하고 프록시 서버가 Api서버에 다시 요청을 하여 데이터를 받아 온 후 브라우저에 보내주는 방식이다.
2-1 package.json 파일에 proxy 설정
- cra로 만들어진 프로젝트 폴더의 package.json 파일에 proxy속성을 추가하고 여기에 api를 요청할 서버의 origin을 입력해 주면 된다.
- 그리고 클라이언트에서 get이나 post요청을 할 때는 endpoint만 작성하면 된다.
"proxy": "http://localhost:4000"
2-2 http-proxy-middleware
- 프록시 서버를 직접 구현하기 어렵 다면 http-proxy-middleware를 사용하여 익스프레스와 쉽게 연동할 수 있다.
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
//😀 어떤 endpoint의 요청에 대해 proxy할지 입력해 준다.
'/api',
createProxyMiddleware({
//😀 target에 Api서버의 Origin을 입력해 준다.
target: 'http://localhost:5000',
changeOrigin: true,
})
);
};