[소프트웨어공학] 소프트웨어 아키텍처

수진·2023년 6월 11일
0

소프트웨어공학

목록 보기
16/20

1. 소프트웨어 아키텍처

  • 상위 수준에서 소프트웨어를 설계하는 기본 틀을 제공
  • 아키텍처를 결정할 때 기능보다도 품질 속성이 보다 많은 비중을 차지한다. 같은 기능을 구현한 두개의 구조가 다를 수 있는 것은 달성하고자 하는 품질 속성이 다르기 때문
  • 모든 품질 속성을 만족시키는 아키텍처를 구성하기는 사실상 어렵기 때문에 품질 속성에 우선 순위를 두어 아키텍처를 결정
  • 보안성, 성능과 같은 품질 속성은 아키텍처 결정에 많은 영향을 줌

2. 계층 아키텍처(layered architecture)

  • 가장 일반적으로 많이 사용되는 아키텍처 시스템을 여러 계층으로 나누어 설계하여 구현
  • 계층 아키텍처에서 보통 계층 N은 N+1 계층에 서비스를 제공하는 역할을 수행한다. 즉, 각 계층은 보다 상위에 위치한 계층들에게는 서비스를 제공하고, 하위 계층들로부터는 서비스를 제공받는 클라이언트의 입장이 된다.
  • 동일한 계층을 다르게 구현한다 할지라도 각 계층에 동일한 인터페이스를 제공한다면 상호 대체가 가능(인터페이스 동일하게 로직만 변경 가능)
  • 모든 계층을 동일한 개발자가 모두 개발할 필요가 없으며 다른 개발자가 개발한 계층을 구입하여 사용할 수 있음

3. 3-계층 아키텍처

  • [프리젠테이션 계층] - 사용자 인터페이스
    - 화면을 조작하고 사용자와의 소통을 수행
    - 시스템과 외부의 소통을 담당하는 컴포넌트들을 모아 놓은 Layer
    - 사용자로부터 입력받거나 시스템의 계산 결과를 보여주는 컴포넌트들을 모아 놓음
  • [비즈니스 로직 계층]
    - 애플리케이션 로직을 실행
    - 프리젠테이션 계층으로부터 들어온 입력으로 실제 일을 함
    - API 함수를 호출하면 변환값을 전달
  • [데이터 접근 계층]
    - 비즈니스 로직 수행에 필요한 여러 정보를 외부 영속 장치(DB 등)에서 읽거나 기록하기 위한 계층

4. 파이프 & 필터

  • 시스템을 구성하는 각 컴포넌트를 필터(filter)라 부르며 필터 간의 연결 관계를 파이프(pipe)라고 부름
  • 각 필터는 입력된 데이터를 변환하여 최종적으로 출력 데이터를 생산하는 데이터 변환기 역할을 수행하고 파이프는 한 필터의 출력을 다른 필터의 입력으로 전달하는 역할을 수행
  • 필터들은 서로 상태 정보를 공유하지 않아야 함
  • 필터는 자신에 앞서 수행하는 필터(Upstream Filter)나 자신의 출력 결과를 받는 필터(Downstream Filter)에 대한 정보를 알지 못함
  • 자신의 앞에 있는 필터의 출력 결과가 자신의 입력 결과로 파이프를 통해 도달할 때 동기화가 되어 처리됨
  • 필터는 병렬적으로 수행되며 파이프를 통해 동기화가 이루어짐

