D2 2. Special Object - swkim0128/PARA GitHub Wiki
Text & Code
Latex
Icons & Images
Add shape: image for standalone icon shapes
SQL Tables
Classes
Sequence Diagrams
Sequence diagrams are D2 objects
explanation: |md
  # I can do headers
  - lists
  - lists
  And other normal markdown stuff
|
λλΆλΆμ κ²½μ° D2λ μ€κ΅μ΄, μΌλ³Έμ΄, νκ΅μ΄μ κ°μ λΉλΌν΄ λ¬Έμλ₯Ό ν¬ν¨νμ¬ μ¬μ©νκ³ μΆμ μ΄λ€ μΈμ΄λ μ§ μ§μν©λλ€. μ¬μ§μ΄ μ΄λͺ¨μ§λ κ°λ₯ν©λλ€!
Latex μΈμ΄ λΈλ‘μ μ§μ νλ λ° latex λλ texλ₯Ό μ¬μ©ν  μ μμ΅λλ€.
plankton -> formula: will steal
formula: {
  equation: |latex
    \\lim_{h \\rightarrow 0 } \\frac{f(x+h)-f(x)}{h}
  |
}
Latex λΈλ‘μ λν΄ μ£Όμν΄μΌ ν λͺ κ°μ§ μ¬νμ΄ μμ΅λλ€:
- μμ μμμ λ³Ό μ μλ―μ΄, μ΄μ€μΌμ΄ν λ¬Έμλ‘ μ¬μ©λλ \λ₯Ό μ΄μ€μΌμ΄νν΄μΌ ν©λλ€.\\λ₯Ό μ¬μ©ν κ²μ μ°Έκ³ νμΈμ.
- λΌν
 λΈλ‘μ font-sizeμ€νμΌμ μ μ©νμ§ μμ΅λλ€. λμ λΌν  μ€ν¬λ¦½νΈ λ΄μμ λͺ λ Ήμ΄λ₯Ό μ¬μ©νμ¬ μ€νμΌμ μ μ©ν΄μΌ ν©λλ€:- \tiny{ }
- \small{ }
- \normal{ }
- \large{ }
- \huge{ }
 
- κΈ°μ μ μΌλ‘, μ΄κ²μ MathJaxλ₯Ό μ¬μ©νκ³ μμ΅λλ€. μ΄κ²μ μμ ν λΌν μ€κ° μλλλ€ (μμ ν λΌν μ€λ λ¬Έμ λ μ΄μμ μμ§μ΄ ν¬ν¨λ©λλ€). D2μ λΌν μ€ λΈλ‘μ μνμ μΈ νκΈ°λ²μ νμνκΈ° μν κ²μ΄λ©°, κΈ°μ‘΄ λΌν μ€ λ¬Έμμ νμμ μ§μνμ§ μμ΅λλ€. μ§μλλ λͺ¨λ λͺ λ Ήμ΄ λͺ©λ‘μ μ¬κΈ°λ₯Ό μ°Έμ‘°νμμμ€.
μΌλ°μ μΌλ‘, κΈ΄ ννμ ν
μ€νΈλ λ€μ΄μ΄κ·Έλ¨μ νΉμ  μμμ μμΈν λ΄μ©μ μΆκ°ν©λλ€. near ν€μλλ₯Ό μ¬μ©νμ¬ μ΄λ μμΉμ μΆκ°ν μ§ μ§μ ν  μ μμ΅λλ€.
You can set near to either
- the ID of another shape
- a constant value
aws: {
  load_balancer -> api
  api -> db
}
gcloud: {
  auth -> db
}
gcloud -> aws
explanation: |md
  # Why do we use AWS?
  - It has more uptime than GCloud
  - We have free credits
| {
  near: aws
}
ν
μ€νΈκ° aws λ
Έλ κ·Όμ²μ μμΉνκ³  gcloud λ
Έλ κ·Όμ²μ μμΉνμ§ μλ κ²μ μ£Όλͺ©ν΄λ³΄μΈμ.
Important
POSSIBLE CONSTANT VALUEStop-left, top-center, top-right,center-left, center-right,bottom-left, bottom-center, bottom-right
title: |md
  # A winning strategy
