객체지향 (소프트웨어 공학)




소프트웨어 공학 분야에서 객체지향 기술은 오래전부터 여러 분야에서 연구가 되어 왔던 아이템이다. 특히 1990년대부터 소프트웨어 분야에서는 매우 중요한 기술로 다뤄지며 생산성에 초점을 맞춘 프로그래밍 분야에서는 이제는 빼놓을 수 없는 핵심기술이다. 이는 소프트웨어의 발전이 하드웨어를 따라가지 못한다는 ‘소프트웨어 위기’를 타개할 수 있는 방법으로서 이제는 개발 주류가 된 객체지향은 특수화되고 적절하게 변경이 되며 소프트웨어 부품을 보다 체계적으로 다시 사용할 수 있는 인프라가 되었다.

 

객체지향 특징

객체지향의 특징은 무엇보다도 절차적인 프로그램과의 차이점을 보면 명확해진다.

🚩 모형의 적합성
복잡해지는 문제를 잘 모델링하기 위해서는 부분적인 자세함도 필요하지만 적절하게 자세한 것을 생략할 수 있는 추상화도 가능하여야 한다. 이는 객체지향에서 정보은닉과 메시지 교환이라는 개념을 활용하여 작업이 분산되고 감춰진다. 함수의 집합으로 구성된 절차적인 프로그래밍과 달리 객체지향 프로그램은 내부가 감춰진 객체들의 상호작용으로 구성된다. 그래서 자료를 따로 가진 객체들이 필요할 때만 협력한다. 더불어 개념이나 실체를 이산적인 객체로 모델링하여 독립된 객체로서 구현시킨다.

🚩 재사용 용이
재사용이 쉽다. 객체는 열림 특성과 닫힘 특성을 모두 갖추고 있고 재사용 부품으로서 그 역할을 한다. 닫힘은 변하지 않는 부분은 손대지 않고 그대로 다시 사용하는 것을 말하며 열림은 그 반대로 이를 변경 또는 확장하여 사용할 수 있는 것이다. 이를 가능하게 하는 개념은 바로 상속과 다형성이다. 추상화 클래스를 정의하고 파라미터를 용도에 맞게 사용할 수도 있고 캡슐화된 클래스를 그대로 쓰면서 필요에 따라 확장도 가능한 것이다.

🚩 Time to market
소프트웨어의 효율성 외에도 품질이나 유지보수 용이성, 시장 출하 시점도 소프트웨어 설계에 있어 매우 주요한 설계 기준이다. 시장에 처음 출시된 제품이 나중에 나온 제품보다 기능이 떨어지더라도 시장을 선점하고 점유한 상태를 무시할 수 없기 때문이다. 객체지향은 재사용이 용이하고 재설계가 필요 없기 때문에 개발기간을 단축할 수 있고 필요시 원하는 시점에 맞춰 제품 출하를 가능하게끔 하는 기술이다.

🚩 설계와 프로그래밍 매핑
절차적 방법에 비해 설계단계에서 프로그래밍으로의 전환이 매우 순조롭다. 즉 쉽게 매핑될 수 있다는 것인데 프로그램의 기초 단위인 객체나 클래스 개념을 말하는 것이다. 물론 코딩 자체는 다소 어려울 수 있더라도 분석 설계 단계에서 부분적인 코딩이 자유로운 객체지향은 모델링 기초 개념이 동일하여 이 또한 개발기간을 단축할 수 있는 결과를 가져올 수 있다.

 




기본개념

🚩 객체(Object)
객체는 현실 세계의 개체나 개념을 소프트웨어적으로 모델링한 것이다. 즉 필요한 자료구조와 이에 수행되는 함수들을 가진 하나의 소프트웨어 모듈로 볼 수 있다. 이는 자료구조를 갖고 상태를 가진다는 것인데 데이터와 해당 데이터를 처리하는 메소드(함수)를 함께 포함한다. 예로, 자동차 객체는 브랜드, 모델, 속도 등의 데이터와 가속, 정지와 같은 동작을 수행하는 메소드로 구성된다. 결국 객체는 상태와 행위, 정체성을 갖는, 비슷한 객체의 구조와 행동이 공통 클래스로 선언된다.

🚩 클래스(Class)
클래스는 객체를 생성하기 위한 템플릿이며 객체의 구조와 행동을 정의한다. 즉 객체의 타입이 클래스이다. 클래스는 속성(변수)과 메소드(함수)로 구성되며 객체를 생성할 때 이러한 속성과 메소드가 해당 객체에 포함된다. 자동차 클래스는 자동차 객체들이 가져야 할 속성과 메소드를 정의하는 것이 그 예이며 클래스에 속하는 객체를 이 클래스의 인스턴스라고 한다. 이런 클래스를 정의하기 위해서는 클래스가 가지는 속성을 도출하여야 한다. 다시 말해 클래스는 객체들이 갖는 속성과 적용 연산을 정의하고 있는 템플릿이다.

🚩 캡슐화(Encapsulation)
캡슐화는 객체의 상태(속성)와 행동(메소드)을 하나의 단위로 묶는 것이다. 객체는 외부에서 직접 접근하는 것을 제한하고 객체의 내부 동작을 숨기는 것으로 정보은닉을 지원하는데 이를 통해 객체의 내부 구현 세부 사항을 감추고 외부에서는 필요한 인터페이스를 통해 상호 작용할 수 있다. 캡슐화는 설계나 분석 단계에서 주어진 문제를 간단히 처리할 수 있는 추상화의 수단이 된다.

🚩 상속(Inheritance)
상속은 클래스 간의 계층 구조를 만들어 기존 클래스의 속성과 메소드를 다른 클래스가 상속받아 재사용할 수 있게 해준다. 부모 클래스(상위 클래스 또는 기본 클래스)의 특징을 자식 클래스(하위 클래스 또는 파생 클래스)가 물려받아 확장하거나 수정할 수 있다. 이를 통해 코드 재사용성과 계층적 구조를 갖는 클래스들을 구성할 수 있다. 이런 상속은 슈퍼 클래스, 서브 클래스로 클래스를 세분화하며 객체가 갖는 특유의 속성들을 추가할 수 있다. 참고로 두 개 이상의 슈퍼 클래스에서 상속받는 것을 복수 상속이라 한다.

🚩 다형성(Polymorphism)
다형성은 같은 이름의 메소드를 다양한 객체에서 호출할 때 다른 동작을 수행하도록 하는 개념으로 여러 가지 형태를 가지고 있다는 말이다. 이는 상속과 연결되어 있으며, 자식 클래스는 부모 클래스의 메소드(특정한 클래스를 위해서 오퍼레이션을 구현한 것)를 오버 라이딩(재정의)하여 자신에 맞게 수정할 수 있다. 다형성을 통해 객체 간의 유연하고 일관된 상호작용을 가능하게 한다. 다형성은 현재 코드를 변경하지 않고 새로운 클래스를 쉽게 추가할 수 있다.

 




객체지향 프로세스

객체지향 프로세스의 단계들은 선형적인 순서로 진행되는 것이 아니라 실제 개발 과정에서는 반복되거나 중첩되는 경우가 많다. 이는 소프트웨어 개발의 복잡성을 다루기 위해 계획, 설계, 구현, 검증, 유지보수 등을 체계적으로 수행하여 효율적이고 유지보수가 가능한 소프트웨어를 만들기 위한 접근법으로 큰 틀에서는 일반적인 소프트웨어 개발 프로세스와 동일하다.

✔️ 요구사항 분석
프로젝트의 목적과 필요한 기능을 파악하고 문서화한다. 이 단계에서는 사용자와 고객의 요구사항을 파악하고 이를 객체와 클래스로 변환하여 소프트웨어의 주요 기능과 특성을 정의한다. 주요 과정으로는 요구추출 단계에서는 액터, 시나리오, 여러 사례들을 찾고 구체화하며 여러 사례 간의 관계를 바탕으로 비기능적 요구를 명확화한다. 이후 요구분석을 통해 분석모형을 위한 객체, 객체 간 모형화, 연관관계, 속성 등을 찾고 정리한다.

✔️ 시스템 설계
요구사항을 바탕으로 시스템의 구조와 아키텍처를 설계한다. 클래스와 객체의 관계, 데이터베이스 구조, 인터페이스 등을 정의하고 시스템의 전체적인 동작 방식을 계획한다. 즉 설계목표를 정의하고 서브 시스템을 파악하고 여러 저장소를 설계하며 이를 패키지 다이어그램으로 정리한다.

✔️ 클래스 설계
시스템 설계를 바탕으로 클래스와 객체의 세부 사항을 설계한다. 클래스의 속성과 메소드를 식별하고 클래스 간의 관계를 설정하며 적절한 상속 구조를 설계한다. 객체를 정의하고 부품의 선택과 최적화를 통해 설계를 진행하며 상세화된 클래스 다이어그램을 작성한다.

✔️ 구현 및 테스트
클래스 설계를 기반으로 실제 코드를 작성한다. 각 클래스의 메소드를 구현, 데이터를 처리하며 객체들을 생성하고 관리한다. 이 단계에서는 객체지향 프로그래밍 언어를 사용하여 클래스와 메소드를 코드로 표현한다. 그리고 작성한 코드를 검증하여 시스템이 요구사항을 충족하는지 확인한다. 단위 테스트, 통합 테스트, 시스템 테스트 등 다양한 수준의 테스트를 수행하여 버그를 찾고 수정한다.

✔️ 배포 및 유지보수
개발한 소프트웨어를 배포하고, 사용자가 실제로 사용하면서 발생하는 문제를 해결하고 기능을 추가 또는 개선한다. 유지보수 단계에서는 시스템의 변경이나 업데이트가 필요한 경우 이를 수행한다.

✔️ 문서화, 평가와 개선
프로세스의 각 단계에서 만든 문서들을 정리하고 보완하여 개발된 소프트웨어의 설명서를 작성한다. 프로젝트가 완료된 후에는 전체 프로세스를 돌아보고 개발한 시스템의 성능과 사용성을 평가한다. 이를 통해 개선점을 발견하고 다음 프로젝트에 반영하기 위한 교훈(lessons learned)을 얻는다.




설계3 (소프트웨어 공학)

프로그램 설계

프로그램 설계(Programming Design)는 소프트웨어 공학의 개발 과정 중 하나로, 시스템의 각 모듈 안에서 일어나는 일들과 모듈 안에서의 자료구조에 관하여 설계하는 단계이다. 각 모듈 안에 사용될 알고리즘을 고안하는데 이는 소프트웨어 개발에서 설계 도면과 같은 역할을 한다. 이런 프로그램 설계는 시스템 구조설계와 분리하여 별도의 단계로 추진하기도 하지만 때로는 병행 진행하기도 한다. 프로그램 설계는 효율적이고 유지보수가 가능한 소프트웨어 시스템을 만들기 위해 필수적인 활동이며 요구사항 분석을 바탕으로 시스템의 목표를 이루기 위한 적절한 아키텍처와 구조를 결정하는 것으로서 잘 설계된 소프트웨어 시스템은 확장성, 유지보수성, 재사용성 등을 갖추어 복잡한 프로젝트의 성공을 보장하는 데 도움을 준다. 이에 프로그램 설계는 크게 두 가지 측면에서 이루어진다.

  • 구조적 설계: 시스템을 하위 모듈로 분할하고 각 모듈 간의 인터페이스와 관계를 정의한다. 모듈은 기능적으로 관련된 작업을 수행하는 코드 블록으로 소프트웨어 시스템을 조직화하는 데 사용되며 시스템 전체적인 레이아웃을 계획하고 모듈 간의 데이터 및 제어 흐름을 결정하는 역할이다.
  • 상세 설계: 구조적 설계 완료 후, 각 모듈의 내부 동작 및 구현 세부 사항을 정의하는 단계로 모듈 내부의 변수, 함수, 알고리즘 등을 설계하며 코드의 실제 구현 방식을 결정한다. 이는 실제 프로그래밍 단계에 진입하기 전에 개발자들이 따라야 할 로드맵을 제공한다.

