튜토리얼

아키텍처 다이어그램 생성하기

IBM Bob을 사용해 Galaxium Travels 코드베이스를 분석하고 Mermaid UML 클래스 다이어그램, 시퀀스 다이어그램, 유스케이스 다이어그램을 생성합니다. Ask mode에서 컨텍스트 멘션을 활용해 코드를 탐색하고, Agent mode로 결과물을 저장소에 저장하는 방법을 배웁니다.

아키텍처 다이어그램은 코드베이스를 수정하기 전에 팀이 공유할 수 있는 시각적 언어를 제공합니다. 이 튜토리얼에서는 Bob을 사용해 Galaxium Travels 소스 파일을 읽고 세 가지 유형의 UML 다이어그램, 즉 UML 클래스 다이어그램, 시퀀스 다이어그램, 유스케이스 다이어그램을 생성합니다. Ask mode를 사용해 코드를 안전하게 탐색하고 Mermaid를 사용하는 다이어그램 마크업을 생성합니다. 이후 Agent mode로 전환해 다이어그램을 프로젝트에 저장합니다.

GitHub는 Markdown 파일에서 Mermaid 다이어그램을 기본으로 지원하므로, 생성된 다이어그램을 .md 파일로 저장하면 GitHub에서 렌더링된 형태로 확인할 수 있습니다.

이 튜토리얼에서 Bob의 출력은 코드베이스의 현재 상태에 따라 예시와 다를 수 있습니다. 생성된 마크업을 출발점으로 삼아 필요에 따라 수정하세요.

학습하는 주요 기능

  • 컨텍스트 멘션: @ 기호를 사용해 프롬프트에서 특정 파일과 폴더를 참조합니다. 컨텍스트 멘션을 통해 Bob이 정확한 다이어그램을 생성하기 위해 분석해야 할 파일을 정확히 알 수 있습니다.
  • Ask mode: Bob이 파일을 변경하지 않고 코드를 읽고 분석합니다.
  • Agent mode: Bob이 자율적으로 파일을 작성해 생성된 결과물을 프로젝트에 저장합니다.

사전 요구 사항

이 튜토리얼을 완료하려면 다음이 필요합니다:

  • Bob IDE 설치.
  • Galaxium Travels 예제 저장소를 클론할 수 있도록 로컬에 Git 설치.
  • Bob 사용 기본기. Bob이 처음이라면 빠른 시작 튜토리얼부터 시작하세요.

워크스페이스 설정

Galaxium Travels 저장소 클론

터미널에서 다음 명령어를 실행해 Galaxium Travels 예제 저장소를 클론합니다:

git clone https://github.com/ibm/galaxium-travels.git

IBM Bob 실행

컴퓨터에서 IBM Bob IDE를 실행합니다.

예제 프로젝트 열기

Bob IDE에서 클론한 galaxium-travels 폴더를 엽니다. Bob이 "폴더에 있는 파일의 작성자를 신뢰합니까?"라고 묻는다면 예, 작성자를 신뢰합니다를 클릭하세요.

루트 디렉터리의 README.md 파일을 검토해 애플리케이션과 아키텍처를 파악합니다. Galaxium Travels 앱은 React 프론트엔드, Python FastAPI 백엔드, Java 인벤토리 홀드 서비스로 구성된 항공권 예약 시스템을 시뮬레이션합니다. 코드베이스는 의도적으로 복잡하고 실제 애플리케이션을 대표하도록 설계되어 아키텍처 다이어그램을 생성하기에 적합합니다.

Bob 채팅 인터페이스 열기

채팅 인터페이스가 아직 열려 있지 않다면 내비게이션 바의 Bob 아이콘을 클릭하거나 단축키 Option + Command + B(Mac) 또는 Ctrl + Alt + B(Windows)를 사용합니다.

프로젝트 컨텍스트 초기화

Bob은 시작 시 기본적으로 Agent mode로 실행됩니다. 모드를 변경했다면 초기화 명령을 실행하기 전에 Agent mode로 전환하세요. Bob이 프로젝트 컨텍스트를 설정하려면 파일을 작성해야 합니다.

