Uber clone-2(ft. channels & react)

Hyeseong·2023년 4월 30일
0

uber-clone

목록 보기
2/3

Table of Contents

  1. Project Setup
  2. Postgres and Redis
    1. With Docker
    2. Without Docker
  3. Django Config
    1. Custom User Model
    2. Admin
    3. Channels Config

Project Setup

우선 프로젝트 시작을 위해서 "taxi-react-app"이라는 디렉토리를 만들겠습니다.

$ mkdir taxi-react-app && cd taxi-react-app

그런 다음 "taxi-react-app" 내에서 프로젝트의 종속성을 격리할 새 가상 환경을 만듭니다.

$ mkdir server && cd server
$ python3.10 -m venv env
$ source env/bin/activate
(env)$

Django, Django REST Framework, Django Channels, channel_redis, pytest-asyncio, pytest-django, Pillow, djangorestframework-simplejwt 및 Psycopg2를 설치합니다. 그런 다음 Django 프로젝트와 앱을 만듭니다.

(env)$ pip install \
       Django==4.1.3 \
       djangorestframework==3.14.0 \
       channels==4.0.0 \
       channels-redis==4.0.0 \
       daphne==4.0.0 \
       pytest-asyncio==0.20.1 \
       pytest-django==4.5.2 \
       Pillow==9.3.0 \
       djangorestframework-simplejwt==5.2.2 \
       psycopg2-binary==2.9.5

(env)$ django-admin startproject taxi .
(env)$ python manage.py startapp trips

여러 파일들과 모듈들이 담긴 프로젝트 구조는 아래와 같습니다.

└── server
    ├── manage.py
    ├── taxi
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── trips
        ├── __init__.py
        ├── admin.py
        ├── apps.py
        ├── migrations
        │   └── __init__.py
        ├── models.py
        ├── tests.py
        └── views.py

OS 또는 Docker 컨테이너를 이용하여 직접 Postgres 및 Redis를 설정하고 실행할 수 있습니다. 1부에서 Docker를 사용할 필요는 없지만 2부에서는 Docker를 사용하므로 1부에서도 Docker를 계속 사용하는 것이 좋습니다.

Postgres and Redis

With Docker

도커 설치한 이후 아래 명령어를 실행해 주세요.

$ docker run --name some-postgres -p 5432:5432 \
    -e POSTGRES_USER=taxi -e POSTGRES_DB=taxi -e POSTGRES_PASSWORD=taxi -d postgres

Docker Hub에서 공식 Postgres Docker 이미지를 다운로드하고 백그라운드에서 포트 5432를 잡고 실행합니다. 또한 사용자, 암호 및 데이터베이스 이름이 모두 taxi로 설정된 데이터베이스를 설정하게 됩니다.

다음으로 Redis를 포트 6379로 잡고 컨테이너 기동을 하도록 합니다.

$ docker run --name some-redis -p 6379:6379 -d redis

정상 기동이 되었는지 확인하기 위해서 아래 명령어를 실행합니다.

$ docker exec -it some-redis redis-cli ping

PONG

Without Docker

시스템에 가장 적합한 방법을 사용하여 PostgreSQL을 다운로드하고 설치합니다. PostgreSQL이 기본 포트인 5432에서 실행 중인지 확인합니다. 이 포트를 사용하여 Django를 데이터베이스에 연결합니다.

다음으로 Redis를 다운로드하여 설치합니다. Redis 서버를 시작하고 기본 포트인 6379에서 실행 중인지 확인합니다. Django에게 Redis와 통신하는 방법을 알려줄 때 포트 번호가 중요합니다.

  • 혹시 Mac쓰시나요? 아래 명령어로 설치하면 되요.
$ brew install postgresql
$ brew services start postgresql
$ brew install redis
$ brew services start redis

psql 클라이언트를 사용하여 Postgres에 연결합니다.

$(env) psql -U postgres

다음 명령을 사용하여 새 데이터베이스와 사용자를 만듭니다.

postgres=# CREATE USER taxi WITH SUPERUSER CREATEDB CREATEROLE PASSWORD 'taxi';
postgres=# CREATE DATABASE taxi OWNER taxi;

\q를 입력하고 RETURN 버튼을 눌러 psql을 종료합니다.

Django Config

다음으로 선택한 코드 편집기에서 프로젝트를 열고 settings.py를 다음과 같이 변경합니다.

# server/taxi/settings.py

import os # add with the other imports

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.postgres', # new
    'django.contrib.staticfiles',
    'rest_framework', # new
    'trips', # new
]

# changed
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.getenv('PGDATABASE', 'taxi'),
        'USER': os.getenv('PGUSER', 'taxi'),
        'PASSWORD': os.getenv('PGPASSWORD', 'taxi'),
        'HOST': os.getenv('PGHOST', 'localhost'),
        'PORT': os.getenv('PGPORT', '5432'),
    }
}

AUTH_USER_MODEL = 'trips.User' # new

INSTALLED_APPS에 문자열 몇개를 추가하여 앱등록을 하도록 합니다.

기본 SQLite3 데이터베이스를 PostgreSQL로 교체했습니다. 환경 변수에서 데이터베이스 설정을 가져오고 있습니다. Django 서버를 실행하는 동일한 환경에서 해당 변수를 설정했는지 확인해야 합니다.

