프론트엔드 netlify 배포 (cors)
프론트엔드와 백엔드의 도메인 주소가 다른 경우 cors 문제가 생기는데 로컬에서 이를 해결하기 위해 프론트 쪽에서 proxy 설정을 해두어 cors 문제를 해결했었다. 하지만 netlify에 배포한 뒤에는 cors 에러가 아닌 계속 404에러가 나타났다. 다시 로컬로 돌아가서 확인해보니 또 cors 문제없이 서버와의 통신이 가능했다. cors 에러가 아닌 404에러 메시지 나타나기 때문에 해결하는 데 굉장히 어려움이 있었다. 로컬에서는 아무 이상 없이 돌아갔기 때문에 왜 이런 에러가 나타나는지 이해할 수 없었다. 어쨌든 서버와 통신을 할 수 없었고 proxy 설정이 뭔가 잘못돼서 404에러는 나타내는 게 아닌가 생각했다. 이리저리 많은 블로그나 문서에 나와있는 여러 가지 방법을 모두 시도해보았지만 해결되지 않았다. 그렇게 계속 시도한 끝에 스택오버플로우에서 netlify에서는 cors 문제를 서버에서 해결해 주어야 한다는 글을 보았다. 개인 프로젝트를 진행했었을 때에도 netlify로 프론트엔드쪽 배포를 했었는데 cors 문제를 서버에서 해결했었다. 이번 프로젝트의 경우 proxy로 cors 문제를 해결했었고 proxy로 문제를 해결하고 싶었는데 결국 netlify에서 배포 후 서버와 통신하기 위해서는 cors 문제를 서버에서 해결해 주어야 했었다.
다른 도메인간 쿠키 전송하기(credentials)
서버에서 cors 문제를 해결한 후 프론트와 서버 간의 쿠키 전송이 되지 않아 로그인을 할 수 없었다. 요청과 응답에 헤더를 설정해 준 뒤 쿠키 전송에 성공하였다. 서버에서 origin을 허용하고 클라이언트와 서버 모두 Credentials를 활성화해야 한다.
server
Access-Control-Allow-Origin
요청을 보내는 프론트 주소와 응답을 보내는 백엔드 주소가 다른경우 cors에러가 발생한다. 이 때, 서버에서 응답메시지로 Access-Control-Allow-Origin에 허용할
클라이언트 주소
또는*
을 적어 주어야 에러가 나지 않는다.*
을 명시해 줄 경우 모든 요청을 보내는 모든 프론트 주소를 허용한다는 의미이다. 이렇게*
을 명시해줄 경우 모든 요청을 허용하기 때문에 보안에 취약해질 수 있다.- 다른 도메인간 쿠키를 전송하기 위해서 Access-Control-Allow-Origin에
*
(와일드 카드)를 사용할 수 없다. 허용할origin
또는true
를 명시해야한다.
- 다른 도메인간 쿠키를 전송하기 위해서 Access-Control-Allow-Origin에
Access-Control-Allow-Credentials은
true
로 설정한다.
1
2
3
4
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header('Access-Control-Allow-Methods', 'POST, PUT, GET, DELETE');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
1
- cors 미들웨어를 사용할 경우
1
2
3
4
5
6
7
app.use('/user', cors({
orgin: <허용할 클라이언트 주소>, // or true
methods: ['POST', 'GET', 'PUT', 'DELETE', 'PATCH'], // 허용할 메소드
credictials: true,
allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization'],
}), userRouter);
client
클라이언트에서도 요청을 보낼 때, 헤더에 Credentials를 활성화해야한다. 클라이언트에서 헤더에 Credentials 활성화를 한 후 요청을 보내는 데이 아래의 세 가지 방법을 사용했었다. 다른 블로그에서는 첫 번째나 두번째 방법으로 해결이 되었지만 나 같은 경우 마지막 방법으로 해결이 되었다. 세 가지모두 같은 의미이긴 한데.. 디폴트로 설정한 후 해결이 되었다.
- axios.create({withCredentials: true})
1
2
3
4
5
6
7
8
9
10
11
12
import axios from 'axios';
const api = axios.create({
withCredentials: true
});
api.get('/')
.then((res) => {
console.log(res)
})
.catch(err => console.error(err))
- withCredentials: true 를 설정한 후 요청을 보낸다.
1
2
3
4
5
6
7
import axios from 'axios';
axios.get('/', { withCredentials: true })
.then((res) => {
console.log(res)
})
.catch(err => console.error(err))
- default로 설정한다. (index.js 에 한번만 설정해 주어도 된다.)
1
2
3
import axios from 'axios';
axios.defaults.withCredentials = true;