5. 블랙보드

  • 해결책이 명확하지 않은 음성인식, 차량번호판인식, 자율주행과 같은 도메인에 사용됨
  • Controller, Knowledge Source, Blackboard로 구성됨
    - Blackboard: 시스템의 현재 상태(해결책)를 저장하는 중앙의 자료 저장소
    - Knowledge source: 블랙보드를 통해 시스템의 (부분적인) 해결책을 제시하고 이를 블랙보드에 지속적으로 반영
    - Controller: Knowledge source를 시스템에 등록하고 스케줄링
  • 만약 자료 저장소의 상태에 변화가 생기면 controller는 Knowledge source들에 이 사실을 알리고 컴포넌트로 하여금 적절한 작업을 수행하도록 함
  • 컴포넌트들이 직접적으로 서로 소통을 하지 않기 때문에(독립적인 개체로 있음) 컴포넌트 재사용이 용이하고 새로운 서비스를 제공하기 위한 컴포넌트를 쉽게 추가하는 것이 가능
  • 자료 저장소와 컴포넌트들 간의 결합도가 매우 강하여 자료 저장소의 구조 변화에 따라 컴포넌트들도 변경되어야 할 가능성이 커짐
    -> 새로운 Knowledge source(전문가)를 추가시키는 작업이 용이하지만 자료 저장소를 모두 공유하고 있기 때문에 자료 저장소에 변화가 생기면 전체적인 시스템의 구성요소들이 영향을 받음

6. MVC

  • 시스템의 컴포넌트를 3가지 유형으로 구분함
    (1) 모델
    애플리케이션의 핵심이 되는 데이터와 기능을 제공하는 컴포넌트이며, 모델 컴포넌트는 뷰 컴포넌트와 컨트롤러 컴포넌트에 영향 받지 않도록 설계함
    (2) 컨트롤러
    사용자로부터의 요청을 처리하여 모델을 생성하고 필요한 애플리케이션 로직을 실행하고, 사용자 요청에 대한 적절한 뷰를 선정하는 책임도 수행, 사용자는 오직 컨트롤러를 통해서만 시스템과 상호작용
    (3) 뷰
    모델을 입력으로 받아 사용자에게 보여주는 인터페이스 컴포넌트
  • 모델과 뷰 간의 결합 관계를 약화하여 동일한 모델에 대하여 다양한 뷰를 쉽게 추가할 수 있게 해주며 뷰가 변경되어도 모델에 영향을 주지 않도록 함
  • MVC 아키텍처 스타일을 사용한 대표적인 예는 스프링 프레임워크
  • Business Logic + data(Model)과 사용자 인터페이스(View)를 분리시키기 위함
  • Controller를 통해 Model과 View의 결합도를 약화시킴
    -> 비즈니스 로직과 사용자 인터페이스 부분을 독립적으로 개발 가능(직접적으로 서로 영향을 안 주고 수정할 수 있는 장점이 있어 시스템의 개발 속도가 향상됨)

7. 마이크로서비스(microservice) 아키텍처

  • 마이크로 서비스는 대형 소프트웨어 프로젝트의 기능들을 작고 독립적이며 느슨하게 결합된 모듈로 분해하여 서비스를 제공하는 아키텍처
  • 여러 개의 마이크로 서비스들로 구성되어 있으면 각각의 서비스가 결합력이 약하고 DB 공유도 안 이루어지고, 서로 분리되어 있음
  • 현재 각광받고 있는 스타일로, 기존의 모노리식 서비스와 대조적임

Monolithic 아키텍처와 마이크로서비스 아키텍처의 차이

<Monolithic 아키텍처>

  • 한 프로젝트의 덩치가 너무 커져서 애플리케이션 구동 시간이 늘어나고 빌드, 배포 시간도 길어짐
  • 조그마한 수정사항이 있어도 전체를 다시 빌드하고 배포를 해야함
  • 많은 양의 코드가 몰려있어 개발자가 모두를 이해할 수 없고 유지보수도 힘듦
  • 일부분의 오류가 전체에 영향을 미침
  • 기능별로 알맞는 기술, 언어, 프레임워크를 선택하기가 까다로움(전체적으로 하나를 선택해 개발)

