전공과목 정리/소프트웨어분석및설계

[소프트웨어분석및설계🛠️] 8장 소프트웨어 설계

최연재 2024. 11. 12. 00:03

출처 : 강의 교안, 시스템분석설계 with 애자일 (생능출판사, 최은만)

 

🔎 분석에서 설계로

- 요구 분석 : '무엇을 만들 것인가'를 다루는 작업

- 설계

  • '어떻게 실현할 것인가'를 구체적으로 결정하는 활동
  • 기본 구조 설계 : 아키텍쳐 설계로 각 모듈의 역할과 인터페이스를 정의
  • 상세 설계 : 모듈 내부의 알고리즘과 데이터를 명세화

 

1. 설계의 개념과 원리

1.1 설계의 개념

- 설계

  • 높은 수준의 의사 결정 과정의 연속
  • 설계 원리와 중요

- 전통적 설계 방법 : 분할 정복, 추상화, 합성 등의 원리를 적용

- 최근의 방법

  • 아키텍쳐 기반의 설계 방법
  • 아키텍쳐 이해
    • 서브시스템, 모듈의 개념과 설계 작업의 관점, 설계 작업을 숙지해야 함.

 

1.2 설계 작업 과정

- 의사결정 과정이면서 동시에 시스템을 알아가는 과정

 

1.3 품질 목표

- 품질 제약 사항은 설계에 대한 목표가 될 수 있음

  • 비기능적인 요구를 설계 목표로 구체적으로 명시
  • 이를 만족시키기 위하여 설계안을 만들고 그 중에서 최적안을 골라내는 작업

 

2. 설계 원리

🍀소프트웨어 설계의 중심이 되는 원리

  • 추상화 (Abstraction)
  • 정보은닉 (Information hiding)
  • 단계적 분해 (Stepwise refinement)
  • 모듈화 (Modularization)

 

2.1 추상화 (abstraction)

- 대상의 특정한 목적에 관련된 정보에 집중하고 나머지 정보는 생략하는 과정

- SW는 데이터나 절차적인 동작 관점으로 정의

 

2.2 정보 은닉

- 캡슐화 : 추상화된 대상이 제공하는 서비스를 쉽게 접근하게 하는 개념

- 캡슐화를 통해 정보은닉이 가능해짐.

- 정보은닉은 좀 더 높은 수준의 추상화를 실현

 

2.3 모듈화

1) 모듈(module)

- 독립적인 기능이 있는 논리적 묶음

- 소프트웨어 구조를 이루는 기본적인 블록

 

2) 모듈화

- 모듈로 소프트웨어 시스템을 구성할 수 있도록 개발한다는 의미

  • 이해하기 쉬움
  • 팀 단위의 개발 작업이 쉬워짐
  • 변경에 의한 수정 사항 반영이 쉬움
  • 재사용 가능성이 높아짐
  • 추적성이 높아짐 : 분석에서 설계, 구현까지 일관적으로 체계적인 모듈 간의 연결구조를 제공

3) 소프트웨어 구조

: 모듈 및 모듈 간의 관계를 나타냄

 

4) 좋은 모듈화 구조를 갖는 소프트웨어 설계

  • 모듈을 구성하는 내적 요소가 상호 관련성이 있는 것들로 묶여야 함.
  • 모듈 간의 상호작용이 가능하면 간단한 형태로 구성되어야 함.

5) 모듈화의 기준

- 모듈의 응집력(cohesion)이 높게

- 모듈 간의 결합력(coupling)은 약하게

 

6) 모듈 간의 결합

- 결합도(coupling)는 모듈 간의 상호 의존하는 정도

  • 모듈은 하나의 블랙박스로 다른 모듈에 대한 독립성이 높아야 함.
  • 독립적인 모듈이 되기 위해서는 다른 모듈과의 결합도가 낮고 의존하는 모듈이 적어야 함.

- 모듈 사이의 의존 정도

  • 모듈 간 인터페이스의 수
  • 각 인터페이스의 복잡성

- 설계 목표

  • 모듈 간의 결합도가 약하게(loosely coupled) 설계
  • 모듈 간의 결합력을 최소화 할 때의 장점
    • 시스템의 구성 요소 간 결합이 느슨해짐
    • 변경에 의한 파급 효과를 막을 수 있음
    • 소프트웨어에 대한 이해도를 높임.
    • 모듈의 인터페이스가 단순해지고 재사용성이 좋아짐.

(1) 자료 결합도 (Data coupling)

- 모듈들이 정수형, 문자형 등의 단순한 기본 데이터 타입을 갖는 매개변수(paraeters)에 의해 상호작용하는 경우

-  주고받는 데이터는 모듈의 로직을 제어하지 않는 순수한 자료형 요소

- 한 모듈을 변경해도 다른 모듈에는 영향을 미치지 않는 결합 상태

 

(2) 스탬프(Stamp) 결합도

