TIL. 최종프로젝트(13) 배포와 wss
[오늘 한일]
- 배포 진행
[오늘 배운점]
어제까지 배포는 3중 컨테이너 (장고, postgresql, nginx)를 동작시키고
웹서비스까지 구현했다.
오늘은 이어서 redis 컨테이너를 구성하고 웹소켓을 동작시키는걸 진행했다.
<웹소켓 wss로 올리기>
redis 컨테이너는 우리가 개발환경에서 사용하던 그대로를 설정하여 구동시켰다.
잘 구동되었다.
프론트 페이지를 열어서 웹소켓 요청을 보내 봤다.
1. 첫번째로 만난 에러는
Mixed Content: The page at "백엔드주소" was loaded over HTTPS 였다.
웹브라우저 콘솔창에 나오는 에러인데,
브라우저가 발생시키는 에러로 알고있다.
아래 내용을 읽어보니 HTTPS와 ws 통신이 혼합하여 사용되고 있다는 뜻이다.
그래서 ws를 wss로 업그레이드할 필요가 있었다.
ws를 wss요청으로 올리기 위해서는 JS 요청을 먼저 바꿔야 한다.
이는 뜻밖에도 아주 간단했다.
const chatSocket = new WebSocket(
"wss://" +
BACK_WEBSOCKET_URL +
js에서는 webSocket이라는 기능으로 웹소켓 통신을 제공한다.
webSocket유형이 정의되는 것 자체가 websocket연결을 요청하는 동작을 포함한다.
이때 원래 ws://주소로 요청하던것을 위처럼 wss://로만 바꿔주면,
websocket 기능이 알아서 wss요청으로 보내게 된다.
아주 간단하고 좋다.
그 다음으로는 요청을 받아들이는 부분이 바껴야 할것인데,
배포 아키텍처상으로 wss요청은 먼저 ELB를 만나게 된다.
HTTPS요청은 ELB를 만나고 ELB부터는 HTTP통신으로 EC2와 통신하게된다.
WSS요청도 ELB가 잘 받아들이고 내부로 넘겨줄지 궁금했다.
결론적으로 곧바로 잘 통신이 됬다.
결국 웹소켓 connect request또한 HTTP를 이용해 요청이 들어온다.
WSS는 HTTPS를 이용하게 된다.
결국 장고에까지 WSS통신이 잘 도달하게 되었다.
2. 두번째로 만난 문제는, Gunicorn이 WS통신과 HTTP통신을 구분하지 못한다는 점이였다.
웹브라우저 콘솔에서 웹소켓 커넥트가 성공하지 못했다는 메세지가 나왔다.
docker-compose logs를 보니,
통신 요청이 GET/ /ws/battle~~ 이런식으로 찍혔다.
원래는 WEBSOCKET/ ws/battle 이렇게 찍혀야 한다.
이걸 보고 나는 gunicorn이 웹소켓을 제대로 인식하고 라우팅하지 못하고 있다고 생각했다.
이렇게 포인트를 잡고 인터넷에 알아봤다.
우리가 개발단계에서는 Daphne라는,
장고 channels가 연결지원하는 특별 앱을 이용했다.
이는 장고 앱으로 설치후 사용을 위해서 settings.py에 선언되야 한다.
이 Daphne가 개발단계에서는 웹서버로 구동되며,
ws통신과 http통신의 라우팅을 담당해줬다.
나는 1. 어떻게 gunicorn이 저 동작을 하게끔 할것인가를 고민해봤다.
조금 알아보니 이방법은 어려워 보였다.
(추후 알게 된건데 gunicorn으로는 불가하다. uvicorn이라는 대체제가 일반적이다.)
2. 인터넷에 알아보니 nginx와 daphne를 연계하여 동작시킬수 방법이 있었다.
다만 supervisor를 사용하는등 연계가 까다롭고,
daphne를 어느 위치에서 동작시켜야 하는지도 문제였다.
사실 화요일 밤동안 이문제를 해결못했다.
다음날 아침 튜터님께 찾아간 결과 명쾌한 해답을 얻을수 있었다.
그내용은 다음 일자에 적어보겠다.
※ nginx/default.conf 파일 작성내용
server {
listen 80;
server_name _; # 모든 도메인 혹은 ip로 들어오는 요청에 대해 처리해 줍니다.
location / { # nginx로 요청이 들어왔을 때
proxy_pass http://backend:8000/; # backend 컨테이의 8000번 포트로 전달합니다.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /static/ { # 브라우저에서 /static/ 경로로 요청이 들어왔을 때
alias /static/; # /static/ 경로에 있는 파일들을 보여줍니다.
}
location /media/ { # 브라우저에서 /media/ 경로로 요청이 들어왔을 때
alias /media/; # /media/ 경로에 있는 파일들을 보여줍니다.
}
}
location/ 에 보면
백엔드 컨테이너로 넘기는것 아래줄에 3줄을 추가 작성했다.
이부분은 channels를 보고 작성을 참고하였으며 우리에게 필요한 부분만 추가하였다.
https://channels.readthedocs.io/en/stable/deploying.html#example-setups 참고한 channels공식문서