본문 바로가기

SW 설계/UML

[UML / OOP] Class 간 관계에 대하여

728x90

SW 설계에서 UML 을 공부하다보면 등장하는 5가지 Class 관계가 있다 (OOAP). 이 Class 관계도는 SW 를 설계할 때 어떤식으로 SW를 설계할지에 대해서 확실한 그림을 잡아주기 때문에 상당히 중요한 역할을 하고, 커뮤니케이션에서도 중요한 역할을 하는 것 같다. 개발 실무적인 영역으로만 학습을 많이 했다면 처음 들어보는 관계일 수도 있지만 절대 어려운 개념들은 아니니, 한 번 이해해보는 기회가 되면 좋을 것 같다. 

 

 

 

 

 

이제 배울 내용은 SW를 구현하기 전 설계 단계에서 Class 간 관계를 설계해 놓을 때 많이 사용하고 표시해두는 관계이다. 실무적인 공부만 하다가 다음과 같은 정보를 많이 접하는 것 같았다. 

 

 

Class 들이 서로 의존한다 == Class 코드 안에 다른 Class 가 등장하여 서로의 존재를 알고 있음

 

 

실무적으로는 위의 사실이 크게 문제가 되는 부분은 아니다. 하지만 설계 시점에서 저렇게만 정의하는 것은 설계단과 커뮤니케이션시 다소 문제가 될 수도 있는 부분이기 때문에 조금 더 정확히 알고 넘어가는게 좋다. 우선 간략하게 살펴보면 다음과 같다 

 

 

Class 간 5가지 관계

 

 

1. Dependency - 잠깐 일하고 끝나는 사이 (구현 직전 단계까지 가야 정확히 나오는 관계이다)

2. Association - 설계시 가장 많이 사용하는 관계로, 일정 시간동안 같이 협력하는 사이. Association 에는 두가지 관계가 있다.

3. Shared Aggregation - Association 관계 중 첫번째. 만들어진 Object 를 사용하는 경우

4. Composition - Association 관계 중 두번째. 직접 타 Class 를 통해 Object 를 내부적으로 생성하여 사용하는 경우

5. Inheritance - Generalization 관계로, 부모 / 자식의 관계 

 

 

그림에도 나와있듯이, 5번 관계로 갈수록 두 클래스는 강한 결합의 관계이며, 1번으로 갈수록 약한 결합의 관계라고 볼 수 있다. 또한, UML 중 하나인 Class Diagram 에서는 위 관계들을 표현하는 화살표가 다르다. 이제부터 하나씩 살펴보자. 

 

 

 

Dependency

 

 

public class Group {

    public void updateInfo(GroupInfo groupInfo){
        
        String name = groupInfo.getName();
        
        // ... GropuInfo 를 통해 추후 update 진행
        
    }
}

 

 

위 예제에서는 Group Class 내의 updateInfo() 함수가 GroupInfo Object 를 변수로 받아서 getName()을 통해 내부적인 메세지를 전달한다. 중요한 점은 GroupInfo 가 수정된다면, Group Class 에 영향을 줄 수 있다는 점이다. 또한, updateInfo() 함수가 종료되면 Group 이 GroupInfo 를 parameter 로 받은 상태였기 때문에 함수 종료시 더 이상 GroupInfo 를 참조할 수 없다는 특징도 있다. 위와 같은 Class Diagram 으로 그려질 수 있고, 점선 화살표로 표현이 된다. 

 

 

UML 툴 추천좀

 

 

 

Association

 

 

사실 Association 관계는 대표적인 두 가지 관계 (Aggregation, Composition) 으로 대부분이 정의되기 때문에, 다른 상황에 대해 굳이 구체적으로 알아볼 필요는 없다고 생각한다. 그래도Association 관계에 있어서 다음 용어 및 상황들에 대해서 잠깐 알아보자. 

 

 

 

1) Navigability

 

 

UML에서의 Navigability 표현한 Assocation 관계

 

 

Association 관계에서 추가되는 표현중 Navigability 가 있다. 즉, A 가 B 에 대한 Navigability 를 가지고 있다고 한다면, A 클래스는 B 클래스의 존재를 알고 있어, B 클래스의 visible 한 변수와 함수들에 접근할 수 있다는 뜻이다. 

 

 

위 관계처럼 화살표로 표현하는데, 위 그림처럼 양쪽다 화살표가 없다면 서로 Navigability 가 있다는 뜻이며, 한 쪽으로만 있으면 반대쪽은 Navigability 가 없다는 뜻이라고 한다. (1:N, N:1 매핑할 때 연관관계 매핑을 하냐마냐랑 비슷한 듯) 

 

 

 