구조적 설계에 이어 상세설계 단계는 모듈을 하나씩 다룬다. 각 모듈을 구현하기 위한 알고리즘을 선택하고 기술하는 것이다. 시스템 구조설계가 잘 이루어진 상태라면 각 모듈 안의 설계는 어렵지 않다. 각 모듈의 역할이 분명하고 모듈 사이의 결합도가 낮게 구성되기 기 때문이다. 설계의 원리들을 따 잘 설계하였다면 모듈을 어떻게 구현할 것인가를 결정하는 일은 알고리즘 선택으로 국한된다.




알고리즘 선택

알고리즘 선택의 3가지 원칙은 다음과 같다.

  • 정확성: 알고리즘은 기본적으로 정확해야 한다. 기술된 알고리즘은 제공된 자료를 정확하게 처리하여야 하며 정의된 기능 또한 정확하게 수행하여야 한다. 이런 상황에서 모듈이 수행하여야 할 기능이 새로운 것이 아니라면 기존의 프로그램이나 알고리즘 모음집 등의 자료를 참고하는 것도 좋은 방법이다. 프로그램을 처음부터 새로 구현하는 것보다 증명된 알고리즘을 사용하거나 이미 수행된 프로그램을 사용하면 개발비용과 시간을 절약할 수 있다.
  • 효율성: 알고리즘의 수행에 필요한 컴퓨터 자원의 양을 말한다. 이는 기억장치의 소요량과 수행시간이다. 특히 수행시간은 알고리즘과 밀접한 관계가 있다. 알고리즘의 기본 동작 수는 알고리즘에 따라 선형적일 수도 있고 비선형적일 수도 있다. 같은 문제에 대해서 접근법이 다르다면 그 결과는 천차만별이다. 즉 효율성을 높이면 처리 속도는 매우 크게 개선되며 모듈 안에서의 효율성과 전체 시스템의 효율성을 같이 고려하여 알고리즘을 구현해야 한다.
  • 적합성: 알고리즘은 목표 시스템의 하드웨어와 소프트웨어에 맞아야 한다. 이는 시스템의 특성, 목표, 제약조건 등을 충분히 감안하여 그 방향성에 맞춰 알고리즘을 구사하여야 한다. 설계단계의 모든 것이 고려되어야 하며 필요시 보다 맞는 알고리즘으로 대체할 수 있는 계획을 가지고 있어야 한다.

알고리즘 표현

설계단계에서 사용되는 모든 표현법은 매우 중요하다. 이는 의도하는 바를 정확하게 나타낼 수 있고 의사소통을 원활하게 해준다. 모듈 안 알고리즘을 기술하는 방법도 여러 가지가 있다.

  • 나씨-슈나이더만도표(Nassi-Shneiderman Diagram): 제어 구조를 시각적으로 표현하는 것으로 제어 흐름을 명확하게 표현하여 프로그램의 논리를 이해하고 분석하는데 순차, 선택, 반복과 같은 기본적인 제어 구조를 사용하여 알고리즘을 표현
  • 자연어: 일반적인 언어를 사용하여 알고리즘을 설명하는 것으로 비기술적인 사람들도 쉽게 이해할 수 있으나 그 모호성이나 해석 차이로 인해 정확한 이해를 보장하지 않을 수 있음
  • 순서도(Flowchart): 도형과 화살표를 사용하여 알고리즘의 흐름을 시각적으로 나타내는 것으로 시작과 종료 점, 결정, 처리, 입출력 등의 기호로 표현하여 알고리즘의 논리 구조를 표현
  • 의사 코드(Pseudo code): 일반 언어와 프로그래밍 언어의 중간 형태로 인간이 이해하기 쉬운 형태의 코드이며 실제 프로그래밍 언어가 아니므로 특정 구문이나 규칙에 얽매이지 않고 알고리즘의 논리적 흐름을 설명 가능
  • 프로그래밍 언어: 알고리즘을 실제 프로그래밍 언어로 구현하여 나타내는 방법으로 컴퓨터가 직접 실행할 수 있도록 하며 알고리즘의 구현 세부 사항을 정확히 표현 가능
  • 통합 모델링 언어(UML: Unified Modeling Language): 주로 소프트웨어 설계와 모델링에 사용되며 다이어그램을 사용하여 시스템의 구조와 동작을 표현하고 클래스 다이어그램, 시퀀스 다이어그램, 상태 다이어그램 등을 활용
  • 스토리보드: 주로 사용자 인터페이스 설계에서 활용되며 그림과 텍스트를 사용하여 사용자와 시스템 간의 상호작용 흐름을 시각적으로 표현

 




사용자 인터페이스 설계

사용자 인터페이스 설계(User Interface Design)는 소프트웨어 공학에서 사용자와 소프트웨어 시스템 간의 상호작용을 디자인하는 과정으로 사용자가 시스템과 소통하는 방식을 결정하고 설계한다. 사용자 인터페이스는 시스템의 기능을 사용자가 이해하고 조작할 수 있도록 돕는 중요한 요소이며 사용자 만족을 전제로 한다. 이에 사용자 인터페이스에 대한 평가 요소가 중요하며 특히 배우기 쉬워야 하고 반응속도가 좋고 사용 중 오류의 빈도가 낮아야 하며 사용자를 만족시키고 사용법을 계속 유지해야 하는 점이 강조된다. 이를 모두 만족시키는 것이 이상적이기는 하나 중요한 사항을 선택적으로 충족시키는 경우도 많다. 이에 사용자 요구사항에 대한 우선순위를 고려하여 높은 우선순위부터 사용자 만족을 충족시키는 형태로 개발해야 한다. 이에 사용자 인터페이스 설계는 다음과 같은 목표를 갖는다.

  • 사용자 친화성: 인터페이스는 사용자가 직관적으로 이해하고 사용할 수 있도록 설계되어야 하며 사용자가 복잡한 기능을 쉽게 찾고 사용할 수 있도록 지원
  • 효율성: 인터페이스는 사용자가 작업을 빠르게 수행하고 목표를 달성해야 하며 불필요한 클릭이나 탐색을 최소화하여 작업의 효율성 보장
  • 일관성: 인터페이스 요소들은 일관된 디자인과 동작을 가져야 하며 사용자가 유사한 기능을 다양한 부분에서 일관되게 경험할 수 있도록 작업 
  • 피드백과 가시성: 사용자의 작업에 대한 적절한 피드백과 시각적인 표시를 제공하여 사용자가 자신의 작업을 추적하고 이해할 수 있도록 작업
  • 유연성: 다양한 사용자 요구와 환경을 고려하여 다양한 장치와 환경에서 작동할 수 있는 인터페이스 고려

좋은 사용자 인터페이스 설계는 소프트웨어 제품의 성공과 사용자 만족도에 큰 영향을 미치며 사용자들의 요구와 행동을 고려하여 개발되어야 하는데 보통은 다음과 같은 단계로 진행된다.

  • 요구사항 분석
    • 사용자의 요구사항과 기대를 이해하고 문서화
    • 사용자 그룹을 식별하고, 사용자의 특성, 선호도, 작업 환경 등 파악
    • 시스템의 목적과 기능, 사용자의 목표 정의
  • 설계 및 기획
    • 사용자 경험(UX)을 중심으로 설계
    • 인터페이스의 레이아웃, 구조, 흐름 계획
    • 기능적 요구사항을 각각의 화면 또는 모듈 매핑
    • 정보 구조를 설계하고, 사용자가 쉽게 찾아서 사용할 수 있도록 계획
  • 프로토타이핑
    • 초기 디자인 아이디어를 실제로 시뮬레이션하는 프로토타입 개발
    • 프로토타입을 사용하여 사용자의 피드백을 수집하고, 문제점이나 개선 사항 확인
    • 프로토타입을 통해 디자인과 기능을 검증하며, 수정과 보완 진행
  • 디자인
    • 프로토타입을 기반으로 시각적인 디자인 수행
    • 색상, 아이콘, 글꼴 등을 선택하여 사용자가 시각적으로 쉽게 인터페이스를 이해할 수 있도록 가이드
    • 일관성 있는 디자인 가이드라인을 따르면서 사용자가 헷갈리지 않도록 지침제시
  • 개발
    • 디자인된 인터페이스를 실제 코드 구현
      사용자 인터페이스 요소들을 프로그래밍 언어와 기술을 사용하여 구현
  • 테스트
    • 인터페이스의 기능, 사용성, 성능 테스트
    • 버그, 오작동, 일관성 문제 등을 식별하고 수정
    • 다양한 시나리오와 테스트 케이스를 사용하여 인터페이스 검증
  • 사용자 피드백 수집
    • 완성된 인터페이스를 실제 사용자들에게 제공하고 피드백 수집
    • 사용자의 의견을 수렴하여 인터페이스를 개선 보완
  • 배포 및 유지보수
    • 최종적으로 개발된 사용자 인터페이스 배포
    • 사용자들의 피드백을 기반으로 지속해서 개선과 보완 작업 수행

설계2 (소프트웨어 공학)

소프트웨어 공학에서 구조적 설계는 소프트웨어 시스템을 개발할 때 전체 시스템의 구조와 구성 요소 간의 상호작용을 계획하고 설계하는 단계이다. 이는 소프트웨어 개발 프로세스의 중요한 부분으로 시스템의 복잡성을 다루며 유지보수할 수 있고 확장할 수 있는 소프트웨어 시스템을 만들기 위한 첫 번째 큰 단계 중 하나다. 이러한 구조적 설계는 앞서와 같이 모듈화와 추상화, 모듈 간 인터페이스 설계, 데이터 구조 설계, 제어구조 설계, 자료구조 설계 및 모듈의 응집도와 결합도 등으로 구성되어 있다. 특히 구조적 프로그래밍을 통해 GOTO 문을 최소화하고 대신 조건문과 반복문 등을 사용하여 프로그램 흐름을 명확하게 구조화한다. 이는 코드의 가독성과 디버깅 효율을 높이는 좋은 방법이다. 또한 일반적인 소프트웨어 설계 문제에 대한 해결책으로 사용되는 디자인 패턴을 활용하여 설계의 일관성과 재사용성을 향상한다.

구조적 설계는 소프트웨어의 크기와 복잡성을 관리하고 효율적인 개발 및 유지보수를 가능하게 해주는 중요 단계다. 이를 통해 개발자는 요구사항을 충족하면서도 확장 가능하고 품질 좋은 소프트웨어 시스템을 개발할 수 있다.

 




구조적 설계

