소프트웨어 설계

**소프트웨어 설계** 또는 **소프트웨어 디자인**(Software design)은 소프트웨어 시스템이 구현되거나 수정되기 전에 어떻게 작동할지 개념화하는 과정이다.
소프트웨어 설계는 설계 과정의 직접적인 결과물인 소프트웨어 작동 방식에 대한 개념을 의미하기도 하며, 이는 공식적으로 문서화되거나 구전을 포함하여 덜 공식적인 방식으로 유지될 수 있다.

설계 과정은 디자이너가 코드 작성 노력을 더 효율적으로 만들기 위한 목적으로 소프트웨어 시스템이 존재하기 전에 그 측면들을 모델링할 수 있게 해준다. 창의성, 과거의 경험, 무엇이 "좋은" 소프트웨어를 만드는지에 대한 감각, 그리고 품질에 대한 헌신은 유능한 설계의 성공 요인이다.

소프트웨어 설계는 집을 위한 건축 계획에 비유될 수 있다. 상위 수준의 계획은 집의 전체상(예: 집의 3차원 렌더링)을 나타낸다. 하위 수준의 계획은 각 세부 사항을 구축하기 위한 지침(예: 배관 배치)을 제공한다. 마찬가지로, 소프트웨어 설계 모델은 제안된 소프트웨어 솔루션에 대한 다양한 뷰를 제공한다.

## 전체 프로세스의 일부
폭포수 개발 프로세스 관점에서 소프트웨어 설계는 요구사항 분석 이후와 코딩 이전에 발생하는 활동이다. 요구사항 분석은 시스템이 어떻게 할 것인지를 결정하지 않고 무엇을 해야 하는지를 결정하므로, 요구사항을 충족하는 여러 설계를 상상할 수 있다. 계획이나 요구사항 분석 없이 코딩하는 동안 설계를 만들 수도 있지만, 더 복잡한 프로젝트의 경우 이는 실행 가능성이 낮다. 코딩 전에 설계를 완료하면 다학제적 디자이너와 분야 전문가가 프로그래머와 협력하여 유용하고 기술적으로 건전한 소프트웨어를 생산할 수 있다.

때때로 유효하고 좋은 설계를 결정하기 위한 노력의 일환으로 시스템을 모델링하기 위해 시뮬레이션이나 프로토타입이 생성된다.

## 설계로서의 코드

소프트웨어에서 설계라는 용어와 관련된 일반적인 혼란은 이 과정이 상위 수준의 소프트웨어 아키텍처와 하위 수준의 컴포넌트, 함수 및 알고리즘과 같은 여러 추상화 수준에서 적용된다는 점이다. 상대적으로 공식적인 과정은 높은 추상화 수준에서 발생할 수 있지만, 낮은 수준에서는 설계의 유일한 산출물이 코드 자체일 정도로 설계 과정이 거의 항상 덜 공식적이다. 이것이 사실인 한, 소프트웨어 설계는 설계의 설계를 의미한다. 에츠허르 데이크스트라는 이러한 의미론적 수준의 계층화를 컴퓨터 프로그래밍의 "급진적인 참신함"이라고 불렀으며, 도널드 커누스는 TeX을 작성한 경험을 바탕으로 프로그램을 구현하기 전에 설계를 시도하는 것의 무의미함을 다음과 같이 설명했다.

## 산출물
설계 과정에는 순서도, 유스 케이스, 의사코드, 통합 모델링 언어 모델 및 기타 기본 모델링 개념과 같은 소프트웨어 설계 문서의 작성이 포함될 수 있다. 사용자 중심 설계 소프트웨어의 경우, 설계에는 사양을 결정하는 데 도움이 되는 스토리보드를 생성하는 사용자 경험 디자인이 포함될 수 있다. 문서를 검토하여 코딩 전에 제약 사항, 사양 및 요구사항까지 조정할 수 있다.

## 반복 설계
소프트웨어 시스템은 본질적으로 불확실성을 다루며, 소프트웨어 컴포넌트의 크기는 시스템의 결과에 긍정적으로든 부정적으로든 상당한 영향을 미칠 수 있다. 닐 포드(Neal Ford)와 마크 리처즈(Mark Richards)는 컴포넌트를 식별하고 적절한 크기를 설정하는 문제를 해결하기 위해 반복적인 접근 방식을 제안한다. 이 방법은 팀이 시스템 동작과 요구사항에 대해 더 미묘한 이해를 발전시킴에 따라 지속적인 개선을 강조한다.

