2.log

08 | 소프트웨어 아키텍처 본문

소프트웨어공학

08 | 소프트웨어 아키텍처

2.log 2023. 4. 30. 21:38
728x90
반응형

* KOWC에 등록된 동국대학교 최은만 교수님의 강의내용을 공부목적으로 정리한 글임을 밝힙니다.
| 출처 : http://www.kocw.net/home/search/kemView.do?kemId=331697&ar=relateCourse  

 

 

 

소프트웨어 아키텍처


소프트웨어의 일관된 모양, 구조, 스타일을 정하는 작업으로, 일단 시스템이 한 번 개발된 뒤에는 잚 못된 구조를 바로잡기 쉽지 않기에 초기에 이를 잘 정립해 둠으로써 이해관계자들의 소통과 추후 발생할 수정 및 유지보수를 용이하게 할 수 있음

 

 

범위

시스템 분할, 전체 제어 흐름, 오류 처리 방침, 서브시스템 간 프로토콜 등

 

 

Design Stamina Hypothesis

 

출처 : https://martinfowler.com/bliki/DesignStaminaHypothesis.html, 20 June 2007, Martin Fowler

 

디자인을 고려하지 않은 소프트웨어의 경우 디자인 활동에 시간을 쏟지 않는 초반부에는 생산성이 높을수 있으나, 시간이 지나수록 코드 수정이 어려워지고 이러한 활동에 더 많은 시간을 낭비하게 되어, 잘 디자인된 소프트웨어가 일정하게 생산성이 향상되는 것과 달리 되려 생산성이 떨어지게 된다는 가설

 

결론은 디자인 퀄리티와 개발 속도는 trade off 관계이므로 pay off line 아래에서 이루어질 활동이 아닌 이상 시간이 좀 걸리더라도 초기에 아키텍쳐를 잘 디자인해 두는 것이 장기적인 관점에서 좋다는 것

 

 

 

 

모듈, 컴포넌트, 서브시스템,  프레임워크


 

출처 : chrome-extension://oemmndcbldboiebfnladdacbdfmadadm/http://kocw-n.xcache.kinxcdn.com/data/document/2014/dongguk/choieunman/09.pdf, 6p, 최은만, CSE 4039 소프트웨어공학

 

모듈

가장 상위에 위치하는 구현의 단위

비슷하거나 연관성 있는 것들로 이루어진 메소드 or 클래스의 집합, 재사용 가능한 코드 모음

 

컴포넌트

런타임에서 실제 동작하고 있는 엔티티

분명한 역할 가지고 있는 HW or SW 조각 (plug-in)

 

** 모듈 vs 컴포넌트

# [ex] 하나의 서버에게 서비스를 제공받는 100개의 클라이언트가 존재하는 경우

# 모듈 : 서버 구현 모듈 1개, 클라이언트 구현모듈 1개 => 총 2개
# 컴포넌트 : 실제 동작하고 있는 엔티티 이므로 서버 1개, 클라이언트 100개 => 총 101 개

 

서브시스템

대규모 시스템을 이루는 부분이면서 그 자체로도 시스템을 이루고 있는 운영환경

한 시스템 내에서 여러개의 서브시스템을 실해하며, 각 서브시스템들은 독립적으로 작동함

 

프레임워크

원하는 기능 구현에 집중하여 개발할 수 있도록 제공하는 뼈대가 되는 개발도구 (for 생산성, 효율성)

 

 

 

 

소프트웨어 아키텍처 패턴


  • 계층화 패턴(Layered Pattern)
  • 클라이언트-서버 패턴(Client-server Pattern)
  • 마스터-슬레이브 패턴(Master-slave Pattern)
  • 파이프-필터 패턴(Pipe-filter  Pattern)
  • 브로커 패턴(Broker Pattern)
  • 피어 투 피어 패턴(Peer-to-peer Pattern)
  • 이벤트-버스 패턴(Event-bus Pattern)
  • MVC 패턴(Model-View-Controller Pattern)
  • 블랙보드 패턴(Blackboard Pattern)
  • 인터프리터 패턴(Interpreter Pattern)

 

