티스토리 뷰

웹/django

[django]웹 서비스 구현 방식, REST

코딩계란 2024. 1. 25. 16:59
728x90

웹 서비스 구현 방식 

서버 사이드 랜더링(SSR, Server Side Rendering)

  • 클라이언트(웹 브라우저)의 요청을 서버가 받아서 처리한 후 서버가 출력하는 코드를 만들어서 클라이언트에게 전송을 하고 클라이언트는 이 코드를 받아서 파싱하여 출력하는 방식
  • 서버 코드와 클라이언트 코드를 하나의 프로젝트에 전부 작성한다. 
  • 서버 코드를 수정할 때 클라이언트 코드가 영향을 받을 수 있고 클라이언트 코드를 수정할 때 서버 코드의 영향을 받을 수 있다. 
  • 이 방식으로 서비스를 만들려면 템플릿 언어라는 것을 학습해야 한다. 
  • 최근에는 선호하지 않는 방식

 

클라이언트 사이드 랜더링(CSR, Client side Rendering)

  • 서버는 클라이언트 요청을 받아서 데이터(XML -> JSON)를 응답으로 전송하고 클라이언트는 응답을 받아서 직접 데이터를 해석해서 출력하는 코드를 만들고 화면에 랜더링하는 방식
  • 이 방식에서는 서버 프로그램(python의 django, java의 spring, javascript의 express.js 등)과 클라이언트 프로그램(vue.js, react.js -> next.js, android-java나 kotlin, ios-swift, 플로터-dart 등)을 별도로 작성한다. 
  • 서버 코드가 클라이언트 코드에 영향을 주지 않고 클라이언트 코드가 서버 코드에 영향을 주지 않는다. 
  • 이렇게 통신만으로 서로 연동되는 경우를 느슨한 결합(loosly coupling)이라고 한다. 
  • 최근에는 프로그램에 유지보수가 자주 발생하므로 이러한 느슨한 결합의 형태로 프로그램을 만드는 방식이 선호된다. 

 

REST

  • representational state transfer의 약자로 분산 하이퍼 미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식
  • 별도의 전송 계층없이 간단한 인터페이스로 자원을 정의하는 방식
  • CSR 방식

6가지 제약조건 

client-server 구조: 클라이언트와 서버는 완전히 독립적. 

stateless: 무상태, 이전에 했던 작업에 대한 내역을 가지고 있지 않다. 쿠키카 세션등을 저장하지 않는다.

  • session: 클라이언트의 정보를 서버에 저장
  • cookie: 클라이언트의 정보를 클라이언트에 저장했다가 사이트 접속시 서버에 전송

Caheable Data: 클라이언트나 서버 측에서 리소스를 캐시할 수 있어야 한다.

Layered System: 여러 개의 계층으로 나누어서 서비스가 가능 

Uniform Interface: 인터페이스가 일관성이 있어야 한다. 

Demand-On-Demand: 선택적 사항으로 클라이언트는 서버에 코드를 요청할 수 있고 서버가 리턴한 코드를 클라이언트에서 실행할 수 있다.

 

위 제약조건을 지켜서 만든 서버를 RESTful하다라고 한다. 


django에서 REST API Server를  구현하기 위한 방법

  • views에서 JsonResponse를 리턴하는 방식. 테스트를 하려면 클라이언트를 구현하거나 테스트 도구를 사용해야 한다. 
  • djangorestframework라는 패키지를 이용하는 방식. 자체 테스트가 가능하다. 

django rest framework 세팅 

1. 작업을 수행할 디렉토리를 생성

 

2. 가상환경을 생성(선택 사항). 방법은 아래 링크 참조

 

[python] 가상 환경 만들기(windows)

가상 환경 생성 python -m venv 가상환경명 위 명령어로 가상 환경을 생성할 수 있다. VScode로 실행할 경우 가상환경 폴더가 생성된 것을 확인 가능. 이후 생성한 폴더로 현재 디렉토리를 변경한다. cd

growingegg.tistory.com

3. 필요한 패키지 설치.

#cmd 창에 입력
pip install django djangorestframework mysqlclient

 

4. 프로젝트와 애플리케이션 생성. 아래 링크 참조 

 

[Django, python] Django 설치 및 프로젝트 생성

Django 패키지 이름: django Django 설치 pip install django 개발 방식(MTV) 프로그래밍을 할 때 역할 별로 분리해서 구현(Django의 개발 방식) Model: 데이터 처리 관련 부분 Template: 출력 관련 부분. 최근에는 거

growingegg.tistory.com

5. 기본 설정 변경: 프로젝트의 settings.py 파일

  • INSTALLS_APPS에 생성한 애플리케이션과 rest_framework를 추가한다.
  • 데이터베이스 접속 정보를 수정 

settings.py 설정 방법은 아래 링크 참조 

 

[Django, python] Django 프로젝트와 에플리케이션 구조

settings.py (프로젝트) 프로젝트 설정에 관한 파일 보안을 위한 해시키 SECRET_KEY = "해시 키" 실제 배포할 컴퓨터의 IP를 등록 ALLOWED_HOSTS = [] *로 할 경우 아무데서나 배포 가능하지만 실제 IP를 작성하

growingegg.tistory.com

6. DB 적용

#cmd찬에 입력
python manage.py makemigrations
python manage.py migrate

 

 

 

요청처리

