[AWS][Django] DRF로 만든 웹소켓 채팅서버를 Docker, nginx, daphne를 이용하여 AWS EC2에 배포하기(3)

이민재·2023년 11월 25일
1
post-thumbnail

저번 시간까지 docker와 nginx관련된 파일들을 작성해보았다. 이제 .env관련된 코드를 작성하면되는데 왜 .env를 쓰는지 의문일 것이다.

📌.env를 사용하는 이유

보안: .env 파일을 사용하면 중요한 비밀 정보(예: 데이터베이스 암호, API 키 등)를 소스 코드 밖에 저장할 수 있습니다. 이렇게 하면 이러한 민감한 정보가 공개 소스 코드 저장소에 실수로 올라가는 것을 방지할 수 있습니다.

환경 구분: 개발, 테스트, 프로덕션 등 다른 환경에서 다른 설정을 사용할 수 있습니다. 예를 들어, 로컬 개발 환경에서는 하나의 데이터베이스를 사용하고, 프로덕션 환경에서는 다른 데이터베이스를 사용할 수 있습니다.

즉 개발환경과 프로덕션환경을 분리하여 애플리케이션의 유연성과 유지 보수를 높이기 위해서다.

이 포스팅에서는 개발환경에서는 sqlite를 프로덕션환경에서는 Postgresql을 사용할것이고 또 장고 프로젝트폴더안의 settings.py에 DEBUG나 SECRET_KEY, ALLOWED_HOSTS 설정들도 개발환경과 프로덕션환경으로 나누어 개발에 용이하게 할것이다.

먼저 settings.py의 코드를 작성해보겠다. 전에 개발했던 settings.py에서 아래와 같이 변경을한다.

📌settings.py 변경

#settings.py

import os

SECRET_KEY = os.environ.get('SECRET_KEY','************************************************')

DEBUG = int(os.environ.get('DEBUG', 1))

if os.environ.get('DJANGO_ALLOWED_HOSTS'):
    ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS').split(' ')
else:
    ALLOWED_HOSTS = []
    
DATABASES = {
    'default': {
        'ENGINE': os.environ.get("SQL_ENGINE", 'django.db.backends.sqlite3'),
        'NAME': os.environ.get('SQL_DATABASE', os.path.join(BASE_DIR, 'db.sqlite3')),
        'USER': os.environ.get('SQL_USER', 'user'),
        'PASSWORD': os.environ.get('SQL_PASSWORD', 'password'),
        'HOST': os.environ.get('SQL_HOST', 'localhost'),
        'PORT': os.environ.get("SQL_PORT", '5432'),
    }
}

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [(os.environ.get('REDIS_HOST', 'localhost'), 6379)],
        },
    },
}

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '_static')

장고에서 ALLOWED_HOSTS 설정을 사용하는 주된 이유는 보안을 강화하기 위해서이다. 이 설정은 장고 애플리케이션에 요청을 보낼 수 있는 호스트(도메인 또는 IP 주소)를 제한한다. 이 포스팅에서는 프론트의 로컬서버 ip를 아래에 .env.prod 파일에 작성할 것이다.

📌CORS_ALLOWED_ORIGINS 설정

우리는 프론트와 http 통신을 할것이다. 그러나 다른 ip를 가진 서버와 통신을 하려면 CORS_ALLOWED_ORIGINS 설정을 해주어야지 지정된 출처의 요청에 대한 리소스 접근을 허용함으로써 다양한 출처 간의 유연한 리소스 공유를 가능하게 해준다. 다시말해 기본적으로 웹 브라우저는 동일 출처 정책(Same-Origin Policy)을 적용한다. 이 정책은 한 출처에서 불러온 문서나 스크립트가 다른 출처의 리소스와 상호작용하는 것을 제한한다. CORS_ALLOWED_ORIGINS를 설정함으로써 어떤 출처가 이 정책을 우회하여 리소스에 접근할 수 있는지를 정의할 수 있게 해준다.

장고는 이를 라이브러리를 사용해서 설정해준다. 아래의 라이브러리를 설치하고

pip install django-cors-headers

settings.py에 있는 INSTALLED_APPS와 MIDDLEWARE의 맨위에 'corsheaders'와 'corsheaders.middleware.CorsMiddleware'를 위치시켜준다. 위치가 중요하다 맨위로 해줘야 장고에서 인식을 해서 오류가 발생하지않는다.

#settings.py

