본문 바로가기

객체지향 디자인 패턴

[UML] 클래스 다이어그램 (Class Diagram)

출처: https://brownbears.tistory.com/577

 

클래스 다이어그램은 구조 다이어그램으로 클래스 내부 구성요소 및 클래스 간의 관계를 도식화하여 시스템의 특정 모듈이나 일부 및 전체를 구조화 합니다. 개발 하기 전, 클래스 다이어그램을 그리게 되면 시스템 내 클래스 간의 의존성 파악과 팀원들 간 의사소통이 편리합니다.

클래스 다이어그램의 목적에 따라 개념, 명세, 구현 단계로 나눌 수 있습니다.

개념 단계에서는 클래스만 도출하고 관계를 단순화하는 것이 목적입니다.

명세와 구현 단계에서는 개발 직전 설계나 구현 이후 설명 목적으로 사용되고 이 다이어그램을 기반으로 코드로 구현하거나 코드를 기반으로 다이어그램을 그리기 때문에 코드와 연관이 깊습니다.

요소 (element)

클래스

클래스 다이어그램에서 클래스는 이름, 속성(변수), 메소드 순으로 나열합니다. 속성과 메소드는 생략이 가능하지만 이름은 필수로 입력해야 합니다.

앞에 +, -, #이 붙는데 +는 public, -는 private, #은 protected, ~는 default를 의미합니다.

{readonly}가 붙으면 final을 밑줄은 static을 의미합니다.

[*] 나 [0...1]은 리스트와 같은 변수에 지정된 사이즈를 뜻합니다. List의 경우는 사이즈가 정해지지 않아서 *로 표기하고 Optional의 경우, 0개거나 1이여서 0..1로 표기합니다. Array와 같이 미리 사이즈를 지정한다면 [5] 와 같은 형태로도 표현할 수 있습니다.

이러한 의미는 속성과 메소드 둘 다 사용하여 표기가 가능합니다.

속성(변수)를 보면 접근 제어자, 필드명, 타입 순으로 작성합니다.

  • {접근제어자} {필드명}: {타입}

메소드는 접근제어자, 메소드명(파라미터 타입), 반환 타입 순으로 작성합니다.

  • {접근제어자} {메소드명}({파라미터타입}): {반환타입}

스테레오 타입

인터페이스나 추상 클래스와 같은 요소를 표기하기 위해 << >> 와 같은 문법을 사용하는데 이를 길러멧(guillemet)이라 부릅니다. 길러멧은 클래스명 위에 작은 글씨로 작성합니다. 길러멧은 보통 인터페이스, enum, 추상 클래스 등에서 사용되지만 사용자의 확장 클래스를 의미하는데에도 사용할 수 있습니다.

추상 클래스

추상 클래스를 나타내는 방법은 총 3가지로 이탤릭체(기울어진 글씨)로 표시하거나 클래스 명에 {abstract}을 붙이거나 길러멧으로 표시하는 방법이 있습니다.

클래스 간 관계

클래스 간 관계를 정확하게 하는 것이 클래스 다이어그램을 그리는 주된 목적입니다. 이러한 관계를 나타내는 표현은 아래와 같습니다.

이미지 참조:  https://en.wikipedia.org/wiki/Class_diagram

 

Association

다른 객체의 참조를 가지고 있을 때 이러한 연관 관계를 나타냅니다. 여기서는 위처럼 방향이 있는 실선과 방향이 없는 실선 두 가지로 연관 관계를 나타낼 수 있습니다.

A → B 와 같이 방향이 있는 실선의 경우, A가 B를 참조한다는 의미입니다.

A - B는 A가 B를, B가 A를 참조할 수도 있고 둘 다 참조 이거나 둘 다 참조가 아니거나 라는 의미입니다.

아래는 방향성 있는 연관관계에 대한 예시입니다. 해당 예시는 동일한 코드를 표현하는 예시들입니다.

Inheritance

상속 관계를 나타냅니다. Generalization - 일반화라고도 많이 부릅니다. 부모 클래스와 자식 클래스 간의 상속 관계를 나타낼 때 사용합니다.

Realization

인터페이스를 상속하여 클래스에서 실제 기능을 실현화 할 때 사용합니다.

실체화는 아래와 같이 두 가지로 표시가 가능합니다.

Dependency

클래스간 참조 관계를 나타낼 때, 사용합니다. Association과의 차이점으로는 Association은 변수로 다른 클래스와 연관이 있을 때, 사용하고 Dependency는 메소드의 파라미터나 반환에 사용되는 클래스 관계를 나타낼 때 사용합니다.

즉, Association 관계는 해당 클래스의 멤버 변수로 할당할 때 사용하고 Dependency 관계는 로컬 변수, 파라미터, 반환 값으로 호출되는 메소드가 실행되는 동안에만 유지가 될 때 사용합니다.

Aggregation

집합 관계를 나타낼 때 사용합니다. (전체 - 부분) Association 관계와 크게 다르지 않고 의미 또한 이해가 잘 되지 않습니다.

Composition

Aggregation과 비슷하게 전체 - 부분의 집합 관계를 나타낼 때 사용하지만 Aggregation 보다는 더 강력한 집합을 의미할 때 사용합니다. 합성 관계에서는 부분이 전체에 종속적이고 라이프 사이클을 관리한다 라고 볼 수 있습니다.

아래 예시를 들어 설명하자면,

User가 전체고 Grade가 부분이 됩니다.

여기서 User는 Grade 인스턴스를 생성하고 User 객체가 소멸될 때, Grade 인스턴스도 소멸되고 User가 복사된다면 Grade 인스턴스도 복사되어야 합니다.

또한 Grade 인스턴스는 공유가 되면 안됩니다.

예를 들어, 아래와 같은 코드가 있다고 가정했을 때 User를 복사한다면 shallow copy(얕은 복사)가 일어나 User와 복사된 User에서 동일한 Grade 인스턴스를 바라보게 됩니다.

var user = new User();
var copyUser = (User) User.clone();
copyUser.getGrade().setGrade("VISITOR");

따라서 Cloneable 인터페이스를 상속받고 clone을 구현해야 합니다.

이러한 복잡한 종속 관계를 만족해야지만 합성 관계를 표시할 수 있습니다.