Django 아키텍처 2부: Container Diagram으로 백엔드 구조 정리하기

Container Diagram image

2부에서는 Container Diagram에 대해서 이야기 해보려고 하는데요. 第1部에서 시스템 컨텍스트 다이어그램으로 “이 시스템이 세상과 어떻게 연결돼 있는지”를 그려봤죠.

이제 한 단계 안으로 들어가서,

“시스템 안에는 어떤 구성요소(컨테이너) 들이 있고
서로 어떻게 통신하는가?”

를 보여주는 것이 바로 컨테이너 다이어그램(Container Diagram)です。

여기서 말하는 컨테이너(Container)
도커 컨테이너가 아니라, 역할 단위의 실행 컴포넌트라고 이해하시면 편해요.

  • Web App (Django)
  • Background Worker (Celery)
  • Database (Postgres / SQLite)
  • Cache (Redis 또는 LocMem)
  • Message Broker
  • Static file server
  • SMTP / Gmail

이런 것들이 전부 컨테이너가 되고,
이들을 연결해서 그린 그림이 바로 컨테이너 다이어그램입니다.

오늘 만들 컨테이너 다이어그램 구조 미리 보기

Container Diagram image

위와 같이 생성된 container.png는 대략 이런 구성을 담고 있습니다.

  • 위쪽
    • Web User (브라우저 사용하는 관리자/응답자/분석자)
  • 중앙 – Survey System 내부 컨테이너
    • Django Web App
      • HTTP 요청 처리, 템플릿 렌더링, REST API 제공
    • Celery Worker
      • 이메일 보내기, 대량 통계 처리 같은 백그라운드 작업
    • Database (SQLite / Postgres)
      • 설문, 면담, 응답, 조직, 사용자 데이터 저장
    • Cache (LocMem / Redis)
      • 세션/캐시
    • Static files
      • CSS, JS, 이미지 등 정적 파일
    • Message broker (RabbitMQ / Redis)
      • Celery 큐
    • SMTP / Gmail
      • 이메일 발송

이걸 텍스트로 모델링한 후 PlantUML로 그리면,
이쁜 컨테이너 다이어그램 PNG가 딱! 생성됩니다.

파일 준비 – container.puml 만들기

1부에서 만든 폴더를 그대로 씁니다.

# 이미 있다면 건너뛰기
mkdir -p docs/architecture

さあ docs/architecture/container.puml 파일을 만들고 편집기를 열어요.

컨테이너 다이어그램 기본 템플릿 코드

아래 코드를 통째로 붙여 넣으면,
현재 시스템과 거의 같은 컨테이너 다이어그램(Container Diagram)이 나옵니다.

@startuml
' C4-PlantUML 컨테이너 다이어그램용 라이브러리
!define C4P https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master
!includeurl C4P/C4_Container.puml

' 1) 사람(사용자) 정의
Person(web_user, "Web User", "브라우저로 설문에 응답하거나 면담을 관리하는 사용자")

' 2) 시스템 전체 박스
System_Boundary(survey_system, "Survey System") {

  ' 2-1) Django 웹 애플리케이션
  Container(django_app, "Django Web App", "Python / Django",
    "HTTP 요청 처리, 템플릿 렌더링, REST API 제공")

  ' 2-2) 백그라운드 작업용 Celery 워커
  Container(celery_worker, "Celery Worker", "Python / Celery",
    "이메일 발송, 대량 통계 처리 등 비동기 작업 실행")

  ' 2-3) 데이터베이스
  ContainerDb(database, "Database", "SQLite (dev) / Postgres (prod)",
    "사용자, 설문, 응답, 면담 기록 등 영속 데이터 저장")

  ' 2-4) 캐시 / 세션 저장소
  Container(cache, "Cache / Session Store", "LocMemCache / Redis",
    "세션, 빈번히 조회되는 데이터 캐시")

  ' 2-5) 정적 파일 서버
  Container(static_files, "Static Files", "Nginx 또는 Django",
    "CSS, JS, 이미지 같은 정적 자산 제공")

  ' 2-6) 메시지 브로커 (Celery 큐)
  Container(message_broker, "Message Broker", "Redis / RabbitMQ",
    "Celery 백그라운드 작업 큐")

  ' 2-7) 이메일 발송용 SMTP
  Container_Ext(smtp, "SMTP / Gmail", "외부 이메일 서비스",
    "알림, 인터뷰 초대 메일 발송")
}

' 3) 관계(Relationship) 정의
Rel(web_user, django_app, "HTTP 요청/응답 (설문, 면담, 대시보드)", "HTTPS")