채팅 인터페이스 입력 필드에 /init 명령을 입력합니다. 자동 승인이 비활성화되어 있으면 Bob이 파일 읽기 및 AGENTS.md 파일 쓰기 권한을 요청합니다.

 /init

Bob이 프로젝트의 관련 파일을 읽고 루트 디렉터리에 메인 AGENTS.md 파일을 생성합니다. 또한 각 모드별 AGENTS.md가 포함된 .bob 폴더를 생성합니다.

생성된 AGENTS.md 파일을 검토해 Bob이 어떻게 프로젝트 컨텍스트를 설정했는지, 각 모드에서 어떤 기능을 사용할 수 있는지 파악하세요.

Ask mode로 전환

채팅 입력 필드 아래의 모드 선택기에서 Ask를 선택합니다. 또는 채팅 입력 필드에 /ask를 입력해 모드를 전환할 수 있습니다.

Agent mode와 달리 Ask mode는 읽기 전용입니다. Bob이 파일을 읽고 분석할 수 있지만 아무것도 생성하거나 수정할 수 없으므로 코드 탐색에 안전합니다.

UML 클래스 다이어그램 생성

UML 클래스 다이어그램은 애플리케이션의 데이터 모델, 즉 엔티티(클래스), 속성, 그리고 엔티티 간 관계를 표현합니다. Galaxium Travels의 경우 백엔드의 Python SQLAlchemy 모델과 인벤토리 홀드 서비스의 Java 도메인 클래스가 해당됩니다.

두 서비스의 데이터 모델을 분석하고 Mermaid classDiagram을 생성하는 프롬프트를 작성합니다. 컨텍스트 멘션을 사용해 Bob이 분석할 관련 파일을 지정합니다. Bob은 기본적으로 Mermaid 다이어그램을 렌더링된 이미지로 출력합니다. 원시 Mermaid 마크업을 확인하려면 프롬프트에 "Output only the Mermaid code block. Do not render the Mermaid diagram." 지시를 추가하세요.

Ask mode에서 채팅 입력 필드에 다음 프롬프트를 입력합니다:

Analyze the data models in @booking_system_backend/models.py and the 
Java domain classes in @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/domain.

Generate a Mermaid classDiagram that shows all classes, their attributes,
their methods (if any), and the relationships between them. 
Include the BookingStatus enum.

Output the Mermaid markup. Do not render the Mermaid diagram.

Bob이 두 파일을 읽고 다음과 유사한 다이어그램 마크업을 생성합니다:

classDiagram
    direction LR

    %% ── Python / SQLAlchemy (booking_system_backend/models.py) ──────────

    class User {
        +int user_id PK
        +str name
        +str email
    }

    class Flight {
        +int flight_id PK
        +str origin
        +str destination
        +str departure_time
        +str arrival_time
        +int base_price
        +int economy_seats_available
        +int business_seats_available
        +int galaxium_seats_available
    }

    class Booking {
        +int booking_id PK
        +int user_id FK
        +int flight_id FK
        +str status
        +str booking_time
        +str seat_class
        +int price_paid
    }

    class BookingStatus {
        <<enumeration>>
        BOOKED = "booked"
        CANCELLED = "cancelled"
        CANCELED = "cancelled"
        COMPLETED = "completed"
    }

    %% ── Java / JPA (holdservice/domain) ────────────────────────────────

    class Quote {
        +String quoteId PK
        +Integer flightId
        +String seatClass
        +Integer quantity
        +Integer travelerId
        +String travelerName
        +Long pricePerSeat
        +Long totalPrice
        +Instant expiresAt
        +QuoteStatus status
        +Instant createdAt
        #onCreate() void
    }

    class QuoteStatus {
        <<enumeration>>
        CREATED
    }

    class Hold {
        +String holdId PK
        +String quoteId FK
        +HoldStatus status
        +Instant reservedUntil
        +String externalBookingReference
        +String errorMessage
        +Instant createdAt
        +Instant updatedAt
        #onCreate() void
        #onUpdate() void
    }

    class HoldStatus {
        <<enumeration>>
        HELD
        EXPIRED
        CONFIRMED
        RELEASED
        CONFIRMATION_FAILED
    }

    class AuditEvent {
        +String eventId PK
        +String entityType
        +String entityId
        +String eventType
        +String details
        +Instant createdAt
        #onCreate() void
    }

    %% ── Relationships ───────────────────────────────────────────────────

    User        "1" --> "0..*" Booking      : places
    Flight      "1" --> "0..*" Booking      : booked on
    Booking          ..>        BookingStatus : status

    Quote       "1" --> "0..*" Hold         : generates
    Quote            ..>        QuoteStatus  : status
    Hold             ..>        HoldStatus   : status

    AuditEvent       ..>        Quote        : references entityId
    AuditEvent       ..>        Hold         : references entityId