2) Association Class

 

 

Association class 란 서로의 관계를 각 클래스에 두기보단, 또 다른 Class 를 만들어 정의하는 방식을 말한다. 관계형 매핑을 해보신 분들은 N:N 관계를 만들 때 연결 객체를 두는 것과 똑같다고 생각하면 된다.

 

 

가령, Lecture 와 Student 와 같은 Class 들이 있다면, Lecture 에는 여러 Student 들이 있고, Student 는 여러 Lecture 을 들을 수 있다. 특정 Lecture Object 와 특정 Student Object 마다 [등록 시간, 확정 여부, 성적, 담당 조교, ...] 등의 내용을 가지고 있어야 하는데, 각각 Class 안에 모든 Object 들을 위해 이런 내용들을 담는 것은 불가능한 일이다. 따라서 다음과 같이 정의한다. 

 

 

UML 툴 추천 좀 ㅇㅇ

 

 

이걸 보고 흔하게 N:N Entity Table 이네 하고 넘어갈 수도 있다. 맞는 말이지만, 지금은 최대한 실무 영역에서 벗어나서 순수 OOP 언어적으로 생각하는게 좋다. 꼭 DB Table 과 매핑되는 Entity 가 아니라, 위와 같은 관계는 OOP 언어적으로 시작된 관계이며, 서로 unique 한 object 를 지칭해야 하기 때문에 Hash 값을 이용하는 방식 등을 사용하기도 한다. 

 

 

 

3) Interface

 

 

우리 모두가 사랑하는 Interface 이다. 디자인 패턴의 핵심이 되는 이 관계는 위에서 말한 두가지 Association 중 하나가 아니지만, Association 관계에 포함시키기는 하는 것 같다 (Interface 는 근데 흔히 Class 간 관계는 아니라고 생각한다. 왜냐하면 Interface 는 클래스가 아니기 때문이다). Interface 는 다음과 같은 하얀 점선 화살표로 표현한다. 

 

 

interface 관계는 이처럼 하얀 점선 화살표로 표시한다

 

 

 

Association 1 - Shared Aggregation (Aggregation) 

 

 

Shared Aggregation 은 A 클래스가 B를 가지고 있을 때, 약한 소유 관계를 가지고 있는 관계이다. A가 B를 Shared Aggregation 관계로 가지고 있다고 하며, 다음과 같이 예시를 들 수 있다. 

 

 

public GroupMember {

    private Group group;
    private Member member;

    public GroupMember(Group group, Member member){
        this.group = group;
        this.member = member;
    }
    // ...
}

 

 

이와 같은 관계일 경우 GroupMember 에는 특정 Group Object 와 특정 Member Object 를 중심으로 형성이 되기 때문에, GroupMember 가 각각 Group 과 Member 를 Shared Aggregation 관계로 가지고 있는 것이다.

 

 

이 때, GroupMember Object 가 사라진다고 해서 (Member가 Group을 탈퇴함), 기존 Group 과 기존 Member 가 없어지지 않는다. 이런 소유 관계를 Shared Aggregation 관계라고 한다. 

 

 

 

Association 2 - Composition

 

 

Composition 관계는 A 클래스가 B를 가지고 있을 때, 강한 소유 관계를 가지고 있는 관계이며, A Object 가 없어진다면 B Object 도 같이 삭제가 된다. 만약 A가 B를 Composition 관계로 가지고 있다고 하며, 다음과 같이 예시를 들 수 있다.

 

 

public Building {

    private Office office;
    
    public Building(Office office){
        
        this.office = new Office(~~, ~~, ~~, ...);
        // ...
    }
    
    // ...    
}

 

 

Building 이 삭제된다면 당연히 Building 안에 있던 사무실 모두 삭제가 되어야 한다. 이런 논리 관계를 위와 같이 표현할 수 있으며, Building 이 Office 를 Composition 관계로 가지고 있는 것이다. 

 

 

 

Inheritance (Generalization)

 

 

지금까지 배웠던 관계 중 가장 강력한 관계를 가지고 있는 관계는 Inheritace 관계이다. Class Diagram 에서는 Interface 화살표에서 점선이 아닌 실선 흰색 화살표로 표현한다. 

 

 

Inheirtance 관계에서의 Class Diagram 모습

 

 