구조적 분석은 설계 결과를 구조도로 나타낸다. 구조도는 시스템의 모든 모듈을 사각형의 박스로 표현하며 모듈의 호출 관계를 화살표로 나타내는 계층적 트리 형식의 표이다. 결국 소프트웨어 구조도는 시스템을 어떤 모듈들로 나누었는가를 명시적으로 나타내며 모듈들의 계층구조와 모듈 간 입출력, 인터페이스, 기능을 나타내는 이름들을 보여준다. 이러한 시스템 구조는 전체적으로 치우침 없는 균형을 이뤄야 한다. 그렇지 못한 경우 처리에 병목현상이 발생한다. 균형은 구조도의 폭과 깊이, 입출력 또는 처리 편중, 영향 범위 등에 의해서 결정된다. 시스템 구조도가 불균형인 경우 모듈의 역할이나 규모를 다시 나누어 균형을 이루도록 해야 한다.

구조의 깊이는 시스템 구조도의 레벨 수다. 깊이는 모듈 사이에서 호출하고 반환하는 과정이 길게 이어진다는 뜻이다. 따라서 깊이가 깊어지면 최하위 모듈까지 통신에 대한 부하가 늘어난다. 또한 구조의 넓이는 상위 모듈이 호출하는 모듈의 개수이다. 이를 보통 Fan-out이라 하며 한 모듈에서 호출하는 하위 모듈이 너무 많으면 호출하는 모듈이 제어할 때 병목 현상이 생길 수 있다. 제어의 범위를 너무 크지 않게 하는 것이 운용의 묘를 살리는 것이며 이 또한 매직넘버 7 내외를 유지하는 것이 좋고 이것이 Fan-out 수다. 여기서 호출하는 모듈수를 줄이려면 중간층의 모듈을 몇 개 두어 중간 모듈이 하위 모듈을 호출하도록 한다. 또한 하위 모듈 중 그룹화할 수 있는 모듈이 있거나 다른 모듈 등이 있다면 이를 분리한다.

구조적 설계는 분석 단계에서 생성된 자료 흐름도를 활용하여 소프트웨어 구조를 추출한다. 이에 두 가지 방법으로서 변환분석과 처리분석으로 구조를 추출한다. 

  • 변환분석(Transformation Analysis): 소프트웨어 시스템 내 데이터 변환과 이동을 분석하는 과정으로 시스템 모듈 간 어떻게 데이터가 전달되고 가공되는지를 파악하여 시스템의 데이터 흐름을 이해한다. 이를 통해 시스템의 기능과 동작을 정확하게 파악하고 데이터 변환 과정에서 발생할 수 있는 오류나 문제를 사전에 예측하고 방지할 수 있다. 
    • 데이터 흐름 다이어그램(DFD) 작성: 시스템 내의 데이터 흐름을 그래픽으로 표현하는 도구인 데이터 흐름 다이어그램을 작성한다. 다이어그램은 프로세스, 데이터 저장소, 데이터 흐름 등을 나타내어 시스템의 데이터 흐름을 시각화한다.
    • 프로세스 식별과 정의: 시스템 내의 각각의 프로세스(기능 또는 서비스)를 식별하고, 그들이 어떤 데이터를 입력으로 받고 어떤 데이터를 출력으로 생성하는지를 정의합니다.
    • 데이터 변환 및 가공 분석: 각 프로세스 내에서 데이터가 어떻게 변환되고 가공되는지를 분석합니다. 데이터의 가공 단계에서 발생할 수 있는 오류나 일관성 문제를 식별하고 이에 대한 대비책을 마련합니다.
    • 데이터 저장소 식별과 정의: 데이터 흐름 중간에 위치하는 데이터 저장소(파일, 데이터베이스 등)를 식별하고, 이들이 어떤 데이터를 저장하고 어떤 프로세스에 의해 엑세스되는지를 정의합니다.
  • 처리분석(Transaction Analysis): 소프트웨어 시스템 내에서 발생하는 트랜잭션을 분석하는 과정으로 시스템 사용자와 시스템 간의 상호작용을 이해하고 각각의 트랜잭션이 어떤 데이터와 기능을 요구하며 어떤 결과를 반환하는지를 파악한다. 이로써 시스템의 기능 요구사항을 정확히 파악하고 시스템의 응답 시간과 성능을 평가할 수 있다.
    • 트랜잭션 식별과 정의: 시스템 사용자의 작업 또는 요청을 트랜잭션으로 식별하고 각 트랜잭션이 어떤 데이터와 기능을 요구하는지 정의
    • 트랜잭션의 처리 흐름 분석: 각 트랜잭션이 어떤 프로세스나 모듈을 통해 처리되는지를 분석하며 트랜잭션의 처리 흐름을 파악하여 성능 병목 현상이나 오류 발생 가능성을 예측하고 대비책을 마련
    • 트랜잭션의 성능 분석: 각 트랜잭션의 응답 시간, 처리량 등의 성능을 분석하여 사용자 요구사항을 충족시킬 수 있는지 평가

 




소프트웨어 구조

흔히 스타일이라고 하면 설계와 시공을 위한 큰 밑그림을 그리는데 여기서 일관된 모양과 조화를 뜻한다. 이 스타일을 소프트웨어 구조에서도 사용할 수 있다. 소프트웨어 시스템이 복잡해지면서 시스템의 구조 문제는 더욱 중요해졌는데 왜냐면 일단 개발이 시작되면 이후 잘못된 부분을 바로잡기가 쉬지 않기 때문이다. 이런 문제의 중요성을 인식하여 소프트웨어 구조 개념이 나타났다. 소프트웨어 구조는 시스템 분할, 전체 제어 흐름, 오류처리 방침, 서브 시스템 간 통신 프로토콜을 포함한다. 이에 몇 가지 주요 스타일이 무엇이 있는지 살펴볼 필요가 있다.

  • 저장소 (Repository) 구조: 소스 코드, 문서, 데이터 등의 자원을 중앙 집중화하여 관리하는 구조로 팀원들은 동시에 작업하거나 버전을 관리하며 변경 사항을 추적할 수 있다. 버전 관리 시스템(VCS)인 Git과 같은 도구가 이 구조의 핵심 역할을 수행하며 이를 통해 협업과 코드 품질을 개선하며 변경 내역을 추적하여 문제를 해결하는 데 도움을 준다.
  • MVC (Model-View-Controller) 구조: 소프트웨어를 세 가지 주요 컴포넌트로 분리하여 구조화하는 패턴으로 코드의 재사용성, 유지보수성 및 확장성을 향상하며 시스템의 구성 요소 간의 결합 도를 낮추는 데 도움을 준다. 
    • Model: 데이터와 비즈니스 로직을 관리한다. 데이터의 상태와 조작 방법을 정의하고 시스템의 핵심 기능을 담당한다.
    • View: 데이터를 시각적으로 표현하는 역할을 한다. 데이터를 사용자에게 표시하거나 입력을 받을 수 있는 인터페이스를 제공한다.
    • Controller: 사용자의 입력을 처리하고 Model과 View 사이의 상호 작용을 조정한다. 사용자 요청을 해석하고 적절한 Model 업데이트 및 View 업데이트를 수행한다.
  • Client/Server 구조: 소프트웨어 시스템을 두 부분으로 분할하는 구조로 클라이언트는 사용자 인터페이스와 관련된 작업을 수행하고 서버는 데이터 처리 및 비즈니스 로직과 같은 작업을 수행한다. 클라이언트는 서버에 요청을 보내고 서버는 해당 요청을 처리하여 결과를 반환한다. 이 구조는 분산 처리 및 확장성을 가능하게 하며 다양한 플랫폼과 기기 간의 상호작용을 지원하는 가장 기초적인 구조이다.
  • 계층 (Layered) 구조: 시스템을 여러 계층으로 나누어 각 계층이 특정 기능을 수행하도록 하는 구조로 각 계층은 자신 바로 아래 계층과 상호작용하며 상위 계층은 하위 계층을 직접적으로 몰라도 된다. 이 구조는 코드의 모듈화와 재사용을 촉진하며 시스템의 유지보수 및 확장성을 개선하는 데 도움을 준다.
  • 파이프-필터 (Pipe-Filter) 구조: 데이터 처리를 여러 단계로 나누어 각 단계를 필터로 생각하고 각 단계 간 데이터를 파이프로 연결하여 처리하는 구조로 각 필터는 특정 작업을 수행하며 데이터를 받아 처리한 후 결과를 다음 필터로 전달한다. 이 구조는 시스템의 기능을 모듈화하고 데이터 처리를 효율적으로 관리하는 데 도움을 준다.

설계1 (소프트웨어 공학)

무엇을 개발할 것인가에 대한 요구분석이 끝나면 다음 단계로서 소프트웨어 내부 구조와 자료구조를 설계해야 하는 일이 있다. 소프트웨어는 그 품질을 인정받기 위해서는 요구분석 산출물에 기술된 기능을 잘 수행하도록 설계되어야 하는 중요성을 가지고 있다. 소프트웨어 구조는 소프트웨어 시스템의 골격과 조직이며 이를 설계하는 것은 모든 구성요소인 모듈들을 정의하고 모듈 사이 인터페이스를 정하는 것이다. 이것들이 제대로 설계되지 않는다면 이후 개발, 테스트 및 유지보수 등에 있어서 큰 어려움이 뒤따른다고 봐야 한다. 소프트웨어 설계 작업의 결과는 여러 원리를 토대로 다양한 결과물을 만들어낸다. 구조와 알고리즘, 프로그래밍, 데이터베이스 등 요구분석서와 설계서 사이 설계단계는 구현으로 가기 위한 징검다리이다.

이러한 설계는 창조적인 작업이다. 하지만 원리적 접근이나 체계적 개념이 없는 것은 아니다. 다른 창작 작업도 일정한 틀과 원리가 적용된다. 소프트웨어를 설계하는 과정에서도 설계 기법과 많은 도구가 쓰인다. 특정한 설계기법의 선택이 품질 좋은 소프트웨어를 만드는 데 필수 요건은 아니다. 다만 설계 기법을 잘 적용하면 소프트웨어 설계는 더 개선된다. 

 




설계

앞선 요구분석서는 시스템 문제를 해결하기 위한 기술서이다. 설계는 분석서에 기술된 문제를 해결 방안으로 변경하는 작업이다. 분석과 설계. 완성된 설계는 요구를 만족시키는 특정한 솔루션이다. 문제를 정의하기 위해서 요구명세서를 작성하고 문제에 대한 솔루션을 만드는 설계 방안은 이에 제한받지 않는다. 즉 설계는 여러 가지 대안 중 여러 가지 제약 조건을 잘 만족시킬만한 하나의 솔루션을 선택하는 것이다. 이런 설계는 사용자와 개발자를 동시에 만족시켜야 하는 책임과 의무가 있다. 사용자는 설계를 보고 시스템이 어떤 기능을 하는지 이해하고 개발자는 시스템이 어떻게 동작하는지 이해하여야 한다. 

일정 규모 이상의 소프트웨어 설계는 다음과 같은 분류를 해볼 수 있다.

  • 소프트웨어 구조설계: 전체 시스템을 구성하는 서브 시스템과 관계를 파악
  • 인터페이스 설계: 서브 시스템 사이 인터페이스 설계 및 정의
  • 자료저장소 설계: 파일, 데이터베이스 설계
  • 프로그램 설계: 시스템 컴포넌트인 모듈, 알고리즘 설계
  • 사용자 인터페이스 설계: 메뉴, 화면, 입출력 양식 등 설계

 




