Django-React Reverse Proxy를 활용해서 Timeline 만들기

Reverse Proxy를 활용해서 Application 작성

Posted by Start Bootstrap on April 28, 2019

Django Back-end Application 작성

일단 Django-admin을 사용해서 백엔드 어플리케이션을 생성할 것입니다. 해당 프로그램의 주요 기능은 적당한 요청을 받으면 그에 해당하는 정보를 반환하는 API를 제공하는 것이 주요 목적입니다. 일단 시작하기 전에 Django의 기본 사항으로 프로젝트를 만들기로 하겠습니다. 적절한 위치에 cmd창에 다음과 같은 명령어를 입력합니다.

        
            django-admin.py startproject config .
        
    

그러면 주요 사항들이 config폴더의 이름으로 현재 디렉터리에 생성됍니다. config폴더에서는 각종 환경 설정 정보(우리는 여기서 데이터베이스 정보와 url에 관한 처리를 할 예정입니다)가 담겨져 있습니다. 설정 이외에 실제 프로그램을 작성해야 하기 떄문에 manage.py 위치에서 새 명령을 적용합니다. manage.py는 Django에서 각종 명령어를 적용하는 역할을 합니다.

        
            python manage.py startapp timeline
        
    

이러면 timeline이라는 폴더 안에 각종 파일들이 생성됍니다. 그 다음은 의존적인 것을 설치해야 하는데 파이썬 가상 환경을 만들어서(Virtualenv등 여러 가지 방법이 있습니다.) 해당 사항을 설치해야 합니다. 이것을 다루기에 내용이 너무 많아지므로 이건 직접 설정해보도록 해보세요. 간단히 연습하기 위해서는 가상환경 만들 필요 없이 설치해도 되긴 합니다. 다만 배포나 여러 면을 고려 했을 때는 환경을 만들어서 배포하는것이 매우 중요합니다.
Django==2.0.1
django-rest-framework==0.1.0
djangorestframework==3.7.7
mysqlclient==1.3.12
pytz==2017.3
를 사용했습니다.

그 다음은 Model을 작성할 것입니다. 일반적으로 MVC패턴이라고 하는 Model-Controller-View가 상호작용하는 방식으로 작성합니다. 일단 저는 Model먼저 작성할 것입니다. 왜냐하면 대부분의 프로그래밍에서 데이터를 어떻게 구성하느냐에 따라 프로그램 작성 방법이 결정돼는 경우가 많기 때문입니다. 그리고 데이터를 먼저 구성해야 프로그램 작성이 더 편합니다. models.py를 다음과 같이 수정합니다.

        
                from django.db import models


                class Timeline(models.Model):
                
                    user = models.CharField(max_length=200)
                    title = models.CharField(max_length=200)
                    description = models.TextField()
                
                    created = models.DateTimeField(auto_now_add=True)
                    updated = models.DateTimeField(auto_now_add=True)
                
                    class Meta:
                        ordering = ('-created',)
        
    

Django의 Model 개체를 상속받아서 Model을 작성했습니다. 해당 데이터는 user(Character), title(Character), description(long text), created(datetime), updated(datetime)으로 정했습니다. models는 데이터베이스 속성과 매칭되는 다양한 속성을 제공해서 사용할 수 있도록 해줍니다. 그래서 프로그래머는 직접 DLL(데이터 정의어)를 작성할 필요 없이 이 Model Class 하나 작성하는 것만으로 모든 문제를 해결할 수 있습니다. 그리고 이 Class는 데이터베이스의 Table 하나와 매칭이 됍니다. 이렇게 Class를 통해서 가상 데이터베이스를 사용하는 방법은 ORM(Object-relational mapping)이라고 합니다. 이것을 사용하면 프로그래머는 직접 DDL이나 DML(데이터 조작어)를 사용할 필요 없이 쉽게 데이터베이스를 사용할 수 있습니다. 하지만 ORM과 데이터베이스 둘다 학습해야하고 서로 잘 알고 있어야 하는 단점이 있습니다. Meta Class를 통해서 다양한 속성을 정의할 수 있습니다. 저는 order by를 사용하고 싶기 때문에 생성된 순서 역순으로 데이터를 가져올 수 있도록 설정했습니다. Django 프로젝트에서 Model은 기반이 돼는 아주 중요한 부분입니다. 그래서 깊은 고려나 고민을 통해서 해당 구성이 적절한지 자주 고민을 해 봐야 하는 부분이기도 합니다.