이 접근 방식은 일반적으로 다음과 같은 여러 단계의 주기를 포함한다.

* 상위 수준의 파티셔닝 전략이 수립되며, 종종 기술 중심 또는 도메인 중심으로 분류된다. "퀀타(quanta)"라고 불리는 의미 있는 최소 배포 단위에 대한 지침이 정의된다. 이러한 기초적인 결정은 초기에 이루어지지만, 필요한 경우 나중에 주기에서 다시 검토될 수 있다.
* 수립된 전략에 따라 초기 컴포넌트가 식별된다.
* 식별된 컴포넌트에 요구사항이 할당된다.
* 명확성을 확보하고 중복을 최소화하기 위해 각 컴포넌트의 역할과 책임을 분석한다.
* 확장성, 장애 허용성, 유지보수성과 같은 아키텍처 특성을 평가한다.
* 개발 팀의 피드백을 바탕으로 컴포넌트를 재구성할 수 있다.

이 주기는 일반적인 프레임워크 역할을 하며 다양한 도메인에 맞게 조정될 수 있다.

## 설계 원칙

설계 원칙은 소프트웨어 엔지니어가 설계 과정을 탐색할 수 있게 해준다. 데이비스(Davis)는 시간이 지나면서 다음과 같이 다듬어진 원칙들을 제안했다.

; 설계 과정은 "터널 시야"에 빠져서는 안 된다: 좋은 디자이너는 대안적인 접근 방식을 고려해야 하며, 문제의 요구사항과 작업을 수행하는 데 사용 가능한 자원을 바탕으로 각 접근 방식을 판단해야 한다.

; 설계는 분석 모델로 추적 가능해야 한다: 설계 모델의 단일 요소는 종종 여러 요구사항으로 거슬러 올라갈 수 있기 때문에, 요구사항이 설계 모델에 의해 어떻게 충족되었는지 추적할 수 있는 수단이 필요하다.

; 설계는 바퀴를 다시 발명해서는 안 된다: 시스템은 일련의 디자인 패턴을 사용하여 구축되며, 그중 많은 것들은 이전에 마주쳤을 가능성이 높다. 이러한 패턴들은 항상 재발명 대신 대안으로 선택되어야 한다. 시간은 짧고 자원은 제한되어 있다. 설계 시간은 (진정으로 새로운) 아이디어를 표현하기 위해 이미 존재하는 패턴을 통합하는 데 투자되어야 한다(해당되는 경우).

; 설계는 소프트웨어와 현실 세계에 존재하는 문제 사이의 "지적 거리 최소화"를 해야 한다: 즉, 소프트웨어 설계의 구조는 가능한 한 문제 도메인의 구조를 모방해야 한다.

; 설계는 균일성과 통합성을 보여야 한다: 설계가 완전히 일관성 있게 보인다면 그것은 균일한 것이다. 이 결과를 얻기 위해 설계 작업이 시작되기 전에 설계 팀을 위한 스타일 및 형식 규칙이 정의되어야 한다. 설계 컴포넌트 간의 인터페이스 정의에 주의를 기울인다면 그것은 통합된 설계이다.

; 설계는 변화를 수용할 수 있도록 구조화되어야 한다: 다음 섹션에서 논의되는 설계 개념들은 설계가 이 원칙을 달성할 수 있게 한다.

; 설계는 비정상적인 데이터, 이벤트 또는 운영 조건이 발생하더라도 완만하게 저하되도록 구조화되어야 한다: 잘 설계된 소프트웨어는 결코 "폭발"해서는 안 된다. 특이한 상황을 수용하도록 설계되어야 하며, 처리를 종료해야 한다면 우아한 방식으로 종료해야 한다.

; 설계는 코딩이 아니며, 코딩은 설계가 아니다: 프로그램 컴포넌트를 위해 상세한 절차적 설계가 만들어지더라도 설계 모델의 추상화 수준은 소스 코드보다 높다. 코딩 수준에서 내려지는 유일한 설계 결정은 절차적 설계가 코딩될 수 있도록 하는 작은 구현 세부 사항을 다루어야 한다.

; 설계는 사후가 아니라 생성되는 과정에서 품질을 평가받아야 한다: 개발 과정 전반에 걸쳐 디자이너가 품질을 평가하는 데 도움을 주는 다양한 설계 개념과 설계 측정 도구를 사용할 수 있다.