설계 원리

소프트웨어 개발 방법의 근간인 개념과 원리로서 방법은 상황에 맞는 것을 적절하게 적용해야 한다. 구조적 설계는 구조적 분석의 ‘형식은 기능을 따른다’는 원리를 일관되게 적용한다. 자료흐름도에서 프로세스들의 패턴은 시스템의 구조를 결정한다. 여기서 분할과 정복이 사용되고 반복한다. 이러한 설계의 중심이 되는 원리들이 몇 가지가 있다.

✔️ 추상화(Abstraction)

추상화는 자세한 사항보다는 근본적 본질에 집중하는 것을 말한다. 다시 말해 자세한 사항은 처음부터 다루지 않고 전체적이고 포괄적인 개념부터 차례대로 세세하게 세분화함으로써 구체화해 나가는 것이다. 이러한 추상화는 어떤 결과가 얻어져야 하느냐는 명세화 관점을 어떻게 달성할 것인가라는 구현관점과는 별개로 하여 설계 작업에 좀 더 집중할 수 있게 만든다. 소프트웨어 설계에서의 대표적 추상화는 기능 추상화, 자료 추상화 및 제어 추상화가 있다.

  • 기능 추상화: 입력자료를 출력자료로 변환하는 과정의 추상화
  • 자료 추상화: 자료와 자료에 적용할 수 있는 기능을 함께 정의하여 자료 객체를 구성
  • 제어추상화: 프로그램의 제어 흐름을 추상화하여 코드의 모듈화와 구조화를 촉진 

 

✔️ 정보은닉(Information Hiding)

설계된 각 모듈은 자세한 처리 내용이 시스템의 다른 부분으로부터 감춰져야 한다는 것이 정보은닉이다. 즉 모듈 안의 내용을 보여주지 않고 잘 정의된 인터페이스를 통해 메시지를 전달하는 개념인데 설계상 모든 결정 사항들이 모듈 안에 감춰져서 다른 모듈이 접근하거나 변경하지 못하도록 하는 것이다. 이는 모듈화의 기준으로도 사용이 가능하며 이에 따른 모듈의 구현은 독립적이며 설계 과정에서 하나의 모듈이 변경되어도 다른 모듈 설계에는 영향을 주지 않는 장점이 있으며 모듈의 이해도도 높일 수 있다.

 

✔️ 단계적 분해

문제를 상위 개념부터 더 구체적인 단계로 하향식 분할하는 개념으로 보통 4가지 과정을 거친다. 먼저 문제를 기본 단위로 나누고 이를 독립된 문제로 구별한다. 이후 구분된 문제의 자세한 내용은 가능한 뒤로 미뤄두고 구체화 작업이 계속 점증적으로 일어난다는 것을 보여준다. 이러한 단계적 분해는 소프트웨어를 이루는 모듈에 대한 구체적 설계를 수행할 때 주로 사용된다. 단계적 분해는 문제를 해결할 만한 작은 문제로 나누고 구체화의 정도를 작게 하여 점증적으로 문제를 다루어 나가는 것이다. 구체적인 설계 결정을 뒤로 미룰 수 있고 조금씩 변경되므로 일관성을 유지 할 수 있는 장점이 있다.

 

✔️ 모듈화

소프트웨어 구조를 이루는 기본적인 블록이 모듈이다. 이 모듈이 구체적으로 어떤 단위를 말하는 것인가에 대해서는 일치되는 정의는 딱히 없다. 그러나 여러 개의 독립적인 프로그램으로 구성된 복합 시스템의 경우에는 시스템 설계 단계에서 모듈은 기능적으로 관련된 여러 개의 프로그램, 함수, 부프로그램의 묶음이기도 하고 추상화된 자료나 병행 처리 프로세스도 모듈로 불린다. 이 모듈의 공통 개념은 수행 가능 명령어, 자료 구조 또는 다른 모듈을 포함하고 있는 독립 단위이다. 모듈은 이름을 가지고 있으며 독립적으로 컴파일이 되고 다른 모듈을 사용할 수도 있으며 다른 프로그램에서 사용될 수도 있다. 

모듈의 크기는 다양하다. 일반적으로 쉽게 이해될 수 있을 정도로 작아야 한다는 데 동의한다. 이런 모듈은 모듈을 이루는 각 요소가 공통의 목적을 달성하기 위해 얼마나 관련이 있는가를 나타내는 응집력을 갖는다. 즉, 응집력은 모듈 안의 요소들이 서로 관련된 정도를 말하며 모듈 설계의 목표는 강력한 응집력을 갖는 모듈을 만드는 것이다. 이러한 모듈 안에서 응집력의 정도를 마이어스는 일곱 가지 단계로 구분했는데 응집력이 강한 것부터 약한 것까지 ‘기능적 – 순차적 – 교환적 – 절차적 – 시간적 – 논리적 – 우연적’ 으로 나열할 수 있다.

모듈의 응집도와 같이 이야기되는 것이 결합도 이다. 결합도는 모듈 간 상호 의존하는 정도를 말하는데 모듈은 하나의 블랙박스로 다른 모듈과의 독립성이 높아야 한다. 이런 독립적 모듈이 되기 위해서는 다른 모듈과의 결합도가 약해야 하며 의존하는 모듈 또한 적어야 한다. 모듈 사이 의존하는 정도는 결합도가 강한 것부터 약한 것까지 ‘내용 – 공통 – 제어 – 스탬프 – 자료’ 결합으로 나열할 수 있다.




구조적 분석 (소프트웨어 공학)




구조적 분석

소프트웨어 개발에 있어 요구분석 단계는 중요하고도 어려운 단계이다. 많은 정보가 수집되어야 하며 의사소통의 어려움도 극복해야 하는 숙제 중 하나다. 이러한 작업을 증명하기 위한 방법은 매우 다양하다. 그중 프로세스 사이의 데이터 흐름을 파악하여 요구사항과 시스템을 파악하는 방법으로 구조적 분석이 있다. 구조적 분석(Structural Analysis)은 시스템의 기능적 요구사항을 구조화하고 조직화하는 단계이다. 이를 통해 요구사항 간의 관련성과 의존성을 이해하고 분해된 요구 모듈 간 관계를 분석하여 시스템의 구조를 설계할 수 있다. 구조적 분석은 데이터 흐름 다이어그램(DFD), 상태 전이 다이어그램, 클래스 다이어그램 등의 모델링 기법을 활용하여 수행된다. 전통적 방법으로서 이 단계에서는 요구사항이 어떻게 상호작용하고 구성되는지를 시각화하여 파악한다.

소프트웨어 개발 프로젝트 초기 단계부터 요구사항을 명확하게 이해하고 효과적으로 관리할 수 있는 구조적 분석은 궁극적으로 프로젝트의 성공 확률을 높일 수 있다. 이 방법은 크게 다음과 같은 단계로 수행되고 여기에 쓰이는 도구도 확인한다.

  • 요구사항 분해
  • 요구사항 상호 연계
  • 요구사항 계층 구조화
  • 요구사항 흐름도

 

  • 데이터 흐름도(Data Flow Diagram, DFD):
    • 사용자 요구사항 기반으로 데이터가 시스템 내에서 어떻게 흐르는지 도식화하며 프로세스(원 또는 둥근 사격형), 외부 엔티티(사각형), 저장소(열린 사각형), 데이터 흐름(화살표) 등을 기호로 하여 시스템 데이터 흐름을 구조화
    • 시스템 모델링에 중요한 추상화와 단계적 분해의 원리를 적용하여 하향식 분할을 통해 복잡한 문제를 작고 독립적 문제로 나누어 하나씩 해결할 수 있는 방법으로 접근
    • 서로 다른 단계 사이 자료 흐름은 표현에 일관성이 필요하고 완벽성 검사와 일관성 검사 시행
    • 크기가 너무 커진다면 프로세스를 그룹화하여 단계적으로 표현하며 하나의 분석에서 한 계층의 DFD만 작성하고 프로세스는 7개 전후로 포함되도록 함
  • 자료 사전(Data Dictionary): 시스템 내에서 사용되는 데이터 항목의 정의, 형식, 구조를 문서화하며 자료 사전은 데이터 항목들의 호환성과 일관성을 확인하고 중복을 제거
    • 일반적 언어사전과 형식은 동일
    • 자료요소 이름이 여러 단어 구성 시 자료사전 표제어에 밑줄 연결
    • 수식은 자료요소와 연산자(+, [], |, ”, 등)로 구성
  • 질의-응답 목록(Question and Answer List): 사전에 정해진 항목에 따라 요구사항을 구체화하는 도구로 시스템과 사용자의 상호작용을 정확하게 이해하고 구조화
    • 질문: 이해 관계자에게 특정 요구사항에 관한 질문 포함
    • 답변: 이해 관계자로부터 받은 답변 기록. 이 답변은 해당 요구사항에 대한 정보와 이해 관계자의 의견 표시
    • 질의자: 각 질문에 대한 원래 질문자 또는 요구사항 분석을 수행한 사람의 이름 기록. 의문 사항이 생길 경우 해당 정보의 출처 확인용
    • 날짜: 각 질문이나 답변이 만들어진 날짜 기록. 문서 갱신/추적용
    • 참고: 다른 문서나 자료와의 연결 표시
    • 상태: 질문이나 답변의 상태 표시, 추적
    • 비고: 해당 질문이나 답변에 대한 추가 설명이나 주석 기록
  • 유스케이스(Use Case): 사용자와 시스템 간의 상호작용을 나타내는 시나리오 기반 기술로 특정 목적 달성을 위한 사용자 관점에서 시스템과의 상호작용 과정 기술
    • 액터(Actor): 시스템 내에서 주요 기능을 수행하는 역할 또는 시스템과 상호작용하는 주체로 시스템 사용자, 다른 시스템, 외부 장치 등
    • 유스케이스 명(Use Case Name): 특정 기능 또는 시나리오의 간결하고 명확한 이름으로 유스케이스를 식별
    • 설명(Description): 유스케이스의 목적과 내용을 간단 설명
    • 사전조건(Preconditions): 유스케이스가 시작되기 전에 충족되어야 하는 조건 설명
    • 주요 시나리오(Main Scenario): 유스케이스의 핵심적인 동작과 순서 설명으로 시스템과 액터 간의 상호작용을 순차적으로 나열
    • 대안 시나리오(Alternative Scenarios): 주요 시나리오 이외의 다양한 상황에 대한 시나리오를 설명하며 주로 예외 상황이나 오류 처리 사용
    • 결과(Results): 유스케이스의 완료 후 기대되는 시스템의 상태 변화나 출력물 등 결과 기록

 




분석 과정

구조적 분석의 세부적인 과정은 크게 4단계로 나눠볼 수 있다. 

🚩 단계 1: 요구사항 수집 및 문서화

시스템에 대한 요구사항을 수집하고 구조화 및 문서화한다. 이 요구사항은 고객, 사용자, 도메인 전문가 등과의 인터뷰, 설문조사, 관찰 등 다양한 방법으로 얻을 수 있으며 최종적으로 기능적 요구사항(시스템이 수행해야 하는 작업)과 비기능적 요구사항(성능, 안전성, 보안 등)으로 구분될 수 있다. 이 과정을 통해 모호한 내용을 명확히 하고 요구사항 간의 관련성과 의존성을 파악, 중복되거나 충돌하는 요구사항을 논리적 블록으로 그룹화, 해결한다.

 

