저자: 한동훈(traxacun at unitel.co.kr)
UML 소개
UML(Unified Modeling Language)은 Grady Booch
[1], James Rumbaugh, Ivar Jacobson에 의해 개발된 언어로 개발 과정에서 산출되는 것들을 명시하기 위해 사용된다. UML은 모델링을 위한 다양한 표기 수단을 제공하기 때문에 시스템 설계자, 분석가, 개발자 뿐만 아니라 고객들에게 구축될 시스템에 대해서 의견을 나눌 수 있게 해준다. 사용 사례(Use Case)등은 얼핏보기에 막대기 인간과 타원 몇 개로 그려지기 때문에 유치하게 보이기도 하지만 어려운 IT 용어 대신에 쉽게 고객과 대화할 수 있는 수단을 제공한다.
UML의 구성 요소는 사용 사례(Use Case), 클래스 다이어그램, 객체 다이어그램, 상태(State) 다이어그램, 활동(Activity) 다이어그램, 협력(Collaboration) 다이어그램, 배치(Deployment) 다이어그램으로 이루어진다. 모든 다이어그램을 소개하는 것은 참고 자료로 미루고 개발자에게 클래스를 보여주고 클래스의 흐름을 보여줄 수 있는 클래스 다이어그램에 대해서만 간략하게 소개할 것이다. 이 소개를 보고 UML을 자세히 알고 싶은 독자는 글의 끝에 있는 관련 자료를 참고하기 바란다.
UML은 매우 방대하지만 반드시 모든 사항을 알아야하는 것은 아니다. 어쩌다 한 번씩 쓰이는 세세한 것들을 알려하다간 자주 쓰이는 것조차 잊어버리게 된다. 자주 쓰는 것을 먼저 확실히 알고, 가끔 쓰이는 것들은 그때 그때 UML 관련 자료들을 참고하는 것이 UML로 표기된 산출물을 이해하는데 도움이 될 것이다.
클래스 다이어그램
최근에는 프로그램을 소개하면서 클래스 다이어그램을 보여주는 경우가 많아졌지만 UML에 익숙하지 않은 사람들은 이 클래스 다이어그램을 보고 코드를 작성하거나 코드의 흐름을 이해하는 것에 어려움을 겪는다. 앞으로의 흐름에서도 클래스 다이어그램을 사용할 것이기 때문에 먼저 이에 대해 설명한다.
클래스 다이어그램은 다음과 같이 표시한다.
[그림 1] Book 클래스
[그림 1]에서 볼 수 있는 것처럼 하나의 상자에서 첫번째 줄에는 클래스 이름을 표기한다. 여기서는 Book 클래스를 나타내는 것이다. 두 번째 줄은 속성(property)을 표기하는 공간으로 여기서는 pages, title, author를 선언하고 있으며 각 속성들의 형식은 ":" 옆에 표시되어 있다. 세 번째 줄은 메소드
[2]를 표기하는 공간으로 여기서는 pages를 설정하는 GetPages와 SetPages를 정의하고 있다. 속성과 메소드 앞에는 "-"와 "+"가 표시되어 있다. 이들 기호는 액세스 한정자(access identifier)
[3]를 뜻하며 "-"는 private, "+"는 public을 뜻한다. 이들 액세스 한정자를 표로 정리하면 다음과 같다.
오퍼레이션 |
액세스 한정자 |
설명 |
+ |
public |
액세스가 제한되지 않으며 다른 모든 클래스에서 액세스할 수 있다 |
- |
private |
동일한 클래스 내의 메서드에서만 액세스할 수 있다 |
# |
protected |
protected로 선언된 클래스와 여기서 파생된 클래스에서만 액세스가 허용된다 |
~ |
internal |
internal로 선언된 멤버와 이 멤버가 속한 어셈블리내에서만 액세스가 허용됨. VS.NET에서는 프로젝트 단위로 액세스가 제한된다 |
# |
protected internal |
protected로 선언된 클래스와 여기서 파생된 클래스에서 액세스가 허용되며 이 클래스가 속한 어셈블리 내에서 액세스가 허용된다 |
.NET에서는 네임스페이스(namespace)를 사용하고 있으나 UML에서는 이에 대해서 패키지(package)라는 용어를 사용한다. UML 모델링 도구는 다양하며 도구에 따라서 internal 대신에 package로 표시되어 있어도 당황하지 말기 바란다. 이것의 의미는 package내에서만 액세스가 허용된다는 의미이며 .NET에서는 동일한 어셈블리 내에서만 액세스할 수 있다는 것을 뜻한다.
protected internal은 C#에서 소개되는 액세스 한정자이며 UML에는 이를 위한 별도의 표기 수단이 정해져있지 않다. Rational Rose와 같은 UML 도구는 "#"로 표기되지만 Power Designer와 같은 도구에서는 이를 표기할 수 없다. 그러나 protected internal은 매우 드물게 쓰이며 모델링 도구에서 이러한 표기를 제공하지 않아도 스테레오 타입(stereo type)을 사용하여 "<< protected internal >>"로 표기할 수 있는 유연함이 있다. - UML 도구에서 생성된 코드를 수정해야하지만.
protected internal는 "protected or internal"이지 "protected and internal"를 뜻하지 않는다.
[그림 1]의 클래스 다이어그램에서 메서드에서 GetPages() : int는 반환형식이 int라는 것을 의미하는 것이며, SetPages( [in] pages : int )는 pages 변수가 int 형이며 함수에 전달되는 입력값을 나타낸다. 인자의 전달방향은 [in]과 [out]을 사용하여 표기한다. 위 클래스 다이어그램에 대한 코드를 작성하면 다음과 같을 것이다. - 실제 UML에서 코드를 작성한다면 구현 내용은 다르지만 겉모습은 같다는 것을 의미한다.
[그림 2] Book 클래스
C#에서는 GetPages와 SetPages 메소드를 대신할 수 있는 속성을 제공하기 때문에 위 소스를 속성으로 변경하고 title, author에 대한 속성을 정의한 클래스 다이어그램은 다음과 같다.
[그림 3] 속성을 정의한 Book 클래스
클래스 다이어그램에서 알 수 있는 것처럼 속성에 대해서는 스테레오 타입 <
>를 사용하였고, 각 속성의 get 블록과 set 블록은 실제로 오퍼레이션이기 때문에 이들 각각을 메소드로 정의한 것을 알 수 있다.
[그림 4] 속성을 정의한 Book 클래스
상속
Book 클래스에 생성자를 정의하고, 정보를 표시하는 Display 메서드를 정의하고, Book 클래스를 상속한 Textbook 클래스를 만들어보자. 또한 Textbook 클래스는 교육과정에서 사용되기 때문에 교육과정에 대한 속성(CourseName)이 추가되었으며 이를 위한 생성자도 새로 추가하였다.
[그림 5]
클래스 다이어그램을 보면 처음보다 복잡해보이지만 자세히 살펴보면 그렇게 복잡하게 바뀌지 않았다는 것을 알 수 있다. 클래스 다이어그램 사이에는 선을 연결해서 클래스간의 관계를 표시한다. 위에서 사용된 선은 상속(Inheritance)[4]관계를 나타낸다.
[그림 6] 상속 관계
Textbook 클래스를 보면 Book 클래스로부터 상속받은 속성과 메서드에 대해서는 표기하지 않는다는 것을 알 수 있다. Display() 메소드와 같이 부모로부터 상속받지만 재정의(override)하는 경우에는 Textbook 클래스에 메소드를 표기한다. 위와 같은 상속 관계는 "is kind of"를 만족해야하며 이 관계를 만족하지 않는 경우에는 상속보다는 연관 관계로 정의하는 것이 바람직하다. 연관 관계에 대해서는 다음에 설명한다. 위 UML 다이어그램에서 작성된 코드는 다음과 같다. - 직접 클래스 다이어그램을 보고 코드를 작성해보는 것도 좋은 방법이다.
[그림 7] Book 클래스
[그림 8] Textbook 클래스
위에 사용된 다이어그램에서 반환 형식이 void인 경우에는 반환형식을 클래스 다이어그램에 표기하지 않았다. UML은 소프트웨어 개발과정에서 필요한 다양한 표기 도구를 제공할 뿐이며, 모델링을 도와주기 위한 도구들이 있지만 말 그대로 표기 수단이기 때문에 사람마다, 모델링 도구마다 표기하는 방법이 다를 수 있다는 것은 이해하기 바란다. Display() 메소드도 여기서는 간단히 설명을 위해 protected로 사용했지만 외부에서 제대로 이용할 수 있게 하려면 protected internal로 선언되는 것이 더 바람직하다.
다음 가사에서는 클래스 다이어그램에서 인터페이스, 연관 관계 등을 어떻게 표기하며 어떻게 코드로 옮기는지 살펴보도록 할 것이다.
각주
[1] 그래디 부치, 제임스 럼버, 이바 야콥슨을 3인방(Three Amigos)이라하며 각자의 방법을 하나로 모아 UP(Unified Process)와 UML이 탄생했다. 부치가 세운 Rational Software Corporation에 럼버, 야콥슨이 영입되었으며 이들이 발표한 UML은 소프트웨어 업계에 많은 영향을 끼치고 있다.
[2] UML에서는 메소드(method)라는 용어를 사용하지 않고 오퍼레이션(operation)이라 사용하지만 여기서는 친숙한 메소드로 사용했다.
[3] UML에서는 액세스 한정자(access identifier)라는 용어를 사용하지 않고 서명(signature)로 사용하지만 C#에서 사용하는 용어, "액세스 한정자"로 설명하였다. UML은 언어중립적인 표기 수단이기 때문에 오퍼레이션, 서명과 같은 독립적인 용어를 사용한다.
[4] 객체지향 언어에서 객체를 모델링한다는 것은 객체의 일반적(General)인 속성을 도출해내고, 이렇게 일반적인 속성을 정의한 클래스로부터 공통된 속성을 물려받는 상속 클래스를 정의한다. UML에서는 이러한 상속관계에 대해서 일반화(Generalization)라는 용어를 사용한다. 따라서 UML 모델링 도구에서 상속(Inheritance) 대신에 일반화(Generalization)라는 용어를 사용하는 것을 보더라도 당황하지 않기 바란다.
참고 자료
- 『UML in a Nutshell』 O"Reilly: UML의 각 구성요소에 대해서 쉽게 찾아볼 수 있는 레퍼런스 형식으로 되어 있다.
- 『IT EXPERT, J2EE 웹 애플리케이션 설계와 구현: 레거시 시스템을 웹으로』: 자바에 대한 내용으로 가득하지만 UML을 어떻게 적용할 것인가에 대한 고민과 함께 실제로 경험했던 내용들을 바탕으로 구성되어 있기 때문에 UML을 프로젝트에서 어떻게 이용할 것인가에 대해서 고민하는 독자라면 찾아보기 바라며, RUP의 핵심만을 추려 간단하게 재단한 ICONIX Process에 대해서도 간략하게 소개되어 있다.
- 『IT EXPERT, 자바 디자인 패턴과 리팩토링』: 이 책 또한 자바에 대한 내용으로 가득하지만 지나치게 자바에 한정된 몇 가지 주제들을 무시하더라도 객체지향 프로그래밍과 보다 좋은 프로그램을 만들기 위해 코드를 진보시켜나가는 자세한 과정들을 담고 있기 때문에 UML, 디자인 패턴, 리팩토링이 두려운 분들에게 좋은 출발점이 될 것이다.
- WithClass 2000: UML 모델링 도구로 국내에는 잘 알려져있지 않다. 이 도구는 컴파일된 C# 코드로부터 UML을 생성해낼 수 있는 기능을 제공한다. C++, Java, Delphi, VB, IDL, Perl, PHP, C#, VB.NET에 대한 리버스 엔지니어링 기능을 제공하기 때문에 기존 코드의 구조를 쉽게 파악하는 데 도움이 될 것이다.
- Rational Software: UML을 개발한 3인방(Three Amigos)이 만든 소프트웨어 회사로 현재 널리 쓰이고 있는 모델링 도구인 Rational Rose, Rational XDE와 같은 다양한 개발 도구들을 제공하고 있으며, RUP에 대해서 찾아볼 수 있다.
- Dia: Linux의 X-Windows 환경에서 널리 쓰이고 있는 GTK+ 기반의 UML 드로잉 도구이다. Dia 역시 다양한 기능을 제공하고 있으며 리버스 엔지니어링을 위한 AutoDia를 사용할 수 있다. 독자가 Mono를 사용하고 있으며 Linux 환경에서 모델링하는 데 관심이 있다면 Dia를 사용해야할 것이다.
- AutoDia: 기존 소스 코드와 XML 데이터로부터 자동으로 UML을 생성하여 Dia에서 사용할 수 있는 파일 포맷으로 작성해주는 기능을 제공한다. Dia를 사용하고 있고, 리버스 엔지니어링을 사용하고 싶다면 AutoDia를 함께 사용해야할 것이다.
- Visio: 마이크로소프트에서 제공하며 VS.NET EA 버전에 함께 제공되는 드로잉 도구로 UML외에 다양한 것들을 모델링할 수 있다.