계층화 패턴(Layered pattern)

n-티어 아키텍처 패턴이라고도 불림

시스템을 계층을 구분하여 구성, 서로 마주 보는 두 계층 사이에서만 상호작용

(ex) OSI 7 layer (일반적인 데스크톱 애플리케이션)

 

 

➕ 하위레이어는 다른 상위 레이어에 의해 사용, 레이어 표준화 쉬움, 한 레이어 변경해도 다른 레이어에 영향 x

➖ 상황에 따라 불필요한 레이어가 있을 수 있으며, 광범위한 적용 어려움

 

 

클라이언트-서버 패턴(Client-server pattern)

클라이언트와 서버 두 부분 서로 독립적으로 구성

서버 컴포넌트는 다수의 클라이언트 컴포넌트로 서비스 제공 (24시간 req 요청 대기)

(ex) 게임 서버는 몬스터 만들고 클라이언트는 잡는..

 

 

➕ 클라이언트가 요청할 수 있는 일련의 서비스를 모델링 할 수 있음

➖ 요청이 일반적으로 서버에서 별도의 스레드로 처리됨, 오버헤드 발생가능

 

 

마스터-슬레이브 패턴(Master-slave pattern)

마스터와 슬레이브 두 부분으로 구성

마스터 컴포넌트는 동등한 구조 지닌 슬레이브 컴포넌트들로 작업 분산

슬레이브들이 결과값 반환하면 최종 결괏값 계산

(ex) 마스터 DB는 신뢰할 수 있는 데이터 소스로 간주, 슬레이브 DB는 마스터 DB와 동기화 

 

 

➕ 서비스 실행이 각기 다른 구현체를 가진 슬레이브들에게 전파됨

➖ 슬레이브가 독립저이라 공유되는 상태가 없음, 실시간 시스템에서 마스터-슬레이브 간 레이턴시 문제, 분리가능한 문제에만 적용 가능

 

 

파이프-필터 패턴(Pipe-filter  pattern)

데이터 스트림 생성/처리 시스템에서 사용 가능

서브 시스템이 입력 데이터 받아 처리하고 출력을 다음 서브시스템의 입력으로 넘김

처리과정은 필터 컴포넌트에서, 데이터는 파이프를 통해 흐르며 파이프는 버퍼링 or 동기화 목적으로 사용 가능

(ex) uinx shell

 

 

➕ 필터 추가가 쉽고 필터의 재사용 가능, 주어진 필터 재구성하여 또 다른 파이프라인 구축 가능

➖ 가장 느린 필터 연산에 의해 효율성 제한될 수 있음, 필터 간 데이터 이동에서 데이터 변환 오버헤드 발생

 

 

브로커 패턴(Broker pattern)

분리된 컴포넌트들로 이루어진 분산 시스템에서 사용

원격 서비스 실행을 통해 상호작용, 브로커 컴포넌트는 컴포넌트 간 통신 조정

서버는 자신의 기능 브로커에게 넘겨주고, 클라이언트가 브로커에게 서비스 요청시 브로커가 적절한 서비스로 리다이렉션

(ex) Apachee ActiveMQ 등의 메시지 브로커 소프트웨어

 

 

➕ 객체의 동적 변경, 추가, 삭제, 재할당 가능

➖ 서비스 표현에 대한 표준화 필요

 

 

피어 투 피어 패턴(P2P, Peer-to-peer pattern)

각 컴포넌트를 피어(peers)라고 부르며, 피어는 클라이언트/서버 역할 모두 가능

(ex) 파일 공유 네트워크, P2P 멀티미디어 프로토콜, Spotify 등의 독점적 멀티미디어 애플리케이션

 

 

