Post

[Software Engineering] 설계

소프트웨어 설계 과정에 대해서

[Software Engineering] 설계

✏️ 설계 기본 개념

  • 요구 분석: 무엇을 만들 것인가에 대한 분석
  • 설계: 그 요구 사항을 어떻게 실현할 것인지에 대한 구체적인 방안을 설계


■ 설계 레벨

소프트웨어 설계는 여러 레벨로 나뉜다:

  1. 소프트웨어 시스템: 시스템 전체의 구조를 설계
  2. 서브 시스템 또는 패키지 수준: 아키텍처 스타일이 적용되는 수준
  3. 패키지 내부의 클래스 수준: 설계 패턴이 적용되는 수준
  4. 클래스 내부 데이터와 메소드 수준: 데이터 구조와 메소드의 설계
  5. 메소드 내부 설계: 메소드 내에서의 로직과 흐름 설계


■ 전통적 설계 방법

소프트웨어 설계에서 널리 사용되는 방법론들:

  • 분할 정복: 복잡한 문제를 더 작은 문제들로 나누어 해결
  • 추상화: 세부 사항을 숨기고, 중요한 개념만을 남김
  • 합성: 더 작은 구성 요소를 모아서 전체 시스템을 구성하는 방법


■ 아키텍처

시스템의 구조와 동작 방식을 정의하는 기본 설계 원칙

소프트웨어 아키텍처는 시스템의 구성 요소들이 어떻게 조직되고 서로 소통하는지를 설명한다. 주요 요소는 다음과 같다:

  • 모듈화: 시스템을 여러 모듈로 나누는 것
  • 계층 구조: 각 모듈의 계층적 관계를 정의
  • 데이터 흐름: 데이터가 시스템 내에서 어떻게 전달되는지 설명
  • 통신 프로토콜: 시스템 내에서 모듈 간의 통신 방법을 정의


■ Package

Class를 포함하는 컨테이너

  • 시스템 아키텍처는 패키지 수준에서 표현된다.
  • 패키지는 클래스들의 그룹으로, 유사한 기능을 가진 클래스들을 모아서 하나의 패키지로 구성한다.
  • 패키지 사이의 관계는 의존성(Dependency)으로 표현된다.




✏️ 설계 작업 과정

설계는 의사 결정 과정이면서 동시에 시스템을 깊이 이해해가는 과정이다. 설계는 단순히 기술적인 과정뿐만 아니라, 소프트웨어의 비기능적 요구 사항도 고려해야 한다.

■ 품질 목표

설계의 목표 중 하나는 비기능적 요구 사항을 만족시키는 것이다. 이는 시스템의 성능, 보안성, 유지보수성, 확장성 등을 포함하며, 구체적인 설계 목표로 명시된다.

  • ISO 25000 표준에 따라 비기능적 요구 사항이 정의된다. 이 표준은 소프트웨어의 품질 목표를 세우는 데 중요한 기준이 된다.




✏️ 전통적인 설계 원리

■ 추상화, 캡슐화, 모듈화

  • 추상화: 특정 목적에 관련된 정보에 집중하고, 나머지 불필요한 정보를 무시하는 개념.
    • 복잡성을 줄이고, 필요한 정보만 제공하는 설계 원칙.
  • 캡슐화: 추상화된 대상이 제공하는 서비스를 쉽게 접근할 수 있게 하며, 객체 내부의 데이터와 메소드에 대한 정보 은닉을 제공.
    • 데이터 무결성을 유지하고 객체의 상태를 보호하는 역할.
  • 모듈화: 소프트웨어를 작은 구성 요소로 나누어, 각 모듈이 독립적으로 작업을 수행하도록 하는 설계 원칙.
    • 패키지 또는 클래스로 나누어 구조화한다.


추상화, 캡슐화, 모듈화의 관계

추상화는 설계의 복잡성을 줄이기 위해 불필요한 세부 사항을 숨기는 것이고, 캡슐화는 데이터와 그 데이터에 접근하는 방법을 보호하며, 모듈화는 소프트웨어를 작은 부분으로 나누어 독립성을 확보하는 것이다.




■ 결합 (Coupling)

모듈 간에 서로 의존하는 정도를 의미하며, 결합이 낮을수록 모듈 간의 독립성이 높아지고 유지보수성이 향상된다.

