멈재

[UML] 클래스 다이어그램 본문

WEB

[UML] 클래스 다이어그램

멈재 2023. 6. 22. 18:52
728x90

소프트웨어를 모델링하는 용도로 흔히 표준화된 모델링 언어인 UML을 종종 사용하게 되는데 그중에서도 정적인 면을 나타내는 클래스 다이어그램을 알아보려 한다.
 
클래스 다이어그램은 다음 이미지와 같이 시스템을 구성하는 클래스, 인터페이스, 관계, 상속 등을 보여주는 다이어그램으로 클래스 내부의 정적인 내용과 클래스간의 의존 관계를 표시하는 용도로 사용한다.
 

이미지 출처: https://velog.io/@zooneon/클래스-다이어그램

 
클래스 다이어그램의 구성 요소는 크게 네 가지로 구분할 수 있다.

  • 클래스
  • 스테레오 타입
  • 추상클래스 / 메서드
  • 클래스간의 관계

 
코드 예시와 함께 하나씩 알아보자.

전체 코드는 Github를 참고해주세요

 

클래스

클래스 다이어그램에서 클래스는 클래스의 이름, 속성(변수), 행위(메서드)를 표현할 수 있다.

  • 가장 윗 부분: 클래스 이름
  • 중간 부분: 속성(변수)
  • 마지막 부분: 행위(메서드)

 

클래스의 필드와 메서드에는 접근제어자, 필드명, 메서드명, 데이터 타입, 매개변수, 리턴 타입 등을 나타낼 수 있다.
 
접근 제어자와 필드 속성에 따라 다음과 같이 표현할 수 있다.

 
 

스테레오 타입

스테레오 타입은 UML에서 제공하는 기본 요소 외에 추가적인 확장 요소를 나타내는 타입으로 쌍 꺾쇠와 비슷하게 생긴 길러멧(«») 사이에 적는 형태로 나타낸다.
 
아래 이미지는 인터페이스와 유틸리티 클래스를 스테레오 타입으로 사용한 예시이다.

일반적으로 스테레오 타입으로 많이 사용되는 것은 «interface», «utility», «abstract», «enumeration» 가 있다.
 
 

추상 클래스와 메서드

추상 클래스란 하나 이상의 추상 메서드(구현체가 없는 메서드)를 포함하는 클래스로 공식적으로는 두 가지 방식의 표기법을 제공하고 있다.

  1. 추상 클래스의 이름과 추상 메서드를 italic체로 표현
  2. {abstract} 프로퍼티를 사용하여 표현
  3. (공식적이지는 않지만) 스테레오 타입으로 추상 클래스를 표기

 
 

클래스간의 관계

클래스 다이어그램의 주된 목적 중 하나가 클래스간의 관계를 한 눈에 보고 의존 관계를 파악하는 용도로 사용한다.
 
클래스간의 관계를 나타낼 때 대상 클래스의 가질 수 있는 인스턴스 개수(Multiplicity)의 범위를 나타낼 수 있는데 이러한 다중성 표기 방법은 다음과 같다.

 
 
본 포스팅에서 설명할 클래스간의 관계는 크게 여섯 가지(와 중첩 관계)를 알아본다.

이미지 출처: https://en.wikipedia.org/wiki/Class_diagram

 

일반화 관계(Generalization)

일반화(generalization) 관계는 객체 지향 개념에서 부모 클래스와 자식 클래스간의 상속 관계를 나타낸다.
 
부모 클래스는 자식 클래스를 일반화(Generalize) 한 것이고, 자식 클래스는 부모 클래스를 구체화(Specitialize)한다.
IS-A 관계 표기법은 클래스 사이에 실선으로 연결하고 부모 클래스 쪽에 비어 있는 삼각형 화살표를 그려 표현한다.

 
 

실체화 관계(Realization)

실체화(Realization) 관계는 interface에 명세(정의)만 되어 있는 메서드를 오버라이딩하여 실제 기능으로 구현하는 것을 나타낸 관계로 인터페이스와 구현 클래스 사이의 실체화(Realize) 관계는 점선으로 연결하고 인터페이스 쪽에 비어있는 삼각형 화살표로 연결하여 표현한다.

 
 

의존 관계(Dependency)

의존 관계는 어떤 클래스가 다른 클래스를 참조하는 것을 의미하는데 클래스간에 점선으로 연결하고 참조할 클래스에 화살표로 연결하여 표현한다.
 
참조의 형태는 다음과 같다.

  • 메서드 내 대상 클래스 객체 생성
  • 메서드 내 대상 클래스 객체 사용
  • 메서드 내 대상 클래스 메서드 호출
  • 메서드 내 대상 클래스 객체 리턴
  • 메서드에서 대상 클래스 객체를 매개변수로 받는 것 등

의존 관계에서의 객체 참조는 계속 유지하지 않고 메서드의 호출이 끝나면 의존 관계의 클래스와 관계가 끝난다는 의미를 갖는다.

 
 

연관 관계(Association & Directed Association)

