Software Engineering & Testing (7) - Design Patterns & Behavioral Model

Charlie·2026년 4월 8일

SE&Testing

목록 보기
7/8
post-thumbnail

Introduction

디자인 패턴은 대규모 시스템 설계에서 특히 중요한 지점을 가진다.

공통의 설계 어휘를 통해서 1) 개발자들간의 의사소통을 명확하게 가져갈 수 있고, 2) 설계 복잡성이 감소하고 재사용성을 촉진한다. 또한 3) 시행착오를 방지하고 4) 유지보수성을 향상시키는 장점을 가진다.

패턴의 목적에 따라서 생성, 구조, 행위 패턴으로 구분해서 분류한다.

인터페이스 관점의 상속

상속을 통한 내부 은폐

인터페이스 관점에서 상속은 내부 은폐의 도구로 사용되기도 한다. 클라이언트에게 Parent 클래스만 보이게 하여 내부의 복잡한 상황들을 숨긴다.

Parent로 Child를 Abstract했다고도 볼 수 있다. 주로 서브 시스템 간의 커뮤니케이션에서 잘 사용된다.

재귀적 구조 정의

재귀적인 구조관계를 상속으로 정의할 수 있는데 디렉토리는 파일이기도 하지만 파일을 포함하고 또 다른 디렉토리도 포함한다.

이걸 단순하게 이야기해서 결론만 도출하면 클라이언트에게 모두 File 클래스로만 인지되며 내부의 복잡한 재귀적인 정의들은 숨겨버린다.

생성 패턴 (Creational Design Patterns)

Singleton

하나의 애플리케이션 내에서 특정 클래스의 인스턴스를 오직 하나만 생성해 보장하고, 어디서든 그인스턴스에 접근할 수 있도록 하는 생성 디자인이다.

시스템 전체를 포괄적으로 관리해야 하는 객체는 무분별하게 여러 개의 객체가 만들어지는 것을 통제해야할 때 사용된다. 구현 원리는 아래와 같다.

생성자 은닉

클라이언트가 new 키워드를 이용해 함부로 인스턴스를 만들지 못하도록 생성자를 protectedprivate로 숨긴다.

Static 변수와 메서드 활용

클래스 내부에 유일한 인스턴스를 저장할 static 포인터를 둔다. 외부에서는 instance()라는 static 메서드만으로 객체에 접근한다

지연 생성

instance() 메서드가 호출되면, 인스턴스가 없는 경우(NULL), 최초로 하나 생성하고, 이미 생성된 경우 기존의 것을 그대로 반환한다.

Prototype

생성할 객체의 종류를 명시하는 Prototypee 객체를 만들어두고 새로운 객체가 필요할 때, 구체적인 생성자(new)를 부르는 대신 이 객체를 Clone하여 새로운 객체를 만든다.

Clone() 메서드 활용

미리 만들어둔 원형의 객체(Prototype)에 자신을 복제하는 Clone() 메서드를 정의해둔다.

클라이언트 추상화

상위 인터페이스(prototype)에 Clone()을 호출하기만 하면 실제 할당된 객체가 무엇이든 알아서 새 객체가 만들어진다.

구조 패턴 (Structural Design Patterns)

Facade

내부와 외부 시스템은 강한 연결을 하지 않는다. 내/외부의 시스템을 연결할 때, facade interface를 만들어 이를 통해서만 소통하게 한다.약한 연결로 소통하는 방식으로 이어간다.

클라이언트가 서브 시스템의 내부를 알 필요 없이 퍼사드(창구)하고만 통신하므로서 의존성을 최소화하고 로직이 변해도 클라이언트에게 영향이 덜해 유지보수도 쉽다.

Adapter

우리가 생각하는 그 어댑터가 맞다. 각기 따로 개발된 클래스나 외부 라이브러리를 수정없이 기존 시스템에 통합할 수 있다. 호환성을 보장해주기 위해 존재하며 클라이언트가 원하는 target 인터페이스로 변환해주는 패턴이다.

Composite

부분-전체 관계를 나타내기 위해 객체들을 트리로 구성하는 패턴으로, 클라이언트가 단일 객체와 이들이 묶인 복합 객체를 동일한 방식으로 취급한다.

행위 패턴 (Behavioral Design Patterns)

Template Method

여러 클래스에서 공통으로 사용되는 메서드를 템플릿화하여 상위 클래스에서 정의하고 하위 클래스마다 세부 동작 사항을 다르게 구현하는 것이다.

변하지 않는 기능들만 상위 클래스에 두고 자주 변하는 기능들을 하위 클래스에 둠으로서 하위 클래스를 수정해서 업로드하면 상위 클래스에 잘 적용되는 것을 목적으로 한다.

Observer Pattern

옵저버 패턴은 옵저버들이 관찰하고 있는 대상의 상태가 변하면 대상이 옵저버들에게 통지하고 옵저버들은 알림을 받고 조치하는 행동 패턴이다.

다른 디자인 패턴들과는 다르게 one-to-many의 의존성을 가진다. 일종의 interactive한 디자인 패턴이라고 볼 수 있다.

행위 모델 : Sequence Diagram

Syntax

철저히 클래스가 아닌 객체 단위로 그려야한다. 아래에 표기법과 관련된 내용을 그림으로 정의해둔다.

메세지의 주요 유형

메세지는 객체 간 서비스를 호출하는 리퀘스트를 의미하며, 화살표의 모양에 따라 실행 방식이 다르다.

Asynchronous message는 선으로만 된 화살표로, 상대의 처리 완료를 기다리지 않고 바로 다음 작업을 병렬로 진행한다.

Call message는 꽉찬 화살표로, 호출한 객체는 수신한 객체의 작업이 끝나고 리턴될 때까지 기다린다.

Reply message는 점선 화살표로 표기하며 처리가 끝나면 제어권과 결과값을 원래 객체에 돌려주는 메세지다.

Lost message는 외부 알 수 없는 곳으로 날아가는 예외적인 이벤트의 흐름을 나타낸다

Found message는 외부 알 수 없는 곳에서 날아오는 예외적인 이벤트의 흐름을 나타낸다

Combinded Fragments

기존의 시퀀스 다이어그램에서 if문이나 반복문을 표현하기 어려웠으나 UML 2.0부터 복합 프레그먼트를 도입하여 로직을 표현한다.

alt는 if-else 조건문을 나타내고, opt는 조건이 참일 때만 실행되는 단일 if문이다. loop는 특정 조건을 만족하는 동안 메세지 교환을 반복하며 par은 여러 흐름이 동시에 수행됨을 의미한다.

neg는 절대 발생해서는 안되는 시나리오를 나타내고, assert는 반드시 발생해야하는 올바른 흐름을 나타낸다. 마지막으로 critical은 임계 영역(병렬 상황에서 한번에 실행을 보장)을 나타낸다.

추가로 ref도 존재하는데, 외부의 시퀀스 다이어그램을 참조하기 위해 가져다 쓰는 것을 의미한다.

Pitfalls in Sequence Diagram

profile
찬찬히 써내려가는 개발일지

0개의 댓글