이전에 배운 요구분석 단계가 끝나면 소프트웨어 개발은 설계단계로 진입하게 됩니다.


설계

설계는 사용자의 요구분석에 따라 요구분석명세서가 만들어지면 해당 문서를 참조해 개발팀에서 소프트웨어 설계서를 만들고 해당 설계서를 기반으로 구현을 진행하게 됩니다.

설계는 요구분석명세서에 따라 어떻게(how)만들지를 결정하는 단계입니다. 따라서 여러 제약 조건을 모두 만족하는 최적의 설계서를 만드는 것이 중요하며 이 설계를 정량적으로 평가할 수 있는 기준 또한 명시해야합니다.

좋은 설계의 조건은 다음과 같습니다.

  • 설계서는 요구분석명세서의 내용을 모두 포함해야합니다.
  • 유지보수가 용이하도록 추적이 가능해야합니다.
  • 변화에 쉽게 적응할 수 있어야 합니다.
  • 시스템 변경으로 인한 영향이 최소화 되도록 국지적이여야 합니다.
  • 설계서는 읽기 쉽고 이해하기 쉽게 작성되어야 합니다.

이 조건들을 만족하기 위해 설계는 모듈이 독립적이어야하고 응집도 강하게, 결합도는 느슨하게 설계해야합니다.

요구분석과 설계 단계의 차이

요구분석과 설계 단계의 차이를 정리하면 다음과 같습니다.

구분요구분석설계
산출물요구분석명세서설계서
관점무엇 (what)어떻게 (how)
특성개념적, 추상적사용 환경을 고려해 구체적
비고운영체제, 데이터베이스, 프레임워크 등은
고려하지 않음
비기능 요구사항, 제약 사항,
플랫폼인 운영체제, 미들웨어, 프레임워크까지 고려

상위 설계와 하위 설계

설계는 상위 설계하위 설계로 나뉘어집니다.

상위(예비) 설계는 다음과 같은 내용이 포함됩니다.

  • 아키텍쳐 설계: 시스템의 전체적 구조.
  • 데이터 설계: 필요한 정보를 자료구조와 데이터베이스 설계에 반영.
  • 시스템 분할: 전체를 여러개의 서브시스템으로 분할.
  • 인터페이스 정의: 구조와 서브시스템 간의 인터페이스 정의.
  • UI 설계: 사용자가 익숙하고 편리하게 사용할 수 있도록 유저 인터페이스 설계.

하위(상세) 설계는 다음과 같은 내용이 포함됩니다.

  • 각 모듈의 내부를 알고리즘으로 표현합니다.
  • 인터페이스에 대한 설명, 자료구조, 변수 등의 설명을 합니다.

설계의 원리 - 객체지향 프로그래밍

객체지향 프로그래밍을 이용해서 설계할 때는 분할과 정복, 추상화, 캡슐화, 정보은닉, 상속, 다형성을 이용해서 설계를 할 수 있습니다.

분할과 정복

분할과 정복은 소프트웨어 하나를 개발할 때 여러 개의 서브시스템으로 나누고, 다시 서브시스템은 더 작은 서브시스템으로 나눈 후 하나씩 개발해 나가는 방식입니다. 이렇게 더 작은 단위로 하나씩 나누는 것이 분할이고, 이 분할한 서브시스템을 개발하는 것을 정복이라고 합니다.

소프트웨어 모듈은 다음 기준으로 분할합니다.

  • 분산 시스템: 클라이언트와 서버로 분할합니다.
  • 시스템: 여러 서브시스템으로 분할합니다.
  • 서브시스템: 하나 이상의 패키지로 분할합니다.
  • 패키지: 유스케이스나 여러 클래스로 분할합니다.
  • 클래스:는 여러 메소드로 분할합니다.

추상화

추상화는 필요한 특징만을 표현한 것입니다. 특정한 목적과 관련된 필수 정보만을 추출해서 강조하고, 세부 사항은 생략해 본질적 문제에 집중할 수 있게 만들어주는 작업 과정입니다.

추상화가 잘 이루어질수록 유지보수가 쉬워집니다. 추상화 개념을 잘 이용하면 문제의 핵심을 잘 파악할 수 있고 문제의 본질을 이해하기 쉬워지기 때문입니다.

객체지향적 설계에서 말하는 추상화는 유사한 특성을 가진 것끼리 그룹화하고 공통점을 뽑아서 이름을 붙이는 것을 의미합니다. 추상화 방식에는 과정 추상화, 데이터 추상화, 제어 추상화 방법이 있습니다.

  • 과정 추상화
    과정 추상화(procedure abstraction)는 상세 부분을 제거하고 전체 흐름만 파악할 수 있는 알고리즘 형태로 작성하는 것을 말합니다.

  • 데이터 추상화
    데이터 추상화는 데이터와 메소드를 클래스 등과 같은 방식으로 캡슐화하여 은닉하고 사용자에게는 필요한 기능만을 사용하도록 공개한 구조입니다. 사용자는 클래스의 내용은 모르지만 제공하는 기능만을 알고 사용하게 됩니다.

  • 제어 추상화
    제어 추상화는 제어 구조를 추상화 시키는 방식입니다. 여러 줄의 제어 구문 내부를 간략하게 줄여 간단하게 나타냅니다.

