가장 구현과 밀접한 다이어그램이 바로 클래스 다이어 그램 입니다. 기존의 개발 방법론과 다르게 객체지향의 가장 중요한 점은 "객체"가 중심이 되어서 그것에 대해서 다른 객체들과의 상호관계에 따른 처리를 해주는 것이죠.
구현상에서 그런 객체를 나타내는 용어가 바로 클래스 인데요, 그래서인지 다이어그램의 이름도 클래스 다이어그램이라고 하는 듯? :)
클래스 다이어그램은 내용이 방대 하기 때문에 스크롤의 압박이 있음을 미리 밝히는 바입니다.(ㅋㅋ)
클래스 다이어그램은 내용이 길어서 포스팅을 나눠서 할게요. 나머지 요소에 대한 설명을 하기에는 여태까지 제가 구현한 부분에서 쓰이지 않는 게 더 많네요 :)
구현상에서 그런 객체를 나타내는 용어가 바로 클래스 인데요, 그래서인지 다이어그램의 이름도 클래스 다이어그램이라고 하는 듯? :)
클래스 다이어그램은 내용이 방대 하기 때문에 스크롤의 압박이 있음을 미리 밝히는 바입니다.(ㅋㅋ)
-
다이어그램(Diagram)의 종류 별 사용
-
클래스 다이어그램(Class Diagram)
사용되는 요소보기(box1)
클래스 다이어그램은 클래스에 대한 요소를 간략 혹은 상세 하게 담은 다이어그램 예요. 고로, 저번 포스팅 까지 만들어 져있었던 EnginCore_TestUI에는 해당 클래스를 가져다 사용하는 부분이 나오고, 그 클래스들을 가지고 있는 EngineCore에 만드려고 해요.
클래스 다이어그램을 추가하는 방법 역시 저번 포스팅 들에서 다이어그램을 추가 하는 방법과 동일하지만 한번 더 올려 놓을게요 :)
- 모델탐색기(Model Explorer)에서 다이어그램 생성을 원하는 모델(여기 예제에서는 EngineCore)요소를 마우스 우클릭 한다.
- 나오게 되는 하위 요소 중 "Add Diagram"에 마우스를 올려 놓는다.
- 나오게 되는 하위 요소중 ""Class Diagram"을 마우스 좌클릭 한다.
클래스 다이어그램은 액티비티나 유즈케이스와는 다르게 클래스 요소에 대한 설명이 조금 필요 할거 같아요.
위의 내용을 코드로 바꾸면 아래와 같아요. 저는 C++ 유저이므로, C++에 대한 설명을 풀어 쓸게요. Java코드는 많이들 있으니까 그 부분 참고 하면 될 거 같아요 ^^
class myClass { // 맴버 변수(Attribute) public: void publicAttirbute; private: void privateAttribute; protected: void protectedAttribute; // 함수(Operation) public: /* 기본적으로 사용되는 것들은 보통 클래스 다이어그램에서 표기하지 않습니다. 의미 전달이 주요 역할인 다이어그램이기 때문에, 개발자들이 일반적으로 사용하는 거는 생략하고 넘어가도 의미의 전달은 되니까요. */ myClass(); ~myClass(); // 그 외에 private, protected에 대한 변수 getter, setter등이 있겠죠? :) public: void publicOperation1(); private: void privateOperation1(); protected: void protectedOperation1(); public: myClass Operation2(int Parameter2, int Parameter3); };
생성한 클래스 다이어그램의 이름은 "전체적인 구조"로 했어요.
이제 슬슬 요소들을 채워서 다이어그램을 이쁘게(?) 만들어 볼까요? :)
가장 하위 요소부터 채워 넣어 볼게요.-
VAL_Globalglobal values의 약어로 만든 구조에요. 가장 베이스가 되면서 모든 클래스는 이게 있어야 동작하게 거의 모든 헤더파일을 include 시켜 놓았어요. 그리고 거의 전역 함수에 가까운 애들도 이 안에 존재 한답니다.
이거는 하나의 서브시스템으로 둘게요.
- "Subsystem" 요소를 마우스 좌클릭 한다.
- Main window에서 마우스 좌클릭 혹은 원하는 크기로 드래그 한다.
- 요소의 이름을 지정 한다.(여기서는 "VAL_Global"로 했음)
VAL_Global 요소의 하위 요소를 깔끔하게 보기 위해서 그에 대한 클래스 다이어그램을 하나 더 삽입 할게요. VAL_Global의 다이어그램이니까 해당 요소로 부터 생성해야 겠죠?
- 원하는 요소(여기서는 VAL_Global)를 마우스 우클릭 한다.
- 나오게 되는 하위 메뉴중에서 "Add Diagram"에 마우스를 올려 놓는다.
- 원하는 다이어그램 요소(여기서는 "Class Diagram")를 마우스 좌클릭 한다.
- 다이어그램의 이름을 지정한다.(여기서는 "VAL_Global"로 했음)
짜잔~ 위 처럼 새로운 클래스 다이어그램을 만들었어요 :)
이제 VAL_Global 다이어그램을 먼저 채워 볼까요?
이 안에는 전역적으로 사용하는 상수들이 몇 개 있어요. 다른 변수명과 헷갈리지 않도록 namespace 처리를 해 두었어요.(Java에서는 package라고 한다죠:D) 관련된 부분을 위해서 "Package" 요소를 넣을게요.
- "Package"요소를 마우스 좌클릭 한다.
- Main Window에서 마우스 좌클릭을 혹은 원하는 크기로 드래그 한다.
- 요소의 이름을 지정한다.(여기서는 "VAL_GLB"로 했음)
패키지는 요소에 변수(Attribute)를 넣을 수가 없어서, 일단 보기에 편하기 위해서 클래스 요소를 하나 넣었어요.
- "Class"요소를 마우스 좌클릭 한다.
- Main Window에서 마우스 좌클릭 혹은 원하는 크기로 드래그 한다.
- 요소의 이름을 지정한다.(여기서는 아무 이름 없는 것으로 했음)
변수(Attribute)만 있는 거니까 함수(Operation)는 안보이게 해둘게요.
- 원하는 요소(여기서는 방금 전에 만들었던 클래스)를 마우스 좌클릭 한다.
- 요소가 선택된 상태(위에 보이는 거처럼 8방향에 사각형 점이 표시된 상태)에서 Tool bar의 "Suppress Operations"아이콘을 클릭 한다.
이제 저 클래스에서는 함수를 아무리 넣어도, 표시되지 않는답니다. 함수를 넣게 되면 실제로 입력은 되지만 "보이지만 않게" 된다는 거죠 :)
이제 변수를 넣어 볼게요. 이 변수들은 VAL_Global이 가지고 있는 랜덤한 숫자 출력에 사용되는 변수와 Pi가 있어요.
변수를 입력하는 방법이 몇 가지 있긴 하지만, 저는 제일 손에 맞는 방법을 사용 해요.
- 원하는 요소(여기서는 방금 만든 클래스)를 마우스 좌 더블클릭 한다.
- 요소의 상단에 나타나게 되는 메뉴에서 "Add Attribute" 아이콘을 마우스 좌클릭 한다.
- 생성된 변수(Attribute)의 이름을 정하거나 일부 옵션 설정을 한다.
여기서는 PI로 해두었어요. 잠시 모델 탐색기(Model Explorer)를 보게 되면 여태까지 생성했던 요소들이 나열되어 있어요. 이중에서 방금 만든 변수(Attribute)를 클릭 한 후, 하단의 속성창(Properties)을 보면 몇 조절할 수 있는 부분들이 몇 가지 나와요.
실제로 PI 값의 구현은 이렇게 되어 있어요.
namespace VAL_GLB { const static double PI = 3.14159265358979323846; }
그럼 속성창(Properties)에서 수정해야 할 몇 가지가 보이죠:)
데이터 타입(Type)은 double
초기값(InitialValue)는 3.14159265358979323846
변경 여부는(Changeability)는 수정 불가
라이프싸이클(LifeCycle)은 static
데이터 타입 부터 고쳐 볼까요?
- 속성창(Properties)의 Type의 우측 부분을 마우스 좌클릭 한다.
- 원하는 이름(여기서는 double)으로 수정한다.
그렇게 하면 아래처럼 콜론(:)뒤에 입력한 데이터 타입이 보여지게 되요.
starUML에서는 기본적인 사용 언어에 대한 데이터 타입은 profile이라는 형식으로 담아져 있는데 언어에 대해서 추가/삭제 할 수도 있고, 사용자가 직접 정의해서 넣을 수도 있습니다. 아직 저는 별도의 정의 까지는 필요하지 않은 상태라서 이 부분에 대한 설정 방법을 잠깐 소개 할 게요.
- 메뉴 바(Menu bar)에서 "Model" 메뉴를 마우스 좌클릭 한다.
- 나타난 하위 메뉴중 "Profiles…" 메뉴를 마우스 좌클릭 한다.
왼쪽에 있는 게 사용 가능한 프로파일(Available profiles)에 대한 부분이고, 오른쪽에 있는 게 현새 사용 중인 프로파일(Included profiles) 에 대한 부분이에요.
저는 딱 C++에 대한 거만 사용하고 있어요. 그 외에 현재 여기서 만들고 있는 다이어그램에서의 클래스로 부터 데이터 타입은 계속 가져다 사용 할 수 있거든요:D
지금과 같은 경우에는 cpp내부에 있는 기본 데이터 타입이기 때문에 별다른 상관이 없지만, 사용자 생성 클래스를 데이터 타입으로 삼는 경우에는 복잡 해서 찾기 힘든 경우가 발생 해요.
그럴 때는 아래와 같이 하면 되요.
- 속성창(Properties)의 Type의 우측에 있는 "…"버튼을 마우스 좌클릭 한다.
- Data Types의 펼침목록을 클릭 하여 원하는 요소를 마우스 좌클릭 한다.
- 혹은, 이미 생성되어 있는 클래스가 있다면 위쪽 탐색기에서 원하는 요소를 마우스 좌클릭 한다.
- (지금은 가려져 있지만) 하단의 "OK"버튼을 마우스 좌클릭 한다.
위와 같은 방법으로도 데이터 타입을 설정 할 수 있답니다 :)
초기값은 단순하게 입력하는 것으로 끝나요.
- 속성창(Properties)에서 초기값(InitialValue)의 우측 영역을 마우스 좌클릭 한다.
- 원하는 값(여기서는 3.14159265358979323846)을 입력 후 엔터 혹은 아무 곳이나 클릭 한다.
C++에서는 const, Java에서는 final 이라는 키워드로 값이 수정 되지 않도록 하는데, 여기서는 동결(frozen)이라는 단어로 수정 되지 않는 값이라는 의미를 부여하네요.
- 속성창(Properties)의 Changeability항목의 우측 영역을 마우스 좌클릭 한다.
- 나타나는 하위 메뉴 중 "FROZEN"을 마우스 좌클릭 한다.
전역변수와 같은 scope을 가진 Life cycle을 만들기 위해서는 아래와 같이 설정 하면 되요.
- 속성창(Properties)의 OwnerScope 항목의 우측 영역을 마우스 좌클릭 한다.
- 나타나는 하위 메뉴 중 "CLASSIFIER"를 마우스 좌클릭 한다.
Static 변수로의 변환은 아래와 같이 밑줄이 생기게 되요:)
이 VAL_GLB안에는 다른 상수들 또한 존재하는데 아래와 같아요.
namespace VAL_GLB { const static double PI = 3.14159265358979323846; // RandomNum(..)을 위한 상수들 const static int RANMIN = 0; // 내부적인 최소값 const static int RANMAX = 10000; // 내부적인 최대값 const static int RANSIZE = RANMAX - RANMIN; // 내부적인 범위 const static size_t RAN_CAL_CNT = 10; // 내부적으로 계산되는 횟수(횟수이상 수행시 false 반환) }
이 부분을 만들면 아래와 같은 결과가 되요. 직접 해보세요 :)
VAL_Global이라는 서브 시스템(구현상 header로 했어요)은 자체적으로 함수를 가지고 있어요. 다시 "전체적인 구조"의 클래스 다이어그램으로 돌아와서 시작 할게요.
- 메인 윈도우(Main window)상단의 다이어그램 중에서 "전체적인 구조" 클래스 다이어그램을 마우스 좌클릭 한다.
- 원하는 요소(여기서는 VAL_Global 서브시스템)를 마우스 우클릭 한다.
- 나오게 되는 메뉴 중 "Add" 항목에 마우스를 올려 놓는다.
- 나오게 되는 메뉴 중 "Operation" 항목을 마우스 좌클릭 한다.
- 원하는 함수(Operation)명(여기서는 RandomNum)을 기입후 엔터를 입력한다.
함수(Operation)가 들어가게 됐어요 :D
이제 함수에 대해서 여러가지를 입력해 줘야겠죠? 실제 선언은 아래와 같이 되어 있어요.
template
bool RandomNum(const T &_min, const T &_max, T &_output);
임의의 타입이다 하더라도 랜덤한 수치를 추출해 내기 위해서 template을 사용 했어요.(Java는 어떻게 해야하는지 모르겠네요ㅠㅠㅋ 구글링 ㄱㄱㄱ!!)
반환 값(return value)까지 변수는 4개 네요(_min, _max, _output, return value). 변수의 인자를 잘 보게 되면, 앞에 두 개는 const로 수정불가 항목을 못박아 뒀고, 실질적으로 _output에 계산된 결과값이 나가는 거에요. 반환값은 값을 잘 추출 했으면 true를 내부적으로 값을 추출하지 못했다면 false를 반환 한답니다.
제 스타일이긴 하지만, 저는 인자를 그냥 한번에 쭈욱- 만들어 놓고 추후에 수정 한답니다. 먼저 인자를 넣어 볼게요.
- 모델 탐색기(Model explorer)에서 방금 전에 생성된 함수(여기서는 RandomNum())를 마우스 우클릭 한다.
- 나오게 되는 메뉴 중 "Add" 항목에 마우스를 올려 놓는다.
- 나오게 되는 메뉴 중 "Parameter" 항목을 마우스 좌클릭 한다.
- 4번 반복한다.
이름을 입력 하도록 나오지만, 저는 바로바로 넘어 갔어요:) 개인 취향에 맞게 만드시면 될 거 같아요.
저는 맨 처음의 인자(Parameter)는 반환 값으로 설정 해 놓아요. 인자의 설정은 클릭 하게 되면 속성창(Properties)에서 할 수 있어요.
다른 부분에 대해서는 앞서 설명을 했었고, 인자의 성질이라는 부분을 보고 넘어가야 할 거 같아요. 물론 번역된 이름이 정해진 이름은 아니고(알아보진 않았습니다 ㅈㅅ;;;) 제가 임의로 해놓은 건데요. 정확히 무슨 의미인지는 모르겠습니다만 저는 이렇게 해석 했어요.- IN : input으로 만 사용
- INOUT : input으로서 이용을 하면서, 값이 정제되어 output으로 사용 가
- OUT : input으로서 사용은 하지 않지만, 값이 정제되어 output으로 사용 가
- RETURN : 반환 값으로 사용
수정하는 방법은 위에서도 언급 했으니까 속성창 수정에 대해서는 결과만 보여주고 넘어 갈게요^^
반환 값(return value)의 경우에는 이름이 다이어그램에 별도로 표기 되지 않으므로 여기에도 있을 필요는 없죠. 하지만 저는 return이라고 이름 지어 놓는답니다:D
반환 값(return value)의 데이터 타입은 bool이죠. 간단한 형식이며, cpp 기본 속성이므로 타이핑으로 하셔되 되요.
구현상 기본적으로 설정되는 값은 없기 때문에, 그냥 공란으로 두었어요. 만약에 return 값을 초기에 설정 한다면, 내부적으로 어떠한 처리 후에 그 값이 바뀐다고 하더라도 초기값을 적어 놓는것이 알아보기 좋겠죠? :)
이 인자는 반환 값이기 때문에 DirectionKind는 "RETURN"으로 설정 할게요.
DirectionKind가 RETURN으로 설정된 요소는 다이어그램상에서 반환되는 데이터 타입만 보이고 이름은 보이지 않는 답니다.
나머지 부분도 바꿔 볼까요? Parameter2와 3은 둘 다 input값으로만 사용하고, 4는 out으로만 사용 해요. 그리고 나머지 세 개 모두 T타입이죠. 이 부분은 명세된 부분이 없기 때문에(C++ 프로파일에) 그냥 타이핑으로 해두면 될 거 같아요.
여기서 Stereotype을 한번 써볼까 해요. 의미상 더 명확하게 하기 위한 요소가 바로 Stereotype이라는 건데, 다이어그램상으로 표현하기 힘들고… C++상에서는 있는 "&" 이 녀석을 위해!
Java는 모든 변수들이 에일리어스(alias)라는 형식으로 사용 되요. 이게 사실 c에서는 포인터(*) 개념이었는데, cpp로 넘어오면서 레퍼런스(reference)라는 요소로 & 를 만들어 줬더랬죠. 포인터는 아니지만, 주소처럼 사용해서 값 전체를 넘기는게 아니라 참조 할 수 있는 값을 넘겨 주는 방식이에요.
뭐.. 그렇다구요 :)
reference라고 해도 좋고, & 이렇게 해둬도 괜찮을거 같아요. 어차피 c++하는 사람들은 다 알아 볼 수 있는 거니까요.
각각의 인자들(Parameter2, Parameter3, Parameter4)을 수정 했어요.
수정된 이후의 다이어그램의 VAL_Global이라는 서브 시스템(Subsystem)을 볼까요?
이렇게 변경된 부분에 대해서 바로 반영 되었어요 :D
DirectionKind가 IN인 인자는 별도의 표시가 되어 있지 않지만, OUT은 인자의 이름 앞쪽에 "out"이라고 명시되어 있어요. INOUT의 경우에도 "inout"이라고 이름 앞에 명시 된답니다.
데이터 타입의 경우에는 인자 이름 뒤에 콜론(:)과 함께 표기 된답니다.
저 역시 별도로 공부를 하면서 이 포스팅을 작성 하고 있는 중인데, 위의 저 함수가 VAL_Global.h 라는 부분에 명시 되어 있긴 해도 논리적으로 어딘가에 포함 되어 있는 함수가 아니라, 전역 함수 이거든요.
"전역 함수"에 대해서 어떻게 표현 할 까 고민하다가 구글링 중 어떤 분의 트윗(http://twitter.com/#!/eritakas/statuses/40367448465223680)을 참고 한건데, 스테레오 타입으로 명시 해주면 되겠더라구요.
사실 UML 이라는게 확 못박아서 "꼭 이렇게 만들어" 라는 건 아니고 굉장히 포괄 적인 범위내에서 규칙을 정해 놓고, "이건 가능하면 이런 식으로 통일 하는게 어때?" 라는 방식이니까 스테레오 타입으로 해놓는 것도 좋은 거 같아요.
앞서 설명한 바와 같이 스테레오 타입은 의미를 좀더 명확히 하기 위한 옵션 같은거라 어떠한 요소에도 포함 될 수 있어요. 함수(Operation)이라고 해도 예외는 아니죠.
- 모델 탐색기(Model Explorer)에서 원하는 요소(여기서는 RandomNum() 이라는 이름의 함수(Operation))를 마우스 좌클릭 한다.
- 속성창(Properties)에서 "Stereotype"의 우측 텍스트 입력 란에 원하는 이름을 기입 한 후 엔터를 입력 한다.
모델 탐색기의 요소에서는 바로 볼 수 없지만 속성창(Properties)과 메인 윈도우에 해당 요소가 있을 경우에는 바로 확인 할 수 있어요 :)
VAL_Global에 하나 더 들어가는 부분이 있는데 구현 코드는 아래와 같아요.
namespace VAL_ANGLE { namespace TYPE { static enum List { RADIAN, DEGREE }; } double Radian2Degree(const double &_radian); // 라디안을 도(Degree)로 환산 double Degree2Radian(const double &_degree); // 도(Degree)를 라디안으로 환산 }
C++에서의 namespace가 starUML에서는 패키지(package)로 사용된다고는 앞서 얘기 한 바 있고, enum이 있군요! 일단, package를 만들어 볼게요.
다이어그램에서 저렇게 표시 되지 않아요. 제가 저렇게 "보이도록" 요소를 직접 위치 한 거 랍니다. 모델 탐색기(Model Explorer)를 보게 되면 계층구조가 나오는 것을 볼 수 있는데, VAL_ANGLE이라는 패키지를 만든 후에 해당 요소 마우스 우클릭으로 "Add"를 하면 하위 요소로 다른 패키지를 또 넣을 수가 있어요.
이제 "TYPE"이라는 패키지 요소 밑에 enum을 표기 해야 겠죠? enum은 열거형 데이터라는 의미로 반복되는 상수(보통은 1 씩 증가되는 상수를 의미)를 사람이 보기 좋은 "이름"으로 저장 해놓는거에요. 실질적으로 컴퓨터 내부에서는 해당하는 이름에 대응하는 상수로 기억 하고 있는 거구요.(자세한 내용은 구글링 ㄱㄱ!!)
- 원하는 요소(여기서는 "TYPE")에서 마우스 우클릭 한다.
- 나오게 되는 메뉴 중 "Add" 항목에 마우스를 올려 놓는다.
- 나오게 되는 메뉴 중 "Enumeration" 항목을 마우스 좌클릭 한다.
- 원하는 이름을 기입 후 아무 곳 이나 클릭 하거나 엔터를 입력한다.
starUML의 열거형 요소(Enumeration)는 함수도 입력 가능 해요. 보기 그렇다 하시는 분들은 앞선 설명에서 함수 안보이게 설정을 하시기 바래요:)
저는 안보이게 했답니다.ㅋㅋ
이제 열거 데이터를 넣어 볼게요. 값은 두 개 밖에 없지만, 한 개 이상인 경우에는 딱 그거 외에 원하지 않을 때 enum을 사용 한답니다.(구현상의 설명은 생략 할게요:D)
- 원하는 요소(여기서는 List 열거형 요소(Enumeration))에서 마우스 우클릭 한다.
- 나오게 되는 메뉴 중 "Add" 항목에 마우스를 올려 놓는다.
- 나오게 되는 메뉴 중 "Enumeration Literal"항목을 마우스 좌클릭 한다.
- 원하는 이름을 기입 후 아무 곳 이나 클릭 하거나 엔터를 입력한다.
제 스타일은 일단 만들고 추후 수정 이기에, 일단 만들었어요 :D
이제 열거 데이터를 수정 해야 겠죠? 이 역시 속성창에서 수정 가능 해요.
VAL_ANGLE이라는 패키지(Package)요소는 두 개의 함수를 가져요. 이 부분은 임시적으로 이름이 없는 클래스 요소를 하위 요소로 넣은 후에, 함수를 추가해 주면 되겠죠?
이제, 다이어그램을 조금 다듬어 주면..(크기 조절ㅋ) 짜잔~
이쁘게 만들어 졌네요.
아마 열거형 요소(Enumeration)가 함수(Operation)을 가지는 이유가 클래스(Class)요소로 부터 파생되어 졌기 때문인거 같아요. 아직 starUML을 자유자재로 설정하면서 쓸 수 있는 내공이 아니여서 모르겠지만, 그러한 요소까지 사용자가 원하는 대로 디자인 할 수 있는걸로 봤거든요.
전체적인 부분에서 몇 가지 클래스를 추가 했어요. 이 부분은 제가 잠시 멈춰놓은 OpenGL 프로젝트 에서 다시 언급을 할 예정이라서 여기서는 자세히 풀어 쓰지는 않을게요.
클래스가 가지고 있는 변수의 설정 중 배열에 대해서 설명을 한번 하고 넘어 갈게요.
-
지금 진행하고 있는 예시 중 가장 기본이 되는 데이터 형이 VEC4 라는 클래스 에요. 그 중 맴버 변수에 관한 부분은 아래와 같이 되어 있어요.
class VEC4 { protected: double m_elems[4]; // ..생략 };
다른 부분은 설명을 많이 했으니까 아시겠지만, 어? 배열이네?? 이건 어떻게 하지? 라고 하실 분을 위해서 설명 할게요. "m_elems"는 다음과 같은 성격을 가지고 있어요.
- 자료형 : double
- 접근성 : protected
- 이름 : m_elems
- 개수 : 4개
- 수정 가능 여부 : 수정가
다른 부분에 대해서는 설명 했지만 개수에 대한 부분은 아래의 필드 값을 수정 하면 된답니다.
(사전 뜻은 다수, 다양성 이라고 나와 있는데 적절한 명사는 모르겠네요), Multiplicity를 수정 하게 되면, 아래와 같은 결과를 볼 수 있지요~
-
클래스 다이어그램은 내용이 길어서 포스팅을 나눠서 할게요. 나머지 요소에 대한 설명을 하기에는 여태까지 제가 구현한 부분에서 쓰이지 않는 게 더 많네요 :)
'Programming > Architecture' 카테고리의 다른 글
04 Statechart Diagram (2) | 2012.07.10 |
---|---|
03 Class Diagram 2 (6) | 2012.05.30 |
02 Activity Diagram (0) | 2012.05.10 |
01 UseCase Diagram (3) | 2012.04.29 |
StarUML 툴 구조 (0) | 2012.04.27 |