연관 관계는 보통 다른 객체의 참조를 가지는 필드를 의미한다.
경우에 따라서 방향이 있는 실선과 방향이 없는 실선 두 가지로 방향성(navigability)에 따라 연관 관계를 나타낼 수 있다.
 
방향이 있는 실선 (Directed Association)

연관 관계에서 화살표가 있다는 것은 단방향 연관 관계를 의미한다. 이 말은 한쪽은 알지만, 다른 쪽은 상대방의 존재를 모른다는 관계를 나타낸 것이다.
여기서 - comments는 역할 이름을 나타내며, 코드 내에서 Comment가 Board에 참조될 때 어떤 참조 속성의 이름인지를 의미한다.
 
방향이 없는 실선 (Association)
만약 아래 이미지처럼 실선으로만 이어져있다면 Board가 Comment를 참조할 수도, Comment가 Board를 참조할 수도, 둘 다 참조할 수도 있음을 의미한다.

 
연관 관계가 어떻게 되는지 숫자로도 표현이 가능하다.

 
다중성 표기를 풀어쓰면 다음과 같다.

  • 사용자는 휴대폰을 0개 또는 그 이상을 가질 수 있다.
  • 학생은 1개 이상의 강좌를 가져야 하고, 강좌는 1명 이상의 학생을 가져야 한다.

 
 
참고로 연관 관계는 다음과 같은 형태로도 표현이 가능하다.

public class Creator {
    @Embedded
    private Platform platform;
}

@Embeddable
class Platform {
    @Embedded
    private PlatformUrl platformUrl;

    @Embedded
    private PlatformType platformType;
}
JPA(Java Persistence API)의 값 타입 적용

 
 

public class Collegian {
    private List<Grade> grades
}

class Grade {
    private Subject subject;
}

class Subject {}

 
 
다음에 설명할 집합 관계(Aggregation)와 합성 관계(Composition)는 연관 관계(Association)를 특수하게 나타낸 것으로 전체(whole)와 부분(part)으로 나타낸다.
 

집합 관계(Aggregation, Shared Aggregation)

집합 관계는 연관 관계의 집합 관계를 나타내는 것으로 Collection이나 Array를 이용하는 관계로 아래 이미지에서 전체(Whole)는 Vulture이게 되고, 부분(Part)은 Mine이 된다.
 
표기법은 전체 쪽에 비어있는 다이아몬드로 표기하고, 부분 쪽에는 화살표를 명시하여도 되고, 명시하지 않아도 된다.

 

집합 관계는 앞서 살펴본 연관 관계와 비슷한 형태를 띄고 있다.
심지어는 코드도 연관 관계의 코드와 동일하다.

사실 연관 관계와 집합 관계의 차이는 집합이라는 개념적인 차이만 존재하고 있기 때문에 아직까지도 일부에서는 집합 관계의 명확한 정의를 제공하지 않아서 현재까지도 갑론을박이 계속된다고 한다.

그래도 각각의 정의를 나타내면 다음과 같이 설명할 수 있다.
- 연관 관계: 다른 객체의 참조를 가진다. 집합이라는 의미를 내포하고 있지 않다.
- 집합 관계: 다른 객체의 참조를 가진다. 집합이라는 의미를 내포한다.

 
 

합성 관계(Composition, Composite Aggregation)

합성 관계는 집합 관계처럼 전체(Whole)와 부분(Part)으로 이루어져 있지만 개념적으로 집합 관계보다 더 강한 집합을 의미한다. 표기법은 집합 관계와 표기법은 거의 비슷하고, 다이아몬드의 내부가 채워져 있다는 점만 다르다.

 
집합 관계와 합성 관계를 스타크래프트 유닛으로 예시를 들어보겠다.

혹시라도 예시가 적절하지 않거나 문제 된다면 댓글에 남겨주세요 :)

 
집합 관계는 부분이 전체에 독립적이다.

  • 전체(Whole) 객체의 라이프 사이클과 부분(Part) 객체의 라이프 사이클이 독립적이다.
  • 즉, 전체 객체가 메모리에 존재하지 않아도, 부분 객체는 메모리에 유지되고 있다.

집합 관계는 스타크래프트의 벌처 마인으로 예시를 들 수 있다.
전체인 벌처가 존재하지 않아도 부분인 마인은 유지되기 때문이다.

 
반면 합성 관계는 어떨까
 
합성 관계는 부분이 전체에 종속적이다.

  • 부분 객체의 라이프 사이클이 전체 객체의 라이프 사이클에 의존적이다.
  • 즉, 전체 객체가 메모리에서 해제되면 부분 객체도 메모리에서 해제된다.

합성 관계는 스타크래프트 캐리어의 인터셉터로 예시를 들 수 있다.
부분인 인터셉터는 전체인 캐리어에 의존적이기 때문에 캐리어가 존재하지 않으면 인터셉터는 사라지게 된다.

 
 

중첩 관계(Nested)

중첩 관계는 외부 클래스 안에 내부 클래스가 존재하는 경우를 의미한다.

 
 
 
참고