캡슐화

캡슐화는 사용자에게 해당 객체의 기능과 사용법만 제공해 사용하기 쉽게 만들지만 내부 로직은 감추는 것입니다. 주로 내부 데이터를 조작할 수 있는 메소드를 제공해 메소드만을 통해 값을 조작할 수 있게 만드는 방식이 대표적인 캡슐화 방식 중 하나입니다.

캡슐화의 장점은 다음과 같습니다.

  • 추상화를 통해 문제를 쉽게 개념화할 수 있다.
  • 객체의 제공자와 사용자를 분리할 수 있다.
  • 메소드의 구현 방법이 바뀌어도 사용자에게는 영향을 주지 않는다.
  • 메소드의 기능만 알면 객체를 쉽게 사용할 수 있다.
  • 객체 내 자료구조, 알고리즘이 바뀌어도 다른 객체에 영향을 적게 준다.
  • 객체간 독립성이 보장된다.
  • 내부 구조 변경이 사용자에게 주는 영향이 적어서 변경하는데 부담이 적다.
  • 사용자는 구조를 알 필요 없이 사용법만 익히면 되므로 이해하기 쉽다.
  • 모듈의 기능 추가가 쉽다.

정보은닉

정보은닉은 외부에서 내부의 데이터를 볼 수 없게하는 개념입니다. 내부 데이터에 접근하고 싶다면 메소드를 통해 객체에게 요청하는 과정을 거쳐야합니다.

클래스의 접근 제어자인 private, protected, public이 정보은닉에 사용됩니다.

  • private: 자기 자신만이 메소드를 통해 프로퍼티에 접근할 수 있다.
  • protected: 자기 자신과 상속받은 하위 클래스만이 프로퍼티에 접근할 수 있다.
  • public: 누구가 자유롭게 프로퍼티에 접근할 수 있다.

상속

상속은 부모 클래스의 프로퍼티와 메소드를 자식 클래스가 물려받아 마치 자신의 것처럼 사용하는 것입니다.

상속을 사용하면 개별의 클래스들을 관계가 있는 것끼리 상속을 묶어서 구조를 쉽게 파악할 수 있습니다. 또한 상속 관계의 클래스, 데이터, 메소드의 추가도 쉽습니다. 데이터나 메소드를 변경할 때 상위 클래스의 내용만 수정하면 되므로 일관성을 유지하는 것도 쉬워집니다.

다형성

다형성은 여러개의 형태를 갖는다는 의미로 객체지향에서는 오버로딩오버라이딩으로 나뉩니다.

오버로딩 overloading

오버로딩중복 정의라고 표현할 수 있습니다.

객체지향 언어에서 이미 존재하는 이름의 메소드나 함수를 매개변수의 수나 타입이 다르게하면 같은 이름으로 함수와 메소드를 정의할 수 있습니다. 이를 메소드 오버로딩이라고 합니다.

또한 + 연산자에서 숫자 연산을 하면 덧셈을 수행하고, 문자열 연산을 하면 문자열 연결을 하는데 이런 상황을 연산자 오버로딩이라고 부르기도 합니다.

오버라이딩 overriding

오버라이딩은 재정의라고 합니다. 재정의는 앞에서 정의한 내용을 무시하고 새로 정의한 내용으로 덮어쓴다는 것입니다.

부모 클래스의 메소드 정의는 무시하고 하위 클래스에서 메소드를 재정의해서 사용합니다.


모듈화

개발을 수행할 때는 작은 단위로 쪼개서 하나씩 개발해나갑니다. 이때 작은 단위로 나누는 것을 모듈화라고 합니다.

모듈은 큰 규모의 소프트웨어를 작은 단위로 나뉘었을 때의 단위, 또는 소프트웨어 구조를 이루는 기본 단위라고 할 수 있습니다. 아니면 하나 이상의 논리적 구조를 수행하기 위한 명령어 집합이라고도 할 수 있습니다.

모듈의 특징은 다음과 같습니다.

  • 다른 것과 구별되는 독립적인 기능을 갖습니다.
  • 유일한 이름을 갖습니다.
  • 하나의 모듈에서 또 다른 모듈을 호출할 수 있습니다.
  • 다른 프로그램에서도 모듈을 호출할 수 있습니다.

좋은 모듈 설계 원칙은 다음과 같습니다.

  • 모듈간의 결합(coupling)은 느슨하게 합니다.
  • 모듈 내의 구성 요소 간 응집(cohesion)은 강하게 합니다.

모듈의 평가

좋은 모듈 설계 원칙은 응집도결합도에 의해 결정됩니다.

응집도

