개발을 하면서 기획 단계나 어쩌다보니 산출물을 정리하는 단계에서 class diagram을 사용 해야 할 경우가 생긴다. 언젠가는 공부 해서 정리를 하고자 했는데 미루다 보니 한참 밀리게 되었다. IntelliJ Ultimate만 써도 알아서 만들어 주는것 같던데 UML과 그 중 class diagram은 사실 꽤 중요한 문서인 만큼 간략히 정리하고자 한다.
또한 Notion에 mermaid block이 있는데, 잘 사용하면 좋겠다는 생각이 들어서 mermaid 코드도 간략히 함께 첨부하고자 한다.

mermaid JS
UML이란 OMG(Object Management Group)에서 표준으로 관리하는 SW 공학에서 사용되는 표준화된 범용 모델링언어(Standard of Modeling Language)이다. 통합 모델링 언어란, 객체 지향 프로그래밍에서 시스템을 개발할 때 산출물을 명세화, 시각화, 문서화할 때 사용되며, UML은 시스템을 시각화하는 표준안을 제공한다.
UML은 하나의 소통을 위한 도구로서, 설계자 및 개발자 등 구성원들 간 잘못된 의사소통을 줄이고, 문서를 통해 명확한 의사소통이 가능하게 한다.
UML에는 7개의 구조(Structure) 다이어그램과 7개의 행위(Behavior) 다이어그램, 총 14개의 다이어그램이 있다.
class, component, object, package, deployment diagram 등이 있다.activity, use case, interaction diagram 등이 있다.Class diagram은 구조 다이어그램(Structure Diagram)에 해당하며, class 내부 내용이나 class들 간 관계를 표기한다. OOP에서 많이 사용되며, 시스템의 논리적인 구조를 표현하며, 요구 사항의 작업에 대한 책임을 분할한다.
Class는 보통 3개의 구역으로 나누어 class 이름, 속성, 기능을 표기한다.

아래는 위 사진에 대한 mermaid code이다.
classDiagram
class User{
- int id
- String name
+ getId() int
+ String getName() String
}
- / +는 접근 제어(visibility)를 의미하며 각각 아래와 같다
| 표기 | 접근 제어자 |
|---|---|
| + | public |
| - | private |
| # | protected |
| ~ | package/internal |
Stereo Type이란 UML의 기본 요소 외 추가적인 확장 요소로, 길러멧(ghuillemet, << >>) 사이에 표기한다.

classDiagram
class Person
<<interface>> Person
mermaid code
위와 같이 interface임을 명시하기 위한 <<interface>>, abstract class임을 명시하기 위한 <<abstract>> 등이 사용되며, 필요에 따라 추가하여 사용한다.
Stereo type을 사용하여 abstract class/method를 표기할 수 있지만, UML에서는 추상 클래스/메소드 이름을 italic체, 또는 {abstract} property를 사용하여 표기한다.
Class Diagram을 그리고 있는 mermaid 에서는 italic체나 { }를 지원하지 않기에, 우선 그림은 생략한다. 공식적인 표기법은 아니지만, stereo type을 사용하여 아래와 같이 표기하기도 한다고 한다.

classDiagram
class Person {
<<abstract>>
+ breath()* void
}
mermaid code
mermaidJS에서는 method에 *를 통해 abstract method를, $를 통해 static method를 표현할 수 있다. mermaidJS 공식 문서에서는 static field에서도 사용 가능하다고 하지만, notion의 mermaid block에서는 지원하지 않는 것 같다.

classDiagram
class Person {
+ staticMethod()$ void
}
mermaid code
Class 내부에 선언된 class는 outer class의 이름까지 포함한 이름으로 표기한다.

classDiagram
class Outer
class `Outer.Inner`
Class Diagram은 클래스간 관계를 쉽게 알아볼 수 있도록 하는 것이 주된 목적이다. 따라서, Class diagram에서 가장 중요한 것은(어려운 것은) Class간 관계가 아닐까 싶다.
Class 간 관계의 종류는 아래와 같다.
이름부터 어렵지
각 관계와, UML 표기법에 대해서는 아래에서 구체적으로 알아보겠다.
일반화는 super class와 sub class간의 상속(Inheritance) 관계를 나타낸다. 일반화는 sub class의 관점에서 sub class를 super class로 일반화 하는 것이며, 반대는 구체화(Specialize)로 super class의 관점에서 sub class를 구체화 하는 것이다.