🚩단계 2: 데이터 흐름 다이어그램 작성

명세화된 요구사항을 기반으로 소프트웨어의 핵심 문제를 파악하고 분석할 수 있는 구조로 정리한다. 이때 데이터 흐름도(DFD), 자료사전, 프로세스 명세 등의 도구를 활용한다.

  – 주요 프로세스 식별: 수집된 요구사항을 기반으로 시스템 내의 주요 기능적 프로세스 식별하며 DFD로 표현 (시스템의 입력, 출력, 처리 과정 포함)
  – 데이터 흐름 식별: 프로세스 간에 주고받는 데이터(정보) 흐름 식별
  – 데이터 저장소 식별: 시스템 내 사용되는 데이터 저장소를 식별하는데 이는 데이터의 정의, 속성, 구조 등을 포함하고 이를 데이터 요소 간의 관계와 종속성을 파악

 

🚩단계 3: 데이터 흐름 다이어그램 작성 및 분석

분석된 요구사항이 사용자의 기대와 일치하는지 검증하여 문제가 없는지 확인하는 단계로 사용자와 지속적인 의사소통으로 유스케이스 테스트나 프로토타입 방식을 사용하여 실제 사용자의 반응을 수집할 수 있다. 특히 요구사항과 부합하며 일관성 있는 모델을 구축하는 것이 중요한데 이 결과를 바탕으로 소프트웨어의 전체적인 아키텍처를 설계할 수 있다. 특히 모듈화, 계층화, 컴포넌트 구조 등을 고려하여 시스템 구조를 결정한다.

  – 0레벨 DFD 작성: 주요 프로세스, 데이터 흐름, 데이터 저장소 등을 기반으로 0레벨 DFD를 작성하며 이 다이어그램은 시스템의 전체 구조를 보여주고 각 프로세스와 데이터 흐름의 관계를 가시화
  – 상세화: 0레벨 DFD를 기반으로 더 상세한 1레벨 DFD를 작성하여 프로세스를 세분화하고 데이터 흐름을 더욱 구체적으로 표현
  – 유효성 검사: 작성한 DFD를 검토, 논리적 오류나 모순점이 있는지 확인 

 

🚩단계 4: 문서화 및 의사소통

작성한 DFD를 문서화하여 요구사항 명세서나 설계 문서에 포함한다. 이에 개발팀 간 의사소통을 원활하게 하고 시스템 구조를 이해하는 데 도움을 준다. 요구사항이 변경되거나 갱신이 되면 요구사항 관리를 통해 변경된 요구사항에 따른 작업의 우선순위를 조정하고 추적 관리한다. 이 문서들은 개발 및 테스트 과정에서 참고 자료로 활용한다. 다시 말해 문서화와 의사소통의 중요성은 각기 다음과 같다.

  • 명확한 이해: 문서화로 프로젝트팀의 구성원, 고객, 스테이크 홀더 등 모두가 요구사항을 명확하게 이해 가능
  • 기능 및 범위의 정의: 문서화로 시스템의 기능과 범위가 정확하게 정의되며 프로젝트 방향성 보장
  • 변경 관리: 요구사항이 변경될 경우, 문서화로 변경 내역을 추적하고 관리 가능
  • 품질 향상: 문서화된 요구사항은 개발자들이 시스템을 설계하고 구현할 때 일관성 있고 정확한 정보를 참조할 수 있도록 지원

 

  • 이해 관계자 간의 의사소통: 프로젝트 구성원, 고객, 이해당사자 간 이해로 프로젝트 목표를 달성하기 위한 방향을 정하는 중요 기반
  • 오해 방지: 의사소통으로 모든 이해 관계자들이 동일한 의미로 요구사항을 이해할 수 있도록 지원하여 오해나 혼란이 줄어들면서 프로젝트 품질 향상
  • 피드백 수렴: 의사소통을 통해 고객이나 사용자의 피드백을 수렴하고 반영하여 요구사항의 정확성과 적절성 향상
  • 변경 관리: 프로젝트 진행 중 요구사항이 변경 시 이를 이해 관계자들과 공유하여 일관성을 유지하고 변경에 따른 영향을 평가 가능




요구분석 (소프트웨어 공학)

소프트웨어 공학에서 요구분석은 소프트웨어 개발 프로세스의 초기 단계에서 매우 중요하고 가장 어려운 부분 중 하나다. 그 이유는 요구분석 외 다른 작업은 만약 잘못되었을 때 비교적 적은 비용으로 오류를 수정, 보완할 수 있으나 요구분석의 경우에는 처음부터 다시 개발해야 하는 비용이 증가하고 개발기간은 늘며 소프트웨어 품질 저하의 직접적 원인이 되기 때문이다. 요구분석은 사용자 및 이해관계자와의 의사소통을 통해 시스템의 기능, 성능, 제약조건 등을 명확하게 이해하고 시스템이 충족해야 할 기능적 요소와 비기능적 요소를 파악, 정제하여 적절한 시스템 설계와 구현 기초를 다지는 과정이다. 이는 프로젝트의 성패를 좌우하는 결정적 요소로, 보다 정확하고 완전한 요구사항을 수집하고 분석하는 과정을 포함하며 이를 통해 시스템의 목표와 범위를 확실히 하여 성공적인 소프트웨어 개발을 돕는다.

다시 말해 요구분석은 다음과 같은 이유로 소프트웨어 개발에서 매우 중요하며

  • 소프트웨어 시스템의 개발, 구현, 테스트, 유지보수의 모든 단계에서 요구사항 참조
  • 소프트웨어 시스템의 개발 비용 절감 가능
  • 소프트웨어 시스템의 개발 기간 단축 가능
  • 소프트웨어 시스템의 품질 향상 가능

요구분석을 통해 얻을 수 있는 이점은 다음과 같다.

  • 소프트웨어 시스템 개발 목표 및 범위 명확화
  • 소프트웨어 시스템 기능/비기능 요구사항 명확화
  • 소프트웨어 시스템 테스트 사항 명확화
  • 소프트웨어 시스템 개발, 테스트, 유지보수에 드는 시간 및 비용 절약
  • 소프트웨어 시스템 성공적인 개발 보장

이러한 요구분석의 과정은 크게 요구, 요구추출 및 분석, 구조적 분석, 요구분석 명세로 구분할 수 있다. 이 단계들을 철저히 수행하여 프로젝트 초기부터 요구사항에 대한 명확한 이해와 관리가 가능하고 개발 프로세스의 효율성과 최종 제품의 품질 향상에 기여하여 소프트웨어 시스템의 성공적 개발을 보장받는다. 

 




요구(Requirement)

요구는 시스템이 외형적으로 나타내는 기능, 성능, 품질, 인터페이스, 환경, 보안, 유지보수, 제약사항 등의 동작을 말한다. 요구는 사용자, 고객, 시스템 이해관계자들로부터 도출되는데 명시적이고 모호하지 않으며 변하지 않는 특성을 가져야 한다. 이를 통해 소프트웨어 개발팀은 프로젝트의 목표와 범위를 파악할 수 있다. 이런 요구는 기능적 요구와 비기능적 요구로 크게 구분되며 기능적 요구는 시스템의 기능이나 동작에 관련된 것이고 비기능적 요구는 성능, 안전성, 보안 등과 같은 품질 속성에 관련된 것이다.

  • 기능적 요구: 시스템이 수행해야 할 특정 작업이나 기능에 대한 요구로 웹 서비스의 경우 사용자 등록, 로그인, 상품 검색 등의 기능을 말함
    • 시스템이 무엇을 언제 그 일을 하는가?
    • 시스템 운영 시 여러 다른 모드가 존재하는가?
    • 시스템이 언제 어떻게 변경 또는 확장되는가?
  • 비기능적 요구: 시스템이 충족시켜야 할 성능, 안정성, 사용성, 유지보수성 등과 같은 운영적, 환경적 제약 조건들로 응답 시간, 동시 접속자 수, 확장성 등이 포함
    • 시스템의 속도, 반응시간, 처리율, 처리자료 크기
    • 시스템 가동 평균 시간, 중단 후 복구시간
    • 시스템 설계변경 용이성, 용적률

그래서 요구는 매우 잘 정의되어야 하며 충분히 구체적이고 명료하여 개발자들이 이를 이해하고 작업에 착수할 수 있게 도움을 줄 수 있어야 한다.

 




요구추출 및 분석

요구추출은 소프트웨어 개발에서 특히 중요한 작업이다. 사용자가 무엇을 원하는지 결정을 내리는 작업으로서 이해관계자와의 대화, 설문 조사, 브레인스토밍, 워크숍 등의 여러 방법을 사용하여 요구를 도출한다. 요구추출 후에는 요구사항을 분석하고 중복, 모호성, 불일치 등을 식별하고 정제한다. 이 과정에서 중요한 것은 사용자의 실제 기대에 부합하도록 정확하게 요구사항을 파악하는 것이다. 요구추출이 잘못되면 소프트웨어 시스템이 사용자의 요구를 충족하지 못하거나, 개발 비용이 증가하거나, 개발 기간이 늘어나거나, 소프트웨어 시스템의 품질이 저하될 수 있다.

이러한 요구추출은 크게 3가지 우선순위를 따지는데 첫째는 절대적으로 필요한 요구인가? 둘째는 꼭 필요하지 않은 요구인가? 셋째는 요구로 판단되나 제외할 수 있는가? 이다. 그러면서 다음 사항을 고려해야 한다.

  • 사용자 요구의 정확한 이해
  • 요구사항 명확성과 간결성
  • 요구사항 완결성과 일관성
  • 요구사항 실행 가능성

요구추출 후 진행하는 요구분석에 있어 가장 중요한 것은 사용자가 현재 안고 있는 문제점을 이해하는 것이다. 이에 분석가는 사용자의 입장에서 현황을 파악하고 사용자가 원하는 문제 해결이 무엇인지 이해하여야 한다. 즉 수많은 정보를 수집하고 재구성하는 데 있어 ‘육하원칙’에 따라 질문하고 답을 구하는 단계가 요구분석이라고 볼 수 있다. 이러한 질문을 통해서 사용자의 문제를 이해할 수 있고 해결 방법을 찾는 데 도움을 받을 수 있다. 또한 해결 과정에서의 제약점과 이를 사용자가 수용할 수 있는지도 살펴야 한다. 특히 구체화한 목표가 명확해야 한다.

  • 분석 대상 업무에 누가 관계되어 있는가? 그들은 누구인가? 어떤 일을 하는가?
  • 현재의 상태는 어떠한가? 문제가 있는가? 요구 기능은 무엇인가?
  • 신규 시스템은 언제 완료되어야 하는가? 언제 교체하는가? 
  • 신규 시스템을 어떤 환경으로 운영할 것인가? 인력은 어떻게 배치하는가?
  • 왜 신규 시스템을 고려하였는가? 개선하고자 하는 이유는?
  • 신규 시스템은 어떻게 작동되어야 할 것인가? 작동의 제약사항은 무엇인가?

이러한 요구분석에는 구조적 분석, 객체지향 분석, 정보공학 및 정형화 방법 등 여러 기법이 존재한다.

 




구조적 분석

