이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.


Subgraph 기본#

Subgraph는 관련된 노드들을 논리적으로 그룹화하는 기능입니다. 시스템의 계층 구조나 도메인 영역을 시각적으로 구분할 때 유용합니다.

기본 문법#

flowchart TB
    subgraph 그룹명
        A --> B
    end
    C --> A
flowchart TB
    subgraph 그룹명
        A --> B
    end
    C --> A

ID와 제목 분리#

Subgraph에 별도의 ID를 지정하면 참조가 쉬워집니다.

flowchart TB
    subgraph api[API Layer]
        A[Controller]
        B[Service]
    end
    subgraph db[Data Layer]
        C[(MySQL)]
        D[(Redis)]
    end
    A --> B
    B --> C
    B --> D
flowchart TB
    subgraph api[API Layer]
        A[Controller]
        B[Service]
    end
    subgraph db[Data Layer]
        C[(MySQL)]
        D[(Redis)]
    end
    A --> B
    B --> C
    B --> D

Subgraph 방향 제어#

이것이 Mermaid 레이아웃의 핵심입니다. direction 키워드로 각 subgraph 내부의 배치 방향을 개별적으로 지정할 수 있습니다.

direction 키워드#

flowchart LR
    subgraph TOP[상단 영역]
        direction TB
        A --> B --> C
    end
    subgraph BOTTOM[하단 영역]
        direction TB
        D --> E --> F
    end
    TOP --> BOTTOM
flowchart LR
    subgraph TOP[상단 영역]
        direction TB
        A --> B --> C
    end
    subgraph BOTTOM[하단 영역]
        direction TB
        D --> E --> F
    end
    TOP --> BOTTOM

주의사항#

중요: Subgraph 내부의 노드가 외부 노드와 직접 연결되면, 해당 subgraph의 direction 설정이 무시되고 부모 flowchart의 방향을 따릅니다.

flowchart LR
    subgraph sub1[Direction이 무시되는 경우]
        direction TB
        A --> B
    end
    B --> C
    %% B가 외부 노드 C와 연결되어 direction TB가 무시됨
flowchart LR
    subgraph sub1[Direction이 무시되는 경우]
        direction TB
        A --> B
    end
    B --> C
    %% B가 외부 노드 C와 연결되어 direction TB가 무시됨

레이아웃 패턴 마스터하기#

패턴 1: 수평으로 나란한 그룹들 (메인 LR)#

전체는 좌→우로 배치하고, 각 그룹 내부는 위→아래로 배치합니다.

flowchart LR
    subgraph Frontend[프론트엔드]
        direction TB
        F1[React App]
        F2[Redux Store]
        F3[API Client]
        F1 --> F2 --> F3
    end

    subgraph Backend[백엔드]
        direction TB
        B1[API Gateway]
        B2[Auth Service]
        B3[Core Service]
        B1 --> B2
        B1 --> B3
    end

    subgraph Database[데이터베이스]
        direction TB
        D1[(PostgreSQL)]
        D2[(Redis Cache)]
        D1 --- D2
    end

    Frontend --> Backend --> Database
flowchart LR
    subgraph Frontend[프론트엔드]
        direction TB
        F1[React App]
        F2[Redux Store]
        F3[API Client]
        F1 --> F2 --> F3
    end

    subgraph Backend[백엔드]
        direction TB
        B1[API Gateway]
        B2[Auth Service]
        B3[Core Service]
        B1 --> B2
        B1 --> B3
    end

    subgraph Database[데이터베이스]
        direction TB
        D1[(PostgreSQL)]
        D2[(Redis Cache)]
        D1 --- D2
    end

    Frontend --> Backend --> Database

패턴 2: 수직으로 쌓인 그룹들 (메인 TB)#

전체는 위→아래로 배치하고, 각 그룹 내부는 좌→우로 배치합니다.

flowchart TB
    subgraph Presentation[프레젠테이션 계층]
        direction LR
        P1[Web UI] --- P2[Mobile App] --- P3[Admin Panel]
    end

    subgraph Business[비즈니스 계층]
        direction LR
        B1[User Service] --- B2[Order Service] --- B3[Payment Service]
    end

    subgraph Data[데이터 계층]
        direction LR
        D1[(Users DB)] --- D2[(Orders DB)] --- D3[(Payment DB)]
    end

    Presentation --> Business --> Data