그 다음은 django-rest-framework의 serializer를 작성할 것입니다. serializer의 주요한 역할은 python의 dictionary로 저장돼어 있는 데이터의 형태를 json형태로 반환할 것입니다. HTTP를 통한 API 제공시에 여러 가지 형태를 제공하지만 일반적으로 많이 쓰이는 방식은 JSON형식입니다. 왜냐하면 Key-Value로 간단하게 구성돼어 있기 때문에 사용하거나 이해하기가 편하기 때문입니다. serializer를 작성하는 방법이 여러 가지 있지만 저는 model 형태 그대로를 사용하고 싶기 떄문에 다음과 같이 작성했습니다. serializers.py를 하나 만들어서 내용을 채우면 됍니다.

        
                from rest_framework import serializers

                from .models import Timeline

                class TimelineSerializer(serializers.ModelSerializer):

                    class Meta:
                        model = Timeline
                        fields = (
                            'pk',
                            'user',
                            'title',
                            'description',
                            'created',
                            'updated',
                        )
        
    

ModelSerializer를 사용하면 실제 Model의 형태로 JSON을 제공하기 때문에 일단 편하게 사용할 수 있습니다. Meta Class에 속성을 정의해야 하는데 model 속성에는 내가 사용할 Model Class를 적용하는 곳입니다. fields는 Model에 있는 데이터 중 어떤 데이터를 제공할 지를 결정합니다.

그 다음은 Controller를 작성하는 일입니다. Django에서는 Controller의 역할을 담당하는 것을 View라고 부릅니다. View는 간단히 정리하면 요청 객체를 받고 응답 객체를 반환하는 역할을 하는 것입니다. View는 크게 함수 기반으로 작성하거나 또는 클래스 기반으로 작성하는 방법 두 가지가 있습니다. 저는 클래스 기반으로 작성할 예정인데 as_view() 클래스 매서드를 통해서 내장 함수를 반환합니다. 또한 장고는 제네릭 클래스 기반 뷰(generic class-based view)를 제공합니다. 저는 django-rest-framework의 generics를 사용할 것입니다. 그리고 저는 View 코드의 양은 적으면 적을수록 좋다. 믹스인은 간단 명료해야 한다 라는 가이드를 가지고 대부분 제네릭을 사용합니다.

        
                from rest_framework import generics

                from .models import Timeline
                from .serializers import TimelineSerializer
                
                
                class TimelineList(generics.ListCreateAPIView):
                
                    queryset = Timeline.objects.all()
                    serializer_class = TimelineSerializer
                    name = 'timeline-list'
                
                class TimelineDetail(generics.RetrieveUpdateDestroyAPIView):
                
                    queryset = Timeline.objects.all()
                    serializer_class = TimelineSerializer
                    name = 'timeline-detail'
        
    

generics.ListCreateAPIView는 데이터의 list를 제공(HTTP GET Method)와 데이터 생성(HTTP POST method)의 기본적인 역할을 사용할 수 있는 믹스인 클래스 입니다. 그리고 RetrieveUpdateDestroyAPIView는 데이터 SELECT(HTTP GET Method)와 데이터 수정(HTTP UPDATE Method)와 데이터 삭제(HTTP DELETE Method)의 기본 기능을 제공합니다. 이것은 Django의 기본 클래스 기반 뷰를 REST 기반으로 사용하기 위한 Wrapper Class입니다. 따라서 이처럼 간단한 경우에는 매우 쉽게 사용할 수 있지만 조금만 복잡해지면 내부 구조를 파악해 수정할 정도로 복잡한 경우에는 좋지 않습니다. 따라서 용도를 잘 확인해서 사용하면 더 적은 코드로 일할 수 있습니다. 저는 개인적으로 다양한 도구들을 사용하기에 문제가 없다면 최대한 활용하는 것이 좋다고 생각합니다.

