안녕하세요.
Java 공부를 하다보니 클래스 설계에 UML 클래스 다이어그램이 종종 쓰이는 것 같아 총 정리를 해보려고 합니다 :)
UML은 Unified Modeling Language의 약자로, 통합 모델링 언어입니다.
쉽게 말하자면 모델을 만들고 설명하는 표준 언어(약속)라고 생각하면 됩니다.
다른 사람들과의 협업에 필요합니다.
UML 형식을 차용해 의사소통하면, 의미가 명확하고 설계에 대한 논의가 순조롭게 이루어질 수 있습니다.
전체 시스템의 구조와 클래스의 의존성을 파악합니다.
다이어그램을 분석하면, 시스템의 구조는 물론 클래스 간의 의존성도 파악하기 쉽습니다.
그 후에 설계를 더 세분화할 수 있겠죠?
유지보수를 위한 백엔드 문서로 사용합니다.
위의 항목과 이어지는 방법입니다. 구조적으로 효율적이지 않거나, 모듈화 또는 구체화해야하는 작업이 필요하다고 생각한다면 UML을 먼저 작성해보고 구조를 수정하는 것이 좋겠습니다.
UML 다이어그램은 구조 다이어그램과 행위 다이어그램으로 나뉩니다.
구조 다이어그램 (Structure Diagram) 은 각 요소들의 정적인 면을 보기 위한 다이어그램입니다.
따라서 시스템의 개념, 관계 등의 측면에서 요소들을 나타냅니다.
오늘 살펴볼 클래스 다이어그램도 구조 다이어그램에 속합니다.
행위 다이어그램 (Behavior Diagram) 은 요소들의 동적인 면을 보기 위한 다이어그램입니다.
시퀀셜한 표현을 위한 다이어그램이라고 설명하기도 합니다.
그 중에서 특히 클래스 다이어그램은 의존 관계를 명확하게 보여주며, 순환적인 의존이 발생하는 지점을 쉽게 찾아내 해결할 수 있습니다.
클래스는 보통 3개 구역으로 나뉜 사각형으로 그립니다.
클래스의 이름, 속성, 기능을 표기할 수 있으며 이름만 필수로 명시해야 합니다.
보통 속성과 기능을 생략해 다이어그램을 그리는 경우는 주로 클래스의 흐름 분석 위주의 작업입니다.
클래스의 세부사항은 필드와 메서드의 접근 제한자(Access modifier)
, 필드명(메서드명)
, 데이터 타입
, 매개변수(parameter)
, 리턴 타입
등을 나타낼 수 있다.
+
: public-
: private#
: protected- title: String = ""
+ setTitle(String)
+ getTitle(): String
public class User {
private int id;
private String name;
public Todo getTodo() {
// 투두리스트를 확인한다.
return null;
}
public void write(String text) {
// 투두리스트에 글을 적는다.
}
}
위 다이어그램을 코드로 구현한 결과입니다.
다이어그램을 구성할 때 클래스의 세부사항들을 상세하게 적는 것이 유용할 때도 있지만, 클래스 다이어그램은 필드나 메서드를 모두 선언하는 곳이 아니기 때문에 다이어그램을 그리는 목적에 필요한 것만 명시하는 것이 좋습니다.
(ex. toString())
보통 3개 구역으로 구분하지만 사용자 정의 모델 속성을 나타내기 위한 구역을 추가로 사용할 수도 있습니다.
UML에서 제공하는 기본 요소 외에 추가적인 확장 요소를 나타내는 타입입니다.
길러멧 기호 («») 사이에 적습니다.
위 다이어그램은 인터페이스와 유틸리티 클래스를 표현하고 있습니다.
필드, 메소드 밑의 밑줄은 static(정적)
필드 또는 메소드를 의미합니다.
{readOnly} 는 final
키워드를 사용하는 상수를 의미합니다.
public interface Shape {
public double area;
}
public class Math {
public static final double PI = 3.14;
public static double cos(double theta) {
// Cosine 계산...
return 0.0
}
}
위 다이어그램을 코드로 구현한 결과입니다.
그 외에도 «abstract»
, «enumerate»
등을 많이 사용합니다.
추상 클래스란 1개 이상의 메소드가 구현체 없이 명세만 존재하는 클래스를 말합니다.
추상 클래스의 이름과 메소드를 italic 체로 기울여서 표현하거나, {abstract} 프로퍼티를 사용합니다.
스테레오 타입을 사용해 표기할 수도 있습니다.
public abstract class User {
public abstract void work();
}
위 다이어그램을 코드로 구현한 결과입니다.
클래스 다이어그램의 주 목적은 클래스 간의 관계와 의존 관계를 쉽게 파악하는 것입니다.
그렇기 때문에 가장 중요한 것이 클래스 간의 관계라고 볼 수 있습니다.
부모(슈퍼) 클래스와 자식(서브) 클래스 간의 상속 관계 (Inheritance) 를 나타냅니다.
부모 클래스는 자식 클래스를 일반화한(Generalize) 것이고, 자식 클래스는 부모 클래스를 구체화한(Spectialize) 입니다. IS-A 관계
상속은 부모 클래스의 필드 및 메소드를 구체화해 사용하며 필드 및 메소드를 추가하거나 필요에 따라 메소드를 재정의하여(overriding) 사용합니다.
부모 클래스가 추상 클래스인 경우는 추상 메소드를 반드시 오버라이딩 해야합니다.
위와 같이 표기법은 클래스 사이에 실선을 연결하고 부모 클래스 쪽에 비어 있는 삼각형 화살표를 그립니다.
public class User {
private int id;
private String name;
public Todo getTodo() {
// 투두리스트를 확인한다.
return null;
}
public void write(String text) {
// 투두리스트에 글을 적는다.
}
}
public class Student extends User {
public void study() {
// 공부한다.
}
}
public class Teacher extends User {
public void teach() {
// 가르친다.
}
}
자바에서는 extends
키워드를 사용해 상속을 구현합니다.
interface
의 기능을 실제 기능으로 구현하는 것을 의미합니다.
인터페이스와 클래스 사이의 Relize 관계는 점선과 인터페이스 쪽에 비어있는 삼각형 화살표로 연결합니다.
public interface Shape {
public double area;
public abstract double calcArea();
}
public class Circle implements Shape {
@Override
public double calcArea() {
// 면적 계산
return area;
}
}
자바에서는 implements
키워드를 사용해 인터페이스를 구현합니다.
클래스 다이어그램에서 일반적으로 제일 많이 사용되는 관계입니다.
어떤 클래스가 다른 클래스를 참조하는 것을 의미합니다.
클래스 사이를 점선과 참조할 클래스에 화살표를 선으로 그려 표현합니다.
참조의 형태는 아래와 같습니다.
이와 같은 객체 참조는 계속 유지하지 않고 메서드의 호출이 끝나면 의존 관계의 클래스와 관계가 끝납니다.
다이어그램은 위에 그려진 어떤 형태로도 모두 가능합니다.
스테레오 타입으로 어떤 목적의 Dependency인지 의미를 명확히 명시할 수 있습니다.
스테레오 타입을 사용하는 방법은 Dependency의 목적 또는 형태가 중요할 경우 사용할 수 있습니다.
public class User {
public Todo createTodo() {
// 객체 생성 및 리턴
return new Todo();
}
public void writeTodo(Todo todo) {
// 객체를 매개변수로 받아 사용
Todo todo = todo.getTodo();
}
}
자바에서 참조하는 형태에 따른 코드입니다.
클래스 다이어그램에서의 Association은 보통 다른 객체의 참조를 가지는 필드를 의미합니다.
위의 다이어그램은 두 가지 형태의 Association 을 나타내고 있습니다.
일반적인 Association
실선 하나로 클래스를 연결합니다.
방향이 없으므로 User
가 Phone
을 참조할 수도, Phone
이 User
를 참조할 수도, 둘 다일 수도 있습니다.
Directed Association
클래스를 실선으로 연결 후 끝에 화살표를 추가합니다.
User
에서 Phone
으로 화살표가 향하고 있으므로 User
가 Phone
을 참조하는 것을 의미합니다.
화살표 옆의 -phones
는 roleName(역할명)을 나타내고 어떤 역할로 참조되는지를 의미합니다.
두 형태의 Association 간의 차이는 방향성입니다.
방향의 유무에 따라 참조하는 쪽과 참조 당하는 쪽을 구분합니다.
*
은 개수를 나타내는데 대상 클래스에 가질 수 있는 인스턴스 개수 범위를 뜻합니다.
1
: 1개*
: 0~n개n...m
: n부터 m까지 연관관계를 맺음public class User {
private List<Phone> phones;
}
자바로 위 다이어그램의 연관 관계를 나타냈습니다.
Association 관계를 조금 더 특수하게 나타내 전체(whole)와 부분(part)의 관계를 나타냅니다.
Aggregation은 Association의 집합 관계를 나타내는 것으로 Collection
이나 Array
를 이용하는 관계입니다.
이 관계는 일반적인 Association으로도 나타낼 수 있어 논란이 지속되고 있습니다.
관련 토론 게시글
Aggregation과 비슷하게 전체(whole)와 부분(part)의 집합 관계를 나타내지만 개념적으로 Aggregation 보다 강한 집합을 의미합니다.
Composition vs Aggregation
Aggregation과 명확하게 다르게 나타나는 부분들
Aggregation과 Composition을 UML 툴에서 그린 후 코드를 만들면 똑같은 코드가 생성됩니다.
하지만 Composition에서는 개발자가 구현해야 할 부분이 몇 가지 있습니다.
Deep Copy
를 구현합니다.Garbage Collector
가 객체 소멸을 담당하므로 part 인스턴스의 소멸은 신경쓰지 않아도 됩니다.싸피 교육 과제 자료에서 클래스 다이어그램이 자주 보여 한번 정리해 보았습니다.
확실히 명확하게 알게 되어 추후 협업 시에 사용해볼 수도 있을 것 같습니다!
감사합니다 :)
넥스트리소프트 Class Diagram
UML 클래스 다이어그램 이해하기
Association vs Aggregation