flowchart TB
    subgraph Presentation[프레젠테이션 계층]
        direction LR
        P1[Web UI] --- P2[Mobile App] --- P3[Admin Panel]
    end

    subgraph Business[비즈니스 계층]
        direction LR
        B1[User Service] --- B2[Order Service] --- B3[Payment Service]
    end

    subgraph Data[데이터 계층]
        direction LR
        D1[(Users DB)] --- D2[(Orders DB)] --- D3[(Payment DB)]
    end

    Presentation --> Business --> Data

패턴 3: 3열 그리드 레이아웃#

flowchart TB
    subgraph Row1[입력 처리]
        direction LR
        A1[HTTP 요청] --- A2[검증] --- A3[파싱]
    end

    subgraph Row2[비즈니스 로직]
        direction LR
        B1[인증] --- B2[권한확인] --- B3[처리]
    end

    subgraph Row3[출력 처리]
        direction LR
        C1[직렬화] --- C2[압축] --- C3[응답]
    end

    Row1 --> Row2 --> Row3
flowchart TB
    subgraph Row1[입력 처리]
        direction LR
        A1[HTTP 요청] --- A2[검증] --- A3[파싱]
    end

    subgraph Row2[비즈니스 로직]
        direction LR
        B1[인증] --- B2[권한확인] --- B3[처리]
    end

    subgraph Row3[출력 처리]
        direction LR
        C1[직렬화] --- C2[압축] --- C3[응답]
    end

    Row1 --> Row2 --> Row3

패턴 4: 중첩 Subgraph#

Subgraph는 중첩이 가능합니다.

flowchart TB
    subgraph Cloud[AWS Cloud]
        subgraph VPC[VPC]
            subgraph Public[Public Subnet]
                ALB[Application Load Balancer]
            end
            subgraph Private[Private Subnet]
                EC2[EC2 Instances]
                RDS[(RDS)]
            end
        end
    end

    User[사용자] --> ALB
    ALB --> EC2
    EC2 --> RDS
flowchart TB
    subgraph Cloud[AWS Cloud]
        subgraph VPC[VPC]
            subgraph Public[Public Subnet]
                ALB[Application Load Balancer]
            end
            subgraph Private[Private Subnet]
                EC2[EC2 Instances]
                RDS[(RDS)]
            end
        end
    end

    User[사용자] --> ALB
    ALB --> EC2
    EC2 --> RDS

패턴 5: 마이크로서비스 아키텍처#

flowchart LR
    Client[Client App]

    subgraph Gateway[API Gateway]
        direction TB
        Kong[Kong]
        Auth[Auth Middleware]
        Kong --> Auth
    end

    subgraph Services[Microservices]
        direction TB
        subgraph Core[Core Domain]
            direction LR
            UserSvc[User Service]
            OrderSvc[Order Service]
        end
        subgraph Support[Support Domain]
            direction LR
            NotifySvc[Notification]
            LogSvc[Logging]
        end
    end

    subgraph Data[Data Stores]
        direction TB
        MySQL[(MySQL)]
        Redis[(Redis)]
        Kafka[Kafka]
    end

    Client --> Gateway --> Services
    Core --> Data
    Support --> Kafka
flowchart LR
    Client[Client App]

    subgraph Gateway[API Gateway]
        direction TB
        Kong[Kong]
        Auth[Auth Middleware]
        Kong --> Auth
    end

    subgraph Services[Microservices]
        direction TB
        subgraph Core[Core Domain]
            direction LR
            UserSvc[User Service]
            OrderSvc[Order Service]
        end
        subgraph Support[Support Domain]
            direction LR
            NotifySvc[Notification]
            LogSvc[Logging]
        end
    end

    subgraph Data[Data Stores]
        direction TB
        MySQL[(MySQL)]
        Redis[(Redis)]
        Kafka[Kafka]
    end

    Client --> Gateway --> Services
    Core --> Data
    Support --> Kafka

Subgraph 간 연결#

Subgraph 자체를 노드처럼 연결할 수 있습니다.

flowchart LR
    subgraph A[서비스 A]
        A1 --> A2
    end
    subgraph B[서비스 B]
        B1 --> B2
    end
    subgraph C[서비스 C]
        C1 --> C2
    end

    A --> B
    B --> C
    A --> C
flowchart LR
    subgraph A[서비스 A]
        A1 --> A2
    end
    subgraph B[서비스 B]
        B1 --> B2
    end
    subgraph C[서비스 C]
        C1 --> C2
    end

    A --> B
    B --> C
    A --> C

