Skip to content

Latest commit

 

History

History
96 lines (81 loc) · 8.49 KB

20210520.md

File metadata and controls

96 lines (81 loc) · 8.49 KB

Django

인상 깊은 조언

  • 특정 방법론이 항상 효율적인 것은 아니므로 상황에 맞는 선택이 중요하다.
  • 같은 이유로 특정 방법론을 신봉하는 것은 좋지는 않다.
  • 그러나 복수/단수 네이밍은 꼭 지켜주자.

앱 구조 설계

지난 시간까지

  • 하나의 프로젝트에 하나의 app으로 모든 기능을 담았다.
  • config에 모든 세팅이 들어갔는데, settings.py를 하나로 하는 경우도 많지는 않다.
    • 서버만 해도 test 서버, dev 서버, production 서버 세개를 두는 게 일반적이다.
    • test를 위해 DB를 건드렸는데 실제 production DB에 영향이 가면 안되기 때문에 같은 DBMS는 일관성을 위해 같이 쓰지만 DB는 서로 달라야 한다.
    • config 안에 settings 폴더를 넣고 구분하여 관리할 수 있다.
  • app이 로그인, 회원가입, class 정보, student 정보, 댓글, 팔로우 등 모든 기능을 담당해서 views가 길어졌다.
  • 만약 class를 추가하거나 수정하는 등 또다른 기능을 넣는다면 앱이 너무 커지므로 쪼개줄 필요가 있다.

앱 구조 설계하기

  • app은 하나의 역할, 하나의 기능을 담당한다고 생각하고 디자인하자.
  • 그러나 여전히 개인의 선택이다. 하나의 앱 속에서 파일만 다르게 해줄 수도 있다.
  • url 단위를 기준으로 나누는 RESTful 한 방식을 실습해보자.
  • 우리가 만든 community라는 프로젝트는 예컨대 blog(글 관련), social(팔로우), account(로그인, 마이페이지 등) 등으로 나눌 수 있다.

URL 설계를 위한 REST API

REST(REpresentational State Transfer)란?

  • 리소스의 상태에 대한 표현
    • 리소스(자원)는 곧 DB 테이블와 같은 말이라고 볼 수 있다.
  • URI를 통해 어떤 자원인지 명시한 후, HTTP Method를 통해 해당 자원에 대해 어떤 동작을 수행할지 명시하는 것

REST의 특징

  • client & server: 자원을 가지고 있는 서버(api 제공, 비즈니스 로직 처리)와 이를 요청하는 클라이언트(사용자 세션을 직접 관리)
    • stateless: 사용자의 상태(쿠키, 세션)를 서버에 저장하지 않고, 각각의 요청은 독립적으로 존재하므로 DB 상태 변경 외에는 요청의 순서가 상관없다.
  • cacheable: 캐시 처리가 가능하다. (응답 시간이 빨라지고 자원 이용 효율이 증가)
  • layered system: 아키텍쳐를 계층화하여 구성. 서버의 다양한 layer에서 각각의 역할을 나누어 처리하므로 api 서버에서는 비즈니스 로직만 처리하고 다른 layer에서 SSL 등의 보안이나 로드밸런싱 등을 처리한다.

REST의 장점

  • 유지보수/운영 효율 증가, 확장성 & 재사용성 증가
  • 항상 절대적으로 효율적인 건 아니다. 예컨대 작은 서비스인 경우 RESTful API를 구축하고 이에 숙달시키기 위한 시간과 노력이 더 들 수가 있다.
  • toss같은 곳에서도 의도적으로 지키지 않는 경우도 있으므로 상황에 맞게 선택하는 것이 중요하다.

REST를 적용하는 방법

  • URI는 동사보다는 명사를, 소문자로, 상황에 맞는 복수와 단수를 사용, '/'로 계층을 구분하며 마지막에는 '/'를 포함하지 않는다(장고에서는 포함함).
  • URI에는 언더스코어(_)보다는 하이픈(-)으로 표현하고, 파일확장자는 포함하지 않는다.
  • CRUD와 관련된 요청행위는 적절한 HTTP 메서드를 사용한다.

프로젝트 안에서 앱을 나누기

  • 늘 하던대로 프로젝트를 시작해주자. 까먹었을 수도 있으니 다시 한 번 해보자면...
    • $ mkdir {디렉토리명}'(디렉토리 생성), '$ cd {디렉토리명}'(디렉토리 진입), $ virtualenv venv(가상환경 구축), $ source venv/bin/activate(가상환경 진입), $ pip install django(장고 설치), $ django-admin startproject config .`(현재 디렉토리에 config라는 이름의 프로젝트 시작)
  • $ python manage.py startapp {앱 이름}을 앱 개수만큼 해주고, config 폴더의 settings.py에 INSTALLED_APP에 앱 이름을 추가해준다.

