본문 바로가기
django

장고에 대하여

by shinminkyoung 2025. 1. 7.

1.1 웹 프로그래밍과 백엔드 프로그래밍

웹 프로그래밍: 서버와 클라이언트 개발을 분리하지 않고 양쪽 개발을 한 번에 하는 개발 방식

SPA (single page application): 하나의 페이지만 존재하는 웹 애플리케이션

  • 웹의 각 페이지마다 HTML 파일이 별도로 존재하고 페이지를 이동하면 브라우저에서 해당 페이지의 HTML을 받아와서 화면에 표시해주는 원리

요즘은 웹 프로그래밍 방식이 아닌 분업화된 방식을 주로 사용

1.2 장고 MTV 아키텍처: 템플릿의 한계

MTV: Model / Template / View → 장고의 모듈과 매핑됨

  • Model
from django.db import models

class AModel(models.Model);
	....
  • Template
<!DOCTYPE html>
html lang="en">

<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title> Title...</title>
</head>
....
  • View
from django.views.generic import TemplateView

class MainPageTemplateView(TemplateView):
		template_name = 'pages/dashboard/dashboard.html'

→ 3개의 모듈을 사용해서 애플리케이션을 개발하기에 장고의 개발 방식은 MTV 패턴 기반으로 이루어짐

이때, 장고의 Template은 자바스크립트의 기능 중 하나인 UI(HTML)에 데이터를 전달해주는 역할을 대신 함

MTV 방식의 웹 애플리케이션에서는 Template이 데이터를 전달해주기도 하며 자바스크립트가 전달해주기도 함

  • MTV 패턴은 최근 웹 애플리케이션 개발 트렌드에서 그리 선호하지 않는 개발 방식
  • 일정 수준 이상의 복잡도가 요구되는 서비스를 개발하기 위해 MTV 패턴의 템플릿이 해야 하는 역할을 자바스크립트(프론트엔드)가 전부 대체하기 때문

→ 앞으로 template에 대한 내용을 다루지 않을 것 (다시 언급하자면, 백엔드와 프론트엔드 분업되어 있으면 template 모듈은 거의 사용되지 않음)

대신, URL-Resolver, DRF-라우터, 쿼리셋, 미들웨어, Request/Response, DRF-Serializer 등과 같은 사용 빈도 높은 모듈에 대해 다룰 것

1.3 장고란 무엇인가

1.3.1 풀스택 프레임워크

  • 장고라는 생태계 내부에서 대부분의 기능이 전부 제공됨
  • 자체 ORM을 가지는 몇 안 되는 파이썬 웹 프레임워크
    • 필수 모듈 중 하나인 django REST framework를 붙이면 풀스택 웹 프레임워크로도 볼 수 있음
  • 풀스택 웹 프레임워크는 마이크로 프레임워크와 다르게 1가지를 더 고민함
    • ‘높은 복잡 도를 가지는 프로젝트의 각 도메인과 모듈 간 계층이 높은 응집도와 낮은 결합도를 가질 수 있도록 시스템 아키텍처를 분리할 수 있는가’

+) 도메인이란?

소프트웨어로 해결하고자 하는 문제 영역

DDD (Domain Driven Design)의 개념과 관련이 있는데 이는 매우 추상적

→ django App (장고 앱): 장고는 장고 앱이라는 단위로 도메인을 분리할 수 있는 아키텍처를 제공

  • 시스템 복잡도를 낮추기 위해서는 도메인과 모듈 간 계층을 분리하는 것이 중요
  • → 장고에서는 이러한 고민을 장고 앱이라는 단위의 분리 방식을 적용할 것을 제안
  • 장고는 복잡한 시스템을 분리할 수 있는 아키텍처를 제공하기에 개발자는 별다른 고민 없이 장고가 제공하는 패턴을 지키면서 개발할 수 있는 장점을 제공함
  • 하지만, 반대로 장고가 제공하는 패턴을 지키지 않으면 개발을 할 수 없는 제약이 존재

정리하자면, 장고가 다양한 조건을 두기에 개발자에 입장에서는 편할 수도, 제약으로 여겨질 수도 있음

1.3.2 장고 이외의 다양한 선택지

  1. 플라스크: 가장 인기 있는 파이썬 마이크로 프레임워크로 간결하다는 장점이 있음
  2. FastAPI: 2018년 탄생. 가장 빠른 성능을 보여주며 문법도 간결함

1.3.3 주니어 개발자가 장고를 선택해야 하는 이유

  1. 대중성
  2. 풀스택 프레임워크
  3. 거대한 커뮤니티 조성/트러블슈팅 정보량의 차이