classDiagram
class Person{
- String namne
- int age
+ breath() void
}
class Customer{
- int cash
+ breath() void
}
class Employee{
- int id
+ breathe() void
}
Person <|-- Customer
Person <|-- Employee
UML을 통해서는 실선과 비어있는 삼각형을 사용하며, sub class에서 super class 쪽으로 화살표 방향이 가도록 표기한다.
Java의 extends 관계이다.
실체화는 interface를 구현(implement)하는 것, 즉 interface의 명세를 구현하여 실제 기능으로 구현하는 것을 의미한다.

classDiagram
class UserService {
+ signup() void
}
<<interface>> UserService
class UserServiceImpl {
- UserRepository userRepository
+ signup() void
}
UserService <|.. UserServiceImpl
UML을 통해서는 점선과 비어있는 삼각형을 사용하며, 구현 class에서 interface쪽으로 화살표 방향이 향하도록 표기한다.
또 다른 표기 방법으로는 interface를 원으로 표기하고 이름을 명시한 후 구현 class와 interface를 실선으로 연결하는 방법이 있다.
Generalization이 Java의 extends라면, Realization은 Java의 implements 이다.
의존은 class diagram에서 가장 많이 사용되는 관계이며, class가 다른 class를 참조하는 것을 말한다.

classDiagram
class Store
class Employee
Store ..> Employee
UML에서는 점선과 화살표를 통해 나타내며, 다른 class를 참조하는 class에서 참조 대상이 되는 class로 화살표 방향이 향하도록 표기한다.
참조는 다양한 형태로 이루어질 수 있는데, 객체 생성, 객체 사용(속성/필드 및 메소드), 매개변수 등이 있으며 stereo type을 통해 이를 명시할 수 있다.
연관은 다른 객체의 참조를 가지는 속성(필드)을 의미한다.
실선 만을 통해 일반적인 Association을 나타낼 수 있으며, 화살표를 추가하여 Directed Association을 나타낼 수 있다. 두 관계의 차이는 방향성으로, 이를 통해 참조하는 곳과 참조 당하는 곳을 구분할 수 있다.

classDiagram
class Member
class Group {
- List~Member~ members
}
Group "1" --> "*" Member : -members
Group의 field로 Member의 List를 갖는 것을 위와 같이 표현할 수 있다. -members는 역할명(role name)을 나타내며, 참조 시 클래스가 갖는 역할을 나타내는데, 보통 참조하는 field의 이름이 된다.
1과 *은 Multiplicity(개수, or Catdinality)를 나타내며 class가 가질 수 있는 instance의 개수를 나타낸다. 0...1 과 같이 ...으로 구분하여 최소, 최대 값을 나타낼 수 있으며, 0, 1, 또는 *(Many)을 사용한다.
Aggregation에는 Shared Aggregation과 Composite Aggregation이 있으며, Association 관계를 더 구체화 하여 나타낸 것으로, 전체와 부분의 관계를 나타낸다.(집합의 의미를 가지고 있다)
Aggregation(or Shared Aggregation)은 아래와 같이 빈 다이아몬드와 실선을 통해 표기할 수 있다.

classDiagram
class Group {
- List~Memeber~ members
}
class Member
Group o-- Member : -members
전체(whole) 부분에 빈 다이아몬드를 표기하고, 부분(part)에는 화살표를 명시하지 않아도 된다.
위 diagram을 실제 코드로 구현한다면, 위 Association과 크게 다르지 않을 것이다. 1:1, 1:N 등 다양한 관계를 나타낼 수 있는 Association과 달리, Aggregation은 1:N이라는 관계를 나타낸다는 의미 차이는 있지만, 실제 코드에서 이를 구분하기 어렵다. 그래서 논란이 많은 듯 하다.
Composite(or Composite Aggregation)은 Shared Aggregation과 같이 전체와 부분의 관계를 나타내지만, Shared Aggregation보다 더 강한 집합을 의미한다. 표기법 또한 Shared Aggregation과 유사하지만, 다이아몬드 내부를 채워 표기한다.

classDiagram
class Group {
- List~Member~ members
}
class Member
Group *-- Member : -members
강한 집합이 뭔데
강한 집합이란 부분이 전체에 종속적임을 의미한다. 즉, Group이 Member instance들을 소유함을 의미한다. Shared Aggregation은 부분이 전체에 대해 독립적임을 의미하는 점에서 차이가 있다. Shared Aggregation과 달리 나타내는 점은 아래와 같다
위 두 조건을 모두 만족하기 위해 부분(part) instance들은 함께 복사 되어야 하지만, 공유 되지 않아야 하기에 shallow copy가 아닌 deep copy가 되도록 구현하여야 한다.