내부 노드와 외부를 연결할 수도 있습니다.

flowchart LR
    subgraph Producer[Producer]
        P[메시지 생성]
    end

    Queue[(Message Queue)]

    subgraph Consumer[Consumer]
        C[메시지 처리]
    end

    P --> Queue --> C
flowchart LR
    subgraph Producer[Producer]
        P[메시지 생성]
    end

    Queue[(Message Queue)]

    subgraph Consumer[Consumer]
        C[메시지 처리]
    end

    P --> Queue --> C

스타일링#

classDef로 스타일 정의#

flowchart LR
    classDef primary fill:#4F46E5,stroke:#3730A3,color:white
    classDef secondary fill:#10B981,stroke:#059669,color:white
    classDef danger fill:#EF4444,stroke:#DC2626,color:white
    classDef database fill:#F59E0B,stroke:#D97706,color:black

    A[시작]:::primary --> B[처리]:::secondary
    B --> C{조건}
    C -->|성공| D[(저장)]:::database
    C -->|실패| E[에러]:::danger
flowchart LR
    classDef primary fill:#4F46E5,stroke:#3730A3,color:white
    classDef secondary fill:#10B981,stroke:#059669,color:white
    classDef danger fill:#EF4444,stroke:#DC2626,color:white
    classDef database fill:#F59E0B,stroke:#D97706,color:black

    A[시작]:::primary --> B[처리]:::secondary
    B --> C{조건}
    C -->|성공| D[(저장)]:::database
    C -->|실패| E[에러]:::danger

여러 노드에 스타일 적용#

flowchart LR
    classDef serviceStyle fill:#E0E7FF,stroke:#4F46E5

    A[Service A]
    B[Service B]
    C[Service C]

    class A,B,C serviceStyle

    A --> B --> C
flowchart LR
    classDef serviceStyle fill:#E0E7FF,stroke:#4F46E5

    A[Service A]
    B[Service B]
    C[Service C]

    class A,B,C serviceStyle

    A --> B --> C

연결선 스타일링#

flowchart LR
    A --> B --> C --> D

    linkStyle 0 stroke:#ff3,stroke-width:4px
    linkStyle 1 stroke:#3f3,stroke-width:2px
    linkStyle 2 stroke:#33f,stroke-width:2px,stroke-dasharray:5
flowchart LR
    A --> B --> C --> D

    linkStyle 0 stroke:#ff3,stroke-width:4px
    linkStyle 1 stroke:#3f3,stroke-width:2px
    linkStyle 2 stroke:#33f,stroke-width:2px,stroke-dasharray:5

linkStyle 뒤의 숫자는 0부터 시작하는 연결선의 순서입니다.

default 클래스#

default라는 이름의 클래스는 모든 노드에 자동 적용됩니다.

flowchart LR
    classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px

    A --> B --> C
flowchart LR
    classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px

    A --> B --> C

실전 예제: 주문 처리 시스템#

flowchart TB
    classDef userAction fill:#DBEAFE,stroke:#3B82F6
    classDef process fill:#D1FAE5,stroke:#10B981
    classDef decision fill:#FEF3C7,stroke:#F59E0B
    classDef data fill:#E0E7FF,stroke:#6366F1
    classDef error fill:#FEE2E2,stroke:#EF4444

    subgraph Client[클라이언트]
        direction LR
        Order[주문 요청]:::userAction
    end

    subgraph OrderService[주문 서비스]
        direction TB
        Validate[주문 검증]:::process
        CheckStock{재고 확인}:::decision
        Reserve[재고 예약]:::process
        NoStock[재고 부족]:::error
    end

    subgraph PaymentService[결제 서비스]
        direction TB
        Payment[결제 처리]:::process
        PayResult{결제 결과}:::decision
        PayFail[결제 실패]:::error
    end

    subgraph FulfillmentService[배송 서비스]
        direction TB
        Ship[배송 준비]:::process
        Notify[알림 발송]:::process
    end

    subgraph DataStores[데이터 저장소]
        direction LR
        OrderDB[(주문 DB)]:::data
        InventoryDB[(재고 DB)]:::data
        EventBus[Event Bus]:::data
    end

    Order --> Validate
    Validate --> CheckStock
    CheckStock -->|있음| Reserve
    CheckStock -->|없음| NoStock
    Reserve --> Payment
    Payment --> PayResult
    PayResult -->|성공| Ship
    PayResult -->|실패| PayFail
    Ship --> Notify

    Reserve --> InventoryDB
    Payment --> OrderDB
    Notify --> EventBus