url 쪼개기

  • config의 urls.py 안에 각 앱의 urls.py를 import한다.
    • path('blog/', include('blog.urls')), path('social/', include('social.urls'))
    • 이렇게 하면 blog/로 들어오는 요청은 자연스레 blog 앱으로 가는 등 요청이 들어왔을 때 자동으로 각 앱의 이름에 따른 urls.py로 찾아간다.
  • 각 앱 폴더에 urls.py를 만들고, 처음 부분의 from django.urls import path는 복붙한다.
    • 각 앱에서 views를 사용하여 경로에 맞는 함수처리를 할테니까 from {app name} import views
    • urlpatterns = []로 path를 정해주는데, 이미 앞에 blog라는 경로가 붙어 온다는 것을 염두에 두고 중복되지 않도록 정해준다.
    • 여러 개의 아이템 중 하나를 pk값 등으로 받아 처리할 경우 경로 이름을 복수로 해준다.
  • 앱의 urls.py에 app_name이라는 변수에 문자열을 할당하면 네임스페이스를 사용할 수 있다.
    • urlpatterns에서 name으로 지정한 내용 앞에 붙을 이름을 app_name에 할당하면, 굳이 name을 blog-index라고 구체화하지 않아도 템플릿이나 redirect의 인자에서 blog:index로 해당 경로를 지칭할 수 있다.

비즈니스 로직 처리 위치에 대한 다양한 의견

  • 지금까지는 views에서 error handling이나 validation을 모두 처리했는데, 그러다보니 너무 길어진다는 문제가 생겼다.
  • 다양한 로직을 어떻게 처리할 것인지에 대한 의견이 여러 개 있는데 그 중에 Fat Models, Service Layers, Model Managers가 있다.

Fat Models

  • models.py에서 모델이 비즈니스 로직까지 모두 수행하게 한다.
  • class 안의 메서드로 로직을 정의한다.
  • 장점: view가 얇아지고, 객체지향의 의미를 살릴 수 있다.
  • 단점: 모델이 가진 변수나 필드를 한 번에 직관적으로 이해하기 힘들다.

Service Layers

  • 3-layer-architecture로 더 알려져있으며, MTV를 지향하는 장고의 철학과는 썩 맞지 않을 수도 있다. (다른 웹 프레임워크에서 시작된 이론이기 때문에)
  • control과 service를 완전히 분리하여 처리한다. 이 때 controller, service, data(model)의 세 개 계층으로 나뉘기 때문에 3-layer-architecture라고 불리며, 이 위에 template이 존재한다.
    • controller: urls.py로 요청을 받고, views.py로 응답을 내보내는 역할만 한다. DB에 직접적으로 접촉하지 않는다.
    • service: service.py라는 파일에서 DB에 관련된 모든 로직을 처리한다.
    • data(model): service와만 접촉한다.
  • views.py에서는 model을 import할 필요도 없게끔 전혀 모델(DB)을 직접 작업하지 않는다. (대신 service.py의 함수들을 import한다.)
  • 장점: 서로 완전히 분리되어 어디에서 오류가 났는지 알고 대응하기 편하다. (response error는 views, DB connection error는 service 등)
  • 단점: views.py에서 filter 한 번만 하면 되는데 이걸 굳이 하나의 레이어를 더 거쳐야 하는 경우 등 비효율적일 수 있다.
  • MVC 기반 프레임워크에서 볼 수 있는 양상으로, 스프링이 이를 활용한다고 한다.

Model Managers

  • 원래 장고가 활용하는 objects managers를 바꾼다.
  • 모델이 너무 방대해지고, 기존 모델 매니저를 쓰지 않는 게 확고하게 유리하다고 판단될 경우 사용하는 방법이다.
  • is_deleted가 True인 data를 exclude하는 경우 등 특정 모델메서드를 일반적인 상황에서 모두가 써야 하는 경우에 적합하다.

Service Layers 실습

  • app 폴더 안에 service.py 파일을 만든다. 함수보다는 class로 만들고 해당 class 안의 메서드로 정의하여 사용하는 것이 편하다. (ArticleService.method처럼)
  • 하지만 먼저 함수로 작업하고 불편함을 느껴보고 클래스로 전환하자.
  • service는 DB에 직접 접근하여 작업하는 것을 목적으로 한다. 중복 제거나 함수 처리가 목적이 아니므로 DB에 닿는 모든 처리만 service에 넣을 것
  • validation이나 helper 함수 역할을 하는 것은 service가 아닌 utils로 뺀다.

느낀 점

  • 방법론이 참 많기도 한 걸 보니 사람들은 정말 똑똑하다.
  • REST에 대해 공부하던 중에 수업에서도 마침 타이밍 좋게 배울 수 있어서 좋았다.