그 다음에 API의 URL을 결정하는 부분입니다. Reverse Proxy 방식으로 서버를 구성하려면 URL를 통해 정확한 기능 구분이 중요합니다. 이것은 사람 뿐만 아니라 시스템도 URL을 통해 어떤 기능을 하는 서버인지 알 수 있어야 합니다.

        
                from django.urls import path
                from .views import TimelineList, TimelineDetail

                urlpatterns = [
                    path("timeline/", TimelineList.as_view(), name=TimelineList.name),
                    path("timeline/<int:pk>>", TimelineDetail.as_view(), name=TimelineDetail.name),
                ]
        
    

Django 2.0부터 사용가능한 django.urls의 path를 활용하면 쉽게 urlpatterns를 작성할 수 있습니다

다음은 Settings에 우리가 사용하는 package를 등록하고 실제 timeline app을 django에 등록시켜서 우리가 작성한 코드를 구동할 수 있게끔 하는 설정을 추가할 것입니다. config/settings.py의 INSTALLED_APPS을 다음과 같이 수정합니다. 그리고 DATABASES도 다음과 같이 수정합니다. 아마 기본적으로 sqlite3를 사용하게끔 설정되어 있을 겁니다.

        
                INSTALLED_APPS = [
                    'django.contrib.admin',
                    'django.contrib.auth',
                    'django.contrib.contenttypes',
                    'django.contrib.sessions',
                    'django.contrib.messages',
                    'django.contrib.staticfiles',
                    'rest_framework',
                    'timeline.apps.TimelineConfig',
                ]
                .....

                DATABASES = {
                    'default': {
                        'ENGINE': 'django.db.backends.mysql',
                        'NAME': 'tiemline', # DB 이름을 적어주세요
                        'USER' : 'root', # DB 계정을 적어주세요 난 임의로 root라 해야지
                        'PASSWORD' : '1234', #DB 비밀번호를 적어주세요 난 임의로 1234라고 해야지
                        'HOST' : '127.0.0.1',
                        'PORT' : '3306'
                    }
                }

        
    

그리고 config/urls.py를 다음과 같이 수정합니다. 이 작업은 아까 작성했던 timeline의 urls.py를 사용할 수 있게끔 등록하는 것입니다.

        
                from django.contrib import admin
                from django.urls import path, include

                urlpatterns = [
                    path('admin/', admin.site.urls),
                    path("api/", include('timeline.urls'))
                ]
        
    

django admin을 사용하지 않을 거긴 하지만 딱히 제외 이유는 없어서 남겨두었습니다. 이러면 남은 과정은 Database를 생성하고 마이그레이션 하는 과정입니다. 마이그레이션을 통해서 ORM 시스템에게 DB Table을 생성해달라고 요청할 수 있습니다. 그러면 코드에 Mapping되는 DB Table 형태가 생성이 됩니다.

        
                DROP DATABASE IF EXIST TIMELINE;

                CREATE DATABASE TIMELINE CHARACTER SET UTF8
        
    

다음과 같이 하면 기존의 TIMELINE이름의 DATABASE가 있으면 삭제하고 TIMELINE이라는 이름의 CHARACTER SET이 UTF8 속성을 가진 DATABASE가 생성이 됍니다. 그 다음에 마이그레이션을 요청하는 명령어를 입력하면 됍니다

        
                python manage.py makemigrations

                python manage.py migrate
        
    

다음과 같이 명령어를 입력하면 Django가 ORM이나 Migrate에 필요한 기본 Table을 만들고 그 다음에 Model에 해당하는 Table을 만들 것입니다. 이름을 따로 설정하기 않았기 떄문에 timeline_timeline이라는 Table 이름을 가지고 생성할 것입니다.

        
                python manage.py runserver 0.0.0.0:8000
        
    

다음과 같이 명령어를 입력하면 드디어 Django가 8000번 포트에다가 서버를 실행시킬 겁니다. 이제 8000번 포트로 URL에 맞게 요청을 보내면 응답을 받을 수 있습니다.

다음은 Nginx를 통해서 HTTP Reverse Proxy서버를 실행할 것입니다.

작성중....