ISO/IEC/IEEE 24765 용어집은 소프트웨어 설계(software design)를, 미리 정한 기능을 최대한 경제적이고 효율적으로 수행하도록 소프트웨어 시스템을 정의하는 데 과학적 원리, 기술 정보, 상상력을 쓰는 것으로 정의한다.[1] ISO/IEC/IEEE 12207:2026은 설계(design)를, 아키텍처를 그에 맞게 구현할 수 있을 만큼 완전한, 시스템 요소와 그 관계의 명세로 정의한다.[2]
설계 원리
SWEBOK V4.0a에 따르면 설계 원리는 설계 중에 결정을 내리는 방향과 지침을 주고, 설계의 세 단계 어디에나 적용된다. 원리로는 추상화, 관심사 분리, 모듈화, 캡슐화(정보 은닉), 인터페이스와 구현의 분리, 결합도와 응집도, 균일성, 완전성, 검증 가능성이 있다.[3]
- 추상화(abstraction): 겉보기에 다른 대상들의 공통된 본질적 속성을 찾게 돕는다.
- 캡슐화(encapsulation): 정보 은닉이라고도 한다. 추상화와 모듈화를 바탕으로 본질적이지 않은 정보에 덜 접근하게 해, 모듈을 쓰는 이가 인터페이스의 본질적 요소에 집중하게 한다.
- 인터페이스와 구현의 분리: 캡슐화를 적용한 것으로, 클라이언트가 알고 접근하는 공개 인터페이스를 명세해 컴포넌트를 정의하고, 컴포넌트를 쓰는 일을 그 컴포넌트가 만들어진 방식의 세부와 떼어 놓는다.
- 균일성(uniformity): 소프트웨어 컴포넌트 사이의 일관성 원리로, 공통되거나 되풀이되는 문제에는 공통 해법을 낸다. 이름 규칙, 표기와 문법, 서비스와 메커니즘에 접근하는 인터페이스, 요소와 파라미터의 순서가 여기에 들고, 규칙·형식·스타일 같은 관례로 이룬다.
- 완전성(completeness): 충분성이라고도 한다. 소프트웨어 컴포넌트가 추상화의 중요한 특성을 빠짐없이 담는 것이다. 가장 중요한 꼴은 요구사항에 대한 설계의 완전성으로, 설계는 요구사항이 어떻게 충족될지 보일 수 있을 만큼 충분해야 하고, 소프트웨어의 모드와 상태에 대해서도 완전해야 한다.
- 검증 가능성(verifiability): 요구사항과 다른 제약에 비추어 설계를 검증하는 데 필요한 정보가 있는 것이다. 보안, 신뢰성, 안전이 중요한 높은 보증 소프트웨어에서 특히 중요하고, SDD(software design description)는 설계를 검증하는 바탕이 될 만큼 충분해야 한다.[3]
ISO/IEC/IEEE 24765 용어집은 추상화를, 특정 목적에 관련된 정보에 집중하고 나머지 정보는 무시하는 대상의 관점으로 정의한다. 이 용어집은 캡슐화를, 시스템 기능이나 데이터와 그 연산을 한 모듈 안에 떼어 두고 그 모듈에 정확한 명세를 주는 소프트웨어 개발 기법으로 정의하고, 모듈에는 내부와 구별되는 외부, 곧 외부 인터페이스와 내부 구현이 있다는 생각으로도 정의한다.[1]
정보 은닉
이 용어집은 정보 은닉(information hiding)을 두 가지로 정의한다. 하나는 모듈의 인터페이스가 모듈의 내부 동작을 되도록 적게 드러내고, 다른 모듈이 그 모듈의 인터페이스 명세에 없는 정보를 쓰지 못하게 하는 소프트웨어 개발 기법이다. 다른 하나는 설계나 구현 결정 하나를 한 모듈 안에 담아 다른 모듈에서 감추는 것이다.[1]
Parnas는 1972년 논문에서 순서도로 모듈을 나누는 대신, 어렵거나 바뀌기 쉬운 설계 결정의 목록에서 시작해 모듈마다 그런 결정 하나를 다른 모듈에서 감추도록 시스템을 나누자고 제안했고, 이 기준을 information hiding이라 불렀다. 그는 KWIC(keyword in context) 색인 예에서, 바뀌기 쉬운 설계 결정을 모듈마다 하나씩 감춘 분해에서는 그런 결정(예: 줄을 저장하는 방식)이 바뀌어도 그 모듈만 고치면 되지만, 처리 단계대로 나눈 분해에서는 여러 모듈, 때로는 모든 모듈을 고쳐야 함을 보였다.[4]
설계 단계
SWEBOK V4.0a에 따르면 소프트웨어 설계는 흔히 아키텍처 설계, 상위 설계(high-level design), 상세 설계의 세 단계로 나뉜다. 아키텍처 설계 단계는 시스템 전체의 기본 사항을 환경과의 관계 안에서 다루고, 상위 설계 단계는 바깥을 향해 소프트웨어의 최상위 구조와 구성, 그 컴포넌트, 그리고 시스템과 컴포넌트가 환경과 상호작용하는 방식을 정한다. 상세 설계 단계는 안을 향해, 각 컴포넌트를 만들 수 있고 바깥에 대한 의무를 다할 수 있을 만큼 자세히 명세한다. 모든 소프트웨어 프로세스에 모든 단계가 있지는 않지만, 단계가 있으면 각 단계는 다음 단계에 의무를 지운다. 단계 사이에 무엇을 언제 해야 하는지의 엄격한 경계는 없다. 예를 들어 정렬 알고리즘의 선택은 많은 시스템에서 프로그래머에게 미뤄지지만, 어떤 시스템에서는 알맞은 알고리즘이 있는지가 아키텍처적으로 중요해 생명주기 초기에 정해야 한다.[3]
상위 설계는 시스템의 주요 컴포넌트가 서로, 그리고 사용자, 장치, 다른 시스템 같은 환경과 어떻게 상호작용하는지 명세한다. 시스템이 응답하거나 내야 하는 외부 이벤트와 메시지, 그 데이터 형식과 프로토콜, 입력과 출력 사이의 순서와 타이밍 관계, 종단 간 트랜잭션의 추적과 분석, 데이터 지속성을 다룬다.[3] 상세 설계가 정하는 것은 소프트웨어 유닛 설계에서 다룬다.
ISO/IEC/IEEE 24765 용어집은 예비 설계(preliminary design)를, 설계 대안을 분석하고 시스템이나 컴포넌트의 아키텍처, 컴포넌트, 인터페이스, 타이밍과 크기 추정을 정하는 것으로 정의한다.[1]
설계 표기
SWEBOK V4.0a에 따르면 소프트웨어 설계에는 흔히 여러 종류의 표기를 함께 쓰고, 표기는 크게 구조를 기술하는 것과 행위를 기술하는 것으로 나뉜다. 어떤 표기는 주로 아키텍처 설계에서, 어떤 표기는 주로 상세 설계에서 쓰이고, 설계의 모든 단계에 쓸모 있는 표기도 있다. UML(Unified Modeling Language)은 구조와 행위를 모두 다루는 표기 모음으로, 아키텍처 설계부터 상세 설계까지 모든 설계 단계에 쓰인다.[3]
구조 표기는 주요 컴포넌트와 그 연결(정적 뷰), 컴포넌트와 모듈에 대한 책임 할당을 기술한다. 클래스·객체 다이어그램, 컴포넌트 다이어그램, 클래스-책임-협력자 카드, 배치 다이어그램, 개체-관계 다이어그램, 인터페이스 기술 언어, 구조도가 여기에 든다. 행위 표기는 소프트웨어 시스템과 컴포넌트의 동적 행위를 기술한다. 활동 다이어그램, 상호작용 다이어그램(통신 다이어그램과 시퀀스 다이어그램), 데이터 흐름 다이어그램, 결정표, 순서도, 상태 다이어그램과 statechart, 정형 명세 언어, 의사코드와 프로그램 설계 언어가 여기에 든다.[3]
구조적 설계와 객체지향 설계
기능 지향 설계라고도 하는 구조적 설계(structured design)는 고전적인 소프트웨어 설계 방법의 하나로, 분해로 주요 소프트웨어 기능을 찾아 하향식으로 구체화한다. 구조적 설계는 흔히 구조적 분석에 이어서 하며, 데이터 흐름 다이어그램과 그에 딸린 프로세스 기술을 만든다. 객체지향 설계(object-oriented design)는 명사가 객체, 동사가 메서드, 형용사가 속성을 나타내고 상속과 다형성이 핵심인 1980년대 중반의 초기 객체지향 설계에서, 리플렉션 등으로 메타정보를 정의하고 접근할 수 있는 컴포넌트 기반 설계로 발전해 왔다.[3]
설계 근거
설계 근거(design rationale)는 설계 결정을 왜 내렸는지를 담는다. 앞서 둔 가정, 검토한 대안, 한 방법을 고르고 나머지를 버리려고 분석한 절충과 기준이 여기에 든다. 결정의 이유는 지금의 설계 팀에게는 뻔해도 배포 뒤에 시스템을 고치거나 유지보수하는 이들에게는 덜 뻔할 수 있으므로, 근거를 기록하면 소프트웨어 제품의 장기 유지보수성이 높아진다. 버린 결정과 그 이유도 남겨 두면, 가정이나 요구사항이나 제약이 바뀌었을 때 버린 결정을 다시 검토할 수 있다. 설계 근거는 SDD의 일부나 딸린 산출물로 남길 수 있고, 흔히 글로 남기지만 설계를 서로 이어진 결정의 네트워크로 그린 그래프 같은 다른 꼴도 쓸 수 있다.[3]
설계 품질 분석
SWEBOK V4.0a에 따르면 설계 리뷰는 설계의 진척이나 완성도, 요구사항을 얼마나 다루는지, 열려 있거나 풀리지 않은 문제, 잠재 문제 같은 관심사를 평가하는 포괄적 검토다. 설계의 어느 단계에서나 할 수 있고, 설계 팀, 독립된 제3자, 다른 이해관계자가 할 수 있다. 설계 감사는 정해 둔 특성 목록(예: 기능 감사)에 더 좁게 초점을 둔다.[3]
설계 품질을 분석하고 평가하는 기법은 다음과 같다.[3]
- 설계 리뷰: SDD와 다른 설계 산출물을 바탕으로 소프트웨어 품질을 가늠하는 비공식 기법과 엄격한 기법. 아키텍처 리뷰, 설계 리뷰와 인스펙션, 시나리오 기반 기법, 요구사항 추적이 있다.
- 정적 분석: 설계를 평가하는 정형이나 반정형의 정적(실행하지 않는) 분석. 결함 트리 분석이나 자동 교차 검사가 그 예다.
- 시뮬레이션과 prototyping: 설계를 평가하는 동적 기법. 성능 시뮬레이션이나 실현 가능성 prototype이 그 예다.[3]
측정치는 설계의 크기, 구조, 품질 같은 여러 측면을 정량으로 가늠하거나 추정하는 데 쓰인다. 측정치는 크게 두 갈래로 나뉜다. 기능 기반(구조적) 설계 측정치는 기능 분해를 분석해 얻고 흔히 구조도 위에서 계산하며, 객체지향 설계 측정치는 흔히 클래스 다이어그램 위에서 계산한다.[3]