[Django] CORS에 대해 알아보고 Django 프로젝트에 설정하기

김동욱·2024년 3월 7일

Django

목록 보기
3/6
post-thumbnail

CORS에 살펴보기

CORS란

CORS란 Cross-Origin Resource Sharing의 약자로, 서로 다른 출처(origin) 간에 자원을 공유할 수 있도록 하는 메커니즘이다. 브라우저에서는 보안상의 이유로 동일 출처 보안 정책(Same-Origin Policy)을 따르는데, 이는 다른 출처에서 온 요청에 대한 자원 접근을 제한한다. CORS는 이 정책을 우회하고 다른 출처 간의 통신을 가능하게 한다.

출처(origin)는 Protocal, Host, Port의 조합을 의미한다. 세가지 요소 중 하나라도 다르다면 다른 출처이다.

CORS 동작 방식

프리플라이트 요청(Preflight Request)

프리플라이트 요청은 실제 요청 전에 브라우저가 보내는 추가적인 요청이다. 주로 브라우저가 서버에게 실제 요청을 보내기 전에 해당 요청이 안전한지 여부를 확인하기 위해 사용된다.

프리플라이트 요청의 흐름은 다음과 같다.

  1. 브라우저는 실제 요청을 보내기 전에 OPTIONS 메서드를 사용하여 서버에게 프리플라이트 요청을 보낸다.
  2. 서버는 프리플라이트 요청을 받고, 요청이 안전한지 확인한 후 허용할지 여부를 결정한다.
  3. 서버는 Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers 등의 CORS 관련 헤더를 포함하여 응답한다.
  4. 브라우저는 프리플라이트 응답을 확인하고, 허용된 경우 실제 요청을 보낸다.

단순 요청(Simple Request)

단순 요청은 프리플라이트 요청을 거치지 않고 직접 서버에게 보내는 요청이다. 이는 브라우저가 복잡한 요청이 아니라고 판단하는 경우에 발생한다.

단순 요청은 아래의 상황에서 발생한다.

  • HTTP 메서드는 GET, POST, HEAD 중 하나여야 한다.
  • 헤더로 Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width만 사용할 수 있다.
  • Content-Type 헤더는 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나를 사용해야 한다.

단순 요청의 흐름은 다음과 같다.

  1. 브라우저는 서버에게 실제 요청을 보낸다.
  2. 서버는 해당 요청을 받고, CORS 허용 정책에 따라 응답한다.

Django 프로젝트에 CORS 설정하기

CORS 패키지 설치

Django 앱에서 CORS 헤더를 쉽게 관리할 수 있도록 하기 위해 아래의 패키지를 설치한다.

pip install django-cors-headers

설정 변경하기

현재 진행 중인 프로젝트는 설정을 base.py, dev.py, prod.py 각각으로 나눠서 진행 중이다. base.py의 내용을 각 환경의 설정 파일에서 import 후 추가적인 설정을 한다.

base.py(settings.py)

설정 파일에 패키지 추가해야 한다. base.py(settings.py) 파일에 corsheaders를 앱에 추가하고, 미들웨어를 등록한다.

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

참고로 CorsMiddleware는 반드시 CommonMiddleware보다 위에 위치해야 한다.

dev.py

dev 환경에서는 다양한 출처에서 요청을 테스트할 수 있는 유연성을 제공해야 하기 때문에 모든 출처(origin)에서 오는 요청들을 허용한다. 아래의 설정을 추가한다. 참고로 default 설정은 False이다.

CORS_ORIGIN_ALLOW_ALL = True

prod.py

운영 환경에서는 CORS_ALLOWED_ORIGINS 설정을 통해 해당 서버에 요청을 할 수 있는 origin을 명시할 수 있다. 아래와 같이 uri scheme, hostname, port를 조합하여 명세한다.

CORS_ALLOWED_ORIGINS = [
    "https://example.com",
    "https://www.example.com",
    "http://www.example.com",
]

추가적인 설정을 통해 Cross-Origin Resource Sharing (CORS) 정책을 더 세부적으로 제어할 수 있다. 이러한 설정은 특정 HTTP 메소드와 헤더에 대한 접근을 제한하여 웹 애플리케이션의 보안을 강화할 수 있다.

  • CORS_ALLOW_METHODS
    CORS_ALLOW_METHODS 설정은 서버가 허용하는 CORS 요청의 HTTP 메소드를 정의한다. 이 설정을 사용하여 API 엔드포인트는 POST나 PUT 요청만을 허용하도록 제한할 수 있다. 불필요한 메소드에 대한 접근을 차단함으로써 보안을 강화할 수 있다.
  • CORS_ALLOW_HEADERS
    CORS_ALLOW_HEADERS는 서버가 허용하는 특정 HTTP 헤더를 명시한다. 이 설정은 클라이언트가 API로 전송할 수 있는 헤더를 제한할 때 사용된다. 특히, 보안과 관련된 헤더들(Authorization, X-CSRFToken)에 대한 접근을 통제하여 보안을 강화할 수 있다.

아래는 위에서 언급한 설정의 기본값이다. 추가적인 허용 및 제한을 위하여 설정 파일에 새로 작성하여 기존의 기본 설정을 덮어쓸 수 있다.

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
)

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)




참고 자료

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS#%EA%B8%B0%EB%8A%A5%EC%A0%81_%EA%B0%9C%EC%9A%94

profile
안녕하세요! 질문과 피드백은 언제든지 환영입니다:)

0개의 댓글