- 모듈들이 구조체와 같은 non-global 자료구조(복합 데이터)를 이용하여 상호작용

- 두 모듈이 동일한 자료구조를 참조하는 형태

- 자료구조의 형태가 변경되면, 그것을 참조하는 모든 모듈에 영향을 주며 변경되는 필드를 실제로 참조하지 않는 모듈에도 영향을 줄 수 있음.

 

(3) 제어(Control) 결합도

- 어떤 모듈이 다른 모듈 내부의 논리적인 흐름을 제어하는 요소를 전달하는 경우

- 파리미터로 전달되는 값에 따라서 모듈 내부 로직의 처리가 달라지는 flag 값 등으로 결합되는 형태

 

(4) 공통 (Common) 결합도

- 여러 모듈이 하나의 데이터 영역 (전역 변수, global variable)을 참조하여 사용하는 형태

  • 전역 변수의 변경이 여러 모듈에 영향을 끼치게 됨
  • 모듈의 독립성을 보장하기 위해 꼭 필요한 변수만 광역 변수로 선언해야 함.

 

(5) 내용 (Content) 결합도

- 어떤 모듈이 사용하려는 다른 모듈의 내부 기능과 데이터를 직접 참조하는 경우

  • 다른 모듈의 로컬 데이터에 접근하는 경우처럼 사용하고자 하는 모듈의 내용(코드)을 알아야 함.
  • 모듈에서 변경이 발생하는 경우 이를 참조하는 모듈의 변경이 반드시 필요하게 됨.
  • 내용 결합력은 현재 거의 발생하지 않음

ex. goto문

 

7) 모듈의 응집

- 모듈의 응집

  • 응집력(cohesion)은 모듈 안의 구성 요소들이 공통의 목적을 달성하기 위해 관련되어 있는 정도
  • 모듈 안의 여러 요소들이 하나의 목적을 위해 유기적으로 관련되어 있는 것이 가장 이상적
  • 응집력이 높을 떄
    • 재사용하기도 쉽고, 이해하기 쉬움
    • 수정에 의해 받는 영향이 적어짐
  • 설계목표 : 한 모듈이 정확히 정의되는 단일 기능을 갖도록 설계

- 응집의 단계

(1) 기능적 응집도 ( Functional Cohesion )

- 모듈을 구성하는 모든 요소가 잘 정의된 하나의 기능을 구현하기 위해 구성된 경우

- 다른 추가 연산이나 기능 수행 없이 하나의 기능이 종료될 수 있음

- 기능 응집력이 있는 모듈의 예

  • 수학의 코사인각 계산
  • 문장의 알파벳 오류 체크

 

(2) 순차적 응집도 (Sequential Cohesion)

- 모듈을 구성하는 요소들 사이에서 한 요소의 출력이 다른 요소의 입력으로 사용되는 형태

- ex : 어떤 모듈이 특정 파일을 읽고 처리

 

(3) 교환적 응집도 (Communicational Cohesion) 

- 모듈을 구성하는 모든 요소가 동일한 입력 또는 출력을 사용하여 서로 다른 기능을 수행하는 경우

- 처리 순서는 중요하지 않으므로 순차적 응집도보다 묶인 이유가 약해짐.

 

(4) 절차적 응집도 (Procedural Cohesion)

- 순서가 정해진 몇 개의 구성 요소를 하나의 모듈로 구성하는 경우

- 구성요소들 사이에 의미상 서로 관련은 없으나, 제어흐름의 순서가 있는 경우

- 구성요소의 출력과 입력이 연관되어 있는 순차적 응집도보다 묶인 이유가 훨씬 약해짐.

- ex : 파일을 읽을 때 접근 허가를 확인하고, 파일 읽기

 

(5) 시간적 응집도 (Temporal Cohesion)

- 같은 시간대 처리되어야 하는 활동들의 모듈로 구성

- 시간상으로 동일하게 진행되기 때문에 입출력이 서로 영향을 주는 것은 아님

- 시간 응집력을 발생시키는 예

  • 데이터를 사용하기 전 모든 변수를 처음에 초기화
  • 예외상황이 발생했을 때 오류 로그를 전송하는 기능

 

 (6) 논리적 응집도 (Logical Cohesion)

- 유사한 성격을 갖거나 특정 형태로 분류되는 요소들을 하나의 모듈로 묶은 경우

- 순서와 무관하며, 서로 입력과 출력 간의 상호의존도 없는 경우가 많고, 단지 기능적으로 비슷해보이는 요소 간의 묶음

- 논리적으로 비슷한 기능을 수행하지만 서로의 관계를 밀접하지 않은 형태

 

(7) 우연적 응집도 (Coincidental Cohesion)

- 가장 나쁜 형태로, 절대 작성되어서는 안되는 모듈 구성

- 모듈을 구성하는 모든 요소가 아무런 관련성이 없는 것으로 묶인 경우

- 유사한 성격이나 형태가 없으며, 모듈 수정이 side effect를 유발시킬 가능성이 있음

 

 