<마이크로서비스 아키텍처>

  • 서비스가 개별적으로 독립적인 단위의 애플리케이션이기 때문에 변경이 용이하고 그 변경이 다른 서비스에 미치는 영향이 적음
  • 개별 서비스 단위의 배포가 가능하기 때문에 하루에도 필요에 따라 여러 번 배포하는 것이 가능
  • 부하가 집중되는 특정 서비스를 위해 전체 애플리케이션 스케일 아웃할 필요가 없기 때문에 불필요한 자원의 낭비를 줄일 수 있음
  • 해당 서비스의 개선과 수정 작업이 다른 서비스의 이해 당사자들과 독립적으로 진행될 수 있기 때문에 의사결정이 빠르고, 독립적인 테스트의 구축이 용이하기 때문에 품질이 개선

8. 이벤트 기반 아키텍처(EDA, Event-Driven Architecture)

  • 마이크로서비스 아키텍처에서 많이 사용, 마이크로 서비스 간의 상호작용
  • 이벤트로 통신, 결합도가 낮음

이벤트 기반 아키텍처의 필요성을 이야기하기 위해 전통적인 서비스들 간의 커뮤니케이션 방식을 살펴보겠다.

  • Request-Response Model
  • 주문한 후에 결제가 끝난 후에야 새로운 주문을 받을 수 있다. 만약 결제 서비스에 장애가 발생한다면 더 이상 주문을 받지 못함. 이는 동기화 통신으로 인한 서비스들 간의 강한 결합이 발생
  • 한 서비스가 다운될 경우 전체 통신이 안됨

  • EDA는 서비스1에서 이벤트를 보낸다. 그리고 서비스2의 경우 이 이벤트만 알고 서비스1의 존재는 모른 채 이벤트를 처리한다.
  • 즉, 서비스1은 서비스2가 있다는 사실을 알 필요가 없고, 서비스2도 마찬가지다. 오직 '이벤트'라는 존재만 알면 됨
  • Broker: Publisher(송신자)로부터 전달받은 메시지를 Subscriber(수신자)로 전달해주는 중간 역할이며 응용 소프트웨어 간 메시지를 교환할 수 있게 함
    (이벤트 브로커, 메시지 브로커라고 함)
  • EDA는 서비스 간에 결합을 약하게 하므로 동일한 이벤트를 실행(소비)하는 서비스를 쉽게 추가할 수 있다.
  • broker가 이벤트를 보관하고 있어서 소비자가 읽을 때까지 이벤트를 유지할 수 있음
  • 브로커는 비동기 통신을 지원하므로 결제 서비스에 장애가 발생하더라도 주문을 계속 받을 수 있음(전체적인 시스템의 문제를 방지)

9. Hexagonal 아키텍처

  • Ports and Adapters 패턴이라고도 함
  • 시스템의 핵심이 되는 부분(domain/business logic)을 사용자 인터페이스나 데이터베이스 접근과 같은 저수준의 영역과 분리하는 것을 목적
  • 즉, 저수준의 변경(UI나 DB의 변화)에 핵심 영역이 영향 받지 않도록 설계
  • 마이크로서비스 아키텍처에서 자주 사용되는 아키텍처

DIP와 Hexagonal Architecture

  • 의존성 역전 원칙(Dependancy Inversion Principle)
    첫째, 상위 모듈은 하위 모듈에 의존해서는 안된다.
    상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
    둘째, 추상화는 세부 사항에 의존해서는 안된다.
    세부사항이 추상화에 의존해야 한다.

  • 상위 모듈은 고수준 영역(core)이 되고, 하위 모듈은 저수준 영역(UI/DB/다른 시스템과 연결되는 부분)이 된다.

  • 시스템의 핵심이 되는 부분은 외부 다른 시스템과 분리시키기 위해 depandancy가 core로 가있음 = core는 다른 외부 영역과 의존 관계 x

  • port에서 제공하는 인터페이스를 다른 영역에서 adapter를 구현해 core를 사용할 수 있음

0개의 댓글