장고 유저 모델의 경우 표준 필드가 제공하는 것보다 더 많은 사용자 데이터를 저장해야 하므로 사용자 모델을 참조하도록 AUTH_USER_MODEL 설정을 추가했습니다.

Custom User Model

server/trips/models.py 파일에서 사용자 정의 모델을 작성합니다.

# server/trips/models.py

from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    pass

이 사용자 정의 모델을 사용하면 나중에 필드를 추가할 수 있습니다.

그럼. 첫 마이그레이션을 진행합니다.

(env)$ python manage.py makemigrations
Migrations for 'trips':
  trips/migrations/0001_initial.py
    - Create model User

이제 사용자 지정 유저 모델을 사용하도록 앱 설정도 했으니. Django 마이그레이션 명령을 실행할 수 있습니다. 모든 데이터베이스 테이블도 물론 생성됩니다.

(env)$ python manage.py migrate

아래와 비슷한 뭔가가 나올겁니다.

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, trips
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying trips.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying sessions.0001_initial... OK

개발 서버를 실행하여 모두 정상인지 확인합니다.

(env)$ python manage.py runserver

브라우저를 열고 아래 주소를 입력합니다. http://localhost:8000/

Control+C를 입력하여 서버를 종료합니다.
다음으로 Django 관리 페이지를 설정해 보겠습니다.

Admin

createsuperuser 관리 명령을 사용하여 새 수퍼유저 계정을 만듭니다. 메시지가 표시되면 사용자 이름, 이메일 및 비밀번호를 선택하십시오.

(env)$ python manage.py createsuperuser

trips/admin.py 파일을 열고 내용을 다음 코드로 바꿉니다.

# server/trips/admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DefaultUserAdmin

from .models import User


@admin.register(User)
class UserAdmin(DefaultUserAdmin):
    pass

서버를 다시 실행하십시오. 브라우저에서 http://localhost:8000/admin/을 방문하고 수퍼유저로 로그인합니다.

Channels Config

다음으로 기본 Redis 백엔드를 설정하고 settings.py 파일에서 라우팅하여 CHANNEL_LAYERS를 구성합니다.

# server/taxi/settings.py

REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379')

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [REDIS_URL],
        },
    },
}

그런 다음 Django Channels를 INSTALLED_APPS에 추가합니다.

# server/taxi/settings.py

INSTALLED_APPS = [
    'daphne', # new
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.postgres',
    'django.contrib.staticfiles',
    'rest_framework',
    'trips',
]

다음 내용이 포함되도록 taxi/asgi.py 파일을 수정합니다.

# server/taxi/asgi.py

import os

from django.core.asgi import get_asgi_application

from channels.routing import ProtocolTypeRouter

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'taxi.settings')

application = ProtocolTypeRouter({
    'http': get_asgi_application(),
})

마지막으로 settings.py 파일을 엽니다. WSGI_APPLICATION 설정을 찾아 해당 줄 아래에 다음을 추가합니다.

# server/taxi/settings.py

ASGI_APPLICATION = 'taxi.asgi.application'

서버가 오류 없이 실행되는지 확인합니다.

(env)$ python manage.py runserver

디렉토리 구조는 다음과 같아야 합니다. (가상환경 및 기타 시스템 파일은 제외됩니다.)

└── server
    ├── manage.py
    ├── taxi
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── trips
        ├── __init__.py
        ├── admin.py
        ├── apps.py
        ├── migrations
        │   ├── 0001_initial.py
        │   └── __init__.py
        ├── models.py
        ├── tests.py
        └── views.py

잠시 시간을 내어 지금까지 수행한 모든 작업을 되새겨 보길 추천 드립니다.
예를 들어 Django 채널의 인메모리 레이어 대신 Redis를 사용한 이유가 뭘까??

장고 채널스에서 인메모리 대신 레디스를 사용하는 주요 이유는 다음과 같습니다:

  1. 데이터의 영속성: 인메모리 스토리지는 프로세스가 종료되면 데이터가 손실되지만, 레디스를 사용하면 데이터를 디스크에 저장하여 영속성을 보장합니다. 이렇게 하면 서버가 다시 시작되거나 크래시한 경우에도 데이터를 유지할 수 있습니다.

  2. 분산 시스템 지원: 레디스는 여러 서버에 데이터를 분산시키기 위한 복제 및 샤딩 기능을 제공합니다. 이를 통해 시스템의 확장성을 높일 수 있으며, 여러 서버에서 웹소켓 연결을 처리할 때 메시지를 동기화하는 데 유용합니다.

  3. 성능: 레디스는 인메모리 데이터 구조 저장소로, 대용량 데이터 처리에 매우 빠른 속도를 제공합니다. 이는 실시간 애플리케이션에서 빠른 응답 시간을 요구하는 웹소켓과 같은 기능에 적합합니다.

  4. 다양한 데이터 구조: 레디스는 문자열, 해시, 리스트, 세트, 정렬된 세트 등 다양한 데이터 구조를 지원합니다. 이를 통해 개발자는 애플리케이션 요구 사항에 따라 적합한 데이터 구조를 선택할 수 있습니다.

  5. 장고 채널 레이어와의 호환성: 장고 채널스에서는 레디스를 지원하는 공식 채널 레이어 패키지인 channels_redis를 제공합니다. 이 패키지를 사용하면 쉽게 레디스를 백엔드로 설정하고 웹소켓 메시지를 처리할 수 있습니다.

profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글