; 설계는 개념적(의미론적) 오류를 최소화하기 위해 검토되어야 한다: 때때로 설계를 검토할 때 세부 사항에 집중하여 숲을 보지 못하고 나무만 보는 경향이 있다. 설계 팀은 설계 모델의 구문을 걱정하기 전에 설계의 주요 개념적 요소(누락, 모호함, 불일치)가 해결되었는지 확인해야 한다.

## 설계 개념

설계 개념은 디자이너에게 더 정교한 방법이 적용될 수 있는 토대를 제공한다. 설계 개념에는 다음이 포함된다.

; 추상화: 개념이나 관찰 가능한 현상의 정보 내용을 줄여서, 일반적으로 특정 목적에 관련된 정보만 유지하는 것. 배경 세부 사항이나 설명 없이 필수적인 기능을 표현하는 행위이다.

; 아키텍처: 소프트웨어의 전반적인 구조와 그 구조가 시스템에 개념적 무결성을 제공하는 방식. 좋은 소프트웨어 아키텍처는 성능, 품질, 일정 및 비용 측면에서 프로젝트의 원하는 결과와 관련하여 투자 대비 좋은 수익을 제공할 것이다.

; 제어 계층: 프로그램 컴포넌트의 조직을 나타내고 제어의 계층 구조를 암시하는 프로그램 구조.

; 자료 구조: 데이터 요소 간의 논리적 관계를 표현하는 것.

; 디자인 패턴: 디자이너는 과거에 해결된 시스템의 설계 측면을 식별할 수 있다. 이러한 패턴의 재사용은 소프트웨어 개발 속도를 높일 수 있다.

; 정보 은닉: 모듈은 모듈 내에 포함된 정보가 해당 정보를 필요로 하지 않는 다른 모듈에서 접근할 수 없도록 지정되고 설계되어야 한다.

; 모듈성: 솔루션을 부분(모듈)으로 나누는 것.

; 정제: 정교화 과정. 프로그래밍 언어 문장에 도달할 때까지 거시적인 기능 선언을 단계적으로 분해하여 계층 구조를 개발한다. 각 단계에서 주어진 프로그램의 하나 또는 여러 지침이 더 상세한 지침으로 분해된다. 추상화와 정제는 상호 보완적인 개념이다.

; 소프트웨어 절차: 각 모듈의 처리에 개별적으로 집중한다.

; 구조적 파티셔닝: 프로그램 구조는 수평 및 수직으로 나눌 수 있다. 수평적 파티션은 각 주요 프로그램 기능에 대해 별도의 모듈식 계층 분기를 정의한다. 수직적 파티셔닝은 제어와 작업이 프로그램 구조에서 하향식으로 분산되어야 함을 시사한다.

그래디 부치는 추상화, 캡슐화, 모듈화 및 계층을 근본적인 소프트웨어 설계 원칙으로 언급한다. 계층, 추상화, 모듈화 및 캡슐화 원칙(PHAME)이라는 구절은 이러한 원칙들을 가리킨다.

## 설계 고려 사항

소프트웨어 설계에는 고려해야 할 많은 측면이 있다. 각 측면의 중요성은 소프트웨어가 생성되는 목적과 기대치를 반영해야 한다. 주요 측면은 다음과 같다.