시퀀스 다이어그램 생성

시퀀스 다이어그램은 특정 흐름에서 컴포넌트가 런타임에 어떻게 상호작용하는지 시간 순서대로 보여줍니다. Galaxium Travels의 예약 흐름은 React 프론트엔드, Python FastAPI 백엔드, Java 인벤토리 홀드 서비스에 걸쳐 있습니다.

전체 예약 흐름을 추적하고 Mermaid sequenceDiagram을 생성하는 프롬프트를 작성합니다. 컨텍스트 멘션을 사용해 Bob이 분석할 관련 파일을 지정합니다. 분석할 파일과 다이어그램으로 표현할 흐름을 프롬프트에 구체적으로 명시할수록 출력 결과가 더 정확합니다.

Ask mode에서 채팅 입력 필드에 다음 프롬프트를 입력합니다:

Analyze the booking flow across @booking_system_frontend/src/services,
@booking_system_backend/server.py, @booking_system_backend/services/booking.py,
and @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/api.

Generate a Mermaid sequenceDiagram showing the complete flow for a
user booking a flight, including the quote and hold steps with the Java service.

Output the Mermaid markup. Do not render the Mermaid diagram.

Bob이 상호작용 체인을 추적하고 다음과 유사한 다이어그램 마크업을 생성합니다:

sequenceDiagram
    autonumber
    participant U  as User (Browser)
    participant FE as Frontend<br/>(api.ts)
    participant PY as Python Backend<br/>(server.py)
    participant BS as BookingService<br/>(booking.py)
    participant QC as QuoteController<br/>(Java)
    participant QS as QuoteService<br/>(Java)
    participant HC as HoldController<br/>(Java)
    participant HS as HoldService<br/>(Java)
    participant DB as Python SQLite
    participant JDB as Java SQLite

    Note over U,JDB: ── Phase 1: Create Quote ──────────────────────────────────

    U->>FE: createQuote({ flightId, seatClass,<br/>quantity, travelerId, travelerName })
    FE->>PY: POST /quotes
    PY->>QC: POST /api/v1/quotes
    QC->>QS: createQuote(request)
    QS->>QS: generateQuoteId() → "Q-2025-000001"
    QS->>QS: pricingService.calculatePrice(flightId, seatClass)
    QS->>JDB: save Quote (status=CREATED, expiresAt=+24h)
    QS->>JDB: save AuditEvent (QUOTE / CREATED)
    QC-->>PY: 201 Quote
    Note right of PY: Returns {"error":"..."} HTTP 200<br/>if Java service unreachable
    PY-->>FE: Quote JSON
    FE->>FE: assertNotProxyError(response.data)
    FE-->>U: quoteId

    Note over U,JDB: ── Phase 2: Create Hold ───────────────────────────────────

    U->>FE: createHold(quoteId)
    FE->>PY: POST /quotes/{quoteId}/holds
    PY->>HC: POST /api/v1/quotes/{quoteId}/holds
    HC->>HS: createHold(quoteId)
    HS->>JDB: findById(quoteId)
    JDB-->>HS: Quote
    HS->>HS: check quote not expired
    HS->>HS: generateHoldId() → "H-2025-000001"
    HS->>JDB: save Hold (status=HELD,<br/>reservedUntil=+15min)
    HS->>JDB: save AuditEvent (HOLD / CREATED)
    HC-->>PY: 201 Hold
    PY-->>FE: Hold JSON
    FE->>FE: assertNotProxyError(response.data)
    FE-->>U: holdId

    Note over U,JDB: ── Phase 3: Confirm Hold → Create Booking ─────────────────

    U->>FE: confirmHold(holdId)
    FE->>PY: POST /holds/{holdId}/confirm
    PY->>HC: POST /api/v1/holds/{holdId}/confirm
    HC->>HS: confirmHold(holdId)
    HS->>JDB: findById(holdId)
    JDB-->>HS: Hold
    HS->>HS: check status == HELD
    HS->>HS: check reservedUntil not passed
    HS->>JDB: findById(hold.quoteId)
    JDB-->>HS: Quote

    HS->>PY: POST /internal/bookings/from-hold<br/>{ travelerId, travelerName, flightId, seatClass }
    PY->>BS: book_flight(db, user_id, name,<br/>flight_id, seat_class)
    BS->>DB: query Flight (check seats available)
    BS->>DB: query User (validate user_id + name match)
    BS->>DB: decrement {seat_class}_seats_available
    BS->>DB: insert Booking (status="booked")
    DB-->>BS: Booking row
    BS-->>PY: BookingOut

    alt booking succeeded
        PY-->>HS: 200 { booking_id, ... }
        HS->>JDB: update Hold (status=CONFIRMED,<br/>externalBookingReference=booking_id)
        HS->>JDB: save AuditEvent (HOLD / CONFIRMED)
        HC-->>PY: 200 Hold (CONFIRMED)
        PY-->>FE: Hold JSON
        FE->>FE: assertNotProxyError(response.data)
        FE-->>U: Booking confirmed ✓
    else booking failed (name mismatch / no seats / user not found)
        PY-->>HS: 400 { error, error_code, details }
        HS->>JDB: update Hold (status=CONFIRMATION_FAILED,<br/>errorMessage=...)
        HS->>JDB: save AuditEvent (HOLD / CONFIRMATION_FAILED)
        HC-->>PY: 400 Bad Request
        PY-->>FE: error response
        FE-->>U: Error shown to user ✗
    end