1.3.4 시니어 개발자 또는 테크 리더가 장고를 선택해야 하는 이유

FastAPI와 장고는 추구하는 방향이 다름

비즈니스 로직이 상대적으로 덜 방대하거나 특정 영역에 집중해야 하는 서비스는 FastAPI와 같은 마이크로 웹 프레임워크로 구축하는 것이 유리함

하지만, 마이크로 프레임워크로 프로젝트를 진행하다 보면 장고에서는 이미 라이브러리로 제공되는 기능을 일일이 구현하느라 시간을 많이 소비할 수 있음

1.3.5 장고의 설계 철학

  1. 낮은 결합도 (Loose coupling)
    • ‘결합도는 낮게 응집도는 높게’
  2. 암시적인 것보다 명시적인 것이 낫다
    • 개발자가 예상하지 못하는 동작은 일으키지 않아야 함
    • 암시적인 동작을 만들기보다 (오버라이딩 하는 등) 차라리 커스텀한 메서드를 새로 만드는 게 낫다
    • 명시적으로 동작하게 하거나, 아니면 장고의 시그널을 활용하는 방법 존재
  3. 장고의 시그널
    • 메서드를 오버라이딩해야 하는 상황이 불가피하다면 장고의 시그널을 사용
    • 시그널은 어떠한 동작이 수행되었을 때 이를 신호로 받아서 다른 동작을 수행하도록 해주는 기능
      • ex. 계좌와 같은 민감한 데이터는 항상 변경될 때마다 변경 전 잔고와 변경 후 잔고 값을 이력으로 저장해놓아야 한다면 시그널을 사용해서 코드를 작성
      • 시그널 작성 예시
        • save() 메서드를 오버라이딩하지 않고도 모델이 save()를 수행한 다음 이 코드를 수행함
      • # accounts.models.signals.py 패키지를 생성 from django.db.models.signals import post_save # pre_save도 존재한다. save() 수행 직전을 의미함 from django.dispatch import receiver from django.models import Account @receiver(post_save, sender=Account) def log_the_balance_after_save(sender, **kwargs): # 로그를 쌓는 로직 작성 print("Account 모델이 .save() 될 때마다 print됩니다.")
      • 뷰에는 코드가 세 개의 시그널이 존좨함
      • request_started // API 요청이 들어왔을 때 request_finished // API 요청이 끝났을 때 got_request_exception // API 요청이 수행 도중 실패했을 때
    • 시그널을 남용하면 안 됨.
    • 시그널 사용 원칙의 예시
      • 시그널 로직은 반드시 models/signals.py 또는 views/signals.py 패키지 안에서만 작성하자.
      • 이력을 쌓아야 하는 경우에만 시그널을 사용하자.
  4. 모델 모듈이 도메인 로직을 캡슐화하도록 작성
    • 장고에는 Fat Model 패턴이 있음
    • 특정 모델과 관련된 데이터 조작 메서드를 모델 내부에 구현하여 모델을 사용하는 외부 모듈이 가벼워지게 하는 방식
  5. 효율적인 SQL 수행
    • SQL 수행은 프레임워크 관점에서 굉장히 무거운 동작이기에 가능한 한 적게 수행되어야 하고 내부적으로 최적화되어야 함
    • 장고의 쿼리셋은 이러한 철학을 따름

1.3.6 장고 어드민

  • 장고 어드민은 실무에서 사용하기 ㅇ매우 어려움
  • 고정된 UI에서 다양한 장고의 모델 기반으로 데이터를 제어할 수 있는 것
  • 설계 목적에 맞게 장고 어드민이 제공하는 모델 어드민 옵션을 사용한다면 매우 적은 코드량으로도 데이터를 CRUD 처리할 수 있음
  • 하지만, 프론트엔드로의 확장은 불가능

1.4 앞으로 사용할 라이브러리

  • poetry
  • mypy
  • black
  • django
  • django-restframework
  • django-extensions
  • drf-spectacular

1.4.1 poetry

파이썬 프로젝트 의존성 관리 도구 (requirements.txt 대체제)

  • poetry의 기본적인 명령어
    • poetry show → 현재 프로젝트에 설치된 패키지 정보를 전부 보여줌
    • (pip list와 동일한 동작)
    • poetry install → 현재 프로젝트에서 pyproject.toml 파일이 선언되어 있는 패키지를 설치
    • (pip install -r requirement.txt와 동일한 동작)
    • poetry add “라이브러리명=^2.25.1” → 라이브러리 설치
    • (pip install “라이브러리명=^2.25.1”과 동일한 동작)
    • poetry update 라이브러리명 → 현재 프로젝트에서 사용하는 해당 라이브러리의 버전을 현재 사용 가능한 가장 최신 버전으로 업데이트한다.
    • poetry remove 라이브러리명 → 현재 프로젝트에서 해당 라이브러리를 삭제한다.
    • (poetry uninstall 라이브러리명과 동일)

