react - django, cors 문제. django-cors-headers를 깔아도 문제가 발생할 때

     

지옥의 CORS

리액트를 조금만 하다 보면 지옥의 CORS문제와 만나게 된다. CORS는 Cross-Origin Resource Sharing의 약자로 프론트엔드가 백엔드로 요청할 때 프론트와 백엔드의 도메인이 다르면 발생하는 문제다. 근데 이건 프론트엔드에서 발생하는 게 아니라 브라우저에서 발생한다.

 

따라서 django로 rest api 서버를 만들었을 때, 모바일 앱에서는 rest 호출이 정상적으로 되지만 프론트엔드(react, vue, angular,..)에서는 에러가 날 수 있다. 왜냐하면 도메인이 다르기 때문! 참고로 모바일 앱에서도 웹뷰를 띄워서 호출한다면 동일한 문제가 발생한다. 왜냐하면 웹뷰의 근원은 브라우저니까.

 

 

 

django와 react를 쓸 때 보통 이런 문제가 발생하면 django에 django-cors-headers 패키지를 설치하고 settings.py middleware쪽에 추가해주면 별 탈 없이 문제를 해결할 수 있다. (사실 문제를 해결한다기보다 그냥 cors설정을 우회한다 느낌?)

 

pip install django-cors-headers를 해주고 settings.py에 아래와 같이 추가한다.

 

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
	...
]


CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = False

CORS_ORIGIN_ALLOW_ALL = True를 하게 되면 모든 도메인을 허용하게 된다. 혹시 특정 도메인만 추가하고 싶으면 아래와 같이 화이트리스트를 만들어 관리할 수 있다.

CORS_ORIGIN_WHITELIST = (
    'localhost:3000',
    '127.0.0.1:3000'
)

 

이제 다시 호출해보면 cors문제가 해결된 것을 확인할 수 있다.

 

 

 

 

 

하지만 HTTP 콜에 헤더 값을 추가하면 어떨까?

 

그렇게 잘 쓰고 있었는데, react에서 axios를 이용해 rest call을 할 때 http 헤더에 값을 좀 넣어서 보내려고 했더니 다시 cors오류가 나더군요 ㅡㅡ?!

 

그래서 뭔 짓을 해도 안되길래 react에서 proxy를 사용해 해결했습니다. 

 

먼저 npm install http-proxy-middleware를 설치해줍니다.

 

요걸 깔아야합니다.

 

그리고 src 경로 아래 setupProxy.js를 만들어주고 아래와 같이 코드를 입력합니다.

 

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
    app.use(
        '/todo',
        createProxyMiddleware({
            target: 'http://localhost:8000',
            changeOrigin: true,
        })
    );
};

 

여기서 /todo의 경우 제 백엔드 url이 ~/todo이기 때문에 이렇게 적었고, target은 백엔드 주소를 적으면 됩니다. 저는 django가 8000번 포트로 떠있기 때문에 http://localhost:8000으로 적었습니다.

 

이제 api를 호출하는 소스에 가서 axios 호출 안에 url을 바꿔줍니다.

 

export async function PostCreateEx4(inputUserId, inputName){
    const headers = {
        'id': inputUserId,
        'version': '1.1'
    }
    const response = await axios.post(
//        'http://localhost:8000/todo/create',{
            '/todo/create',{
            user_id:inputUserId,
            name:inputName
        },{headers});
    return response.data;
}

 

풀 url을 그냥 /todo로 시작하게 바꿔주면 위에 세팅해놓은 proxy를 타고 가기 때문에 cors오류가 안 납니다. 왜 헤더를 추가하면 django-cors-header가 안 먹는지 이유는 모르지만 아마 django-cors-header 소스를 까 보면 헤더에 모르는 필드가 있을 경우 튕기게 해놨나 봅니다 ㅋㅋ 아무튼 이 문제 때문에 2시간 정도 고생하다가 이제는 해결!!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

댓글

Designed by JB FACTORY