➕ 탈 중앙화 된 컴퓨팅 지원, 특정 노드 장애에 매우 강함, 리소스 및 성능 면에서 확장성 높음

➖ 노드들의 자발적 참여이므로 서비스 품질 보장 어려움, 노드 개수에 따라 성능 좌우

 

 

이벤트-버스 패턴(Event-bus pattern)

이벤트 소스(event source), 이벤트 리스너(event listener), 이벤트 버스(event bus), 채널(channel)로 구성

소스는 버스를 통해 특정 채널로 메시지 발행(publish)

리스너는 특정 채널에서 메시지 구독(subscribe) 및 이전 구독 채널에 대한 알림 받음

(ex) 알림 서비스

 

 

➕ 새로운 발행자(publisher)와 구독자(subscriber) 및 연결 추가가 쉬움, 고도로 분산된 애플리케이션에 효과적

➖ 모든 메시지가 동일한 이벤트 버스를 통해 전달되어 확장성 문제 발생 가능

 

 

모델-뷰-컨트롤러 패턴(MVC, Model-View-Controller pattern)

모델, 뷰, 컨트롤러 3개의 서브 시스템으로 구조화하는 패턴

#모델 : 핵심 기능 및 데이터 보관
#뷰 : 사용자에게 보여지는 화면
#컨트롤러 : 사용자로부터 받은 요청 처리

정보가 사용자에게 제공되는 방식과 사용자로부터 받아들여지는 방식에서 정보의 내부적인 표현을 분리하기 위함

각 부분이 분리되어 있어 독립적으로 작업 가능하고, 효율적인 재사용 가능

(ex) 일반적인 웹 앱플리케이션(excel..), 설계 아키텍처, Django or Rails 등의 프레임 워크

 

 

➕ 동일 모델에 대해 여러 개의 뷰 생성 가능, 런타임에 동적으로 연결 및 해제 가능

➖ 복잡성 증가, 사용자 행동에 대한 불필요한 업데이트 발생

 

 

블랙보드 패턴(Blackboard pattern)

블랙보드(blackboard), 지식 소스(knowledge source), 제어 컴포넌트(control compnent)로 구성

#블랙보드 : 솔루션의 객체를 포함하는 구조화 된 전역 메모리
#지식 소스 : 자체 표현을 가진 특수 모듈
#제어 컴포넌트 : 모듈 선택, 설정 및 실행 담당

해결 전략 알려지지 않은 문제에 유용

모든 컴포넌트는 블랙보드에 접근 및 블랙보드에 추가되는 새로운 데이터 객체 생성 가능

기존의 지식소스와 패턴매칭으로 블랙보드에서 특정 종류의 데이터 찾음

(ex) 음성인식, 차량 식별 및 수정 등

 

 

➕ 새로운 애플리케이션 쉽게 추가가능, 데이터 공간의 구조 쉽게 확장 가능

➖ 모든 애플리케이션이 영향받기에 데이터 공간의 구조 변경 어려움, 동기화 및 접근 제어 필요할 수 있음

 

 

인터프리터 패턴(Interpreter pattern)

특정 언어로 작성된 프로그램 해석하는 컴포넌트 설계 시 사용

언어 문법을 기술하는 규칙들에 대한 형식 문법 정의 후 규칙을 클래스를 통해 구현

클래스는 Context 객체 공유

Context 객체로부터 값 입력받고 변수 저장하는 등 작업하게 됨