구조적 분석은 시스템의 기능적 요구사항을  분해하고 구조화하여 조직화하는 단계다. 이를 통해 요구사항 간의 관련성과 의존성을 이해하고 시스템의 구조를 설계할 수 있다. 구조적 분석은 문제 영역을 이해하기 위해 데이터 흐름 다이어그램(DFD), 상태 전이 다이어그램, 클래스 다이어그램 등의 모델링 기법을 활용하며 요구사항이 어떻게 상호작용하고 구성되는지를 시각화한다. 구조적 분석은 보통 다음과 같은 단계로 수행한다.

  • 요구사항 분해
  • 요구사항 상호 연관
  • 요구사항 계층 구조화
  • 요구사항 흐름도 작성

이런 단계를 통해 현재 시스템과 목표 시스템의 모형이 만들어진다. 일반적인 모형들은 정보나 아이디어를 추상화하여 집약적으로 나타내며 시스템 구성 요소들의 상호 작용과 기능들을 표현하여 사용자의 이해를 돕는다. 이는 건축과 같이 철저히 양식이 기능을 따르는 원리를 적용한다.

 




요구분석 명세

문제를 명확히 이해하고 목표가 정해지면 문서화가 필요하다. 요구분석 명세는 수집된 요구사항을 정확하게 문서화하는 것을 말하며 이 과정에서는 요구 사항들에 대한 정규화, 우선순위 정하기, 추적 행렬 생성 등이 이뤄진다. 이를 통해 개발자, 테스터 및 다른 이해관계자들이 이를 이해하고 활용할 수 있도록 한다. 이 문서는 요구사항의 상세 내용과 우선순위, 변경 요청 프로세스 등을 포함하고 시스템 설계 및 구현의 입장에서 충분한 정보를 제공, 개발자와 관계자들이 이해할 수 있는 언어로 아주 명료하게 작성하여 이후 개발 및 테스트 단계에서 참조되는 중요한 자료이다.

요구분석 명세(Software Requirement Specification)는 소프트웨어 개발 모든 단계에서 중요한 역할을 수행하며 보통은 다음과 같은 내용을 포함하며

  • 시스템의 목적
  • 시스템의 기능
  • 시스템의 성능과 품질
  • 시스템의 인터페이스
  • 시스템의 환경
  • 시스템의 보안
  • 시스템의 유지보수

그 평가 기준은 아래와 같다.

  • 무결성/완벽성: 사용자의 요구사항을 오류 없이 완벽하게 반영
  • 일관성: 상호 간 모순 없이 존재
  • 명확성: 여러 의미로 해석되지 않음
  • 기능적: ‘어떻게’가 아닌 ‘무엇’에 초점
  • 검증가능성: 사용자 요구 만족과 시스템 일치성
  • 추적 가능성/변경 용이성: 체계적 정리

 

프로젝트 계획 (소프트웨어 공학)

프로젝트 문제와 범위 정의

소프트웨어 개발 시 일정이 지연되거나 비용이 초과고 기대했던 품질에는 못 미치는 산출물, 그에 따라는 여러 유지비용의 증가 등과 같은 문제들은 기본적으로 계획의 부재에서 오는 경우가 많다. 개발 일정을 준수하면서 질 좋은 소프트웨어를 개발 생산하기 위해서는 정밀하고 세심한 계획수립이 필요하다. 소프트웨어 개발 프로젝트 초기 단계에서 프로젝트의 목표를 기반으로 여러 불분명한 사안들을 확인해 가면서 계획을 수립하는 것은 매우 어렵다. 하지만 계획작업을 통해 불분명한 목표, 사용자 요구사항 및 제약사항 등을 명확히 하는 것이 필요하다. 이러한 계획은 보통 문제의 범위를 확인, 정의하고 필요한 활동들을 정하며 세부적인 일정계획과 비용을 추정하고 최종적으로 계획서를 작성하는 절차로 이뤄진다. 

다시 말해 프로젝트 계획은 대상업무와 문제들을 고객이 이해하는 용어로 정확하기 정의하고 기술하는 것으로 시작한다. 문제는 철저하게 고객의 입장에서 정의되어야 하며 기술관련 전문용어 등을 사용해서는 안된다. 문제를 정의하는 것은 범위를 정하는 것이다. 이는 개발대상의 기능, 성능, 제약조건, 인터페이스 등의 프로젝트에 대한 타당성과 신뢰성 및 초기 계획을 작성가능한가에 대한 판단 근거로 쓰인다. 문제 정의는 제일 먼저 그 배경을 이해하여야 한다. 이를 위해선 고객과의 면담, 현장답사 및 실제 업무를 수행하는 실무자의 실제 업무를 관찰하거나 직접 수행을 해보기도 한다. 그러면서 객관적 시각에 문제를 파악한다. 이 모든 것이 끝나면 문제 해결을 위한 준비를 한다.

 




일정 계획

일정은 프로젝트 개발에 있어 모든 프로세스를 구성하는 작업들을 파악하여 그 우선순위와 기간을 산정하며 진행한다. 이에 모든 작업들을 수준별로 나열을 하며 산출물이 있다면 각각 기술해 준다. 프로젝트의 규모가 작다면 큰 일이 아닐 수도 있으나 대규모의 프로젝트에서는 작업도출과 더불어 각 작업들 간의 상관관계를 면밀히 검토하여야 한다. 이때 보통은 PERT/CPM을 활용하며 최종적으로 간트차트 등을 사용하여 거시적 관점에서의 일정을 관리할 수 있도록 한다. 이렇듯 소프트웨어 공학은 엔지니어링 작업으로서 정확하고 현실적인 계획을 수립하고 작업 수행에 소요되는 여러 자원들을 최적화하여야 한다. 이에 따라 프로젝트의 진척도를 실시간으로 점검할 수 있고 계획과 비교하여 문제가 있을 시에 다방면의 조치로 문제해결이 가능하다.

간트차트로 보여지는 프로젝트 작업들, 일정표는 그 수준에 맞춰 분해가 이뤄지고 계층적으로 구성하여야 하는데 이를 위해 WBS(Work Breakdown Structure)를 사용한다. 이는 작업들이 모여 소요 일정이 예측되며 이를 통해 프로젝트 전체 일정을 예측할 수 있다. WBS는 큰 단위의 업무를 관리하기 쉬운 작은 단위의 작업으로 나누기 위한 도구이다. 여기서 관리 가능한 작은 작업들은 업무 지시를 하는 단위가 되며 작업시작일, 종료일, 소요기간, 담당자, 필요 자원 등을 병기하여 관리한다. WBS는 일정계획 작업의 입력값이며 작업 분해는 프로젝트가 어떤 작업으로 구성되었는지를 알아내는 것이고 일정 계획은 이들 작업을 어떤 순서로 할 것인가를 정하는 일이다.

  • 소프트웨어 개발모형 선정, 단계별 작업을 분해 후 작업결과 정의
  • 각 작업간 상호의존관계 정리
  • 각 작업소요기간 정의 및 프로젝트 완료에 필요한 최소기간 산출
  • 프로젝트 규모추정을 통한 M/M 산출
  • 확정 결과 정리 및 공유

 




비용 추정

소프트웨어 개발에 있어 비용을 정확히 예측하기는 매우 어려운 일이다. 특히 계획단계에서는 불분명한 사항들이 많고 여러 환경적인 요소로 비용에 대한 입장차도 존재한다. 그럼에도 불구하고 기준을 바탕으로 수립되는 소프트웨어 개발 비용예측은 특히 투입되는 개발자와 기간에 매우 큰 변수로 작용한다. 이에 과거 프로젝트의 경험이 중요하며 특히 유사 프로젝트가 있다면 규모와 비용, 인력들을 감안하여 예측을 어느 정도 가능하게 한다. 그러므로 정확한 예측은 프로젝트 성공율을 높이는 필수 조건이다. 이에 비용 예측방법도 매우 다양하며 인건비의 경우 소요기간을 기준으로 하거나 프로그램 규모를 기준하는 방법으로 크게 나뉜다.

첫번째 방법은 소요기간 기준이다. 이는 프로젝트 내 작업들에 소요되는 기간을 구하고 여기에 투입인력과 참여도를 반영하여 최종 인건비를 산출한다. 이 방법은 상향식이라 불리우며 단순히 헤드카운팅이라고도 하는데 시스템 개발에 필요한 모든 작업에 대한 노력들을 하나하나 계획할 수 있는 장점이 있으나 객곽적이 못한 추정 가능성이 있을 수 있다. 두번째 방법은 하향식으로 프로그램 규모를 추정하고 과거 경험을 바탕으로 예측 규모에 대한 소요인력과 기간을 추정한다. 프로그램 규모는 원시코드의 라인수(LOC)나 시스템의 기능을 정량화한, 좀더 복잡한 기능점수(Function Point) 등올 산출할 수 있다. 

 




조직 구성

경영관리에서 조직이란 개개인의 역할을 잘 정의하고 할당하여 프로젝트 목표 성취를 하기 위한 것이다. 이는 기업이나 단체 등 다수의 사람이 모여서 하나의 목표를 이루기 위한 방안으로 조직이 생겨난 것이다. 이러한 조직 구성의 목적은 공통된 목표를 위하여 상호 협력을 하는 것으로 프로젝트에서도 동일하게 적용된다. 이런 조직구성은 조직의 생산성과 효율에 얼마나 많은 영향을 미치고 그 결과가 어떻게 나타나냐에 대한 근본 원리를 따진다. 소프트웨어 개발 프로젝트에서 소프트웨어는 타 제품과는 다른 특징들로 인해 어떠한 조직을 구성하여 진행했느냐에 따라 소프트웨어 개발에 많은 영향을 미친다. 즉 소프트웨어의 품질을 향상시킬 수 있는 소프트웨어의 특성을 잘 살린 조직 구성이 필요한 것이다.

조직의 선택에 영향을 주는 요소는 비용 예측에 사용되는 요소와 유사하다. 알맞은 조직 구성은 프로젝트 기간과 매우 밀접하다. 장기 프로젝트의 경우 구성원들의 사기를 높이고 이직과 이탈을 막기 위하여 개개인의 만족도가 중요 시 된다. 경험이 많은 인력과 적은 인력이 적절하게 섞여야 하며 상호 간 배우고 배울 수 있는 관계 설정도 필요하다. 대규모 프로젝트의 경우 요구의 변경과 명세가 어려운 특성으로 인하여 프로젝트 후반에 신규 인력을 투입하면 일정은 그만큼 지연된다. 이는 인력 상호 간 의사소통의 통로 이슈와 기존 업무의 인수인계 등에 따른 시간을 고려한다고 해도 해소되지 않는 난제이다. 다시 말해 작업의 특성과 조직 구성원 사이의 의사소통의 횟수는 조직의 규모에 맞춰야 하며 필요 이상의 결과에 집중하지 않게 적정 선을 지키는 것이 중요하다.

