UML 관계 유형을 설계에 반영하는 방법
UML의 연관, 집합, 구성, 일반화, 실체화, 의존 관계를 소유권·다중성·결합도 관점에서 설계와 구현에 연결하는 가이드
2026-08-14 · 최초 발행 2025-10-14
관계선이 설계 의도를 드러내는 방식
객체와 컴포넌트 사이의 관계는 단순한 연결 표시가 아니다. 참조와 협력, 소유, 상속, 계약 이행, 일시적 사용을 구분해 설계 의도를 남기는 UML 메커니즘이다. 관계를 구체적으로 선택하면 결합도를 낮추고 변경 범위를 관리하며 일관성 규칙을 코드와 문서에 함께 반영할 수 있다.
UML에서 자주 다루는 관계는 다음과 같다.
- 연관(Association)은 한 요소가 다른 요소를 참조하거나 협력하는 구조적 연결이다.
- 집합(Aggregation)은 연관을 특수화한 형태로, 전체와 부분의 약한 소유 관계를 뜻한다.
- 구성(Composition)은 강한 소유와 생명주기 종속을 나타낸다.
- 일반화(Generalization)는 IS-A 계층을 표현하는 상속 관계다.
- 실체화(Realization)는 인터페이스 계약을 구현한다는 뜻이다.
- 의존(Dependency)은 시그니처나 구현을 일시적으로 사용하는 비소유적 의존이다.
결합도와 생명주기로 관계를 구분하기
방향성은 가능한 한 단방향(→)으로 두고, 양방향이 꼭 필요한 경우에만 추가한다. 양방향 참조는 결합도를 높이고 순환 의존이 생길 가능성도 키운다.
변경이 전파될 위험은 대체로 의존 < 연관 < 집합 < 구성 < 일반화 순으로 커지는 경향이 있다. 이 순서는 절대적인 규칙이 아니라 관계의 의미와 변경 비용을 검토하기 위한 기준이다.
구성에서는 전체가 사라질 때 부분도 함께 소멸한다. 따라서 강한 소유와 카스케이드 삭제 요구가 뒤따른다. 반면 집합의 부분은 공유할 수 있고 독립적인 생명주기를 유지한다. 다만 구현 단계에서는 집합과 단순 연관의 구분이 모호해질 수 있다.
다중성은 1, 0..1, 0.._, 1.._처럼 카디널리티를 표현하며, 도메인이 요구하는 최소·최대 개수 제약을 드러낸다. {ordered}, {unique}, {readOnly}, XOR 같은 제약을 함께 적으면 불변조건을 명시해 데이터 일관성을 보강할 수 있다.
일반화는 언어의 상속으로, 실체화는 인터페이스 구현으로 이어진다. 연관과 구성은 필드 참조 및 소유권 모델링에 대응한다. 의존은 메서드 파라미터나 로컬 사용, 팩토리, DI 컨테이너 바인딩으로 구현할 수 있다.
일반화·실체화·구성은 비교적 정적인 관계여서 설계 안정성은 높지만 변경 비용도 크다. 의존과 일시적 연관은 런타임 결합을 제어하기 쉬우며 테스트 용이성에도 유리하다.
도메인과 시스템 경계에서의 적용
주문 도메인에서 Order와 OrderLine은 구성으로 모델링할 수 있다. Order가 삭제되면 Line도 카스케이드 삭제되며, 1..* 다중성을 적용한다. Customer와 Order는 고객이 삭제된 뒤에도 주문을 보존해야 한다면 집합 또는 단순 연관으로 선택한다.
권한 모델의 User와 Role은 다대다 연관으로 두고, 유효기간이나 부여자 같은 속성이 필요하면 Association Class를 적용한다. Role과 Permission은 정적 모델을 안정화하고 변경 드리프트를 줄이는 관점에서 다룬다.
계층형 설계에서는 Service ..|> Interface로 실체화를 표현해 DIP를 적용한다. 테스트 시에는 Mock을 주입해 의존을 끊을 수 있다. Controller → Service는 의존으로 제한하고, 양방향 참조는 두지 않는다.
마이크로서비스의 동기 API 호출은 의존 관계다. 타임아웃과 서킷브레이커로 실패를 격리한다. 비동기 이벤트는 더 느슨한 의존을 만들며, 도메인 이벤트로 결합도를 완화할 수 있다.
영속성 매핑에서도 관계의 의미를 유지해야 한다. 구성은 FK와 ON DELETE CASCADE, 단일 트랜잭션 경계에 연결되고, 연관은 FK와 지연 로딩 전략으로 성능을 제어한다.
관계 선택이 만드는 특성 차이
| 관계 유형 | 성능 | 확장성 | 일관성 | 안정성 | 운영 편의 |
|---|---|---|---|---|---|
| 의존(Dependency) | 유리 | 유리 | 보통 | 보통 | 유리 |
| 연관(Association) | 보통 | 유리 | 보통 | 보통 | 유리 |
| 집합(Aggregation) | 보통 | 유리 | 보통 | 보통 | 보통 |
| 구성(Composition) | 보통 | 보통 | 유리 | 유리 | 보통 |
| 일반화(Generalization) | 보통 | 보통 | 유리 | 유리 | 보통 |
| 실체화(Realization) | 보통 | 유리 | 유리 | 유리 | 유리 |
여기서 유리·보통·불리는 상대적 경향치다. 실제 효과는 도메인 제약, 트랜잭션 경계, 로딩 전략에 따라 달라진다.
주문 모델에 관계를 배치한 예
Order와 OrderLine은 강한 소유 관계이므로 카스케이드 삭제가 필요하다. Customer와 Order는 생명주기가 독립되어 있어 고객 탈퇴 후에도 주문을 보존할 수 있다. Repository와 IRepository를 분리하면 계약을 기준으로 테스트와 구현 교체를 다룰 수 있다. NotificationService ..> Order는 런타임 참조로 제한해 구조적 결합을 낮춘다.
관계를 모델에서 구현까지 연결하는 흐름
모델링은 도메인 요구사항, 유스케이스, 데이터 일관성과 성능 목표를 입력으로 시작한다. 경계 컨텍스트, 트랜잭션 경계, 삭제·보존 정책도 함께 확인한다.
클래스를 식별한 뒤 책임을 할당하고, 경계 컨텍스트별로 그룹화한다. 이어 관계 후보를 찾고 구성·집합·연관 가운데 소유권의 의미를 결정한다. 방향성은 최소화하며, 다중성·역할·제약을 명시해 {ordered}, {unique}, XOR 같은 불변조건을 정의한다.
구현 매핑에서는 트랜잭션 경계, FK와 카스케이드, 로딩 전략, DI 바인딩을 함께 설계한다. UML 다이어그램만 남기지 않고 관계 규칙 표, 테스트 가능한 코드 스텁, 영속성 매핑 스펙까지 산출물에 포함한다.
검증 시에는 계층 간 역참조를 막아 순환 의존을 탐지한다. 링이 생기면 인터페이스를 추출하거나 이벤트로 관계를 끊는다. 구성은 삭제 전 제약과 카스케이드 규칙을 테스트하고, 일반화는 상위 타입의 불변조건을 위배하지 않는지와 과도한 상속 깊이를 점검한다. N+1 쿼리, 과도한 양방향 연관, 넓은 트랜잭션 경계도 성능 점검 대상이다.
관계를 과도하게 만들지 않는 기준
런타임 사용만 필요한 경우에는 연관보다 의존으로 제한하고, 인터페이스와 DI를 적용한다. 다만 추상화가 과도하면 가시성이 낮아지고 복잡성이 증가할 수 있다.
삭제와 저장의 원자성이 요구되는 범위에는 구성을 적용해 트랜잭션 일관성을 강화한다. 그 대가로 확장성과 분산 트랜잭션 측면의 제약이 커질 수 있다.
일반화 계층은 얕게 유지하고, 공통 계약은 인터페이스로 표현하며 재사용에는 컴포지션을 우선한다. 반대로 위임이 지나치면 호출 체인이 복잡해진다. 집합은 전체-부분이라는 의미가 실제로 필요할 때만 사용한다. 코드 수준에서는 연관과 차이가 희박할 수 있으므로, 문서화 이점이 추가 복잡성을 정당화하는지 판단해야 한다.
변경 영향 범위는 단일 PR 평균 변경 파일 수, 컴파일 브레이크 수, 리팩터링 시간으로 추적할 수 있으며 10~30% 감소 범위를 기대할 수 있다. 일관성 제약을 명시하면 릴리스당 회귀 결함/스토리포인트와 삭제·카스케이드 관련 장애 건수를 관리할 수 있고, 데이터 무결성 결함은 20% 내외 감소를 기대할 수 있다.
명세와 일치하는 다이어그램은 신규 기능 리드타임, 코드 리뷰 소요, 온보딩 기간을 관리하는 기반이 된다. 리뷰·온보딩은 15~25% 단축을 기대할 수 있다. 의존과 이벤트를 분리하면 장애 전파 범위, 롤백율, 피처 토글 의존 폭을 줄여 장애 격리 수준을 높일 수 있다.