flowchart TB
    classDef userAction fill:#DBEAFE,stroke:#3B82F6
    classDef process fill:#D1FAE5,stroke:#10B981
    classDef decision fill:#FEF3C7,stroke:#F59E0B
    classDef data fill:#E0E7FF,stroke:#6366F1
    classDef error fill:#FEE2E2,stroke:#EF4444

    subgraph Client[클라이언트]
        direction LR
        Order[주문 요청]:::userAction
    end

    subgraph OrderService[주문 서비스]
        direction TB
        Validate[주문 검증]:::process
        CheckStock{재고 확인}:::decision
        Reserve[재고 예약]:::process
        NoStock[재고 부족]:::error
    end

    subgraph PaymentService[결제 서비스]
        direction TB
        Payment[결제 처리]:::process
        PayResult{결제 결과}:::decision
        PayFail[결제 실패]:::error
    end

    subgraph FulfillmentService[배송 서비스]
        direction TB
        Ship[배송 준비]:::process
        Notify[알림 발송]:::process
    end

    subgraph DataStores[데이터 저장소]
        direction LR
        OrderDB[(주문 DB)]:::data
        InventoryDB[(재고 DB)]:::data
        EventBus[Event Bus]:::data
    end

    Order --> Validate
    Validate --> CheckStock
    CheckStock -->|있음| Reserve
    CheckStock -->|없음| NoStock
    Reserve --> Payment
    Payment --> PayResult
    PayResult -->|성공| Ship
    PayResult -->|실패| PayFail
    Ship --> Notify

    Reserve --> InventoryDB
    Payment --> OrderDB
    Notify --> EventBus

보이지 않는 연결선으로 레이아웃 조정#

때로는 노드 배치를 원하는 대로 조정하기 위해 보이지 않는 연결선이 필요합니다.

flowchart LR
    A --> B
    B --> C

    %% D를 C와 같은 높이에 배치하고 싶을 때
    A ~~~ D
    D --> E
flowchart LR
    A --> B
    B --> C

    %% D를 C와 같은 높이에 배치하고 싶을 때
    A ~~~ D
    D --> E

~~~는 보이지 않는 연결선을 만듭니다. 렌더링 엔진에게 노드 간의 관계를 암시하여 배치를 조정합니다.

Configuration으로 전역 설정#

YAML frontmatter로 다이어그램 전체 설정을 변경할 수 있습니다.

---
config:
  flowchart:
    curve: basis
    defaultRenderer: elk
---
flowchart LR
    A --> B --> C
---
config:
  flowchart:
    curve: basis
    defaultRenderer: elk
---
flowchart LR
    A --> B --> C

주요 설정 옵션#

옵션설명기본값
curve연결선 곡선 스타일basis
defaultRenderer렌더러 (dagre, elk)dagre
nodeSpacing노드 간 간격50
rankSpacing계층 간 간격50

ELK 렌더러#

복잡한 다이어그램에서는 elk 렌더러가 더 나은 레이아웃을 제공하기도 합니다.

---
config:
  flowchart:
    defaultRenderer: elk
---
flowchart TB
    subgraph A[Group A]
        A1 --> A2 --> A3
    end
    subgraph B[Group B]
        B1 --> B2 --> B3
    end
    A1 --> B1
    A2 --> B2
    A3 --> B3
---
config:
  flowchart:
    defaultRenderer: elk
---
flowchart TB
    subgraph A[Group A]
        A1 --> A2 --> A3
    end
    subgraph B[Group B]
        B1 --> B2 --> B3
    end
    A1 --> B1
    A2 --> B2
    A3 --> B3

레이아웃 제어 요약 치트시트#

원하는 결과메인 방향Subgraph 내부 방향
그룹들이 가로로 나란히, 내부는 세로LRdirection TB
그룹들이 세로로 쌓임, 내부는 가로TBdirection LR
모두 가로로LRdirection LR
모두 세로로TBdirection TB

배치 원칙#

  1. 외부 연결 주의: Subgraph 내부 노드가 외부와 연결되면 direction이 무시됨
  2. Subgraph 단위 연결 권장: 복잡한 레이아웃에서는 subgraph 자체를 연결
  3. 보이지 않는 연결선 활용: ~~~로 배치 힌트 제공
  4. ELK 렌더러 시도: 기본 렌더러로 원하는 결과가 안 나오면 elk 사용