| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- 국비지원교육
- 오픈챌린지
- 디자인강의
- UXUI기초정복
- 부트캠프
- 환급챌린지
- 티스토리챌린지
- Be
- 백엔드 부트캠프
- UXUIPrimary
- 백준
- baekjoon
- Java
- 패스트캠퍼스
- 국비지원취업
- 내일배움카드
- 디자인챌린지
- UXUI챌린지
- Spring
- OPENPATH
- 시스템설계
- 국비지원
- API
- JPA
- KDT
- 오블완
- 오픈패스
- mysql
- 백엔드개발자
- 디자인교육
- Today
- Total
군만두의 IT 개발 일지
[스터디14] 07. UML을 활용한 소프트웨어 모델링 본문
목차
9장. UML을 활용한 소프트웨어 모델링
9-1 UML이란?
- UML: 표준 표기법을 사용하여 소프트웨어 시스템의 구조와 동작을 시각적으로 모델링하고 문서화하는 언어
UML의 4가지 특징
- 가시화(Visualization): 눈에 보이는 그래프 형태로 작성하여 시스템의 구조와 동작을 한눈에 파악한다.
- 명세화(Specification): 개발 과정마다 필요한 모델을 완전하고 정확하게 표현한다.
- 구축화(Construction): 객체 지향 언어로 변환할 수 있어 모델을 바탕으로 실제 시스템을 구축한다.
- 문서화(Documentation): 이해관계자 간의 평가와 의사소통을 위해 문서화를 지원한다.
UML 다이어그램의 종류
UML 다이어그램은 크게 구조 다이어그램, 행위 다이어그램, 상호 작용 다이어그램으로 구분한다.
| 분류 | 설명 | 대표 다이어그램 |
| 구조 다이어그램 | 시스템의 정적 구조와 구성 요소 간의 관계를 표현함 | 클래스, 컴포넌트, 객체, 복합 구조, 배포, 패키지 다이어그램 |
| 행위 다이어그램 | 시간 흐름에 따른 객체 간의 상태 변화와 상호 작용을 표현함 | 액티비티, 유스 케이스, 상태 차트 다이어그램 |
| 상호 작용 다이어그램 | 행위 다이어그램의 한 유형으로, 객체 간 상호 작용 중심의 데이터 전달과 흐름을 표현함 | 시퀀스, 커뮤니케이션, 인터랙션 오버뷰, 타이밍 다이어그램 |
9-2 유스 케이스 다이어그램
유스 케이스(use case)란 사용자가 시스템을 사용하는 시나리오를 문서화한 것으로, 기능적 요구 사항을 도출할 수 있다. 작성 수준에 따라 세 종류로 분류한다.
- Brief(간략한 유스 케이스): 최초 작성 단계에서 사용하며, 2~3줄로 간략히 요약한다.
- Casual(일반 유스 케이스): 메인 시나리오, 대체 시나리오, 예외 시나리오 등을 구분하여 작성한다.
- Fully Dressed(상세 유스 케이스): 가장 상세한 유스 케이스로, 사전 조건(precondition)과 후속 동작(postcondition) 등을 추가로 명확히 정의한다.
유스 케이스 작성법
유스 케이스를 작성할 때는 유연한 스타일과 블랙박스 스타일을 적용하는 것이 중요하다.
- 유연한 스타일: 구체적인 방법보다 사용자 관점의 시나리오에 집중하는 방식이다.
- 블랙박스 스타일: 시스템의 내부 구현을 기술하지 않고 외부에서 보이는 기능에만 집중하는 방식이다.
| 구분 | 좋은 예 | 나쁜 예 |
| 유연한 스타일 | Admin이 자신을 인증합니다. | Admin이 키보드로 ID와 PW를 입력하여 인증합니다. |
| 블랙박스 스타일 | 상품 정보를 저장합니다. | SQL DB에 INSERT INTO 쿼리로 상품 정보를 저장합니다. |
초기 단계에서 너무 구체적인 개발 수준으로 작성하면 이후 요구 사항 변경에 유연하게 대응하기 어렵고 개발자의 피로도가 증가할 수 있다. 따라서 사용자 관점에 집중한 유스 케이스를 먼저 작성하는 것이 바람직하다.
유스 케이스 다이어그램과 구성 요소
유스 케이스 다이어그램은 시스템, 액터, 유스 케이스, 관계 이렇게 4가지 요소로 구성된다.
- 시스템(system): 유스 케이스를 둘러싼 사각형 영역이다. 외부에서 액터가 바라보는 시스템의 경계와 내부 동작을 하나의 영역으로 구분한다.
- 액터(actor): 시스템 외부에서 시스템과 상호 작용하는 사용자 또는 시스템이다. 주 액터(primary actor)는 시스템을 주로 사용하는 사용자를, 보조 액터(secondary actor)는 기능을 지원하는 외부 요소를 나타낸다.
- 유스 케이스(use case): 사용자가 시스템을 통해 수행할 수 있는 기능을 타원형으로 표현한다.
- 관계(relation): 액터와 유스 케이스, 그리고 유스 케이스 간의 연관성을 나타낸다.