응집도(Cohesion)는 모듈 내부의 구성 요소간의 밀접 정도입니다. 응집도가 높다는 것은 필요한 구성 요소만이 모여있고, 낮을 수록 서로 관련이 적은 구성 요소들이 모여있음을 의미합니다.

응집도엔 다양한 유형이 있는데 기능적 응집(Functional Cohesion)이 가장 높은 응집도를 보이고 내려갈수록 나쁜 응집도를 보여줍니다.
이미지 출처

  • 기능적 응집 Functional Cohesion
    기능적 응집은 함수적 응집이라고도 부르며, 응집도가 가장 높은 경우입니다. 단일 기능의 요소가 하나의 모듈을 구성합니다.

  • 순차적 응집 Sequential Cohesion
    순차적 응집은 두 요소가 하나의 모듈로 구성된 경우입니다. 두 요소가 아주 밀접한 관계가 있어서 하나로 묶게 되는 경우입니다.

  • 교환적 응집 Communication Cohesion
    교환적 응집은 정보적 응집이라고도 하며, 같은 입력을 사용하는 구성 요소가 하나의 모듈로 사용되는 경우를 의미합니다.

  • 절차적 응집 Procedural Cohesion
    절차적 응집은 순서가 정해진 몇 개의 구성 요소가 하나의 모듈로 구성된 경우입니다.

  • 시간적 응집 Temporal Cohesion
    시간적 응집은 모듈 내 구성 요소의 기능이 각기 다르지만 같은 시간대에 함께 실행된다는 이유로 묶인 모듈입니다.

  • 논리적 응집 Logical Cohesion
    논리적 응집은 구성 요소간의 공통점, 공통 임무, 기능이 비슷해서 하나의 모듈로 구성한 경우입니다.

  • 우연적 응집 Coincidental Cohesion
    우연적 응집은 말 그대로 우연히 모여 구성된 모듈입니다.

결합도

결합도(Coupling)는 모듈과 모듈 사이의 관련 정도를 의미합니다. 모듈간 관련이 적을수록 모듈의 독립성이 높아지고 영향이 적어져 좋은 설계가 됩니다.

결합도에도 다양한 유형들이 있습니다. 이미지 출처

  • 비관련 결합 No Direct Coupling
    비관련 결합은 두 모듈간 직접적인 결합이 없는 것입니다.

  • 데이터 결합 Data Coupling
    데이터 결합은 매개변수만을 가지고 데이터를 주고받아 간섭을 최소화한 결합니다.

  • 스탬프 결합 Stamp Coupling
    스탬프 결합은 필요한 데이터가 포함된 데이터 전체를 주고 받는 결합입니다. 이 과정에서 필요없는 데이터까지도 주고받게 됩니다.

  • 제어 결합 Control Coupling
    제어 결합은 제어 플래그를 통해 모듈간의 내부 구조를 알고 논리적 흐름을 제어하는 결합입니다.

  • 외부 결합 External Coupling
    외부 결합은 두 모듈이 외부에서 전달되는 데이터나 인터페이스를 공유하는 결합입니다. 외부 장치와 통신하는 구조에서 등장합니다.

  • 공통 결합 Common Coupling
    공통 결합은 모듈이 공통 변수를 함께 사용하는 결합입니다. 전역 변수를 사용하게 되면 공통 결합이 됩니다.

  • 내용 결합 Content Coupling
    내용 결합은 모듈간에 인터페이스 등을 사용하지 않고 직접 데이터가 왔다갔다 하는 결합입니다.


사용자 인터페이스 설계

사용하기 편리한 소프트웨어를 만들기 위해서는 좋은 사용자 인터페이스를 설계해야합니다.

초기 인터페이스는 사용자가 문자열 입력을 통해 결과를 처리하고 문자열로 결과를 표시하는 문자 사용자 인터페이스(CUI, Character User Interface), 명령줄 사용자 인터페이스(CLI, Command Line Interface)가 사용되었습니다. 이는 사용자가 명령어를 익혀야한다는 불편함이 동반되었는데요.

이를 개선하여 등장한 것이 그래픽 사용자 인터페이스(GUI, Graphic User Interface)입니다. 최근에는 더 편리하게 사용자의 터치나 음성, 행동으로 인식하는 내추럴 사용자 인터페이스(NUI, Natural User Interface)가 사용되기도 합니다.

좋은 사용자 인터페이스를 설계하기 위한 내용은 다음과 같습니다.

  • 사용법을 배우기 쉬워야 한다.
  • 사용하기 편리해야 한다.
  • 사용자가 데이터 입력을 제어할 수 있어야 한다.
  • 사용자의 입력에 반응해야 한다.
  • 도움말을 제공해야 한다.
  • 일관성을 유지해야 한다.
  • 입력 작업은 최소로 해야 한다.
  • 효율성을 고려해야 한다.
  • 사용자 오류에 대한 되돌리기 기능을 제공해야 한다.
  • 삭제 또는 취소 버튼 클릭 시 재확인을 요구해야 한다.
  • 사용하기 쉽게 직관적이어야 한다.

0개의 댓글