(ex) sql 등의 DB query 언어, 통신 프로토콜 정의하기 위한 언어

 

  • AbstractExpression(Regularexpression) : 추상구문트리에 속한 모든 노드에 해당하는 클래스들이 공통으로 가져야 할 Interprets() 연산을 추상 연산으로 정의
  • TerminalExpression(LiteralEpression) : 문법에 정의한 터미널 기호와 관련된 해석 방법 구현, 문장을 구성하는 모든 터미널 기호에 대해 해당 클래스 만들어야 함
  • NonterminalExpression(AlternationExpression, RepetitionExpression, SequenceExpression) : 문법의 오른쪽에 나타나는 모든 기호에 대해서 클래스 정의해야 함, 이때 Interpret 연산은 일반적으로 각 인스턴스 변수를 재귀적으로 호출
  • Context : 번역기에 대한 포괄적인 정보 포함
  • Client : 언어로 정의한 특정 문장 나타내는 추상 구문트리로, NonterminalExpression & TerminalExpression 클래스의 인스턴스로 구성되며 이 인스턴스의 Interpret() 연산을 호출함

 

➕ 매우 동적인 설계 가능, 최종 사용자가 프로그래밍하기 좋음, 쉽게 프로그램 교체가 가능해 유연성 향상

➖ 일반적으로 컴파일 언어보다 실행속도(runtime) 느려서 성능 문제 발생 가능

 

 

 

 

휴리스틱


<Code Complete에 있는 9가지 휴리스틱>

 

1. 객체 식별

2. 일관적인 추상 적용(결합도 낮추고 응집 높이기 위하여)

3. 구현에서 결정할 상세한 것은 캡슐화

4. 상속보다 합성 사용

5. 정보 은닉

6. 느슨한 결합, 강한 응집 유지

7. 변경될 것 같은 부분 식별 (ex. 서비스 해외진출 시 언어 확장 등 고려)

8. 디자인 패턴 사용

9. 테스트하기 쉽게 만들기 (UI 인터페이스와 테스트 인터페이스 적절히 구분해서..)

 

 

 

 

상속(Inheritance) vs 합성(Composition)


코드를 재사용하여 중복을 제거하기 위한 대표적인 방법으로 상속과 합성이 있는데, 상속보다는 합성 사용 권장

합성이 추상화, 재사용, 캡슐화, 결합도 면에서 상대적으로 우수

 

상속과 합성 비교

 

why?

상속은 부모와 자식클래스의 관계가 컴파일 시점에 결정되어 실행 시점에 객체 종류변경이 불가하기에 유연성이 떨어짐. 또한 자식클래스는 부모 클래스의 코드를 직접 호출할 수 있기에 부모 클래스의 내부 구조가 자식에게 노출되며, 이는 곧 캡슐화를 약하게 하고 부모-자식 간의 결합도를 높임. 이 때, 부모와 자식간 결합이 높기에 유연성과 확장성이 떨어지게 되며 부모- 자식의 다양한 조합이 필요한 경우 조합의 수만큼 새로운 클래스를 추가해야 하므로 클래스 폭발 문제가 발생할 수도 있음. 그리고 자바에서는 다중상속을 허용하지 않기에 상속이 필요한 클래스가 다른 클래스를 이미 상속 중이라면 이에 따른 문제 역시 발생할 수 있음

 

반면 합성은 컴파일 타임이 아닌 런타임 시점에 의존성이 결정되는 런타임 의존성을 가지는데, 이 때문에 추상에 의존하여 객체 내부가 공개되지 않고 인터페이스를 통해 코드를 재사용하게 되므로 구현에 대한 의존성이 인터페이스에 대한 의존성으로 변경되어 결합도를 낮춤. 이는 결과적으로 캡슐화를 유지하면서 높은 유연성과 낮은 결합을 가능케 하여 유지보수 용이하게 함

 

 

 

 

UML 패키지 다이어그램


패키지

클래스를 의미 있는 연관 그룹으로 구성하는 메커니즘으로, UML에서 서브 시스템 표현 시 도입된 개념

UML 모델 요소를 조직화 / 계층화함

패키지는 각각의 name space를 가지므로 패키지만 다르면 동일한 이름의 클래스 가질 수 있음

 

 

장점

복잡한 시스템을 서브시스템으로 나누어 컨트롤 용이하게 함

(패키지 이름 정의하여 알고 있으면 외부에서 패키지 안에 자세한 사항 몰라도 import 하여 사용가능)