| { near: top-center }
poll the people -> results
results -> unfavorable -> poll the people
results -> favorable -> will of the people
μ½λ λΈλ‘μ νλ‘κ·Έλλ° μΈμ΄λ₯Ό mdμμ λ€λ₯Έ μΈμ΄λ‘ λ³κ²½
aws: {
  load_balancer -> api
  api -> db
}
gcloud: {
  auth -> db
}
gcloud -> aws
explanation: |go
  awsSession := From(c.Request.Context())
  client := s3.New(awsSession)
  ctx, cancelFn := context.WithTimeout(c.Request.Context(), AWS_TIMEOUT)
  defer cancelFn()
| {
  near: aws
}
μΌλΆ κ²½μ°μλ λ§ν¬λ€μ΄ ν
μ€νΈκ° νμνμ§ μμ μ μμ΅λλ€. μλ§λ λ§ν¬λ€μ΄μ΄ λ§μμ λ€μ§ μκ±°λ D2μμ μ¬μ©νλ GitHub μ€νμΌλ§μ μνμ§ μμ μλ μκ³ , λνμ λΉ λ₯΄κ² ν
μ€νΈλ‘ λ³κ²½νλ €κ³  ν  μλ μμ΅λλ€. κ·Έλλ shape: textλ‘ μ€μ νλ©΄ λ©λλ€.
title: A winning strategy {
  shape: text
  near: top-center
  style: {
    font-size: 55
    italic: true
  }
}
poll the people -> results
results -> unfavorable -> poll the people
results -> favorable -> will of the people
λ§μ½ TypeScriptλ₯Ό μμ±νλ κ²½μ° νμ΄ν κΈ°νΈ |κ° μΌλ°μ μΌλ‘ μ¬μ©λ©λλ€. κ·Έλ λ€λ©΄ λ λ€λ₯Έ νμ΄ν ||λ₯Ό μΆκ°νλ©΄ λ©λλ€.
my_code: ||ts
  declare function getSmallPet(): Fish | Bird;
||
μ€μ λ‘ Typescriptλ || μ μ¬μ©νκΈ° λλ¬Έμ, κ·Έλ κ² νλ©΄ μλνμ§ μμ΅λλ€. κ³μ μ§νν©μλ€.
my_code: |||ts
  declare function getSmallPet(): Fish | Bird;
  const works = (a > 1) || (b < 2)