INSTALLED_APPS = [
    'corsheaders',
    'channels',
    'daphne',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'chat',
    'rest_framework',
    'drf_yasg',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware', 
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

그리고 이제 아래와 같은 CORS_ALLOWED_ORIGINS 설정을 해준다. 프론트서버를 로컬에서 열거기 때문에 아래와 같은 주소를 적는다.

CORS_ALLOW_ALL_ORIGINS = False

CORS_ALLOWED_ORIGINS = [
    "http://127.0.0.1:8000",
]

아래의 CSRF_TRUSTED_ORIGINS 설정은 장고 애플리케이션에서 특정 원점으로부터 오는 요청을 CSRF 보호 메커니즘의 일환으로 신뢰하도록 하여 보안을 강화하고, 다양한 환경 및 동적 IP 환경에서의 안전한 서버 간 통신을 지원하는 중요한 보안 구성 요소이다. 이것도 적자.

CSRF_TRUSTED_ORIGINS = ['http://탄력ip',]

프로젝트에 필요한 Python 패키지들을 나열해두는 파일을 생성한다. 이 파일을 통해 다른 개발자나 서버에서도 동일한 환경을 쉽게 구성할 수 있다. requirements.txt 파일에 나열된 패키지들을 설치하려면, 다음과 같은 명령어를 사용한다

pip freeze > requirements.txt

📌.env.prod 파일 추가

# .env.prod

DEBUG=0
SECRET_KEY=************************************
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1:8000 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=chatting_prod
SQL_USER=test
SQL_PASSWORD=test123
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres
REDIS_HOST=redis

📌.env.prod.db 파일 추가

# .env.prod.db

POSTGRES_USER=test
POSTGRES_PASSWORD=test123
POSTGRES_DB=chatting_prod

위의 .env.prod와 .env.prod.db는 만약에 실제 배포를 할때 쓰여야할 중요한 부분이기때문에 유출이 되서는 안된다. 만약 깃허브에 올리는데 private로 설정을 하더라도 만약을 대비해 .gitignore에 위 파일들을 작성하여 깃허브에도 올라가지않게하여 보안에 신경써주길 바란다. 우리는 위에 미리적어놓은 것을 putty롤 접속한 프로젝트 폴더안에서 ctrl+c, v를 하여 파일을 생성할 것이다.

이제 이와같이 배포할 설정을 마무리하였으니 일단 위의 변경사항을 github에 git push 한 후에 putty에서 프로젝트폴더 안으로 들어온 후 git pull을 하여 git hub에 있는 변경사항을 putty의 프로젝트폴더에 내려받아 동기화를 시켜준다.

그리고 아래와 같이 입력한다.

touch .env.prod .env.prod.db

ls -A명령어를 치면 파일이 생성된 것을 볼수있다.

nano .env.prod 또는 nano .env.prod.db 명령어를 사용하여 각 파일을 연다.

nano .env.prod
nano .env.prod.db

그리고 VS코드에서 필요한 코드를 선택하고 Ctrl+C를 사용하여 복사하고 PuTTY에서 마우스 오른쪽 클릭을 통해 복사한 내용을 붙여넣는다. 파일을 편집한 후, Ctrl+O를 눌러 저장한다. Enter 키를 눌러 저장한 파일명을 확정합니다. Ctrl+X를 눌러 편집기에서 나온다.
이러한 단계들을 통해 PuTTY를 사용하여 원격 서버에서 .env.prod 및 .env.prod.db 파일을 편집하고 저장할 수 있다.

이제 모든 설정을 마쳤다. 우리가 저번 포스팅에서 작성한 docker-compose를 이용해서 배포를 할 차례이다. 그러기전에 먼저 EC2 서버에 도커를 설치를 해야한다. 아래의 절차를 따라가 보자.

📌우분투 업데이트 및 도커 설치

putty에 아래의 명령어들을 입력하자.

sudo apt-get update 명령어로 우분투에서 소프트웨어를 설치할때 주로 사용하는 apt-get을 최신정보로 업데이트한다.

 sudo apt-get update

sudo apt install docker.io 명령어로 도커를 설치한다. 그리고 우분투 서버가 시작될때 도커도 자동으로 실행되도록 start docker와 enable docker 설정을 추가한다.

 sudo apt install docker.io
 sudo systemctl start docker
 sudo systemctl enable docker

docker --version 명령어로 도커가 잘 설치되어 있는지 확인합니다.

 docker --version

docker-compose도 설치를 해줍니다

 sudo apt install docker-compose

📌docker-compose를 이용하여 배포

이제 그디어 배포할 차례이다.

아래는 도커 이미지를 빌드를 하고 detach모드로 컨테이너화 하여 서버에 올리는 명령어 이다. putty에 아래의 명령어를 입력하자.

sudo docker-compose up -d --build

무수히 많은 글자들이 생겨나다가 아래의 4개의 done을 보면 그디어 배포에 성공하였다.!

만약 코드가 잘못되어 오류가발생한다면 아래의 명령어를 쳐서 현재 실행 중인 컨테이너를 내리고 오류를 해결하자.

sudo docker-compose down

아직 끝난게 아니다 서버에도 migrate를 해주어야한다. 아래의 명령어를 입력한다.

sudo docker-compose exec web python manage.py makemigrations
sudo docker-compose exec web python manage.py migrate

슈퍼유저도 만들어보자. admin 페이지에 들어가려면 필요하다.

sudo docker-compose exec web python manage.py createsuperuser

그리고 아래의 명령어 입력해서 정적파일을 한곳에 모이게하는 명령어를 사용하여 서버로 올린 admin 페이지에서도 각종 정적 파일들이 적용이되게 해준다.

sudo docker-compose exec web python manage.py collectstatic
sudo docker-compose restart nginx

이제 서버에 웹소켓채팅 서버를 올리는것을 성공했다. 이제 프론트코드에 get, post , 웹솤켓 연결 코드에서 ip를 우리가 aws에 설정한 탄력 ip로 바꾼후 제대로 동작이 되는지 확인해 보자!

📌개발완료

성공이다!!!

긴 여정의 django 웹소켓 채팅 구현하기 포스팅을 마무리하도록 하겠다!

0개의 댓글