3. 구조적 설계

3.1 구조적 설계

- 시스템을 이루는 모듈의 구조를 파악하는 방법

  • 설계 결과는 구조도(structure chart)로 나타냄
  • DFD를 이용하여 프로그램 구조(call-and-return 구조)를 도출

- 구조적 설게 기법은 데이터의 흐름 형식에 중점

  • 변환흐름(Transform flow)에 따른 변환 분석
  • 처리흐름(Transaction flow)에 따른 처리 분석

- 시스템 구조도 (structure chart)

  • 시스템을 모듈 단위로 분할
  • 모듈의 계층적 구성
  • 모듈 사이의 입출력 인터페이스
  • 모듈의 이름과 기능

 

3.2 시스템 구조도

- 표준 기호

3.3 변환 분석

- 변환흐름 (Transform flow) : sorce-변환-sink

- 변환 분석은 DFD를 입력 흐름, 변환 센터, 출력 흐름으로 분할하는 과정

  • 입력 흐름 : 입력을 준비하는 단계
  • 변환 센터 : 실제 자료가 변환
  • 출력 흐름 : 변환된 자료가 출력되는 단계

- 변환 중심부를 축으로 최상위 구조(first-cut) 작성

3.4 처리 분석

- 처리흐름 (Transaction flow) : 한 프로세스에서의 여러 개의 자료흐름이 유출됨

- 변환 방법

  • DFD에서 처리 센터를 식별
  • 처리 센터를 중심으로 구조도 작성
  • 구조도를 상세화 ➡️ 하위구조도 작성

 

3.5  구조적 설계 원칙

- 모듈의 결합은 줄이고, 응집은 높이도록 최대한 노력

- 전체적인 균형을 이루도록 함

  • 입력 편중, 처리 편중, 출력 편중 방지
  • 구조의 깊이가 깊어지지지 않도록
  • fan-in, fan-out 고려
    • fan-in : 나를 호출하는 모듈의 수
    • fan-out : 내가 호출하는 모듈의 수

- 모듈의 배치 요령

  • 복잡한 모듈의 연결을 피함
  • 과다한 깊이를 가진 구조도를 피함
  • 모듈의 영향권은 그 모듈의 하위에 둔다.

 

4. 객체지향 설계

4.1 객체지향 설계

- 객체지향 분석과 설계는 순차적인 과정이 아님

  • 설계와 구현 사이의 공통 개념을 사용 : 분석과 설계에서 도출된 부분이 프로그램으로 됨
  • 반복적인 사이클로 완성

- 분석과 설계 작업의 명확한 경계가 없음

- 객체지향 분석(OOA)과 설계(OOD) 작업의 근본적인 목표는 시스템에 있어야 할 클래스와 그들의 관계를 찾는 것

 

4.2 클래스 설계를 위한 5대 원칙 SOLID

- OO 기본 원칙 : 인터페이스와 구현의 분리

 

(1) SRP ; 단일 책임의 원칙 (Single-Responsibility Principle)

- 클래스에는 한 가지 종류의 책임만을 두어야 한다.

- 목적 

  • 변화의 유연성 확보
  • SRP 원칙에 따라서 설계를 하게 되면 객체의 약한 결합 (Loose coupling)과 강한 응집력(Tight Cohesion)을 실현할 수 있음

(2) OCP ; 개방-폐쇄의 원칙 (Open-Closed Principle)

- 소프트웨어의 클래스, 모듈, 함수 등의 구성 요소는 확장 (Extension)에 대해서는 열려 있어야 하지만, 변경 (Change)에 대해서는 닫혀 있어야 함.

 

(3) LSP ; 리스코프 교체 원칙 (Liskov Substitution Principle)

- 자식 타입은 언제나 부모 타입을 대체할 수 있어야 한다.

- 상속 관계에서 부모와 자식 간에는 is-a 관계가 성립해야 되고, 이는 자식이 부모의 메소드 중 일부를 거부하면 안 된다는 것을 의미

- 자식 객체의 확장이 부모 객체의 방향을 온전히 따르도록 권고하는 원칙

 

(4) ISP ; 인터페이스 분리의 원칙 (Interface Segregation Principle)

- ISP를 따를 경우, 클라이언트는 자신이 사용하지 않는 메소드와 의존관계를 갖지 않도록 해야 함.

- 하나의 일반적인 인터페이스보다는 구체적인 여러 개의 인터페이스가 낫다.

 

(5) DIP ; 의존관계 역전의 원칙 (Dependency Inversion Principle)

- 클라이언트는 자주 변경되는 구체적(concrete) 클래스에 의존하지 않고, 추상클래스나 인터페이스에 의존해야 함.

 

🎯 SOLID의 핵심

- 추상화와 다형성

- 구체 클래스에 의존하지 않고, 추상 클래스(또는 인터페이스)에 의존함으로써 유연하고 확장 가능한 구조를 만들고 있음.