Search
🌍

a0_4.1_1.1. title: 상속관계와 기호는 이해했지만 연관관계와 기호들이 이해되지 않는다면, 모든 것을 지우고 의존과 연관 기호의 의미를 먼저 이해해야 한다. 본질은 화살표, 밀함(dense), 소함(sparse)이다.

생성
🚀 prev note
🚀 next note
♻️ next note
14 more properties

들어가며

머신러닝(주로 연구) 파이썬에 익숙한 사람들은 프로그램 구조화에 대한 고민을 크게 하지 않는다. 나는 상대적으로 연구보다는 엔지니어링을 많이 했다보니 코드는 금방 방대해졌고 기능추가와 확장성이 좋은 소스코드 구조에 대해 갈증을 느끼곤 했다. 이를 클린 코드, 클린 아키텍처라고 하는 것 같다.
코드 구조화를 고민하고 찾아보다 보면 자연스럽게 UML의 클래스 다이어그램이라는 것을 알게 되는데, 그나마 금방 익숙해지는 것은 상속과 관련된 것들이다. 일반화(Generalization)나 실체화(Realization)이 여기 속한다.
하지만 언제나 연관관계라는 벽에 부딪게 되었다. 상속관계와 기호는 이해했지만 연관관계와 기호들이 이해되지 않았던 것이다. 그래서 모든 것들을 다 그냥 ‘의존관계’ 정도로 표현하고 말았다. 여기서 아쉬움이 있었다. 분명히 연관관계 표기를 구체적으로 나누어 구분해 둔 이유가 있을텐데…
인터넷에서 흔히 찾아볼 수 있는 그림.
난 처음 이것들을 다 외워 버리려고 했다. 뭐 화살표를 외워 버리는 것도 좋다. 하지만 이친구 이거 생각보다 이해할만하다. 한 번 이해해두면 잊기 쉽지 않다. 상속관계와 기호는 이해했지만 연관관계와 기호들이 이해되지 않는다면, 모든 것을 지우고 의존과 연관 기호의 의미를 먼저 이해해야 한다.

의존 관계와 연관 관계