Rel(django_app, database, "ORM으로 읽기/쓰기", "SQL")
Rel(django_app, cache, "세션/캐시 읽기·쓰기", "TCP")
Rel(django_app, static_files, "정적 파일 요청", "HTTP")
Rel(django_app, message_broker, "백그라운드 작업 enqueue", "AMQP / Redis")
Rel(django_app, smtp, "알림 이메일 발송", "SMTP")

Rel(celery_worker, database, "백그라운드에서 데이터 읽기·쓰기", "SQL")
Rel(celery_worker, message_broker, "작업 수신", "AMQP / Redis")
Rel(celery_worker, smtp, "대량 이메일 발송", "SMTP")

SHOW_LEGEND()
@enduml

이 코드가 바로 두 번째 그림인 Container Diagram의 소스에 해당합니다.

컨테이너 다이어그램 라인별 해설

컨테이너 다이어그램 그림

1) System_Boundary 블록

System_Boundary(survey_system, "Survey System") { ... }
  • Survey System이라는 하나의 큰 상자 안에
    여러 개의 컨테이너를 묶어줍니다.
  • 1부의 시스템 Container Diagram에서의 “System”을
    내부 구조로 쪼갠 버전이라고 보면 돼요.

2) Django Web App 컨테이너

Container(django_app, "Django Web App", "Python / Django",
  "HTTP 요청 처리, 템플릿 렌더링, REST API 제공")
  • URL, 뷰, 템플릿, DRF(API) 같은 주요 웹 로직이 다 여기.
  • 나중에 Container Diagram을 보면서
    “이 기능은 Celery Worker로 빼야겠다” 같은 리팩토링 아이디어를 얻기 쉽습니다.

3) Celery Worker 컨테이너

Container(celery_worker, "Celery Worker", "Python / Celery",
  "이메일 발송, 대량 통계 처리 등 비동기 작업 실행")
  • 장고에서 delay()로 보내는 작업들이 도는 곳.
  • 무거운 통계, 리포트 생성, 대량 이메일 등은
    Container Diagram 상에서 항상 Worker 쪽으로 빼두면 구조가 깔끔해집니다.

4) Database / Cache / Static Files

  • Database 컨테이너는 Django ORM이 붙는 쪽
  • Cache 컨테이너는 세션/캐시 역할
  • Static Files 컨테이너는 Nginx든, S3든, 정적 자산을 주는 역할

실제 구현은 조금씩 달라도,
컨테이너 다이어그램에서는 “역할” 기준으로만 깔끔하게 나누는 게 핵심입니다.

5) Message Broker + SMTP

Container Diagram에서 이 둘은 “외부이지만 시스템에 강하게 묶인” 느낌으로 표현합니다.

  • Message Broker: Celery가 의존하는 큐 시스템
  • SMTP: 외부 메일 서버지만, 서비스 입장에서 거의 필수 인프라

이렇게 적어두면, 나중에

“RabbitMQ에서 Redis로 바꿀까?”
“내부 SMTP 서버로 바꿀까?”

같은 논의가 나올 때
컨테이너 다이어그램을 기준으로 자연스럽게 이야기할 수 있습니다.

컨테이너 다이어그램 렌더링 (PNG 생성)

VSCode 플러그인일 때

  1. container.puml 파일 열기
  2. 미리보기 실행 → Container Diagram이 보이는지 확인
  3. 우클릭 → Export as PNG (확장에 따라 기능 이름이 조금 다를 수 있어요)

plantuml.jar일 때

java -jar tools/plantuml.jar docs/architecture/container.puml

실행 후 docs/architecture/container.png가 만들어지면,
이걸 사용하고자 하는 곳에 업로드해서 Container Diagram 설명섹션으로 사용하면 됩니다.

실무에서 컨테이너 다이어그램 활용 팁 3가지

  1. 배포 구조 논의의 기준으로 사용
    • “Django Web App은 몇 개?”
    • “Worker는 Auto Scaling 필요?”
    • “Redis는 세션/브로커 겸용인가, 분리인가?”
      이런 얘기를 할 때 컨테이너 다이어그램을 앞에 두고 회의하면
      말이 훨씬 빨리 통합니다.
  2. 장애 원인 정리 때 사용
    • 예: “Message Broker 장애 → Celery Worker → Django Web App 응답 지연”
      이런 식으로 장애 경로를 컨테이너 다이어그램 위에 표시하면
      보고서나 회의자료로도 훌륭합니다.
  3. 미래 구조(타겟 아키텍처) 그릴 때 복제해서 사용
    • 현재 구조(Container Diagram V1)와
    • 목표 구조(Container Diagram V2)를 두 장으로 만들어 두면
      “무엇을 바꿀지”가 확실해집니다.

컨테이너 다이어그램을 이렇게 써먹다 보면
자연스럽게 3부에서 다룰 컴포넌트 다이어그램으로 내려가는 흐름도 잡히게 돼요.

類似の投稿