프로젝트 팀 구성에 영향을 주는 다른 요소는 작업의 특성 및 팀 구성원 사이에 의사교류의 횟수이다. 의사소통이 원활할 수 있는 조직규모와 인력수는 매우 밀접하며 프로젝트의 복잡도와도 긴밀하다. 이에 공식적인 모형과 인원수도 산출할 수 있는데 중요한 것은 생산성에 촛점을 맞춘 균일한 규모의 조직을 구성하는 것이다. 이 규모는 소프트웨어의 특성과도 연계가 되며 팀은 원칙적으로 작업 수행에 제일 타당하게끔 조직되어야 한다. 그러기 위해선 관리자의 권한과 더불어 일정, 예산, 품질 등 여러 요소를 고려하여 조직 구성방법을 결정하여야 한다. 특히 소프트웨어 개발 팀구성은 의사결정권이 누구에게 있느냐에 따라 구별되며 리더의 역할, 권한, 의무에 따라 크게 3가지 형태의 구성방식을 갖는다.

  • 중앙집중형: 하나의 관리자의 지휘에 따라 움직인다. 기업 조직 내 일반적인 계층형 조직으로 상하관계가 명확하여 대규모 조직보다는 소규모 조직에 적합하고 이의 모듈화로 규모를 키울 수 있다.
  • 분산형: 의사결정을 민주주의식으로 하며 모든 작업은 공동의 작업이다. 팀 구성원 각자가 서로의 작업을 검토하고 타 구성원의 작업결과에 대하여 책임을 진다. 다만 의사소통 비용이 많이들며 이에 따른 생산성 문제가 있다.
  • 혼합형: 중앙집중형과 분산형의 단점을 보완하기 위해 구성된다.

 




위험분석

위험 분석은 프로젝트에 내재한 위험 요소를 인식하고 그 영향력을 분석하여 관리하는 활동이며 프로젝트를 성공시키기 위하여 위험 요소를 사전에 예측, 대비하는 모든 기술과 활동이 포함된다. 위험 요소에 대해 적절히 관리하지 못하면 프로젝트는 실패할 수 있다. 초기 단계에 위험 요소를 인식하고 그 영향을 분석하였어도 이를 다루는 일관성 있는 계획이 없으면 실패하기 쉽다. 이러한 위험을 줄이는 효과적인 방법은 프로토타이핑이나 점증적 개발 방법 있으며 중간 변경 위험을 대비하기 위한 모듈화도 생각해 볼 수 있다. 

< Boehm(Barry William Boehm, 미국 소프트웨어 엔지니어 및 교수, 나선형 모델 제)이 제시한 10가지 위험 요소와 관리 기법 >

  • 인력부족: 유능한 인력 수급, 팀구성, 교육
  • 비현실적 일정/예산: 구체적 비용/일정 예측, 원가분석, 재사용
  • 잘못된 기능의 SW개발: 프로토타이핑, 조직/직능분석
  • 잘못된 I/F개발: 프로토타이핑, 타스크분석, 시나리오기법
  • 과포장: 프로토타이핑, 원가분석, 비용수익분석
  • 계속적인 요구변경: 최대변경상한선, 점증적 개발
  • 외부 모양 빈약: 벤치마킹, 성숙도분석
  • 외부 기능 빈약: 사전검증, 대조확인
  • 실시간 성능 빈약: 벤치마킹, 튜닝, 시뮬레이션
  • 기술적 취약: 기술분석, 비용수익분석

소프트웨어 생명주기 (소프트웨어 공학)

소프트웨어 생명주기 – Software Development Life Cycle

소프트웨어 공학의 목표는 “좋은 품질 소프트웨어를 최소의 비용으로 계획된 일정에 맞추어 개발하는 것“이다. 즉 품질과 생산성이라는 명확한 두 가지 목표를 위하여 소프트웨어 공학은 지속 발전하고 있다. 이 발전의 중심에는 생명주기가 있다. 소프트웨어도 생명체처럼 자라고 성숙하고 쇠퇴하는 단계가 있다. 아무리 잘 개발된 소프트웨어라도 계속 변경되고 새로운 기능이 추가되며 사용되다가 어느 순간 소멸의 때를 맞이하게 된다. 

이러한 소프트웨어를 개발하는 과정은 생명주기 측면에서 보통 요구 분석, 설계, 구현, 테스트 및 설치 인도 등 과정을 거친다. 매 과정의 단계는 각기 범위와 해야 할 항목들이 정해져 있으며 하나의 단계가 마무리되면 다음 단계로 넘어가는 분명한 기준을 가지고 있다. 이런 일련의 프로세스들은 하나의 모형으로 제안되었으며 여러 모형이 SDLC로서 나와 있다. 

 




종류

SDLC는 소프트웨어 개발 프로세스를 가이드하는 구조화된 접근 방식으로서 여러 모델이 있으며 각각의 모델들은 모두 고유한 특징과 장단점을 가지고 있다. 

🚩 폭포수(Waterfall) 모델
: 순차적 프로세스를 따르고 각 단계가 완료되어야 다음 단계로 넘어갈 수 있는 선형적 접근법이다. SDLC의 원형에 가까우며 가장 오랜 역사를 지니고 있으며 산업계의 표준과도 같이 사용된다. 이 모델은 사용자의 의견이 상이하거나 중간 결과 점검에 따라 전 단계의 작업에 결함이 있다면 다시 수정하기 위해 전 단계로 돌아가는 피드백이 있다. 이 모델은 응용 분야가 단순하거나 잘 알고 있는 경우, 사용자 요구사항을 이미 잘 알고 있으며 연구 중심의 문제를 다루는 개발에 적합하다. 또한 생명주기 전반에 걸쳐 변경이나 진화가 예상되지 않는 비교적 위험이 적은 프로젝트에 알맞다.

  • 간단하고 이해하기 쉬움
  • 명확하고 잘 정의된 요구사항이 있는 소규모 프로젝트에 적합
  • 문서화가 잘되어 있어 유지 관리가 쉬움
  • 단계가 완료 시 변경 불가
  • 요구 사항 변경 직면 시 모델 적응력 저하
  • 긴 개발 주기로 인해 최종 사용자의 피드백 지연 가능

🚩 프로토타입(Prototyping) 모델
: 초기 요구 사항을 바탕으로 프로토타입을 개발하여 고객의 피드백을 받고 개선하는 과정을 계속 반복한다. 소프트웨어 개발은 전문가가 아닌 고객/발주자의 입장에서는 블랙박스에 가깝다. 이에 프로젝트의 실현 가능성은 보장받는 일이 묘연하다. 이런 경우 이 모델이 매우 적합할 수 있다. 프로토타이핑이란 시스템의 일부 혹은 시스템 모형이 될 만한 것을 만드는 과정이며 이를 시뮬레이션하여 사용자가 볼 수 있는 반응을 미리 보여준다.

  • 사용자 요구사항을 정확하게 파악하여 빨리 최적화 개발 가능
  • 고객은 완성 시스템을 사전에 확인하고 요구사항을 수정할 수 있음
  • SDLC 내 유지보수가 없어지고 개발 단계 내 유지보수 가능
  • 고객이 프로토타입을 최종 결과라고 믿고 곧 개발이 완료될 것이라는 오해 소지
  • 관리가 쉽지 않음
  • 완전한 문서화 어려움

🚩 나선형(Spiral) 모델
: 소프트웨어 개발 프로세스는 위험 관리 측면에서 매우 중요하다. 이는 개발 계획 및 요구사항 분석 후 각종 위험 요소와 차선책에 대해서 검토하는 단계를 필수로 갖는다. 이를 통해 프로젝트 초기 실패 요인과 위험 요소를 찾아내어 대비하는 것인데 이 모델은 이를 만족시킨다. 즉 반복과 폭포수 모델이 결합한 형태로 증분/진화모델과 함께 중요한 위치를 차지한다. 이 모델은 재정적 또는 기술적으로 위험 부담이 큰 경우 위험분석을 지속하면서 시스템을 발전시켜 나가는 데 적합하다. 

  • 개발 프로세스 전반에 걸쳐 위험 평가 및 관리 강조
  • 일련의 나선형으로 주기마다 소프트웨어를 반복적 구축
  • 개발 프로세스 초기에 위험 식별 및 완화 허용
  • 반복적 특성으로 인해 시간과 비용 과다 소요
  • 위험을 효과적으로 평가하고 관리하려면 숙련된 관리 필요
  • 익숙하지 않은 방법으로 적용에 어려움

🚩 V 모델
: 폭포수 모델에 시스템 검증과 테스트 작업을 강조한 모델이다. 이는 코딩단계를 중심으로 각 단계가 V자 모양의 대칭구조를 이루고 있다. 모듈의 상세 설계를 단위 테스트 과정에서 검증하고 시스템 설계는 통합 테스트 단계에서, 사용자 요구사항은 시스템 테스트 단계에서 검증한다. 또한 이러한 검증을 통해 오류가 발견된다면 요구분석, 설계, 코딩 단계로 되돌아갈 수 있는 모델이다. 이 모델은 무엇보다도 높은 신뢰성이 필요한 의료, 제어 시스템이나 원전 시스템 등의 분야에 적합하다.

  • 각 단계에서 확인 및 확인의 중요성 강조
  • 각 단계에서 광범위한 테스트로 인해 고품질의 소프트웨어 보장
  • 요구 사항과 테스트 사례 간의 추적 가능성 설정
  • 요구 사항의 변화에 ​​적응력 저하
  • 각 단계에서 광범위한 테스트로 인한 시간 소요
  • 개발 중 제한된 고객 참여

🚩 Agile(애자일) 모델
: 소프트웨어 개발 프로세스를 일정 크기의 작은 단위로 개발, 검증 및 수정 과정을 여러 차례 반복적이고 점진적인 개발 접근 방식이다. 이를 통해 협업을 원활히 하고 업무의 적응성과 고객의 피드백에 중점을 둔다. 또한 스프린트라고 하는 잠재적인 출하 가능한 제품에 대한 증분 형태를 제공하는 방식을 지속 반복한다. 이 모델은 프로젝트에 대한 초기 비용 추정이 다소 어려워 대규모 프로젝트보다는 빠른 응답성을 요구하는 프로젝트에 요긴하게 적용할 수 있다.

  • 변화하는 요구 사항에 유연하고 적응력 높음
  • 빈번한 고객 피드백을 통해 지속적인 개선 가능
  • 정기적으로 작동하는 소프트웨어를 제공하여 귀중한 기능을 조기 배포 가능
  • 팀원 간의 강력한 협업과 의사소통 필요
  • 크고 복잡한 프로젝트를 관리하기 어려움
  • 지속적인 변화는 효과적으로 관리되지 않으면 범위 증가 가능성

 




인기

최근에 가장 많이 사용되는 SDLC는 애자일 모델이다. 애자일 방법론은 기존 전통적인 개발 방식과는 달리 민첩하게 변화에 대응할 수 있는 개발 방식을 제공하며 요구사항의 변화에 적절하게 대처할 수 있는 작은 주기로 개발을 진행한다. 이는 요구 사항을 빠르게 반영, 개발의 품질과 고객 만족도를 높일 수 있는 장점이 있어서 대부분의 소프트웨어 개발 프로젝트에서 애자일 방법론을 많이 적용하고 있다. 하지만 모델 하나만으로 모든 것을 만족할 수는 없다. 현장과 업계는 끊임없이 진화하고 있으며 지속해서 새로운 방법론이나 변형들이 등장하고 있다. 