표로 정리되어 있어 복잡해 보이지만, 가장 위부터 하나씩 읽어나갈 수 있게 적어보았다. 하나씩 읽어보자.
의존(Dependency) →
일단 의존이라는 단어를 다시 바로잡자. 의존이라는 단어 자체가 범용적인 단어라 혼란을 많이 만든다. 정말 쉽게 말해 의존은 화살표의 방향을 의미한다. 한편, 의존이라는 단어가 연관-합성-집합과 비교되기도 하는데, 이들과 나란히 비교하는 것은 혼동을 줄 수 있으므로 피하도록 하자. 왜냐하면 의존은 연관-합성-집합 없이도 이해할 수 있기 때문이다. SOLID 라는 것을 들어 본 사람이라면, ‘의존성 역전’이라는 단어는 한번쯤 들어 보았을 것이다. ‘의존성 역전’ 에서 말하는 의존은 의존관계가 어떻게 만들어졌든 상관없이(앞으로 배울 연관 관계나 일반화, 실체화 관계) 그냥 화살표 끄트머리를 의미하기 때문이다. 이들은 모두 ‘저 화살표로 짚은 저 자식이 변하면 나도 바뀌어야 할지도 몰라’ 라는 것을 나타낸다. 그 이상의 의미는 없다. (ref: … aggregation and composition describe how things are build/structured, while dependency is more a property of a certain structure)
연관(Association) ———
연관은 어떤 클래스의 멤버 변수로 다른 클래스의 객체를 들고 있음을 의미한다. 구성연관(Composition)이나 집합연관(Aggregation)을 이해하기 전에 그냥 연관을 이해해야 하는 이유다. (ref: association almost always implies that one object has the other object as a field/property/attribute). 기호가 의미하듯, 다른 클래스의 참조값만을 들고 있다는 것은 그 어떤 화살표도 만들지 않는다. 어떤 클래스가 멤버 변수로 어떤 클래스를 들고 있는 것은, 의존하는 클래스의 변화와 관련이 없다. 따라서, 멤버변수로 들고 있는지 아닌지를 실선과 점선으로 표현한다고 생각하면 된다.
양방향 연관 ←——→
앞서 의존은 연관 없이도 이해할 수 있다고 했지만, 멤버 변수로 다른 클래스의 참조를 들고 있다면 의존을 할 가능성이 높다. 그래서 주로 연관은 화살표와 함께 그려진다.
단방향 연관(Direct …) ——→
당연히 단방향으로 연관을 만들수도 있다. 이를 단방향(Direct) 연관이라고 한다. (ref: IBM Documentation, In UML models, directed association relationships are associations that are navigable in only one direction.)
의존하지만 연관은 아님 - - - → ← - - →
멤버 변수로 다른 클래스의 참조를 들고 있지는 않지만, 다른 클래스를 함수 내에서 사용한다거나 인자로 받는다거나 등의 작업을 수행해서 의존관계가 형성되는 경우. 이를 퉁쳐서 일반적으로 ‘의존’ 이라고 한다.
합성(Composition) *——→
연관의 한 형태다. 그래서 합성연관이라고도 한다. 자동차 클래스는 엔진을 생성해 멤버 변수로 등록한다. 자동차가 폐기되면 엔진도 제거된다. 이런 경우를 ‘한 클래스가 다른 클래스의 생명 주기를 관리한다’라고 표현한다. (ref: … Here you see that a new Engine is created inside Car. The Engine object is part of the Car. This means that a Car is composed of an Engine.) 이제 UML에는 동시에 사라지는지 아닌지를 표기할 기호가 필요하다. 화살표 반대쪽에 다이아몬드를 붙인다. 이 경우 다이아몬드는 꽉 차있다.
집합(Aggregation) o——→
연관의 한 형태다. 그래서 집합연관이라고도 한다. 자동차 클래스는 운전자를 멤버 변수에 등록하지만, 자동차가 폐기되어도 운전자는 생존할 수 있다. (ref: … A child object can exist outside the parent object. A Car has a Driver. The Driver CAN Exist outside the Car.) 화살표 반대쪽에 다이아몬드를 붙인다. 이 경우 다이아몬드는 비어 있다.

기호 표현

위 표에서 기호들을 중심으로 다시 정리해보자.

기호 표현의 본질

연관관계 표현
선택지1
선택지2
의존 방향
부등호 모양의 화살표
없음
멤버 변수
실선
점선
멤버 변수의 공동 생성과 소멸
속이 꽉 찬 다이아몬드
속이 비어 있는 다이아몬드
우리는 연관관계에서의 의존관계들을 이해했지만, 이 기호의 본질은 상속에도 적용된다.
상속관계 표현
선택지1
선택지2
의존 방향
세모 모양의 화살표
부모클래스에 구현체가 존재
실선
점선
그게 무슨 말일까? 위 두 개 표에 공통적으로 적용되는 본질은 생각보다 단순하다. 바로 화살표, 밀함(dense), 소함(sparse)이다.
저 자식이 변하면 나도 위험하다는 것을 화살표로 표현한다.
실선(dense)은 점선(sparse)보다 강한 결합임을 표현한다.
꽉 차 있는것(dense)은 비어 있는 것(sparse)보다 강한 결합임을 표현한다.
이런 짓을 하는 이유는 UML 클래스 다이어그램을 통해 ‘아 여기가 지금 화살표가 너무 길게 이어져 있구나. 너무 강하게 결합되어 있구나.’ 를 알아차리기 위함이다. 쉽게 말해 SOLID 원칙이 잘 지켜지고 있는지 쉽게 알아차리기 위함이다. 그러니까 이런 기호들이 외울 것이 많다고 속상해하기보다는 아주 고마워해보는 것은 어떨까.

연관관계 표현