1.4.2 mypy

선택적 정적 타입 검사기 (optional static type checker)

  • 자바스크립트 진영에서는 타입을 강하게 제약하는 타입스크립트를 만들기도 함
  • 파이썬에서는 3.5 버전부터 타입 힌트라는 문법을 지원하기 시작했고 mypy라는 정적 타입체크 도구를 제공
  • 파이썬 3.5 버전부터 타입 힌트라는 문법이 지원되기 시작했는데 이 문법으로 함수, 변수 등에 타입을 명시할 수 있음
  • 하지만, 타입 힌트 문법은 강제성이 없음

1.4.3 black

코드 포매터 (Code Formatter)

  • 프로젝트 내 모든 코드를 black의 방식대로 강제 포매팅
  • 소스 코드의 통일성을 유지

1.4.4 장고

파이썬 풀스택 웹 프레임워크

  • 유일한 파이썬 풀스택 프레임워크

1.4.5 django REST framework (DRF)

장고 백엔드 프로그래밍을 위한 필수 모듈

  • DRF는 장고의 템플릿 뷰를 대신하여 API 방식으로 개발하기 위한 다양한 뷰 구현체를 제공 (APIView, GenericView, ViewSet)
  • 웹 프로그래밍을 하기 위해서라면 장고만으로도 충분하지만 백엔드 프로그래밍을 위해서는 장고가 제공하는 기능만으로 부족한데 DRF가 이 부분을 채워주는 역할

1.4.6 django-filter

  • 장고 템플릿을 개발할 때 데이터 검색 기능을 손쉽게 개발 가능하게 해주는 라이브러리
  • 템플릿 뿐만 아니라 DRF와 연계해서 검색 API를 만들 때 검색 조건을 개발할 수 있게 해줌

1.4.7 django-extensions

  • 필수 모듈들은 아니지만 많은 편의성을 제공
  • ex. runserver_plus: 기존 runserver로 수행 시 로그를 나타낸 것

1.4.8 drf-spectacular

OAS(OpenAPI Specification) 지원 라이브러리

  • API 문서 자동화 도구 (Swagger Redoc)를 지원
  • 이 라이브러리를 사용하면 DRF로 개발한 API를 drf-spectacular가 자동으로 문서화해줌
  • from drf_spectacular.utils import extend_schema from rest_frameword.viewsets import GenericViewSet # ... class DjangoModelViewSet(GenericViewSet): queryset = DjangoModel.objects.all() serializer_class = DjangoModelSerializer def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginaged_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)

1.5 프로젝트 환경 설정

1.5.1 pyenv와 poetry 설치

  1. pyenv
    • 다양한 버전의 파이썬을 관리하는 명령어 툴
    • 파이썬 프로젝트를 만들려고 하면 로컬 컴퓨터에 파이썬이 설치되어 있어야 하는데 이때 사용하는 것이 pyvenv
    • 파이썬 환경을 붕어빵이라고 한다면 pyenv는 다양한 파이썬 버전을 미리 로컬에 저장해두고 복사할 준비가 되어 있는 붕어빵 틀
    python virtual environment (파이썬 가상 환경)pyenv 명령어 사용법
    1. 현재 로컬에 설치된 파이썬 버전 조회
    2. pyenv versions
    3. 현재 설치 가능한 파이썬 목록
    4. pyenv install -list
    5. 특정 버전의 파이썬 설치
    6. pyenv install 3.11.1
    7. 로컬 컴퓨터 내에서 기본으로 사용할 파이썬 버전 설정
    8. pyenv global 3.11.1
    9. 로컬 내 특정 하위폴더에서 사용할 파이썬 버전 설정
    10. pyenv local 3.11.1
    (pyenv로 로컬 개발 환경 설정 예시)
  2. pyenv install 3.11.1 pyenv install 3.10.9 pyenv versions # 3.10과 3.11 설치되었는지 확인 pyenv global 3.11.1 # 특별한 이유가 없다면 3.11.1을 기본으로 사용하도록 선언
  3. : 파이썬 프로젝트에서 사용하는 파이썬 환경을 파이썬 가상환경이라고 부름. 축약어가 venv
  4. poetry
    • pyenv는 로컬 컴퓨터 내에 다양한 버전의 파이썬을 미리 저장해놓는 저장소의 역할
    • 새로운 파이썬 프로젝트를 생성할 때 pyenv에 설치된 여러 버전의 파이썬 중 하나를 복사해서 사용하기에 직접 건드리지 않는 것이 좋음
    • 그렇다면 새로운 파이썬 프로젝트를 생성할 때 pyenv로 설치한 파이썬에서 어떻게 venv를 설정하고 관리하는가?
      • 이러한 역할을 해주는 것이 poetry
    • poetry로 새로운 파이썬 프로젝트를 생성하는 예시
    • poetry new hello_new_python_project # 파이썬 프로젝트 생성 cd hello_new_python_project # 프로젝트 폴더로 접근 poetry shell # pyproject.toml 파일에 명시된 파이썬 버전으로 venv를 찾거나 없음녀 생성
    • poetry new 명령어로 프로젝트 생성
    • poetry new 프로젝트명
    • 파이썬 프로젝트에 사용되는 파이썬 버전, 프로젝트 이름, 사용하는 라이브러리와 같은 정보를 담아두고 관리하는 파일 → pyproject.toml