위와 같이 상속 관계로 표현되며, 부모의 public, protected 한 정보들을 모두 access 및 override 할 수 있다. 또한, 부모 관계가 가지고 있는 모든 연관 관계를 그대로 상속 받을 수 있다. 이런 관계를 Class Diagram 에서는 굳이 표현하진 않으며, 당연하다고 보는 영역이다.

 

 

참고로 Java 에서는 Multiple Inheritance 관계는 금지하고 있다. C++ 에서는 아니긴 하지만, 일반적으로 Inheritance 관계는 한가지로만 사용하는 것을 권장한다. (Inheritance 는 일반적으로 [종류] 라고 보는데, [종류]가 여러개로 나뉘면 좋은 설계가 아니다) 

 

 

1) Abstract Class

 

 

Abstract Class 는 구체적인 Instance 를 생성하는 것을 금지하며, 오직 상속 관계만을 정의하기 위한 class 이다. Abstract Class 는 Class Diagram 에서 {abstract} 라는 표현을 적어주며, 다음과 같이 보여진다. 

 

 

Abstract 부모 Inheritance 의 Class Diagram

 

 

이 관계에서 Person person = new Person(); 과 같이 Person 에 대한 Instance 를 생성하는 것은 문법적으로 금지되며, 공통적인 속성들만 자식들이 상속받게 되며, 각자의 고유 성질들을 정의할 수 있는 관계가 된다. 

 

 

* Person person = new Person(); (X)
* Person man = new Man(); (O) // 하지만 이럴 경우 Person 의 Object 이기 때문에, Man 만의 변수 / 함수는 사용할 수 없음 
* Man man = new Man(); (O) // 이럴 경우 Man Object로서 활용할 수 있고, Person의 모든 관계들과도 상호작용이 가능
* Person woman = new Woman(); (O)

 

 

Abstract 및 Inheritance 관계를 활용한 Class Diagram 의 예시

 

 

위와 같이 전체적인 Abstract Class 의 관계를 기준으로, 또 다른 일반  Inheritance 관계까지 상관 관계를 정의하는 상황을 만들 수 있다.

 

 

 

정리하며

 

 

언제든지 SW 를 만들기 전에는 설계를 간단하게라도 해보는 것이 정말 너무 중요하다고 느껴진다. 물론 위 관계를 처음부터 완벽하게 그리는건 불가능하다. 

 

 

No silver bullet in SW Engineering


SW 공학에서 완벽한 설계란 없다고 한다. 그 때 상황에 맞게, 그 때에 최적화된 설계를 하고, 전체적인 SW 의 완성도가 진행됨에 따라서 지속적으로 같이 완성되어 나가는게 맞는 것이다. 어렵고 귀찮다고만 생각하지말고 설계의 중요성을 인식한 만큼 실무나 프로젝트에 적용해 나가는 방향으로 해보자!

 

 

 

 * 참고

 

 

많이들 스프링을 통해 Java 를 접했을텐데,  그 때 많이 접한 "의존성" 이란 말은, 위의 모든 관계를 다 포함해서 말했던 것이라고 보면 될 것 같다. 하지만 A 클래스가 B 클래스의 존재를 안다고 하는 상황이, 정말 여러가지 상황이 있기 때문에 위와 같은 관계들을 통해서 "의존한다" 라고 보면 되는 것 같다. 

 

 

@Service
@RequiredArgsConstructor
public class HelloService {

    private final HelloRepository helloRepository;

    // ...
}

 

 

예를 들어, @RequiredArgsConstructor 는 위 Shared Aggregation 관계인 것이다. 생성자를 만들어주고, private 하고 생성 시점 이후로 바뀌지 않는 final 한 Object 를 주입시켜주는 것이기 때문이다. 다만, Spring Container 에서 찾아와서 넣어준다는 것은 여기서 생각할 필요가 없는 것이다. 그 Object 들 역시 모두 하나의 메모리 주소를 가지고 있는 Object 들이기 때문이다. 

 

 

 

Spring 에서 Service 영역은 순수 Java 개발 영역이며, Spring 에서 관여하지 않는 유일한 영역이다. Service Layer 야 말로 개발자의 SW 설계 및 객체지향적 사고 능력을 발휘하는 Layer 가 아닐까?

 

 

 

 

 

 

* 출처) 

 

 

건국대학교 유준범 교수님 OOP / UML / OOAD 수업

728x90

'SW 설계 > UML' 카테고리의 다른 글

[UML] Statechart Diagram 에 대해 알아보자  (0) 2023.10.09
[UML] Sequence Diagram 에 대해 알아보자  (0) 2023.10.08