연관관계 표현
선택지1
선택지2
의존 방향
부등호 모양의 화살표
없음
멤버 변수
실선
점선
멤버 변수의 공동 생성과 소멸
속이 꽉 찬 다이아몬드
속이 비어 있는 다이아몬드
1.
의존방향 없음, 상대 클래스 타입의 멤버변수 있음: 연관
classDiagram
    class A {
        +String data
    }
    class B {
        +String data
    }

    %% 연관 (Association without direction)
    A -- B : "연관"
Mermaid
복사
2.
의존방향 단방향, 상대 클래스 타입의 멤버변수 있음: 단방향 연관
classDiagram
    class A {
        +String data
    }
    class C {
        +String data
    }

    %% 단방향 연관 (Unidirectional Association)
    C --> A : "단방향 연관"
Mermaid
복사
3.
의존방향 양방향, 상대 클래스 타입의 멤버변수 있음: 양방향 연관
classDiagram
    class B {
        +String data
    }
    class C {
        +String data
    }

    %% 양방향 연관 (Bidirectional Association)
    B <--> C : "양방향 연관"
Mermaid
복사
4.
의존방향 양방향, 상대 클래스 타입의 멤버변수 없음: 의존하지만 연관은 아님
classDiagram
    class D {
        +String data
    }
    class E {
        +String data
    }

    %% 의존하지만 연관은 아님 (Dependency but not Association)
    D <..> E : "양방향 의존"
Mermaid
복사
5.
의존방향 단방향, 상대 클래스 타입의 멤버변수 있음, 멤버 변수 공동 생성과 소멸 아님: 집합 연관
classDiagram
    class B {
        +String data
    }
    class E {
        +String data
    }

    %% 집합 연관 (Aggregation)
    E o-- B : "집합 연관"
Mermaid
복사
위와 같이 화살표를 생략하기도 함.
6.
의존방향 단방향, 상대 클래스 타입의 멤버변수 있음, 멤버 변수 공동 생성과 소멸: 합성 연관
classDiagram
    class A {
        +String data
    }
    class F {
        +String data
    }

    %% 합성 연관 (Composition)
    F *-- A : "합성 연관"
Mermaid
복사
위와 같이 화살표를 생략하기도 함.
7.
당연히 멤버 변수가 없다면 멤버 변수의 공동 생성과 공동 소멸도 없을 것이다. 따라서 점선인데 다이아몬드가 있는 경우같은 것은 없다.

벤 다이어그램과 엮어서 생각해보기

실선(dense)과 속이 꽉 찬 다이아몬드(dense)로 표현하는 합성(Composition)은 연관관계 중 가장 강한 결합이다.

상속 관계 표현

상속관계 표현
선택지1
선택지2
의존 방향
세모 모양의 화살표
부모클래스에 구현체가 존재
실선
점선
1.
뚱뚱한 화살표, 실선: 상속을 표현하며, 부모 클래스에 구현체가 존재하는 경우
2.
뚱뚱한 화살표, 점선: 상속을 표현하지만, 부모 클래스에 추상적 구현체만 존재하거나 구현체가 없는 경우
parse me : 언젠가 이 글에 쓰이면 좋을 것 같은 재료을 보관해 두는 영역입니다.
1.
None
from : 과거의 어떤 원자적 생각이 이 생각을 만들었는지 연결하고 설명합니다.
1.
정보처리기사를 공부하다가 생성형 AI와 전통적 소프트웨어공학의 조합이 상당히 좋겠다고 생각해서 코드 레벨의 프로그램 설계를 고민하게 되었다.
supplementary : 어떤 새로운 생각이 이 문서에 작성된 생각을 뒷받침하는지 연결합니다.
1.
None
opposite : 어떤 새로운 생각이 이 문서에 작성된 생각과 대조되는지 연결합니다.
1.
None
to : 이 문서에 작성된 생각이 어떤 생각으로 발전되거나 이어지는지를 작성하는 영역입니다.
1.
None
ref : 생각에 참고한 자료입니다.
1.
None