macOS에서의 pyenv 설치

brew install pyenv
  • xcode 설치
xcode-select --install
  • brew 설치
/bin/bash -c "$(curl -fsSL <https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh>)"

macOS에서의 poetry 설치

curl -sSL <https://install.python-poetry.org> | python3 -
  • 프로젝트 생성해서 테스트
poetry new hello_new_python_project # 프로젝트 생성
poetry shell # virtualenv 생성

-poetry 2.0.0 버전에서는 shell 명령어 x

Poetry 2.0.0 버전에서는 poetry shell 명령어가 지원되지 않는 것으로 보입니다. 대신 poetry env use python3명령어로 가상 환경을 생성하고 설정한 상태입니다. 이제 직접 가상 환경을 활성화하면 됩니다.


1. 가상 환경 활성화

Poetry가 생성한 가상 환경은 아래 경로에 있습니다:

/Users/minkyoungshin/Library/Caches/pypoetry/virtualenvs/hello-new-python-project-KSuzRPgQ-py3.13

→ 이 경로를 이후 마지막 개발 환경 세티에서 사용함! 중요

아래 명령어를 사용해 가상 환경을 활성화하세요:

source /Users/minkyoungshin/Library/Caches/pypoetry/virtualenvs/hello-new-python-project-KSuzRPgQ-py3.13/bin/activate

-실행한 결과

