UML - Class Diagram, mermaidJs

BK·2024년 5월 22일

SW

목록 보기
1/1
post-thumbnail

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

또한 Notion에 mermaid block이 있는데, 잘 사용하면 좋겠다는 생각이 들어서 mermaid 코드도 간략히 함께 첨부하고자 한다.


mermaid JS

UML(Unified Modeling Language)

UML이란 OMG(Object Management Group)에서 표준으로 관리하는 SW 공학에서 사용되는 표준화된 범용 모델링언어(Standard of Modeling Language)이다. 통합 모델링 언어란, 객체 지향 프로그래밍에서 시스템을 개발할 때 산출물을 명세화, 시각화, 문서화할 때 사용되며, UML은 시스템을 시각화하는 표준안을 제공한다.

UML은 하나의 소통을 위한 도구로서, 설계자 및 개발자 등 구성원들 간 잘못된 의사소통을 줄이고, 문서를 통해 명확한 의사소통이 가능하게 한다.

UML에는 7개의 구조(Structure) 다이어그램과 7개의 행위(Behavior) 다이어그램, 총 14개의 다이어그램이 있다.

  1. 구조 다이어그램(Structure Diagram)은 시스템의 개념, 관계 등의 측면에서 요소들을 나타낸다. 그 예시로 class, component, object, package, deployment diagram 등이 있다.
  2. 행위 다이어그램(Behavior Diagram)은 각 요소의 변화나 흐름, 주고받는 데이터 등을 나타낸다. 그 예시로 activity, use case, interaction diagram 등이 있다.

Class Diagram

Class diagram구조 다이어그램(Structure Diagram)에 해당하며, class 내부 내용이나 class들 간 관계를 표기한다. OOP에서 많이 사용되며, 시스템의 논리적인 구조를 표현하며, 요구 사항의 작업에 대한 책임을 분할한다.

Class Diagram의 요소(Element)

Class는 보통 3개의 구역으로 나누어 class 이름, 속성, 기능을 표기한다.

아래는 위 사진에 대한 mermaid code이다.

classDiagram
class User{
	- int id
	- String name
	+ getId() int
	+ String getName() String
}
  • 객체의 이름을 표기하는 방법은 단순명(Simple name)과 경로명(Path name)이 있다.
    • 단순명 : class의 이름만 표기
    • 경로명 : package명을 포함한 class의 이름을 표기
  • 각각 java class의 field, method에 해당하는 속성, 기능은 생략할 수 있으며, 꼭 class의 모든 내용을 담기보다 목적에 따라 필요한 내용을 표시한다.
  • 속성과 기능 앞 - / +는 접근 제어(visibility)를 의미하며 각각 아래와 같다
    표기접근 제어자
    +public
    -private
    #protected
    ~package/internal
  • 세가지 구획 외에도 필요에 따라 발생한 예외 등 새로운 구획을 추가하여 사용할 수 있다.

Stereo Type

Stereo Type이란 UML의 기본 요소 외 추가적인 확장 요소로, 길러멧(ghuillemet, << >>) 사이에 표기한다.

classDiagram
	class Person
	<<interface>> Person

mermaid code

위와 같이 interface임을 명시하기 위한 <<interface>>, abstract class임을 명시하기 위한 <<abstract>> 등이 사용되며, 필요에 따라 추가하여 사용한다.

Abstract Class

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

Inner Class

Class 내부에 선언된 class는 outer class의 이름까지 포함한 이름으로 표기한다.

classDiagram
	class Outer
	class `Outer.Inner`

Class간 관계

Class Diagram은 클래스간 관계를 쉽게 알아볼 수 있도록 하는 것이 주된 목적이다. 따라서, Class diagram에서 가장 중요한 것은(어려운 것은) Class간 관계가 아닐까 싶다.

Class 간 관계의 종류는 아래와 같다.

  • 일반화(Generalization)
  • 실체화(Realization)
  • 의존(Dependency)
  • 연관(Association)
  • 직접연관(방향성 있는 연관, Directed Association)
  • 집합(집합연관 ,Aggregation)
  • 합성(복합연관 ,Composition)

이름부터 어렵지

각 관계와, UML 표기법에 대해서는 아래에서 구체적으로 알아보겠다.

Generalization : 일반화

일반화는 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 관계이다.

Realization : 실체화

실체화는 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 이다.

Dependency : 의존

의존은 class diagram에서 가장 많이 사용되는 관계이며, class가 다른 class를 참조하는 것을 말한다.

classDiagram
	class Store
	class Employee
	
	Store ..> Employee

UML에서는 점선과 화살표를 통해 나타내며, 다른 class를 참조하는 class에서 참조 대상이 되는 class로 화살표 방향이 향하도록 표기한다.

참조는 다양한 형태로 이루어질 수 있는데, 객체 생성, 객체 사용(속성/필드 및 메소드), 매개변수 등이 있으며 stereo type을 통해 이를 명시할 수 있다.

Association : 연관, Directed Association

연관은 다른 객체의 참조를 가지는 속성(필드)을 의미한다.

실선 만을 통해 일반적인 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

Aggregation에는 Shared Aggregation과 Composite Aggregation이 있으며, Association 관계를 더 구체화 하여 나타낸 것으로, 전체와 부분의 관계를 나타낸다.(집합의 의미를 가지고 있다)

Aggregation : 집합, Shared Aggregation

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이라는 관계를 나타낸다는 의미 차이는 있지만, 실제 코드에서 이를 구분하기 어렵다. 그래서 논란이 많은 듯 하다.

Composition : 합성, Composite Aggregation

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과 달리 나타내는 점은 아래와 같다

  • 전체(whole) instance가 부분(part) instance들의 전체 life-cycle을 책임진다
    • 전체가 부분 instance를 생성, 소멸을 담당하고, 전체가 복사 될 때 함께 복사 되어야 한다
  • 부분(part)에 해당하는 instance는 공유 될 수 없다.

위 두 조건을 모두 만족하기 위해 부분(part) instance들은 함께 복사 되어야 하지만, 공유 되지 않아야 하기에 shallow copy가 아닌 deep copy가 되도록 구현하여야 한다.

0개의 댓글