; 호환성: 소프트웨어가 다른 제품과의 상호 운용성을 위해 설계된 다른 제품과 함께 작동할 수 있다. 예를 들어, 소프트웨어 조각은 자신의 이전 버전과 하위 호환성을 가질 수 있다.
; 확장 가능성: 기본 아키텍처에 큰 변화 없이 소프트웨어에 새로운 기능을 추가할 수 있다.
; 장애 허용성: 소프트웨어가 컴포넌트 고장에 저항력이 있고 고장으로부터 회복할 수 있다.
; 유지보수성: 버그 수정이나 기능 수정을 얼마나 쉽게 수행할 수 있는지에 대한 척도. 높은 유지보수성은 모듈성과 확장 가능성의 결과일 수 있다.
; 모듈성: 결과물인 소프트웨어가 잘 정의되고 독립적인 컴포넌트로 구성되어 더 나은 유지보수성으로 이어진다. 컴포넌트들은 원하는 소프트웨어 시스템을 형성하기 위해 통합되기 전에 개별적으로 구현되고 테스트될 수 있다. 이는 소프트웨어 개발 프로젝트에서 작업의 분할을 가능하게 한다.
; 오버헤드: 오버헤드에 필요한 자원 소비가 시스템 요구사항을 달성하는 데 필요한 자원에 어떤 영향을 미치는지.
; 성능: 소프트웨어가 사용자에게 수용 가능한 시간 내에 작업을 수행하며 너무 많은 메모리를 요구하지 않는다.
; 이식성: 소프트웨어가 다양한 조건과 환경에서 사용될 수 있어야 한다.
; 신뢰성: 소프트웨어가 지정된 기간 동안 명시된 조건 하에서 요구되는 기능을 수행할 수 있다.
; 재사용성: 기존 소프트웨어의 일부 또는 모든 측면을 다른 프로젝트에서 거의 또는 전혀 수정 없이 사용할 수 있는 능력.
; 강건성: 소프트웨어가 스트레스 하에서 작동하거나 예측할 수 없거나 잘못된 입력을 견딜 수 있다. 예를 들어, 메모리 부족 조건에 대한 복원력을 갖도록 설계될 수 있다.
; 확장성: 소프트웨어가 증가하는 데이터나 추가된 기능 또는 사용자 수에 잘 적응한다. 마크 브루커(Marc Brooker)에 따르면: "시스템은 추가 작업 부하의 한계 비용이 거의 일정한 범위 내에서 확장 가능하다." 서버리스 컴퓨팅 기술이 이 정의에 부합하지만, 인프라 비용뿐만 아니라 총 소유 비용을 고려해야 한다.
; 보안: 소프트웨어가 적대적인 행위와 영향에 견디고 저항할 수 있다.
; 사용성: 소프트웨어 사용자 인터페이스는 대상 사용자/청중이 사용할 수 있어야 한다. 매개변수의 기본값은 대다수의 사용자에게 좋은 선택이 되도록 선택되어야 한다.

## 모델링 언어

모델링 언어는 일관된 규칙 세트에 의해 정의된 구조로 정보, 지식 또는 시스템을 표현하는 데 사용될 수 있다. 이러한 규칙은 구조 내의 컴포넌트 해석에 사용된다. 모델링 언어는 그래픽적이거나 텍스트적일 수 있다. 소프트웨어 설계를 위한 그래픽 모델링 언어의 예는 다음과 같다.

; 아키텍처 기술 언어 (ADL): 소프트웨어 시스템의 소프트웨어 아키텍처를 설명하고 표현하는 데 사용되는 언어.

; 비즈니스 프로세스 모델링 표기법 (BPMN): 프로세스 모델링 언어의 한 예.

; EXPRESS 및 EXPRESS-G (ISO 10303-11): 국제 표준 범용 데이터 모델링 언어.

; 확장 엔터프라이즈 모델링 언어 (EEML): 여러 계층에 걸쳐 비즈니스 프로세스 모델링에 일반적으로 사용된다.

; 순서도: 알고리즘이나 기타 단계적 프로세스의 도식적 표현.

; 펀더멘털 모델링 콘셉트 (Fundamental Modeling Concepts, FMC): 소프트웨어 집약적 시스템을 위한 모델링 언어.

; IDEF: 모델링 언어 제품군으로, 기능 모델링을 위한 IDEF0, 정보 모델링을 위한 IDEF1X, 온톨로지 모델링을 위한 IDEF5가 가장 유명하다.

; 잭슨 구조적 프로그래밍 (JSP): 데이터 스트림 구조와 프로그램 구조 간의 대응 관계를 기반으로 하는 구조적 프로그래밍 방법.

; LePUS3: 주로 대규모 객체 지향(자바, C++, C#) 프로그램 및 디자인 패턴을 모델링하는 데 적합한 객체 지향 시각적 설계 기술 언어이자 정형 명세 언어.

; 통합 모델링 언어 (UML): 소프트웨어를 구조적 및 행동적으로 설명하기 위한 범용 모델링 언어. 그래픽 표기법을 가지고 있으며 프로파일을 통한 확장을 허용한다.

; 알로이 (사양 언어) (Alloy): 소프트웨어 시스템의 복잡한 구조적 제약과 동작을 표현하기 위한 범용 사양 언어. 1차 관계 논리를 기반으로 간결한 언어 기반을 제공한다.

; 시스템 모델링 언어 (SysML): 시스템 공학을 위한 범용 모델링 언어.

; 서비스 지향 모델링 프레임워크 (SOMF)

## 같이 보기

* 소프트웨어 디자인 패턴
* 구조도

## 각주


분류:컴퓨터 관련 직업