Coupling 종류 설명
Data Coupling 두 모듈이 기본 데이터 타입(정수형, 문자형 등)을 사용하여 상호작용하는 경우. 모든 함수는 기본적으로 데이터 결합 관계에 있기 때문에 이를 완전히 피하기는 어렵다.
Stamp Coupling 복합 데이터 구조의 일부만 사용하는 경우에도 전체 구조를 전달할 때 발생. 이 경우 복합 데이터 구조를 두 개 이상의 구조체로 분리하는 것이 바람직하다.
Control Coupling 한 모듈이 제어 흐름을 다른 모듈에 전달하는 경우 발생한다.
Common Coupling 두 모듈이 전역 변수를 공유하고 있다면 공통 결합 관계에 있다. 이 경우 두 모듈이 동일한 전역 변수에 접근하여 데이터를 읽거나 수정할 수 있다.
Content Coupling 한 모듈이 다른 모듈의 내부를 직접 참조할 때 발생. 절차적 언어에서 goto 명령어가 이에 해당한다.

결합을 낮추는 방법

  • 모듈 간의 인터페이스 수를 줄이고, 각 인터페이스의 복잡도를 낮추어 결합도를 줄일 수 있다.




■ 응집 (Cohesion)

하나의 모듈 안에서 수행되는 작업들이 서로 얼마나 관련된 정도를 의미하며, 응집도가 높을수록 모듈의 독립성과 유지보수성이 향상된다.

응집의 종류 설명
Informational Cohesion 모듈이 여러 작업을 수행하지만, 각 작업은 고유한 시작점과 독립적인 코드를 가진다.
Functional Cohesion 모듈의 모든 요소가 단일한 하나의 기능을 수행할 때 기능 응집도가 높다고 한다.
Communicational Cohesion 모듈의 모든 요소가 동일한 입력 또는 출력을 사용하는 경우 교환 응집력이 있다고 한다.
Procedural Cohesion 모듈 내에서 순서가 정해진 구성 요소들로 이루어진 경우 발생한다.
Temporal Cohesion 모듈의 요소들이 단순히 같은 시간대에 실행된다는 이유로 하나의 모듈로 묶인 경우. 각 요소의 기능이 다르며 상호 의존성이 없다.
Logical Cohesion 구성 요소들이 관련된 임무 또는 비슷한 기능을 수행하기 때문에 하나의 모듈로 묶인 경우.
Coincidental Cohesion 모듈의 구성 요소들이 우연히 모여 응집된 경우로, 가장 낮은 응집도를 의미한다.

응집력과 결합력의 관계

  • 결합력: 서로 다른 모듈, 클래스, 또는 컴포넌트 간에 얼마나 의존하는지를 나타내는 정도.
  • 응집력: 모듈, 클래스, 또는 컴포넌트 내의 모든 요소가 하나의 기능 단위로 협력하는 정도.
  • 결합력은 낮을수록 좋고, 응집력은 높을수록 좋다.




✏️ 객체지향 설계 원리

__S__RP(Single Responsibility Principle): 단일 책임 원칙 __O__CP(Open/Closed Principle): 개방-폐쇄 원칙 __L__SP(Liskov substitution Principle): 리스코프 치환 원칙 __I__SP(Interface segregation Principle): 인터페이스 분리 원칙 __D__IP(Dependency Inversion Principle): 의존관계 역전 원칙

■ SRP(Single Responsibility Principle)

  • 단일 책임 원칙
  • 한 클래스는 하나의 책임만 가져야 한다.


■ OCP(Open/Closed Principle)

  • 개방-폐쇄 원칙
  • 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
  • 클라이언트의 코드를 변경하지 않고, 서버의 코드를 확장하여 문제를 해결


■ LSP(Liskov substitution Principle)

  • 리스코프 치환 원칙
  • 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
  • ex) 액셀 인터페이스의 기능은 “앞으로 전진”이다. 후진하면 프로그램의 정확성을 깨뜨리므로 LSP 위반이다.


■ ISP(Interface segregation Principle)

  • 인터페이스 분리 원칙
  • 하나의 범용 인터페이스를 설계하기 보다는, 특정 클라이언트를 위한 인터페이스 여러개를 설계해야 한다.


■ DIP(Dependency Inversion Principle)

  • 의존관계 역전 원칙
  • 구체화에 의존하지 말고, 추상화에 의존하라
  • 의존한다 == 코드에서 사용된다




This post is licensed under CC BY 4.0 by the author.