유스케이스 다이어그램 생성

유스케이스 다이어그램은 시스템의 액터와 각 액터가 수행할 수 있는 기능을 식별합니다. Mermaid는 유스케이스 다이어그램 타입을 기본으로 제공하지 않으므로, 액터별로 유스케이스를 그룹화하는 flowchart LR로 표현합니다.

전체 애플리케이션에서 모든 액터와 유스케이스를 식별하는 프롬프트를 작성합니다. 액터에는 사용자 유형과 외부 시스템이 포함됩니다. 컨텍스트 멘션을 사용해 프론트엔드 페이지, 백엔드 REST 엔드포인트, MCP 도구를 포함한 관련 파일을 지정합니다. 분석할 파일을 프롬프트에 구체적으로 명시할수록 출력 결과가 더 정확합니다. 또한 Mermaid 렌더러가 중괄호를 템플릿 문법으로 해석하지 않도록 Mermaid 마크업에서 중괄호를 이스케이프하도록 Bob에게 지시합니다.

Ask mode에서 채팅 입력 필드에 다음 프롬프트를 입력합니다:

Analyze the full Galaxium Travels application. 

Identify all actors (user types or external systems) and the use cases each
actor can perform, based on the frontend pages, backend REST endpoints,
and MCP tools.

Generate a Mermaid flowchart LR that represents this as a use case diagram,
grouping use cases under their respective actors using subgraphs.

Escape curly braces in Mermaid markup so that the Mermaid renderer does not
attempt to interpret the curly braces as template syntax.

Output the Mermaid markup. Do not render the Mermaid diagram.

Bob이 애플리케이션을 분석하고 다음과 유사한 다이어그램 마크업을 생성합니다:

flowchart LR

    subgraph Traveller["👤 Traveller (Browser)"]
        T1[Browse available flights]
        T2[Search flights by origin / destination]
        T3[Filter flights by date, price, seat class,\nduration, route category, time period]
        T4[Register account]
        T5[Sign in with name and email]
        T6[Select seat class\neconomy / business / galaxium]
        T7[Get price quote]
        T8[Place seat hold - 15-minute timer]
        T9[Confirm hold and create booking]
        T10[Release hold]
        T11[View active bookings]
        T12[View past bookings]
        T13[Cancel booking]
        T14[View pending holds with countdown]
        T15[Dismiss expired hold]
    end

    subgraph AIAgent["🤖 AI Agent (MCP Client)"]
        A1[list_flights]
        A2[register_user]
        A3[get_user_id]
        A4[book_flight]
        A5[get_bookings]
        A6[cancel_booking]
    end

    subgraph JavaService["☕ Java Hold Service\n(Internal System)"]
        J1[Confirm hold via POST /internal/bookings/from-hold]
        J2[Auto-expire holds after timeout]
    end

    subgraph RestAPI["🐍 Python REST API\n(External Consumers / Swagger)"]
        R1[GET  /flights — list and filter flights]
        R2[POST /register — register user]
        R3[GET  /user — look up user by name and email]
        R4[POST /book — book a flight]
        R5[GET  /bookings/&#123;user_id&#125; — get user bookings]
        R6[POST /cancel/&#123;booking_id&#125; — cancel booking]
        R7[POST /quotes — create quote proxy]
        R8[GET  /quotes/&#123;id&#125; — get quote proxy]
        R9[POST /quotes/&#123;id&#125;/holds — create hold proxy]
        R10[GET  /holds/&#123;id&#125; — get hold proxy]
        R11[POST /holds/&#123;id&#125;/confirm — confirm hold proxy]
        R12[POST /holds/&#123;id&#125;/release — release hold proxy]
        R13[GET  / — health check]
    end

    Traveller   -->|uses frontend which calls| RestAPI
    AIAgent     -->|MCP over HTTP at /mcp| RestAPI
    JavaService -->|calls back via internal endpoint| RestAPI

저장소에 다이어그램 저장

Bob을 Agent mode로 전환하고 생성한 다이어그램을 저장소에 저장하도록 요청합니다. 각 다이어그램은 새로 생성되는 docs/architecture/ 폴더에 Markdown 파일로 저장됩니다.

Agent mode로 전환

모드 선택기에서 Agent를 선택하거나, 채팅 입력 필드에 /agent를 입력합니다.

세 가지 다이어그램 모두 저장

Bob에게 아키텍처 문서 파일을 생성하도록 요청합니다.

Create a docs/architecture/ folder in the repository root.

Save each of the three diagrams we generated as individual Markdown files:
- class-diagram.md — the UML class diagram
- sequence-diagram.md — the booking flow sequence diagram
- use-case-diagram.md — the use case flowchart

Each file should have a short title heading, the Mermaid code block we
generated, and a brief description of the diagram.

Bob이 세 개의 파일을 생성합니다. Bob이 각 파일을 작성할 때 승인저장을 클릭합니다.

출력 결과 확인

Bob 파일 탐색기에서 각 파일을 열어 Mermaid 펜스드 코드 블록이 있는지 확인합니다. 다이어그램을 검증하는 방법은 다음과 같습니다:

  • Bob에게 Markdown 파일 미리보기를 요청합니다.

    채팅 입력 필드에 다음 프롬프트를 입력합니다:

      Show me a preview of docs/architecture/class-diagram.md

    Bob이 Mermaid 다이어그램을 포함한 Markdown 파일을 채팅 인터페이스에 렌더링합니다. 렌더링된 다이어그램을 클릭하면 더 큰 화면으로 볼 수 있습니다.

    세 파일 모두에 대해 이 작업을 수행하면 모든 다이어그램을 렌더링된 형태로 확인할 수 있습니다.

  • 다이어그램 마크업을 Mermaid Live Editor에 붙여 넣어 렌더링된 다이어그램을 미리 봅니다.

  • 변경 사항을 GitHub 저장소에 commit하고 push합니다. 이후 GitHub에서 파일을 열면 렌더링된 다이어그램을 확인할 수 있습니다.

문제 해결

Bob이 컴파일되지 않는 Mermaid 마크업을 생성하는 경우

Mermaid 파서는 엄격합니다. 유효하지 않은 문자 하나, 지원되지 않는 키워드, 또는 누락된 줄 바꿈 하나만으로도 다이어그램이 조용히 실패하거나 파싱 오류가 발생할 수 있습니다. 다음 접근 방식을 사용해 문제를 진단하고 수정하세요.

오류가 발생한 줄 식별

Bob이 파싱 오류를 출력하면 줄 번호와 문제가 있는 코드 스니펫이 포함됩니다.

Bob이 파서 오류를 출력하지 않으면 마크업을 Mermaid Live Editor에 붙여 넣습니다. 편집기가 오류가 발생한 줄을 강조 표시하고 파서 오류를 표시하므로 문제를 식별하는 데 도움이 됩니다.

레이블에 이스케이프되지 않은 특수 문자, 닫히지 않은 subgraph, 화살표 문법 오류 등 일반적인 문제를 마크업에서 직접 육안으로 검사할 수도 있습니다.

증상예상 원인해결 방법
{ 또는 } 근처에서 파싱 오류flowchart 또는 classDiagram 노드 레이블에서 중괄호가 이스케이프되지 않음{&#123;로, }&#125;로 교체하거나 레이블 문구 수정
( 또는 ) 근처에서 파싱 오류노드 ID에 괄호 포함레이블을 따옴표로 감쌈: A["label (note)"]
예상치 못한 end 또는 subgraph 오류subgraph가 닫히지 않음모든 subgraph 블록에 대응하는 end가 있는지 확인
화살표 타입이 인식되지 않음다이어그램 유형에 맞지 않는 화살표 문법-->flowchart용; classDiagram-->, ..>, --|> 등 사용; sequenceDiagram->>, -->> 사용
노드가 정의되었지만 연결되지 않음고립된 노드는 오류를 발생시키지 않지만 일부 렌더러를 혼란스럽게 할 수 있음노드를 연결하거나 제거
다이어그램이 부분적으로 렌더링되다 멈춤레이블에 이스케이프되지 않은 " 문자 포함레이블 내 따옴표 이스케이프: A["it\'s a label"]

Bob에게 문제 수정 요청

Bob에게 파서 오류와 오류가 발생한 줄을 알려주고 특정 줄을 수정하도록 요청합니다.

예시:

The Mermaid classDiagram fails to parse with this error:
Parse error on line 42: ...unexpected token 'NEWLINE'

Here is the relevant block:
    Booking ..> BookingStatus : status (active)

Fix the syntax so it compiles without changing the diagram structure.

Bob은 이미 검토한 내용을 재생성하지 않고 좁은 범위의 수정을 수행할 수 있습니다.

출력 전에 Bob에게 검증 요청

다이어그램을 처음부터 다시 생성하는 경우, 프롬프트에 명시적인 검증 지시를 추가합니다:

Before outputting the Mermaid block, mentally parse it and confirm every node ID
is valid, every subgraph is closed, and all special characters in labels are escaped.

다이어그램이 클 때 범위 좁히기

노드가 많은 다이어그램에서 계속 유효하지 않은 마크업이 생성된다면, 섹션별로 나눠서 Bob에게 요청합니다. 예를 들어 Python 모델을 먼저 생성한 다음 Java 모델을 생성합니다. 그런 다음 Bob에게 블록을 조합하도록 요청합니다. 작은 단위로 나눠 생성하면 Bob이 검증하기 더 쉽고 비교하기도 더 쉽습니다.

다음 단계

이 튜토리얼에서는 컨텍스트 멘션과 Ask mode를 사용해 Galaxium Travels 코드베이스를 탐색하고 Bob으로 세 가지 아키텍처 다이어그램을 생성한 다음, Agent mode를 사용해 저장소에 저장했습니다. 다음 리소스를 통해 계속 학습하세요:

  • Bob 시작 튜토리얼을 탐색해 Galaxium Travels 앱과 함께 Bob의 기능을 더 자세히 알아보세요.
  • 복잡한 기능 계획 및 구현 튜토리얼을 따라 Plan → Agent mode 워크플로를 사용해 새 기능을 추가하는 방법을 배우세요.
  • Bob 모범 사례를 읽고 Bob을 효과적으로 사용하기 위한 프롬프트 전략을 알아보세요.
이 주제는 어떤가요?