minkyoungshin@Minkyoung-MacBook-Air hello_new_python_project % source /Users/minkyoungshin/Library/Caches/pypoetry/virtualenvs/hello-new-python-project-KSuzRPgQ-py3.13/bin/activate
(hello-new-python-project-py3.13) minkyoungshin@Minkyoung-MacBook-Air hello_new_python_project %
  • 실행 터미널 로그
  • Last login: Tue Dec 17 17:48:40 on ttys074 minkyoungshin@Minkyoung-MacBook-Air ~ % curl -sSL <https://install.python-poetry.org> | python3 - Retrieving Poetry metadata # Welcome to Poetry! This will download and install the latest version of Poetry, a dependency and package manager for Python. It will add the `poetry` command to Poetry's bin directory, located at: /Users/minkyoungshin/.local/bin You can uninstall at any time by executing this script with the --uninstall option, and these changes will be reverted. Installing Poetry (2.0.0): Done Poetry (2.0.0) is installed now. Great! To get started you need Poetry's bin directory (/Users/minkyoungshin/.local/bin) in your `PATH` environment variable. Add `export PATH="/Users/minkyoungshin/.local/bin:$PATH"` to your shell configuration file. Alternatively, you can call Poetry explicitly with `/Users/minkyoungshin/.local/bin/poetry`. You can test that everything is set up by executing: `poetry --version` minkyoungshin@Minkyoung-MacBook-Air ~ % poetry new hello_new_python_project zsh: command not found: poetry minkyoungshin@Minkyoung-MacBook-Air ~ % poetry --version zsh: command not found: poetry minkyoungshin@Minkyoung-MacBook-Air ~ % export PATH="/Users/minkyoungshin/.local/bin:$PATH" minkyoungshin@Minkyoung-MacBook-Air ~ % nano ~/.zshrc minkyoungshin@Minkyoung-MacBook-Air ~ % source ~/.zshrc minkyoungshin@Minkyoung-MacBook-Air ~ % echo $PATH /opt/homebrew/opt/mysql@8.0/bin:/usr/local/mysql/bin:/usr/local/mysql/bin:/Users/minkyoungshin/.local/bin:/opt/homebrew/opt/mysql@8.0/bin:/usr/local/mysql/bin:/Users/minkyoungshin/.local/bin:/opt/homebrew/opt/mysql@8.0/bin:/usr/local/mysql/bin:/usr/local/mysql/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/Library/Frameworks/Python.framework/Versions/3.12/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin minkyoungshin@Minkyoung-MacBook-Air ~ % poetry --version Poetry (version 2.0.0) minkyoungshin@Minkyoung-MacBook-Air ~ % poetry new hello_new_python_project Created package hello_new_python_project in hello_new_python_project minkyoungshin@Minkyoung-MacBook-Air ~ % poetry shell The command "shell" does not exist. minkyoungshin@Minkyoung-MacBook-Air ~ % poetry help Description: Displays help for a command. Usage: help [options] [--] [] Arguments: command_name The command name [default: "help"] Options: -h, --help Display help for the given command. When no command is given display help for the list command. -q, --quiet Do not output any message. -V, --version Display this application version. --ansi Force ANSI output. --no-ansi Disable ANSI output. -n, --no-interaction Do not ask any interactive question. --no-plugins Disables plugins. --no-cache Disables Poetry source caches. -P, --project=PROJECT Specify another path as the project root. All command-line arguments will be resolved relative to the current working directory. -C, --directory=DIRECTORY The working directory for the Poetry command (defaults to the current working directory). All command-line arguments will be resolved relative to the given directory. -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug. Help: The help command displays help for a given command: poetry help list To display the list of available commands, please use the list command. minkyoungshin@Minkyoung-MacBook-Air ~ % poetry env use python3 Poetry could not find a pyproject.toml file in /Users/minkyoungshin or its parents minkyoungshin@Minkyoung-MacBook-Air ~ % poetry self update Updating Poetry version ... Poetry could not find a pyproject.toml file in /Users/minkyoungshin or its parents minkyoungshin@Minkyoung-MacBook-Air ~ % poetry shell The command "shell" does not exist. minkyoungshin@Minkyoung-MacBook-Air ~ % curl -sSL <https://install.python-poetry.org> | python3 - Retrieving Poetry metadata The latest version (2.0.0) is already installed. minkyoungshin@Minkyoung-MacBook-Air ~ % cd hello_new_python_project minkyoungshin@Minkyoung-MacBook-Air hello_new_python_project % poetry shell The command "shell" does not exist. minkyoungshin@Minkyoung-MacBook-Air hello_new_python_project % poetry env use python3 Creating virtualenv hello-new-python-project-KSuzRPgQ-py3.13 in /Users/minkyoungshin/Library/Caches/pypoetry/virtualenvs Using virtualenv: /Users/minkyoungshin/Library/Caches/pypoetry/virtualenvs/hello-new-python-project-KSuzRPgQ-py3.13 minkyoungshin@Minkyoung-MacBook-Air hello_new_python_project % source /Users/minkyoungshin/Library/Caches/pypoetry/virtualenvs/hello-new-python-project-KSuzRPgQ-py3.13/bin/activate (hello-new-python-project-py3.13) minkyoungshin@Minkyoung-MacBook-Air hello_new_python_project %

1.5.2 개발환경 설정

  1. 소스코드를 작성할 때 필요한 통합 개발 환경 (IDE)인 파이참 (PyCharm)을 다운로드
  2. 터미널 창에서 poetry shell 명령어 입력
  3. → poetry가 virtualenv를 찾거나 생성
  4. PyCharm 메뉴에서 ‘Settings’를 선택하고 ‘Python Interpreter’에서 ‘Show All’을 선택
  5. [+] 버튼을 누른 뒤 Interpreter Pathdp virtualevn가 설치된 경로와 ‘bin/python’을 입력하고 [OK] 버튼
    • main.py
    • if __name__ == '__main__': print("Hello Pycharm with poetry") main.py 생성 후 Run main으로 수행 확인

https://github.com/KimSoungRyoul/backend-handson-django

'django' 카테고리의 다른 글

모델링과 마이그레이션 (2)  (2) 2025.01.15
모델링과 마이그레이션 (1)  (3) 2025.01.15
3 - ORM과 Django Rest Framework (1)  (1) 2024.05.23
2 - Django Template과 Model  (4) 2024.05.22
1 - web과 Django 기초  (2) 2024.05.11