또한 클래스들의 그룹이므로 높은 수준의 추상화된 서브 시스템 표현 가능

 

 

패키지 다이어그램 예시

 

  • 확장된 패키지 이름은 패키지 탭에 표기
  • 서브시스템 A는 5개의 서로 다른 패키지를 Grouping
  • 서브시스템 B는 C에 의존
  • 서브시스템 D는 B와 G에 의존
  • 서브시스템 E와 F는 D의 상세화

 

 

 

 

 

 

 

 

 

 

[출처]

 

**소프트웨어 아키텍처 패턴 10가지 정리 잘 된 글 : https://moo-you.tistory.com/224

 

소프트웨어 아키텍처 패턴

소프트웨어 아키텍처 패턴 (Software Architecture Pattern) 개념 설계할때 참조할 수 있는 전형적인 해결방식 패턴은 공식같은걸 뜻하고 소프트웨어 아키텍처 에서 일반적으로 발생하는 문제점 들에대

moo-you.tistory.com

** 모듈과 컴포넌트 차이 쉽게 설명 : https://doubled.tistory.com/22

 

모듈과 컴포넌트의 차이

http://imcreator.tistory.com/7위 링크에서 이 질문에 대한 답을 명확히 이해 할 수 있었다.모듈은 가장 상위에 위치하는 구현의 단위,컴포넌트는 런타임 엔티티를 참조하는 단위라고 생각하면금방 그

doubled.tistory.com

**인터프리터 패턴 자세히 설명 : https://johngrib.github.io/wiki/pattern/interpreter/

 

인터프리터 패턴 (Interpreter Pattern)

언어를 위한 인터프리터를 구현한다.

johngrib.github.io

http://imcreator.tistory.com/7

 

Module과 Component의 차이

아키텍처를 설계를 배우면서 끊임없이 듣는 단어인데 Module과 Component는 의미도 왠지 비슷해 보이고 차이가 있는 것 같지만 그걸 설명하기 어려웠다. 아래에서 부터는 참고 자료를 통해 얻은 두

imcreator.tistory.com

https://www.ibm.com/docs/ko/i/7.1?topic=concepts-subsystems 

 

작업 관리: 서브시스템 개념

서브시스템은 시스템에서 작업이 처리되는 위치입니다. 서브시스템은 작업 흐름과 자원 사용을 시스템이 조정하는 하나의 사전정의된 운영 환경입니다. 시스템은 모두가 각각에 독립적으로 작

www.ibm.com

https://mingrammer.com/translation-10-common-software-architectural-patterns-in-a-nutshell/

 

[번역] 10가지 소프트웨어 아키텍처 패턴 요약

10 Common Software Architectural Patterns in a nutshell을 번역한 글입니다. 대형 엔터프라이즈 규모의 시스템들은 어떻게 설계되었는지에 대해 궁금해 한 적이 있나요? 우리는 주요 소프트

mingrammer.com

https://mangkyu.tistory.com/199

 

[OOP] 코드의 재사용, 상속(Inheritance)보다 합성(Composition)을 사용해야 하는 이유

객체지향 프로그래밍에서 코드를 재사용하기 위한 방법으로 크게 상속과 합성이 있습니다. 대부분의 경우 상속보다 합성을 이용하는 것이 좋은데, 이번에는 왜 합성을 사용해야 하는지에 대해

mangkyu.tistory.com

https://mangkyu.tistory.com/226

 

[OOP] 의존성(Dependency)이란? 컴파일타임 의존성과 런타임 의존성의 차이 및 비교

공부를 하다보면 런타임 의존성과 컴파일타임 의존성이라는 얘기가 나옵니다. 그런데 이와 관련되어 잘 정리된 글이 없어서 많은 분들이 이해하는데 어려움을 겪는 것 같습니다. 그래서 이번에

mangkyu.tistory.com

 

728x90
반응형
Comments