6번의 CEOS 백엔드 스터디가 끝나고, 프론트엔드와 백엔드의 합동 스터디만 남았다
이번 과제는 '17기 파트장 및 데모데이 투표 서비스' Django 서버를 배포하는 것!
이번 포스팅은 트러블슈팅 위주로 작성해보겠다
API 문서화를 하기 위해 swagger를 사용했다
로컬에서 http://127.0.0.1:8000/swagger/ 로 접속했을 때 내가 작성한 api들이 잘 뜨는 것을 확인하고 서버를 배포하였다
하지만 이게 웬일~!
배포하고 나니 Swagger UI가 보이지 않고 흰 창이 떴다
Postman으로 요청하니 404 Not Found...
구글링해보니 swagger의 static 파일들을 nginx가 찾지 못 해서 발생한 에러였다
# settings/base.py
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR,'static')
settings/base.py의 STATIC_URL 밑에 STATIC_ROOT를 추가해준다
STATIC_ROOT는 웹서버가 정적파일에 접근하는 경로이다
# urls.py
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
그리고 urls.py에 해당 경로를 추가해준다
# nginx.conf
location /static/ {
alias /home/app/web/static/;
}
배포를 위해 작성한 nginx.conf 파일을 살펴보면 위와 같은 코드가 있다
프로젝트의 정적 파일들은 모두 /home/app/web/static/
에 저장될 것이다
그리고 docker 실행 쉘스크립트를 보면
python manage.py collectstatic --no-input
이렇게 static 파일들을 모아서 static 폴더에 저장하는 명령어가 있다
이렇게 설정이 끝나고 재배포 했더니
이렇게 UI가 정상적으로 떴다
컨테이너를 확인해보니 이렇게 swagger static 파일들이 폴더에 잘 들어가 있었다~!
Postman으로 API 테스트를 하고 정상 동작 하길래 서버를 배포했더니,
Access to XMLHttpRequest at 'https://takgyun.shop/votes/candidates/fe/' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
프론트엔드 측에서 다음과 같은 에러 코드와 함께 CORS 에러가 뜬다고 하셨다ㅜㅜ
로컬 리액트에서 api 요청을 하면서 발생한 에러 같았다
% pip install django-cors-headers
django-cors-headers 설치 후
# settings/base.py
INSTALLED_APPS = [
...
'corsheaders',
...
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
...
'django.middleware.common.CommonMiddleware',
...
]
CORS_ORIGIN_ALLOW_ALL = True
이렇게 설정하고 재배포
이렇게 끝난 줄 알았지만, 여전히 CORS 에러가 발생
그래서 찾아보았더니 Access-Control-Allow-Origin이 와일드카드(*)로 명시되어 있으면 Cookie를 통해 인증 정보를 주고받을 수 없다고 한다
# settings/base.py
CORS_ORIGIN_ALLOW_ALL = True
문제의 코드 ㅎㅎ
# settings/base.py
# CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
"https://example.com",
"https://example.store",
"http://localhost:3000",
"http://127.0.0.1:8000"
)
CORS_ORIGIN_ALLOW_ALL = True
코드를 지우고 Origins를 따로 명시해주었다
그리고 Cookie를 사용할 수 있도록
CORS_ALLOW_CREDENTIALS = True
설정도 추가!
이는 Cookie, Authorization header와 같은 User Credentials를 요청에 포함할 것인지에 대한 설정이다
설정 후 재배포 했더니 프론트엔드에서 요청 성공! 히히
로컬 리액트에서는 잘 되는데 왜 Swagger에서는 안 되는 것인가...!
살펴보았더니 Swagger의 Schemes가 HTTP
로 설정되어있었다 후^^
# settings/base.py
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# urls.py
schema_view = get_schema_view(
openapi.Info(
...
url="https://takgyun.shop/", # 추가
...
),
)
이렇게 추가!
Schemes가 HTTPS
로 바뀌고, CORS 에러도 뜨지 않았다
6번의 CEOS 스터디의 총 집합체였던 이번 미션...
지난 스터디를 하며 레퍼런스를 잘 정리해둬서 다행이라고 생각했다
서버 배포도 여러 번 해보니 확실히 인사이트가 생긴 것 같다
이번 미션을 통해 Django와 Swagger를 처음 연결해보았는데 조금(많이) 에러를 겪었다 그래도 해결해서 뿌듯~!