|||
μλ§λ μΌμ€ νμ΄νκ° μ¬μ©λλ μΈμ΄λ μλ리μ€κ° μμ κ²μ
λλ€. D2λ μ€μ λ‘ 첫 λ²μ§Έ νμ΄ν λ€μ μνλ²³, μ«μ, 곡백 λλ _κ° μλ νΉμ κΈ°νΈλ₯Ό μ¬μ©ν  μ μκ² ν΄μ€λλ€:
# Much cleaner!
my_code: |`ts
  declare function getSmallPet(): Fish | Bird;
  const works = (a > 1) || (b < 2)
`|
D2μλ λ€μκ³Ό κ°μ λΌν μ€ νλ¬κ·ΈμΈμ΄ ν¬ν¨λμ΄ μμ΅λλ€:
amscd plugin: {
  ex: |tex
\\begin{CD} B @>{\\text{very long label}}>> C S^{{\\mathcal{W}}_\\Lambda}\\otimes T @>j>> T\\\\ @VVV V \\end{CD}
|
}
braket plugin: {
  ex: |tex
\\bra{a}\\ket{b}
|
}
cancel plugin: {
  ex: |tex
\\cancel{Culture + 5}
|
}
color plugin: {
  ex: |tex
\\textcolor{red}{y} = \\textcolor{green}{\\sin} x
|
}
gensymb plugin: {
  ex: |tex
\\lambda = 10.6\\,\\micro\\mathrm{m}
|
}
mhchem plugin: {
  ex: |tex
\ce{SO4^2- + Ba^2+ -> BaSO4 v}
|
}
physics plugin: {
  ex: |tex
\\var{F[g(x)]}
\\dd(\\cos\\theta)
|
}
multilines: {
  ex: |tex
\\displaylines{x = a + b \\\\ y = b + c}
\\sum_{k=1}^{n} h_{k} \\int_{0}^{1} \\bigl(\\partial_{k} f(x_{k-1}+t h_{k} e_{k}) -\\partial_{k} f(a)\\bigr) \\,dt
|
}
Icons and images are an essential part of production-ready diagrams.
You can use any URL as value.
μμ΄μ½κ³Ό μ΄λ―Έμ§λ μ ν μμ°μ© λ€μ΄μ΄κ·Έλ¨μ νμμ μΈ λΆλΆμ λλ€.
κ°μΌλ‘λ μ΄λ€ URLμ΄λ μ¬μ©ν μ μμ΅λλ€.
my network: {
  icon: https://icons.terrastruct.com/infra/019-network.svg
}
μμ΄μ½ λ°°μΉλ μλμ λλ€. λ μ΄μμ μμ§μ λ°λΌ κ³ λ € μ¬νμ΄ λ€λ₯΄μ§λ§, λΌλ²¨κ³Ό ν¨κ» μ‘΄μ¬νλμ§, 컨ν μ΄λμΈμ§ μ¬λΆ λ±μ΄ μμ΄μ½μ κ°λ¦¬μ§ μλλ‘ λ°°μΉνλλ° μν₯μ λ―ΈμΉ©λλ€. λ€μ λ€μ΄μ΄κ·Έλ¨μμλ 컨ν μ΄λ μμ΄μ½μ΄ μΌμͺ½ μλ¨μ μμΉνκ³ μ»¨ν μ΄λκ° μλ μμ΄μ½μ΄ μ€μμ μμΉνλ κ²μ λ³Ό μ μμ΅λλ€.
vpc: VPC 1 10.1.0.0./16 {
  icon: https://icons.terrastruct.com/aws%2F_Group%20Icons%2FVirtual-private-cloud-VPC_light-bg.svg
  style: {
    stroke: green
    font-color: green
    fill: white
  }
  az: Availability Zone A {
    style: {
      stroke: blue
      font-color: blue
      stroke-dash: 3
      fill: white
    }
    firewall: Firewall Subnet A {
      icon: https://icons.terrastruct.com/aws%2FNetworking%20&%20Content%20Delivery%2FAmazon-Route-53_Hosted-Zone_light-bg.svg
      style: {
        stroke: purple
        font-color: purple
        fill: "\#e1d5e7"
      }
      ec2: EC2 Instance {
        icon: https://icons.terrastruct.com/aws%2FCompute%2F_Instance%2FAmazon-EC2_C4-Instance_light-bg.svg
      }
    }
  }
}
server: {
  shape: image
  icon: https://icons.terrastruct.com/tech/022-server.svg
}
github: {
  shape: image
  icon: https://icons.terrastruct.com/dev/github.svg
}
server -> github
D2μμλ sql_table λͺ¨μμ μ¬μ©νμ¬ μν°ν°-κ΄κ³ λ€μ΄μ΄κ·Έλ¨(ERD)μ μ½κ² 그릴 μ μμ΅λλ€. λ€μμ μ΅μνμ μμ μ
λλ€:
my_table: {
  shape: sql_table
  # This is defined using the shorthand syntax for labels discussed in the containers section.
  # But here it's for the type of a constraint.
  # The id field becomes a map that looks like {type: int; constraint: primary_key}
  id: int {constraint: primary_key}
  last_updated: timestamp with time zone
}
SQL ν μ΄λΈ λͺ¨μμ κ° ν€λ νμ μ μν©λλ€. κ° νμ κΈ°λ³Έ κ°(μ½λ‘ λ€μμλ κ²)μ ν΄λΉ νμ μ νμ μ μν©λλ€.
κ° νμ μ μ½ μ‘°κ±΄ κ°μ ν΄λΉ SQL μ μ½ μ‘°κ±΄μ μ μν©λλ€. D2λ μΈμνμ¬ μ€μΌ μ μμ΅λλ€:
| constraint | short | 
| primary_key | PK | 
| foreign_key | FK | 
| unique | UNQ | 
νμ§λ§ μνλ μ μ½ μ‘°κ±΄μ μ€μ ν μ μμ΅λλ€. μΈμλμ§ μμΌλ©΄ λ¨μΆλμ§ μμ λΏμ λλ€.
λ ν μ΄λΈ κ° μΈλ ν€ μ°κ²°μ μ μνλ λ°©λ²μ μμμ λλ€:
objects: {
  shape: sql_table
  id: int {constraint: primary_key}
  disk: int {constraint: foreign_key}
  json: jsonb  {constraint: unique}
  last_updated: timestamp with time zone
}
disks: {
  shape: sql_table
  id: int {constraint: primary_key}
}
objects.disk -> disks.id
μ£Ό ν€ λλ μΈλ ν€ μμ 컀μλ₯Ό μ¬λ¦¬λ©΄ ν΄λΉ ν€κ° κ°μ‘° νμλλ κ²μ μ μ μμ΅λλ€.
λ€λ₯Έ λͺ¨λ  λνλ€κ³Ό λ§μ°¬κ°μ§λ‘, sql_tablesμ 컨ν
μ΄λμ μ€μ²©μν€κ³  λ€λ₯Έ λͺ¨μμΌλ‘λΆν° μ£μ§λ₯Ό μ μν  μ μμ΅λλ€. λ€μμ μμμ
λλ€:
cloud: {
  disks: {
    shape: sql_table
    id: int {constraint: primary_key}
  }
  blocks: {
    shape: sql_table
    id: int {constraint: primary_key}
    disk: int {constraint: foreign_key}
    blob: blob
  }
  blocks.disk -> disks.id
  AWS S3 Vancouver -> disks
}
D2 fully supports UML Class diagrams. Here's a minimal example:
D2λ UML ν΄λμ€ λ€μ΄μ΄κ·Έλ¨μ μμ ν μ§μν©λλ€. λ€μμ μ΅μνμ μμμ λλ€:
MyClass: {
  shape: class
  field: "[]string"
  method(a uint64): (x, y int)
}
ν΄λμ€μ κ° ν€λ νλ λλ λ©μλλ₯Ό μ μν©λλ€.
νλ ν€μ κ°μ ν΄λΉ νλμ νμ μ λλ€.
(λ₯Ό ν¬ν¨νλ λͺ¨λ  ν€λ λ°ν νμ
μ΄ μλ λ©μλμ
λλ€.
κ°μ΄ μλ λ©μλ ν€λ λ°ν νμ μ΄ voidμ λλ€.
νλ/λ©μλ κ°μμ±μ λνλ΄λ UML μ€νμΌ μ λμ¬λ₯Ό μ¬μ©ν μλ μμ΅λλ€.
| visiblity prefix | meaning | 
| none | public | 
| + | public | 
| - | private | 
| # | protected | 
λ€μ λ§ν¬λ₯Ό μ°Έμ‘°νμμμ€: https://www.uml-diagrams.org/visibility.html
λ€μμ μλ‘ λ€λ₯Έ κ°μμ±κ³Ό λ 볡μ‘ν μ νμ κ°λ μμμ λλ€:
D2 Parser: {
  shape: class
  # Default visibility is + so no need to specify.
  +reader: io.RuneReader
  readerPos: d2ast.Position
  # Private field.
  -lookahead: "[]rune"
  # Protected field.
  # We have to escape the # to prevent the line from being parsed as a comment.
  \#lookaheadPos: d2ast.Position
  +peek(): (r rune, eof bool)
  rewind()
  commit()
  \#peekn(n int): (s string, eof bool)
}
"github.com/terrastruct/d2parser.git" -> D2 Parser
μνμ€ λ€μ΄μ΄κ·Έλ¨μ κ°μ²΄μ shape: sequence_diagram μ μ€μ νμ¬ μμ±λ©λλ€.
shape: sequence_diagram
alice -> bob: What does it mean\nto be well-adjusted?
bob -> alice: The ability to play bridge or\ngolf as if they were games.
λ€λ₯Έ λꡬμ λ¬λ¦¬, μμλλ₯Ό μν΄ λ°°μμΌ ν νΉλ³ν κ΅¬λ¬Έμ΄ μμ΅λλ€. κ·μΉμ D2 μ 체μμ κ±°μ λμΌνλ©°, λ κ°μ§ μ£Όλͺ©ν λ§ν μ°¨μ΄μ μ΄ μμ΅λλ€.
μνμ€ λ€μ΄μ΄κ·Έλ¨μ μμ μμλ€μ μνμ€ λ€μ΄μ΄κ·Έλ¨ μ 체μμ λμΌν λ²μλ₯Ό 곡μ ν©λλ€.
μλ₯Ό λ€μ΄:
Office chatter: {
  shape: sequence_diagram
  alice: Alice
  bob: Bobby
  awkward small talk: {
    alice -> bob: uhm, hi
    bob -> alice: oh, hello
    icebreaker attempt: {
      alice -> bob: what did you have for lunch?
    }
    unfortunate outcome: {
      bob -> alice: that's personal
    }
  }
}
μνμ€ λ€μ΄μ΄κ·Έλ¨ μΈλΆμμλ aliceμ bobμ 컨ν
μ΄λ λ²μκ° λ€λ₯΄κΈ° λλ¬Έμ μ¬λ¬ μΈμ€ν΄μ€κ° μμ μ μμ΅λλ€. κ·Έλ¬λ shape: sequence_diagram νμμ μ€μ²©λλ©΄ λμΌν aliceμ bobμ μ°Έμ‘°ν©λλ€.
D2μ λ€λ₯Έ κ³³μμλ μμ κ°λ μ΄ μ‘΄μ¬νμ§ μμ΅λλ€. λ€λ₯Έ μ°κ²°μ μ μν νμ μ°κ²°μ μ μνλ©΄ μκ°μ μΌλ‘ λνλμ§ μμ μ μμ΅λλ€. κ·Έλ¬λ μμλμμλ μμκ° μ€μν©λλ€. λͺ¨λ κ²μ μ μνλ μμκ° λνλλ μμμ λλ€.
μ΄κ²μ λ°°μ°λ ν¬ν¨λ©λλ€. νΉλ³ν κ·Έλ£Ήμμ μ²μ λνλ λλ₯Ό μ μΈνκ³ λ λͺ μ μ μΌλ‘ λ°°μ°λ₯Ό μ μ ν νμλ μμ§λ§, νΉμ  μμλ₯Ό μ μνλ €λ©΄ κ·Έλ κ² ν μ μμ΅λλ€.
shape: sequence_diagram
# Remember that semicolons allow multiple objects to be defined in one line
# Actors will appear from left-to-right as a, b, c, d...
a; b; c; d
# ... even if the connections are in a different order
c -> d
d -> a
b -> d
λ€λ₯Έ D2 κ°μ²΄μ λ§μ°¬κ°μ§λ‘, μ΄λ€μ ν¬ν¨, μ°κ²°, λΌλ²¨ λ³κ²½, μ¬μ€νμΌλ§ λ° λ€λ₯Έ κ°μ²΄μ λ§μ°¬κ°μ§λ‘ μ²λ¦¬λ μ μμ΅λλ€.
direction: right
Before and after becoming friends: {
  2007: Office chatter in 2007 {
    shape: sequence_diagram
    alice: Alice
    bob: Bobby
    awkward small talk: {
      alice -> bob: uhm, hi
      bob -> alice: oh, hello
      icebreaker attempt: {
        alice -> bob: what did you have for lunch?
      }
      unfortunate outcome: {
        bob -> alice: that's personal
      }
    }
  }
  2012: Office chatter in 2012 {
    shape: sequence_diagram
    alice: Alice
    bob: Bobby
    alice -> bob: Want to play with ChatGPT?
    bob -> alice: Yes!
    bob -> alice.play: Write a play...
    alice.play -> bob.play: about 2 friends...
    bob.play -> alice.play: who find love...
    alice.play -> bob.play: in a sequence diagram
  }
  2007 -> 2012: Five\nyears\nlater
}
μ€ν¬μ μνμ€ λ€μ΄μ΄κ·Έλ¨ λ΄μμ μνΈμμ©μ μμκ³Ό λμ μ λ¬ν©λλ€.
μ‘ν°μ μ€μ²©λ κ°μ²΄λ₯Ό μ°κ²°νμ¬ μ€ν¬μ μ§μ ν μ μμ΅λλ€.
shape: sequence_diagram
alice.t1 -> bob
alice.t2 -> bob.a
alice.t2.a -> bob.a
alice.t2.a <- bob.a
alice.t2 <- bob.a
κ·Έλ£Ήμ μΌλ ¨μ λ€μ΄μ΄κ·Έλ¨ μ€ μΌλΆλ₯Ό λΌλ²¨λ§νλ λ° λμμ΄ λ©λλ€.
μ°λ¦¬λ λ²μ κ·μΉμ μ€λͺ
ν  λ μ΄μ  μμ μμ μ΄λ₯Ό λ³Ό μ μμμ΅λλ€. λ ꡬ체μ μΌλ‘ λ§νλ©΄, κ·Έλ£Ήμ΄λ μ무κ²κ³Όλ μ°κ²°λμ΄ μμ§ μμ§λ§ μ°κ²° λλ κ°μ²΄κ° ν¬ν¨λ sequence_diagram λͺ¨μ λ΄λΆμ 컨ν
μ΄λμ
λλ€.
shape: sequence_diagram
# Predefine actors
alice; bob
shower thoughts: {
  alice -> bob: A physicist is an atom's way of knowing about atoms.
  alice -> bob: Today is the first day of the rest of your life.
}
life advice: {
  bob -> alice: If all else fails, lower your standards.
}
λ ΈνΈλ μ°κ²°λ νλͺ©μ΄ μλ λ°°μ°μ λν΄ μ€μ²© κ°μ²΄λ₯Ό μ μνμ¬ μ μΈλ©λλ€.
shape: sequence_diagram
alice -> bob
bob."In the eyes of my dog, I'm a man."
# Notes can go into groups, too
important insight: {
  bob."Cold hands, no gloves."
}
bob -> alice: Chocolate chip.
μ‘ν°μμ μκΈ° μμ μΌλ‘ μ ν-μ°Έμ‘° λ©μμ§λ₯Ό μ μΈν μ μμ΅λλ€.
shape: sequence_diagram
son -> father: Can I borrow your car?
friend -> father: Never lend your car to anyone to whom you have given birth.
father -> father: internal debate ensues
λ€λ₯Έ κ²κ³Ό λ§μ°¬κ°μ§λ‘ λͺ¨μκ³Ό μ°κ²°μ μ€νμΌλ§ν μ μμ΅λλ€. μ¬κΈ°μλ μΌλΆ λ©μμ§λ₯Ό μ μ μΌλ‘ λ§λ€κ³ λͺ¨μμ λ°°μ°μμκ² μ€μ ν©λλ€.
shape: sequence_diagram
scorer: { shape: person }
scorer.t -> itemResponse.t: getItem()
scorer.t <- itemResponse.t: item {
    stroke-dash: 5
}
scorer.t -> item.t1: getRubric()
scorer.t <- item.t1: rubric {
    stroke-dash: 5
}
scorer.t -> essayRubric.t: applyTo(essayResp)
itemResponse -> essayRubric.t.c
essayRubric.t.c -> concept.t: match(essayResponse)
scorer <- essayRubric.t: score {
    stroke-dash: 5
}
scorer.t -> itemOutcome.t1: new
scorer.t -> item.t2: getNormalMinimum()
scorer.t -> item.t3: getNormalMaximum()
scorer.t -> itemOutcome.t2: setScore(score)
scorer.t -> itemOutcome.t3: setFeedback(missingConcepts)