이는 한 상황에 충족되지 않는 부분들을 서로 다른 모델들을 결합하여 진행할 수도 있다. 다시 말해 SDLC는 필수적 요소이기는 하나 프로젝트 규모, 복잡성 및 각종 특성 등에 따라 적절한 방법을 선택해야 한다. 이를 통해 빠른 개발 속도, 높은 사용자 만족 및 프로젝트 성공률을 보장받을 수 있는 모델들이 선호되고 있다. 근래에는 특히 개발조직뿐만 아니라 운영조직 간의 긴밀한 협업이나 AI 등을 활용한 자동화에도 중점을 두며 발전되어 나가고 있다. 다만 SDLC를 따르더라도 프로젝트의 위험을 최소화하기 위해 지속해서 프로젝트를 모니터링하고 이에 응당한 조처를 해야 한다.

소프트웨어 공학이란 (소프트웨어 공학)

“소프트웨어가 소수의 탁월한 능력을 갖춘 프로그래머에 의해 만들어지던 규모를 넘어서면서 소프트웨어 개발의 성패는 그 집단의 소프트웨어공학에 대한 숙달 정도에 크게 좌우된다.”

소프트웨어 공학의 첫 등장은 1968년 NATO가 지원한 한 콘퍼런스에서 시작되어 꽤 오랜 시간이 흘렀다. 이는 컴퓨터 소프트웨어 개발, 운영, 및 유지 보수에 관련된 체계적이고 표준화된 접근법에 대한 연구와 적용 기술로 이해된다. 이를 통해 고품질의 소프트웨어를 생산하고 시간과 비용을 최소화하며 고객과 사용자 요구사항을 충족하는 것이다.

그 결과물들은 공학적 원칙과 가이드라인으로 신뢰성, 확장성, 효율성, 보안성 및 사용성의 향상을 기대한다. 그래서 생명체와 같은 생명주기를 바탕으로 여러 기법, 도구 및 방법론이 고안되고 쓰이고 있다. 하지만 학문적 공학의 위치는 실제 현장에서 일하는 개발자들에게는 다소 생경하다. 이는 급변하는 IT 환경, 수요 대비 공급을 원활히 할 수 없는 교육적 생태계, 개발인력에 대한 대우 및 여러 편견 등으로 눈앞에 급한 불만 끄면 된다는 식의 대응에만 몰두한 결과이다.

현실은 현장에서 체득되는 지식도 있지만 학문적 고찰을 통한 지식과 지혜가 없이는 원하는 성과를 만들어낼 수 없다. 이는 수많은 무기를 지니고는 있으나 정작 아무런 전략, 전술도 세우지 않고 무작정 전장에 나서는 장수와 다를 바가 없다. 이제 개발자들은 모두 다시금 소프트웨어 공학을 찬찬히 살펴봐야 할 이유가 여기에 있다.

 

시작

무엇을 시작하든 제일 중요한 것은 “용어”를 제대로 알고 이해하는 것이다. 같은 용어라도 장소와 시간, 쓰임새 및 사람에 따라 모두 다를 수 있기 때문에 가장 먼저 다뤄야 할 용어를 정의하고 눈높이를 맞춰야 한다.

✔️ 프로그램
  : 프로그래밍 언어로 작성된 source code (정적)
✔️ 소프트웨어
  : 프로그램(source code)과 프로그램의 개발, 운용, 보수에 필요한 관련 정보 일체, 즉 산출물, 사용자 매뉴얼 등 모든 것을 포함한 것 (동적)
✔️ 시스템
  : 필요한 기능을 실현하기 위해 관련 요소들을 어떠한 법칙에 따라 조합한 집합체

시스템은 모든 것은 포괄하며 소프트웨어도 시스템 내에서 다른 요소들과 상호 동작하는 하나의 시스템으로 볼 수 있다. 이러한 시스템의 기능과 성능이 잘 발휘되려면 시스템을 구성하는 모든 요소, 서브 시스템이 잘 작동되어야 한다. 즉, 제대로 만들어져야 하는데 소프트웨어의 경우 눈에 보이지 않는 비가시성과 복잡성을 모두 가지고 있다.

물리적인 하드웨어는 눈부시게 발전하면서 구체적인 성과들을 보여주는데 소프트웨어는 그렇지 못하다. 그러다 보니 소프트웨어를 등한시하게 되었으나 하드웨어를 작동시키는 것이 소프트웨어임을, 그 수요가 하드웨어 못지않게 폭발하면서 수많은 수요를 따라가지 못하게 되었고 여기서 소프트웨어 위기라는 것이 발생한다.

 

소프트웨어 위기

이러한 위기는 소프트웨어가 가지는 비가시성과 복잡성을 포함한 또 다른 특징이 있는데 첫 번째. 소프트웨어는 제조가 아닌 개발이라는 것이다. 제조와 개발이 비슷해 보이지만 가장 큰 차이는 제조는 능력별 결과물의 차이가 거의 없지만 개발은 개인의 능력이 매우 중요시되고 그 능력에 따라 결과물의 차이가 크게 난다는 것이다. 둘째. 소프트웨어는 소모되는 것이 아니라 품질이 떨어진다는 것이다. 소프트웨어는 소모성 상품이 아니다. 다만 계속 사용됨으로써 지속적인 사용자의 요구사항을 반영해야 하는데 이것이 여러 사유로 원활하지 않다면 품질은 자연히 떨어지게 되는 것이다. 셋째. 소프트웨어 관리 기술이 전체가 아닌 일부만 사용된다. 즉 개발 프로젝트에서 활용하는 관리지식체계(PMBOK)가 있는데 이를 필요한 부분만 일부 적용함으로써 그 효과를 제대로 보지 못하는 것이다.

✔️ 소프트웨어 위기
  : 소프트웨어 생산성에 대한 심각한 인식 

소프트웨어 위기는 생산성 외에도 많은 문제점을 가지고 있었다. 소프트웨어 개발 프로젝트는 예산을 초과하기 일쑤이고 개발일정의 지연도 반복되었다. 중요한 소프트웨어 개발에 필요한 개발자는 각자 가지고 있는 역량의 편차로 그 결과물의 수준을 예측 할 수가 없었으며 이는 결국 품질문제로 비화되었다. 다른 공산품과 달리 불량품에 대한 관리나 품질보증에 대한 정량적 개념이 부족했고 고객은 인도된 결과물을 신뢰할 수 없었다. 이러한 상황에서 문제를 재인식하고 타계하고자 하는 노력으로 공학적 접근이 대두되었다.

✔️ 공학
  : 기술적 문제를 발견하고 기술적 해결책을 제시하는 학문으로 과학적이고 잘 조직된 지식을 현실적인 문제해결에 체계적으로 적용하는 것

공학의 특성은 자연과학하고 다르며 여러 제약사항이 있는데 우선 기간이 정해져 있고 예산도 정해져 있다는 것이다. 이러한 조건 하에서는 결국 최종적으로 기간을 얼마나 단축하고 보다 적은 비용으로 가능할 수 있는가에 대한 과학적 해법을 마련하는 것이다. 이 관점에서 소프트웨어를 개발하는 과정에서, 공학에서 쓰이고 있는 원리들을 적용하여 개발을 해보겠다는 것이 소프트웨어 공학이라고 볼 수 있다. 보다 효율적인 개발을 통한 생산성을 높이고 품질 좋은 소프트웨어를 제작하려는 것이 소프트웨어 공학의 취지이자 목적이다.

 

소프트웨어와 공학

✔️ 소프트웨어 공학
  : 소프트웨어 개발에 필요한 이론이나 기술, 도구들에 관하여 연구하는 학문

다시 말해 소프트웨어 공학은 “품질 좋은 소프트웨어를 최소의 비용으로 계획된 일정에 맞춰 제대로 개발하는 것”을 말한다. 이러한 품질과 생산성 두마리 토끼를 모두 잡아야 하는 소프트웨어 공학은 방법, 도구, 프로세스 및 페러다임을 가지고 있다. 이는 소프트웨어 개발을 위해 생명주기를 통한 단계별 방법들을 연구하고 효율성과 효과성을 획득하기 위한 적절한 도구의 사용, 사용자 요구사항에 맞게 개발하기 위한 절차와 단계들, 그리고 상황에 맞게 적용가능하고 유연한 철학이 그것이다.

✔️ 방법: 어떤 결과를 생성하기 위해서 적용하는 기법과 절차
✔️ 도구: 더 좋은 방법으로 작업하기 위한 기기 또는 자동화된 시스템
✔️ 프로세스: 도구와 기법을 사용하여 작업하는 순서
✔️ 패러다임: 개발 스타일

이러한 4가지 요소를 바탕으로 소프트웨어는 유기체와 같은 생명주기를 갖는데 이는 계획 단계, 분석 단계, 설계 단계, 구현, 테스트, 유지 보수하는 과정으로 소프트웨어 개발 과정에서의 생산성을 향상시키고 품질 좋은 소프트웨어를 생산하여 고객을 만족시키려고 하는 최종적인 목표에 방점을 찍는다. 생명주기 내 각 단계는 일련의 활동을 포함하며 전체 소프트웨어 프로젝트에 대한 계획과 관리를 수행하고 개발 과정의 체계적인 구조화와 일정 관리를 지원한다.

✔️ 소프트웨어 생명주기(Software Development Life Cycle)
  : 소프트웨어 제품 개발에서 시작하여 최종 사용자에게 배포되고, 유지 보수 및 폐기될 때까지의 전 과정으로 일반적인 작업단계는 다음과 같다.

  – 요구분석: 고객과 사용자의 요구와 기대를 조사하여 프로젝트 목표를 정의
  – 설계: 소프트웨어 기능, 구조, 데이터 흐름, 인터페이스 등을 결정
  – 구현(개발): 설계 문서를 토대로 소프트웨어 코드 작성
  – 테스트: 생길 수 있는 오류와 결함을 찾아내고 수정
  – 배포: 개발된 소프트웨어를 최종 사용자에게 전달, 설치하여 사용할 수 있도록 함
  – 유지보수: 소프트웨어가 효율적으로 동작하도록 지속적으로 업데이트하고 개선
  – 폐기: 소프트웨어 수명이 끝난 경우, 안전하게 제거하고 관련 데이터와 자원을 처리

 


※ SWEBOK(Software Engineering Body of Knowledge)
  : ISO/IEC 국제 표준화 기구와 IEEE(Institute of Electrical and Electronics Engineers)가 승인, 지원하고 전 세계 소프트웨어 전문가들이 협력하여 개발한 소프트웨어 공학 관련 전문 지식의 체계적 모음으로 소프트웨어 공학자들이 필요로 하는 기본 원칙, 개념, 기술 및 실천 방법을 포괄한다. 여기서 다루는 다양한 주제와 영역은 SDLC의 여러 단계에 지침을 제공하고 이는 소프트웨어 개발 및 관리의 범위와 효율성을 높이는 데 도움이 되며 소프트웨어 개발자에게 필요한 기술, 능력 및 전문적 역량을 개발하는 데 중요한 역할을 한다.

※ PMBOK(Project Management Body of Knowledge)
  : 프로젝트관리협회(PMI:Project Management Institute)에서 개발한, 프로젝트 관리에 관한 전문 지식의 체계적 모음으로 ‘프로젝트관리지식체계’라고 하며 PM과 팀원들이 프로젝트를 계획, 실행, 통제하고 성과를 평가하는 데 필요한 일련의 표준 및 가이드라인을 제공한다. 이를 통해 프로젝트를 실천하면 프로젝트의 성공 가능성을 높이고 리스크를 최소화하는 데 도움을 준다.