본문 바로가기

c c++ mfc

UML Class Diagram의 화살표들, Class 간의 관계

반응형

오늘은 UML의 Class Diagram으로 설계를 진행할 때, 항상 이 화살표를 어떤거를 써야하는지 헷갈려서 정리하는 시간을 가져보겠습니다.

 

UML Class Diagram은 시스템의 구조를 시각화하기 위해 사용되며, 클래스 간의 관계를 나타내는 화살표로 다양한 종류의 연관 관계를 표시할 수 있습니다. 이 글에서는 Composition, Aggregation, Association, Dependency, Inheritance, Realization/Implementation관계에 대해 소개하고 각각에 대한 예제 코드도 제공합니다.

 

Class 간의 관계

1. Association (연관)

Association은 두 클래스가 서로 연관되어 있음을 나타냅니다. 연관 관계는 일반적으로 클래스 간의 참조 관계를 의미하며, 다이어그램에서는 두 클래스를 직접 연결하는 화살표로 표시합니다. 방향이 있는 실선과 방향이 없는 실선 두 가지로 연관 관계를 나타낼 수 있습니다.

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

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

class Car {
private:
    Engine* engine;
public:
    Car(Engine* e) : engine(e) {}
    
    void start() {
        engine->start();
    }
};

class Driver {
public:
    void drive(Car* car) {
        car->start();
    }
};

int main() {
    Engine engine;
    Car car(&engine);
    
    Driver driver;
    driver.drive(&car);
    return 0;
}

위 예제에서 Driver는 Car를 사용하여 드라이브하지만, Car의 생명주기를 관리하지 않으므로 일반적인 Association입니다. 

 

2. Inheritance (상속)

Inheritance는 한 클래스가 다른 클래스의 속성과 메서드를 상속받는 관계를 나타냅니다. 상속을 통해 코드의 재사용성과 확장성을 높일 수 있으며, 객체 지향 언어에서 매우 중요한 개념입니다. UML 다이어그램에서는 상속 받는 클래스와 상속하는 클래스를 화살표로 연결하며, 화살표 끝에는 빈 삼각형이 위치합니다. Generalization - 일반화라고도 많이 부릅니다.

class Vehicle {
public:
    void drive() { /* ... */ }
};

class Car : public Vehicle {
public:
    void honk() { /* ... */ }
};

위 예제에서 Car 클래스는 Vehicle 클래스를 상속받습니다. 따라서 Car 클래스는 자신의 메서드인 honk()와 함께 Vehicle 클래스의 drive() 메서드도 사용할 수 있습니다.

3. Realization / Implementation (구현)

Realization 또는 Implementation은 인터페이스와 그 인터페이스를 구현하는 클래스 간의 관계를 나타냅니다. 인터페이스는 메서드 시그니처만 제공하며, 해당 메서드의 구현은 인터페이스를 구현하는 클래스가 담당합니다. UML 다이어그램에서는 인터페이스와 구현 클래스를 점선 화살표로 연결하며, 화살표 끝에는 빈 삼각형이 위치합니다.

class Drivable {
public:
    virtual void drive() = 0;
    virtual void stop() = 0;
};

class Car : public Drivable {
public:
    void drive() override { /* ... */ }
    void stop() override { /* ... */ }
};

위 예제에서 Drivable 인터페이스는 drive()와 stop() 두 개의 함수를 정의하고 있습니다. Car 클래스는 Drivable 인터페이스를 구현하며, 이를 통해 drive()와 stop() 메서드에 대한 구현을 제공합니다.



상속(Inheritance)과 구현(Realization/Implementation) 관계를 이해하고 활용하면 유연한 소프트웨어 설계를 할 수 있으며 코드의 유지보수와 확장에 효과적입니다. 정확한 상속 및 구현 관계를 사용하여 UML Class Diagram을 작성하면 시스템의 구조와 개념을 명확하게 전달할 수 있습니다.

4. Dependency (의존)

Dependency는 한 클래스가 다른 클래스에 의존하는 관계를 나타냅니다. 이 관계는 일반적으로 메서드 내에서 다른 클래스를 사용할 때 발생하며, UML 다이어그램에서는 점선 화살표로 표시됩니다.

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

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

class Engine {};

class Car {
public:
    void startEngine(Engine &engine) { /* ... */ }
};

위 예제에서 Car 클래스의 startEngine 메서드는 Engine 클래스의 객체를 사용하므로, Car 클래스는 Engine 클래스에 의존합니다.

5. Aggregation (집합)

Aggregation은 전체 클래스와 부분 클래스 사이의 약한 포함 관계를 나타냅니다. 전체 클래스가 사라져도, 부분 클래스는 독립적으로 존재할 수 있습니다. UML 다이어그램에서는 전체 클래스와 부분 클래스 사이의 관계를 화살표로 표시하며, 화살표 끝에는 빈 다이아몬드가 위치합니다. 

class Wheel {};

class Car {
public:
    void setWheel(Wheel *newWheel) { wheel = newWheel; }

private:
    Wheel *wheel;
};

위 예제에서 Car 클래스는 Wheel 클래스를 포함하지만, Car 객체가 소멸되어도 Wheel 객체는 독립적으로 존재할 수 있습니다.

6. Composition (합성)

Composition은 전체 클래스(whole)와 부분 클래스(part) 사이의 강한 포함 관계를 나타냅니다. 전체 클래스가 사라지면 부분 클래스도 함께 사라집니다. UML 다이어그램에서는 전체 클래스와 부분 클래스 사이의 관계를 화살표로 표시하며, 화살표 끝에는 검은색 다이아몬드가 위치합니다.

class Engine {};

class Car {
public:
    Car() : engine(new Engine()) {}
    ~Car() { delete engine; }

private:
    Engine *engine;
};

위 예제에서 Car 클래스가 Engine 클래스를 포함하고 있습니다. Car 객체가 소멸될 때 Engine 객체도 함께 소멸됩니다.

 

 

이렇게 UML Class Diagram은 클래스 간의 관계를 시각화하는 데 도움이 되며, 시스템 설계 및 통신을 위한 중요한 도구로 사용됩니다. 다양한 관계를 구분하고 이해하면 더욱 효과적인 시스템을 설계할 수 있습니다.

반응형