관계는 포함 관계, 연관 관계, 확장 관계, 일반화 관계로 나눌 수 있다.
| 종류 | 설명 |
| 포함 관계 | 특정 유스 케이스를 실행할 때 반드시 선행해야 하는 유스 케이스를 나타냄 (include) |
| 연관 관계 | 액터와 유스 케이스 간에 상호 작용하고 있음을 나타냄 |
| 확장 관계 | 기본 유스 케이스를 정상 수행한 후, 조건에 따라 부가 기능을 추가하는 경우에 사용함 (extend) |
| 일반화 관계 | 추상적인 유스 케이스를 구체적인 유스 케이스로 세분화함. 하위 유스 케이스는 상위 유스 케이스의 공통 동작을 상속받음 |
9-3 클래스 다이어그램
클래스 다이어그램을 이해하려면 먼저 객체 지향 분석과 설계(OOAD)를 알아야 한다.
- 객체 지향 분석(OOA): 문제를 정의하고 모델을 제작하여 객체 간의 관계와 동작을 식별하는 단계
- 객체 지향 설계(OOD): 도출한 모델을 기반으로 객체 속성, 동작, 상호 작용을 구체적으로 설계하는 단계
- 클래스 다이어그램은 OOA 단계에서는 도메인 모델로, OOD 단계에서는 디자인 모델로 활용된다.
객체와 클래스의 구성 요소와 표현 방법
- 객체(object): 이름의 첫 글자를 소문자로 표기하고 속성과 현재 값을 명시한다.
- 클래스(class): 첫 글자를 대문자로 표기하고 속성의 구체적인 값 대신 자료형을 표기한다. 또한 오퍼레이션(operation)을 명확하게 기술한다는 점에서 객체와 차이가 있다.
속성과 오퍼레이션에는 접근 가능 영역을 지정하는 접근 제어자를 붙일 수 있다. 명시하지 않으면 기본적으로 private이 지정된다.
| 접근 제어자 | 표시 | 접근 가능 영역 |
| public | + | 모든 영역 |
| private | - | 클래스 내부 |
| protected | # | 클래스 내부와 하위 클래스 |
- / 기호: 접근 제어자가 아니라 다른 속성이나 연산 결과에 의해 자동 계산되는 파생 속성을 나타낸다.
- UML에서는 오퍼레이션과 메서드를 구분한다. 오퍼레이션은 실제 구현 코드가 없는 상태를 의미하며, 다이어그램에 표현되는 것은 메서드가 아니라 오퍼레이션이다.
- 클래스 변수(class variable): 클래스 자체에 속하는 속성이다. static 예약어를 사용하며 다이어그램에서는 밑줄로 표현한다.
클래스 간의 관계 표현
클래스 간의 관계는 관계 강도가 약한 것부터 강한 것 순으로 의존 → 연관 → 집합 → 합성 → 실체화 → 일반화 관계로 표현한다.
의존 관계(dependency)
한 클래스가 다른 클래스를 지역 변수, 매개변수, 반환값 등으로 참조하는 것이며, 점선 화살표로 표현한다. 메서드를 수행하는 동안에만 두 클래스의 생애 주기가 함께 유지된다.
public class Person {
int age;
int weight;
// Food를 매개변수로만 사용하므로 의존 관계
void eat(Food food) {
weight += food.getCalorie() / 100;
}
}
class Food {
int calorie;
int getCalorie() {
return calorie;
}
}
연관 관계(association)
참조하는 클래스를 멤버 변수로 할당하여 두 클래스의 생애 주기를 함께한다는 점에서 의존 관계와 다르다. 연관 관계에서는 방향성과 다중성을 명확하게 이해하는 것이 중요하다. 화살표가 없으면 양방향 참조, 있으면 단방향 참조를 의미한다.
- 방향성: 연관 관계에서 클래스 간의 참조 방향
- 다중성: 클래스 간의 연관 관계에서 객체의 수
| 표기 형식 | 의미 |
| 1 | 1 |
| * | 0 또는 그 이상 (0…*과 동일한 의미) |
| 1…* | 1 또는 그 이상 |
| 0…1 | 0 또는 1 |
| A…B | A에서부터 B 사이의 값 |
| A,B | A 또는 B |
// Student(1) : Email(0…*) → 1:N 연관 관계
public class Student {
private List<Email> emailList;
}
class Email {
String address;
String domain;
String pw;
Date createDt;
}
집합 관계(aggregation)
클래스 간의 전체와 부분 관계를 나타내며, 전체 객체와 부분 객체의 생애 주기가 서로 독립적이라는 특징이 있다. 전체 객체가 소멸되더라도 부분 객체는 독립적으로 유지될 수 있다. 다이어그램에서 빈 마름모로 표현한다.
public class Lecture {
private List<Student> studentList;
private LectureRoom lectureRoom;
private Professor professor;
// 외부에서 부분 객체를 받아오므로 Lecture 클래스가 소멸되어도 부분 객체는 유지됨
public Lecture(List<Student> studentList,
LectureRoom lectureRoom, Professor professor) {
this.studentList = studentList;
this.lectureRoom = lectureRoom;
this.professor = professor;
}
}
합성 관계(composition)
집합 관계와 유사하지만, 전체 객체가 소멸되면 부분 객체들도 함께 소멸된다는 점에서 차이가 있다. 부분 객체는 전체 객체의 생애 주기에 완전히 종속된다. 다이어그램에서 채워진 마름모로 표현한다.
public class Lecture2 {
private List<Student> studentList;
private LectureRoom lectureRoom;
private Professor professor;
// 객체 생성이 클래스 내부에서 이루어지므로 부분 객체가 전체 객체의 생애 주기에 종속됨
public Lecture2() {
this.studentList = new ArrayList<>();
this.lectureRoom = new LectureRoom();
this.professor = new Professor();
}
}
실체화 관계(realization)
인터페이스와 이를 실제로 구현한 클래스 간의 관계를 나타낸다. '나는 인터페이스에 정의된 기능을 수행할 수 있다'는 의미로 해석한다.
interface Flyable {
public void fly();
}
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("날개를 이용하여 날아갑니다.");
}
}
일반화 관계(inheritance)
IS-A 관계라고도 하며, 한 클래스가 다른 클래스를 포함하는 상위 개념일 때 사용한다. 객체 지향 프로그래밍에서는 상속 관계라고도 한다.
public abstract class User {
private String id;
private String pw;
public abstract void login();
}
class NormalUser extends User {
@Override
public void login() {
System.out.println("일반 사용자 로그인");
}
}
class Admin extends User {
@Override
public void login() {
System.out.println("관리자 로그인");
}
}
9-4 시퀀스 다이어그램
시퀀스 다이어그램(sequence diagram)은 시간의 흐름에 따라 객체 간의 상호 작용을 나타내는 가장 널리 사용하는 상호 작용 다이어그램이다. API 호출 흐름이나 유스 케이스 시나리오를 파악할 수 있다.
시퀀스 다이어그램의 구성 요소
- 객체(object): 행동 주체를 나타내며, 직사각형으로 표현한다.
- 생명선(lifeline): 객체의 수명을 점선으로 나타내며, 아래로 갈수록 시간 경과를 의미한다.
- 활성 박스(activation box): 생명선 위에 긴 직사각형으로 표시하며, 해당 객체가 현재 특정 활동을 수행하고 있음을 나타낸다.
- 메시지: 객체 간에 주고받는 데이터로, 요청과 응답을 표현한다.
| 메시지 유형 | 설명 |
| 동기(sync) 메시지 | 요청 결과 응답이 올 때까지 기다림. 실선과 꽉 찬 화살표로 표현하며, 일반 함수 호출과 유사함 |
| 비동기(async) 메시지 | 응답을 기다리지 않고 다른 작업을 수행함. 실선과 빈 화살표로 표현함 |
| 자체(self) 메시지 | 객체가 자체적으로 내부 작업을 처리할 때 사용하며, 자신의 생명선을 따라 회귀하는 화살표로 나타냄 |
| 반환(return/reply) 메시지 | 요청 결과를 반환할 때 사용함. 점선과 빈 화살표로 표현함 |
시퀀스 다이어그램의 흐름 제어
프로그래밍의 조건문이나 반복문처럼 흐름을 제어하기 위해 가드(guard)와 시퀀스 프래그먼트(sequence fragment)를 사용한다.
- 가드: 메시지 앞쪽에 대괄호 [ ]로 조건을 명시하여, 조건을 만족할 때만 메시지가 전달되도록 제어한다.
- 시퀀스 프래그먼트: 여러 생명선과 활성 박스를 포함하는 박스 형태로 표현되며 반복, 조건, 분기 등의 흐름을 제어한다.
| 종류 | 표기 | 역할 |
| Alternative | alt | if~else 문처럼 조건 만족 여부에 따라 분기함 |
| Option | opt | if 문처럼 특정 조건에 만족하는 경우에만 동작함 |
| Loop | loop | 반복문 역할. loop(최솟값, 최댓값) 형식으로 표기함 |
| Break | break | break 문처럼 조건 만족 시 해당 시퀀스를 종료하고 빠져나옴 |
| Parallel | par | 스레드처럼 프로세스의 병렬 처리를 의미함 |
Loop는 다음과 같이 다양하게 표현할 수 있으며, 등호(=)를 기준으로 좌우 표현이 동일함을 의미한다.
loop = loop(*) = loop(0, *)
loop(5, 5) = loop(5)
loop(1, 10) = loop(1 .. 10)
9-5 상태 차트 다이어그램
상태 차트 다이어그램(state chart diagram)은 행위 다이어그램에 속하며, 객체의 생애 주기 동안 발생하는 상태 변화를 시간 순서대로 나타낸다. 주요 구성 요소는 상태와 전이다.
상태 차트 다이어그램의 구성 요소
- 상태(state): 객체가 가질 수 있는 조건이나 상황을 나타내며, 생애 주기 동안 변화한다. 상태를 상세형으로 표기할 때 다음 활동을 함께 작성하면 상태 변화에 따른 동작을 명확하게 나타낼 수 있다.
- entry/Activity(): 객체가 특정 상태에 진입할 때 실행하는 활동
- do/Activity(): 객체가 특정 상태에 머무르는 동안 수행하는 활동
- exit/Activity(): 객체가 특정 상태에서 벗어날 때 실행하는 활동
- 전이(transition):는 하나의 상태에서 다른 상태로 변화하는 과정을 나타낸다. 원래 상태(source state), 목표 상태(target state), 이벤트(event), 조건(guard), 동작(action)으로 구성된다.
상태 차트 다이어그램의 다양한 상태
| 상태 | 설명 |
| 복합(composite) 상태 | 하나의 상태 내에 계층 구조를 포함함(OR 상태). 여러 하위 상태 중 반드시 하나만 활성화되어야 함 |
| 동시(orthogonal) 상태 | 하나의 복합 상태가 2개 이상의 지역(region)으로 분할된 구조(AND 상태). 진입 시 모든 지역이 동시에 활성화됨 |
| 서브머신(SubMachine) 상태 | 하위 상태 다이어그램을 포함한 상태(안경 모양). 복잡한 상태를 더 작은 하위 차트로 분할함 |
| 기록(history) 상태 | 이전에 진행했던 상태를 기억하여 필요할 때 해당 상태로 복귀함 |
기록 상태는 표기법에 따라 두 가지로 구분한다.
- shallow history state (H): 동일한 계층의 시작 노드로 이동한다.
- deep history state (H*): 계층에 관계없이 마지막으로 활성화됐던 substate로 이동한다.
각 상태에 대해 들어오는 전이와 나가는 전이를 모두 정의해야 한다. 들어오는 전이만 있고 나가는 전이가 없으면 종료 상태에 도달하지 못해 무한 루프에 빠지는데, 이러한 상태를 블랙홀 상태(Black Hole State)라고 한다.
9-6 액티비티 다이어그램
액티비티 다이어그램(activity diagram)은 시스템이나 메서드, 함수의 동작 흐름을 보여 준다. 데이터의 상태보다 시스템의 작업 흐름을 시각적으로 나타내는 데 중점을 둔다.
액티비티 다이어그램의 구성 요소
- 활동(activity): 단계별로 실행되는 동작이며, 둥근 사각형으로 표현한다.
- 이동(transition): 두 활동 사이의 흐름이며, 화살표가 있는 실선으로 표시한다.
- 시작점(start state): 검은 원으로 표현하며 다이어그램의 시작을 나타낸다.
- 분기점(decision point): 마름모로 표현하며, 조건(guard)에 따라 흐름이 여러 경로로 분기된다.
- 종료점(final state): 하얀 원 안에 검은 점으로 표현하며, 도달 시 다이어그램이 종료된다.
- 객체(object)와 객체 흐름(object flow): 객체는 사각형으로, 객체 흐름은 점선 화살표로 표현한다.
- 포크 노드(fork node)와 조인 노드(join node): 포크 노드는 프로세스가 병렬로 수행되도록 하나의 흐름을 여러 흐름으로 나누는 역할을 하고, 조인 노드는 분할된 병렬 흐름을 다시 하나로 합친다. 조인 노드 이후의 동작은 받아야 할 모든 흐름을 완료한 후에 시작된다.
스윔 레인
스윔 레인(swimlane)은 객체 간의 역할 분리를 나타내며, 가로 또는 세로로 배치할 수 있다. 각 활동의 주체가 사용자(user)인지 시스템(system)인지를 한눈에 파악할 수 있어 시스템의 흐름을 효과적으로 분석할 수 있다.
액티비티 다이어그램과 상태 차트 다이어그램의 비교
| 항목 | 액티비티 다이어그램 | 상태 차트 다이어그램 |
| 중요 표현 | 객체 간의 동작 흐름을 표현 | 객체의 상태와 상황 표현 |
| 이동 방식 | 각 활동의 완료에 따라 노드 간 이동 | 이벤트 작업 결과에 따라 이동 |
9-7 컴포넌트 다이어그램
컴포넌트 다이어그램(component diagram)은 컴포넌트 간의 관계와 구성을 표현한다. 시스템이 어떻게 모듈화되는지 컴포넌트끼리 어떻게 연결되고 인터페이스에서 상호 작용하는지를 파악할 수 있다.
컴포넌트 다이어그램의 구성 요소
- 컴포넌트(component): 코드로 개발되는 독립된 단위이며, 여러 클래스의 집합이다. 탭이 달린 직사각형으로 표현한다.
- 포트(port): 컴포넌트와 외부 세계 간의 접점을 하나로 묶어 표현할 때 사용하며, 작은 사각형으로 표현한다.
- 의존 관계(dependency): 한 컴포넌트가 다른 컴포넌트를 참조하거나 의존함을 점선 화살표로 나타낸다.
- 아웃풋 인터페이스(output interface): 외부로 제공하는 서비스나 데이터이며, 흰 원으로 표현한다.
- 인풋 인터페이스(input interface): 외부에서 공급받는 서비스나 데이터이며, 빈 반원으로 표현한다.
컴포넌트 다이어그램의 표현 방법
| 방식 | 설명 |
| 볼과 소켓 기호(ball and socket symbols) | 가장 많이 사용한다. 아웃풋은 흰 원, 인풋은 반원으로 표현한다. |
| 스테레오타입(stereotype natation) | 인풋은 의존 관계, 아웃풋은 실체화 관계로 정의하며 각 인터페이스를 명시적으로 작성한다. |
| 텍스트 목록(text listing) | 인터페이스를 컴포넌트 내부에 텍스트 목록 형태로 작성한다. |
어셈블리 커넥터와 대리자 커넥터
- 어셈블리 커넥터(assembly connector): 시스템 내 컴포넌트 간의 연결을 나타낸다.
- 대리자 커넥터(delegation connector): 외부 컴포넌트와 컴포넌트 내부의 구성 요소를 연결할 때 사용한다. 외부에서 발생한 요청이나 이벤트를 컴포넌트 내부의 적절한 영역으로 전달하고, 그 결과를 외부로 전달한다.

이 글은 『 Do it! 클린 프로그래밍 』 책을 학습한 내용을 정리한 것입니다.
'학습일지 > Java' 카테고리의 다른 글
| [스터디14] 06. 소프트웨어 프로세스 모델 이해하기 (0) | 2026.06.24 |
|---|---|
| [스터디14] 05. 객체 지향 프로그래밍 이해하기 & 효과적인 디자인 패턴 활용 전략 (0) | 2026.06.11 |
| [스터디14] 04. 코드 리뷰 이해하기 & 코드 리뷰를 잘 하는 방법 (0) | 2026.06.03 |
| [스터디14] 03. 클린 코드 관점의 테스트 코드 (0) | 2026.05.23 |
| [스터디14] 02. 코드 스멜과 리팩터링 (0) | 2026.05.13 |