요청을 분할해서 처리. 분할하지 않으면 urls.py의 내용이 많아졌을 때 소스 코드를 읽기 힘들어지고 유지 보수가 어려워 여러 명이 종시에 작업하는 것이 어렵다. url 요청을 분할해서 할 경우 urls.py 파일에 django.urls.include를 import하고 path("공통 url", include("처리할 모듈 이름"))을 추가하면 된다. (url 처리를 다른 모듈에게 위임하고자 할 때 사용하는 패키지)

 

exmple/hello 라는 요청이 오면 메시지를 출력하는 처리를 작성

 

url 처리를 다른 모듈에게 위임하는 패키지 import

from django.urls import include

 

path("example/", include("apiapp.urls")), 문장은 example로 시작하는 요청이 오면 apiapp 애플리케이션의 urls.py 파일에 처리를 위임

urlpatterns = [
    path("admin/", admin.site.urls),
    path("example/", include("사용자 어플리케이션.urls")),
]

#예시 
urlpatterns = [
    path('admin/', admin.site.urls),
    path("example/", include("myapp.urls")),
]

 

apiapp.views.py 파일에 요청이 오면 처리하는 함수를 작성

from rest_framework.response import Response
from rest_framework.decorators import api_view
#GET 요청이 오면 함수를 호출
@api_view(['GET'])
def hello(request):
    return Response("Hello REST API")

decorator: 실제 함수를 호출하면 특정 내용을 삽입해서 함수를 실행한다. @를 사용하여 표현한다.

 

애플리케이션 디렉토리에 urls.py 파일을 생성하고 url을 연결하는 코드를 작성

from django.urls import path
from .views import hello

urlpatterns = [
    path("hello/", hello),
]

실행결과

 

 

 

데이터 베이스에 테이블 생성 

models.py 파일에 Model 클래스로부터 상속받는 클래스를 생성

from django.db import models

 

# DB 모델 작성 예시 
class Book(models.Model):
  book_name = models.CharField(primary_key = True, max_length = 30)
  author = models.CharField(max_length = 50)
  price = models.IntegerField()
  publisheddate = models.DateField()

 

변경내용 적용 

# CMD 터미널에 입력
python manage.py makemigrations
python manage.py migrate

이후 데이터베이스를 확인해보면 '어플리케이션 이름_모델 이름'으로 형성된 테이블을 확인할 수 있다. 

 

데이터 삽입과 조회 

  • 데이터를 삽입 하는 경우 클라이언트가 삽입할 데이터를 매개변수로 전송하면 서버는 매개변수를 각각 읽어서 모델 클래스로 변환한 후 save 메서드를 호출하면 삽입돤다.
  • rest_framework 에서는 serializer를 정의하면 클라이언트가 전송한 매개변수를 가지고 모델 클래스로 자동 변환이 가능하다.

애플리케이션 디렉토리에 serializers.py 파일 생성

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        #클라이언트에서 입력하는 데이터만 나열
        #아래 나열한 데이터를 입력하면 Book 클래스의 인스턴스를 자동 생성
        fields = ['book_name', 'author', 'price','publisheddate']

  

데이터 삽입과 처리(views.py)

from rest_framework import status
from rest_framework.generics import get_object_or_404

from .models import Book
from .serializers import BookSerializer

#GET 과 POST 모두를 처리
@api_view(['GET', 'POST'])
def booksAPI(request):
    #GET 방식의 처리 - 전체 조회를 요청하는 경우
    if request.method == 'GET':
        #테이블의 데이터를 전부 가져오기
        books = Book.objects.all()
        #출력하기 위해서 브라우저의 형식으로 데이터를 변환
        serializer = BookSerializer(books, many=True)
        #출력
        return Response(serializer.data)
    #POST 방식의 처리 - 삽입하는 경우
    elif request.method == "POST":
        #클라이언트에서 전송된 데이터를 가지고 Model 인스턴스 생성
        serializer = BookSerializer(data = request.data)
        #유효성 검사를 수행해서 통과하면 삽입, 실패하면 이유 출력
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)

 

애플리케이션 디렉토리의 urls.py 파일에서 url과 함수를 연결

from django.urls import path
from .views import hello, booksAPI

urlpatterns = [
    path("hello/", hello),
    path("books/", booksAPI),
]

 

서버 실행 후 확인 

 

#입력 데이터
{
"book_name":"스토너",
"author":"존 윌리엄스",
"price":18000,
"publisheddate":"2024-01-31"
}

입력후

 

 

데이터를 1개 가져오기 

데이터 1개를 가져올려면 클라이언트에서 기본키 값을 서버에게 제공해야 하고 서버는 이 값을 읽어서 하나의 데이터를 찾아서 넘겨줘야 한다.

 

views.py

@api_view(['GET'])
def oneBookAPI(request, book_name):
    #Book 테이블에서 book_name 컬럼의 값이 book_name 인 값을 찾아옵니다.
    book = get_object_or_404(Book, book_name=book_name)
    #출력할 수 있도록 변환
    serializer = BookSerializer(book)
    return Response(serializer.data)

 

 

애플리케이션 디렉토리(myapp)의 urls.py 수정

from django.urls import path
from .views import hello, booksAPI, oneBookAPI

urlpatterns = [
    path("hello/", hello),
    path("books/", booksAPI),
    path("book/<str:book_name>", oneBookAPI)
]

 

실행결과

 

728x90