Software reuse

  • 대부분의 공학 분야에서 시스템은 다른 시스템에서 사용된 기존 구성 요소를 조합하여 설계됩니다.
  • 소프트웨어 공학은 원래 개발에 더 집중했지만, 이제는 더 나은 소프트웨어를 더 빠르게, 더 저렴하게 달성하기 위해 체계적인 소프트웨어 재사용(systematic software reuse)에 기반한 설계 프로세스가 필요하다는 것을 인식하게 되었습니다.
    • 과거에는 커스텀 소프트웨어를 만들었지만, 현재 에자일 환경에서는 온라인 서비스 환경속에서 소프트웨어 재사용이 중요하게 되었다.
  • 지난 10년 동안 재사용 기반 개발로의 큰 전환이 있었고, 변화는 계속 진행 중입니다.

(교수님이 캡디할 때 Reuse 해서 좋은 작품을 만드는게 좋다고 합니다)


Reuse-based software engineering

  • System reuse
    • 여러 응용 프로그램을 포함할 수 있는 완전한 시스템이 재사용될 수 있습니다.
  • Application reuse
    • 응용 프로그램은 다른 응용 프로그램에 변경 없이 통합되거나 응용 프로그램 계열을 개발함으로써 재사용될 수 있습니다.
  • Component reuse
    • 하위 시스템에서 단일 객체에 이르는 응용 프로그램의 구성 요소가 재사용될 수 있습니다.
  • Object and function reuse
    • 단일 명확하게 정의된 객체나 기능을 구현하는 소규모 소프트웨어 구성 요소가 재사용될 수 있습니다.

Benefits of software reuse

Benefit Explanation
Accelerated development 시스템을 가능한 한 빨리 시장에 출시하는 것이 전체 개발 비용보다 중요한 경우가 많습니다. 소프트웨어 재사용은 개발 및 검증 시간의 단축(both development and validation time may be reduced)으로 시스템 생산을 가속화할 수 있습니다.
Effective use of specialists 동일한 작업을 반복해서 수행하는 대신, 응용 프로그램 전문가들은 자신의 지식을 캡슐화(encapsulate their knowledge)한 재사용 가능한 소프트웨어를 개발할 수 있습니다.

무언가를 가져다가 사용할 때, 잘 아는 사람이 작성한 소프트웨어를 가져다가 사용할 수 있다
ex) 머신러닝 라이브러리
Increased dependability 재사용된 소프트웨어는 이미 작동하는 시스템에서 시험되고 테스트되었기 때문에 새로운 소프트웨어보다 더 신뢰할 수 있습니다. 그 설계 및 구현의 결함이 발견되고 수정되었어야(faults shoud have been found and fixed)합니다.

오랜기간 동안 개발한 것들을 사용하기 때문에 훨씬 더 믿고 사용할 수 있다.

 

Lower development costs 개발 비용은 개발되는 소프트웨어의 크기에 비례합니다. 소프트웨어를 재사용하면 작성해야 하는 코드 라인이 줄어듭니다.(즉, 개발 기간 자체가 줄어듬)
Reduced process risk 기존 소프트웨어의 비용은 이미 알려져 있는 반면, 개발 비용은 항상 판단의 문제입니다. 이것은 프로젝트 관리에 중요한 요소이며, 특히 하위 시스템과 같은 비교적 큰 소프트웨어 구성 요소가 재사용될 때 프로젝트 비용 추정의 오류 범위를 줄입니다. (이미 개발된 걸 가져다가 사용하니)
Standards compliance 일부 표준, 예를 들어 사용자 인터페이스 표준은 재사용 가능한 구성 요소 집합으로 구현될 수 있습니다. 예를 들어, 사용자 인터페이스의 메뉴가 재사용 가능한 구성 요소를 사용하여 구현되면, 모든 응용 프로그램이 동일한 메뉴 형식을 사용자에게 제공할 수 있습니다. 표준 사용자 인터페이스의 사용은 사용자들이 익숙한 인터페이스를 제공받기 때문에 실수를 줄여 신뢰성을 향상시킵니다.

ex) safety critical system 처럼 standard를 따라야 하는 경우 이미 Standard를 따르고 인증 받은 것을 가져다가 사용하면 된다.

Problems with reuse

Problem Explanation
Creating, maintaining, and using a component library 재사용 가능한 구성 요소 라이브러리를 채우고 소프트웨어 개발자가 이 라이브러리를 사용할 수 있도록 하는 것은 비용이 많이 듭니다. 개발 프로세스는 라이브러리를 사용하도록 조정되어야 합니다.

컴포넌트를 재사용 가능하게 만들기 위해 추가적인 노력이 들어간다.
Finding, understanding, and adapting reusable
components
소프트웨어 구성 요소는 라이브러리에서 발견되고 이해되어야 하며, 때로는 새로운 환경에서 작동하도록 조정되어야 합니다. 엔지니어는 구성 요소 검색을 정상적인 개발 프로세스의 일부로 포함하기 전에 라이브러리에서 구성 요소를 찾을 수 있다는 합리적인 확신을 가져야 합니다.

reuse base로 할 때, requirement에 있어서 compromise가 있을 수 있다.
+ reuse component를 찾는 것 자체가 cost가 드는 것임. LLM을 사용하면 cost가 줄어들지만, Verification을 해야하기 때문에 dependability가 낮아짐
Increased maintenance
costs
재사용된 소프트웨어 시스템이나 구성 요소의 소스 코드가 없으면 유지 보수 비용이 높아질 수 있습니다. 시스템의 재사용된 요소가 시스템 변경과 점점 더 호환되지 않을 수 있기 때문입니다.

resuable component를 가져다 쓸 때, 소유한 컴포넌트나 서비스가 아니기 때문에, 만드는 사람들이 뭔가를 바꾸는 것에 대해 우리가 컨트롤 할 수가 없어서, 바뀐 것에 맞춰서 따라야 하는 추가적인 Cost가 발생

 

Lack of tool support 일부 소프트웨어 도구는 재사용을 지원하지 않습니다. 이러한 도구를 구성 요소 라이브러리 시스템과 통합하기 어렵거나 불가능할 수 있습니다. 이 도구들이 가정하는 소프트웨어 프로세스는 재사용을 고려하지 않을 수 있습니다. 이는 임베디드 시스템 공학을 지원하는 도구에 특히 해당되며, 객체 지향 개발 도구에는 덜 해당됩니다.

요즘은 이 부분은 잘 커버됨(ex. maven의 외부 라이브러리 빌드 자동화). LLM은 이쪽 지원이 아직 부족함
Not-invented-here
syndrome
일부 소프트웨어 엔지니어는 구성 요소를 다시 작성하는 것을 선호합니다(rewrite components). 이는 부분적으로 신뢰와 관련이 있으며, 부분적으로는 다른 사람의 소프트웨어를 재사용하는 것보다 원래 소프트웨어를 작성하는 것이 더 도전적인 것으로 여겨지기 때문입니다.

SW 엔지니어가 동일한 일을 하더라도 내가 작성한 코드를 더 신뢰하는 경향이 있다.

Reuse Perspective

Reuse Perspective(관점)을 가지고 SW 개발을 하자

내가 잘 알고 있고 이미 만들어져 있는 것들은 필요한 부분만 수정해서 가져다 사용하자

  • 소프트웨어 재사용에 익숙해지면 문제를 해결할 수 있는 특정 관점을 가질 수 있습니다.
  • 처음부터 문제를 해결하는 대신, 이미 알고 있는 구성 요소를 기반으로 솔루션을 생각할 수 있습니다.
    • Top-down vs. Bottom-up
      • Top-down : 커다란 목표를 부분으로 쪼개는 것. 이렇게 하면 from scratch로 해결해야 하는 부분이 얼마 안된다는 장점이 있음
      • Bottom-up : 부분 부분 문제를 끌어 모아서 큰 문제를 해결하는 것
    • Divide and Conquer
  • 간단한 알고리즘, 구성 요소, 더 복잡한 응용 프로그램, 프레임워크, 기술 또는 전체 시스템을 재사용할 수 있습니다.
    • 문제를 여러 가지 다른 추상화 수준에서 볼 수 있습니다.

 

레고에서 이미 조립되있는 걸 가져다가 사용하면 훨씬 더 크고 높은 건물을 지을 수 있다.


The reuse landscape

  • 재사용은 종종 시스템 구성 요소의 재사용으로만 생각되지만, 재사용에는 여러 가지 접근 방식이 있습니다.
  • 재사용은 간단한 기능에서 전체 응용 프로그램 시스템까지 다양한 수준에서 가능합니다. (Reuse is possible at a range of levels from simple functions to complete application systems)
    • low level 부터 high level까지 reuse가 가능하다
  • 재사용 지형은 가능한 재사용 기술의 범위를 다룹니다.

The reuse landscape

 

Architectural patterns 이나 Design patterns 처럼 abstract 한 것도 reuse이고, System Integration과 같이 종합적인 것도 reuse이다.

  • Figure 15.3
    • Design patterns
    • Architectural patterns
    • ERP systems
    • Application system integration
    • Application frameworks
    • Systems of systems
    • Component-based software engineering
    • Aspect-oriented software engineering
    • Software product lines
    • Configurable application systems
    • Model-driven engineering
    • Program generators
    • Program libraries
    • Service-oriented systems
    • Legacy system wrapping

Reuse planning factors

Reuse 할 때 어떤 것들을 고려해야 하는가?

  • The development schedule for the software(소프트웨어 개발 일정)
    • 소프트웨어를 빨리 개발해야 하는 경우, 개별 구성 요소보다 전체 시스템을 재사용하는 것을 고려할 수 있습니다.
  • The expected software lifetime(예상 소프트웨어 수명)
    • 장기간 사용될 시스템을 개발하는 경우, 즉각적인 재사용의 이점보다는 유지 보수성에 중점을 두어야 합니다.
    • lifetime이 길어지면 maintainability를 무시할 수 없음
  • The background, skills and experience of the development team(개발팀의 배경, 기술 및 경험)
    • 재사용 기술은 상당히 복잡하며, 이를 이해하고 효과적으로 사용하는 데 많은 시간이 필요합니다.
  • The criticality of the software and its non-functional requirements(소프트웨어의 중요성과 비기능적 요구사항)
    • 중요한 시스템의 경우, 소프트웨어 재사용이 다양한 요구사항을 충족시키는 데 어려움을 초래할 수 있습니다.
    • critical SW의 경우 NFR을 지켜야 하기 때문에 reuse가 어려울 수 있다
  • The application domain(응용 도메인)
    • 많은 응용 도메인에서는 로컬 환경에 맞추어 구성함으로써 재사용할 수 있는 일반 제품이 존재합니다.
  • The execution platform for the software will run(소프트웨어가 실행될 플랫폼)
    • 일부 재사용 가능한 구성 요소나 응용 프로그램은 플랫폼에 종속적입니다.
    • ex) Windows, Linux, .. 어디에서 SW를 돌릴 것인가 / 앱으로 만들 것인가, Web으로 만들 것인가... 등등

Framework Definition

  • "..소프트웨어 아티팩트 (classes, objects, components 등)의 통합 세트(set of software artifacts)로, 관련 응용 프로그램 패밀리(family of related applications)를 위한 재사용 가능한 아키텍처를 제공합니다."
  • 코드를 모아뒀는데, 이것들이 합쳐져서 유사한 형태의 다양한 것들을 만들 수 있는 reusable architecture를 제공한다
    • ex) Web application framework에서 html, http request 등 유사한 부분의 처리

Application Frameworks

틀이 굉장히 커서 공부할 양이 많지만, 그만큼 작업량 또한 줄어듬

  • 프레임워크는 재사용 가능한 중간 크기의 엔티티입니다 (Frameworks are moderately large entities that can be reused).
    • 시스템과 구성 요소 재사용의 중간 정도입니다.
  • 프레임워크는 추상 클래스와 구상 클래스, 그리고 이들 간의 인터페이스로 구성된 서브 시스템 설계입니다 (Frameworks are a sub-system design made up of a collection of abstract and concrete classes and the interfaces between them).
    • 정말로 뻔한 것들은 concrete class(구상 클래스)로 구현해두고, 아닌 것들은 abstract class 나 interface 형태로 제공하여, 디테일 한 부분은 원하는 대로 작동하도록 코드를 작성함
    • ex) 채팅 기능에서 메시지 업로드 call-back : 서버에서 메시지를 받고 모두에게 보낸 후, 송신자에게 잘 보냈다고 응답을 받는 구조 --> 프레임워크에서 어떻게 처리해야하는지에 대한 틀을 다 만들어 둠. 이런 서브 시스템들이 다 구현이 되어있다.
  • 서브 시스템은 설계의 일부를 채우고 프레임워크 내 추상 클래스를 인스턴스화하여 구성 요소를 추가함으로써 구현됩니다.

Web Application Frameworks(WAF)

  • 동적 웹사이트 구축을 지원합니다 (Support the construction of dynamic websites).
  • 모든 일반적으로 사용되는 웹 프로그래밍 언어에 대해 사용할 수 있습니다 (e.g., JavaScript, Java, Python, Ruby 등).
  • 상호작용 모델은 Model-View-Controller 복합 패턴에 기반합니다 (Interaction model is based on the Model-View-Controller composite pattern).
    • GUI 디자인을 위한 System infrastructure 프레임워크입니다.
    • 객체의 여러 표현과 이러한 표현과의 별도 상호작용을 허용합니다.
      • model 하나로 여러 View에 뿌릴 수 있다.

The Model-View-Controller Pattern

  • Model-View-Controller 패턴

WAF Features

  • 보안 (Security)
    • 사용자 인증(로그인) 및 접근을 구현하는 클래스를 포함할 수 있습니다.
  • 동적 웹 페이지 (Dynamic web pages)
    • 웹 페이지 템플릿을 정의하고 시스템 데이터베이스에서 이를 동적으로 채울 수 있도록 도와주는 클래스를 제공합니다.
  • 데이터베이스 지원 (Database support)
    • 다양한 데이터베이스에 대한 추상 인터페이스를 제공하는 클래스를 프레임워크가 제공할 수 있습니다.
    • ex) NoSQL에서 Json으로 받고 파싱한 후 출력해주는 것
  • 세션 관리 (Session management)
    • 시스템과 사용자의 여러 상호작용(= 세션)을 생성하고 관리하는 클래스를 포함할 수 있습니다.
  • 사용자 상호작용 (User interaction)
    • 대부분의 웹 프레임워크는 이제 AJAX 지원을 제공하여 보다 인터랙티브(interactive)한 웹 페이지를 생성할 수 있습니다.

Extending Frameworks

generic 한 걸 확장해서 Skeleton architecture를 제공함으로써 틀에 맞게 채워 넣으면 작동하도록 함. (Concrete class를 추가하거나, 기존 operation을 override 하는 등)

 

ex) 부동산 관련 스타트업 CTO라고 해보자. 이 서비스에서 지도는 공통적으로 보여지기 때문에, 내부적으로 concrete class를 구현하고 돌려 쓴다.(이런 것들을 만드는 팀이 따로 존재하는 경우도 있음)

  • 프레임워크는 일반적이며 특정 응용 프로그램 또는 서브 시스템을 만들기 위해 확장됩니다 (Frameworks are generic and are extended to create a more specific application or sub-system).
    • 시스템에 대한 기본 아키텍처를 제공합니다.
  • 프레임워크 확장에는 다음이 포함됩니다 (Extending the framework involves):
    • 프레임워크 내 추상 클래스에서 작업을 상속하는 구체 클래스를 추가합니다.
    • 프레임워크에서 인식하는 이벤트에 반응하는 메서드를 추가합니다.
  •  프레임워크의 문제는 복잡성 때문에 이를 효과적으로 사용하는 데 시간이 많이 걸린다는 점입니다.
    • architecture level로 진행되기 때문에 상당히 복잡함 --> 공부해야할 내용이 많다

Inversion of Control in Frameworks

  • 프레임워크에서 제어의 역전 (Inversion of control in frameworks)

예를 들면 테트리스의 GUI나 웹을 생각해볼 수 있다.

메인 함수에서 쭈루룩 실행되는게 아니라, 각자 기능에 대해 Event Loop이 돌아가면서 떠있는 상태이다.

이런 구조에서 보통 Callback을 한다

application specific class들이 event loop에 대해서 요청을 하는데, 이런 event 가 발생하면 이 함수를 실행하게 해주는 것을 Call back 이라고 함 (ex. Tetris Listener : 이 이벤트가 발생하면 이 함수를 불러줘. 사용자가 이 마우스를 클릭하면 이 함수를 불러줘)

즉 Control이 반대로 뒤집어 지는것을 말함

Software Product Lines

유사한 application이지만 디테일이 다른 것들을 모아두거나 관리하기 위한 방식을 말함

  • 소프트웨어 제품 라인 또는 응용 프로그램 패밀리는 특정 컨텍스트에서 사용하기 위해 적응되고 구성될 수 있는 일반적인 기능을 가진 응용 프로그램입니다 (Software product lines or application families are applications with generic functionality that can be adapted and configured for use in a specific context).
    • generic + specific context
  • 소프트웨어 제품 라인은 공통 아키텍처 및 공유 구성 요소를 가진 응용 프로그램 집합으로, 각 응용 프로그램은 다른 요구 사항을 반영하여 전문화됩니다 (A software product line is a set of applications with a common architecture and shared components, with each application specialized to reflect different requirements).
  • 적응에는 다음이 포함될 수 있습니다 (Adaptation may involve):
    • 구성 요소 및 시스템 구성(Component and System configuration)
      • ex) 언어(한국어, 영어)를 바꾸는 것
    • 시스템에 새로운 구성 요소 추가(Adding new components to the system)
      • ex) 특수 기능을 더해주는 것
    • 기존 구성 요소 라이브러리에서 선택(Selecting from a library of existing components)
    • 새로운 요구 사항을 충족하기 위해 구성 요소 수정(Modifying components to meet new requirements)
      • --> customize를 해주는 것

Base Systems for a Software Product Line

소프트웨어 제품 라인을 위한 기본 시스템

  • 핵심 구성 요소 (Core components)
  • 구성 가능한 응용 프로그램 구성 요소 (Configurable application components)
    • 기존과 유사하지만 살짝 다른 것
  • 전문화된 응용 프로그램 구성 요소 (Specialized application components)
    • 완전히 새로운 기능을 추가하는 경우

Base Applications

기본 응용 프로그램 (Base applications)

 

휴대폰과 같은 임베디드 시스템을 예로 들어보자. 

Core component - 전화기 통신 기능

Configurable component - 국가별 인터페이스 번호

Specialized domain specific - 국가 종교에 맞춘 기능. ex) 중동 지역에서 절하는 시간과 방향에 대한 알림

  • 핵심 구성 요소 (Core components): 인프라 지원을 제공합니다.
    • 제품 라인의 새로운 인스턴스를 개발할 때 일반적으로 수정되지 않습니다.
  • 구성 가능한 구성 요소 (Configurable components): 새로운 응용 프로그램에 맞게 수정되고 구성될 수 있습니다.
    • 내장된 구성 언어를 사용하여 코드 변경 없이 이러한 구성 요소를 재구성할 수 있는 경우도 있습니다.
  • 전문화된 도메인 특정 구성 요소 (Specialized, domain-specific components): 제품 라인의 새 인스턴스를 생성할 때 일부 또는 전체가 교체될 수 있습니다.

Application Frameworks and Product Lines

응용 프로그램 프레임워크와 제품 라인 (Application frameworks and product lines)

 

Application frameworks 는 resuable한 아키텍쳐를 제공해줌. 각 application은 다르지만 공통된 특성은 유지된다는 점에서 product line과 유사함. 하지만 따로 다룬다. Application frameworks는 object-oriented feature에 의존하는 경향이 있음. Product line은 그렇지 않음. 빌드할 때 공통된 부분은 그대로 두고, Special 한 것만 추가함

  • 응용 프로그램 프레임워크는 다형성(polymorphism)과 같은 객체 지향 기능을 활용하여 확장을 구현합니다.
    • 제품 라인은 반드시 객체 지향일 필요는 없습니다.
  • 응용 프로그램 프레임워크는 도메인 특정 지원보다는 기술적 지원 제공에 중점을 둡니다.
    • 제품 라인도메인 및 플랫폼 정보를 포함합니다.
  • 제품 라인은 종종 장비의 응용 프로그램을 제어합니다.
  • 소프트웨어 제품 라인은 일반적으로 동일한 조직이 소유한 응용 프로그램 패밀리로 구성됩니다.
    • ex) 판매하는 나라에 따라서 조금씩 변경해서 판매

Product Line Architectures

제품 라인 아키텍처 (Product line architectures)

 

 

Configurable 한 부분이 A 또는 B를 선택할 수 있도록 해야 한다.

  • 아키텍처는 서로 다른 서브 시스템을 분리하고 이를 수정할 수 있도록 구조화되어야 합니다.
  • 아키텍처는 엔티티와 description을 분리해야 하며,
    • 시스템의 상위 레벨은 직접적으로가 아닌 description을 통해 엔티티에 접근해야 합니다.

Product Line Specialization

제품 라인 특성화 (Product line specialization)

  • 플랫폼 특성화 (Platform specialization): 응용 프로그램의 다양한 버전이 다른 플랫폼용으로 개발됩니다.
  • 환경 특성화 (Environment specialization): 응용 프로그램의 다양한 버전이 다른 운영 환경을 처리하기 위해 생성됩니다.
  • 기능 특성화 (Functional specialization): 고객의 다양한 요구 사항을 반영하여 응용 프로그램의 다양한 버전이 생성됩니다.
  • 프로세스 특성화 (Process specialization): 다양한 비즈니스 프로세스를 지원하기 위해 응용 프로그램의 다양한 버전이 생성됩니다.
    • ex) 규제 방식 : 오후 6시 이후에 시스템을 shutdown해서 업무를 못하게 만듬

Product Instance Development

제품 인스턴스 개발 (Product instance development)

  • 이해관계자 요구사항 도출 (Elicit stakeholder requirements)
  • 가장 적합한 시스템 인스턴스 선택 (Choose closest-fit system instance)
  • 기존 시스템 적응 (Adapt existing system)
  • 요구사항 재협상 (Renegotiate requirements)
  • 새 시스템 인스턴스 제공 (Deliver new system instance)

 

강의 예시)

 

 

A - Z 인스턴스를 골랐더니(Choose closest-fit system instance) 50개중 45개를 만족함

나머지 5개 중에서 2개는 어려운 부분이니 포기하고(Renegotiate requirements), 나머지 3개는 adaptation을 통해서 처리한다.(Adapt existing system) --> 빠른 시간에 Deliver new system instance

 

만약 처음에 잘못 고르면 50개 중에서 30개만 만족해서 20개를 만들어야 할 수도 있다.

최선이 30개라도, 나머지 20개 중에서 기존 회사에서 만든 게 있으면 빠르게 처리할 수 있다.

Application System Reuse

응용 시스템 재사용 (Application system reuse)

  • 응용 시스템 제품은 소스 코드를 변경하지 않고도 다른 고객에게 맞게 조정할 수 있는 소프트웨어 시스템입니다(An application system product is a software system that can be adapted for different customers without changing the source code of the system).
    • 코드를 수정하지 않고, 개별적인 사용자에 맞춰서 설정만 조금 바꿔서 사용하는 것
  • 응용 시스템은 일반적인 기능을 가지며 다양한 환경에서 사용/재사용될 수 있습니다.
    • ex) 노트북 구매 시 OS 설정(사용자 이름, 나라, 언어 등등)
  • 응용 시스템 제품은 종종 특정 고객 요구에 맞게 시스템 기능을 조정할 수 있는 내장된 구성 메커니즘(built-in configuration mechanism)을 사용하여 조정됩니다.
    • 설정하는 과정을 거쳐서 적용해 사용하게 된다 
    • 예를 들어, 병원 환자 기록 시스템에서는 서로 다른 환자 유형을 위해 별도의 입력 양식 및 출력 보고서를 정의할 수 있습니다.
    • ex) 설정만을 가지고 application 기능을 특정 기관에 맞춰서 충분히 사용 가능함

Benefits of Application System Reuse

응용 시스템 재사용의 이점 (Benefits of application system reuse)

 

개발 과정이 코드를 짜는 과정이 아니라, 시스템에서 설정값만 바꾸기 때문에 훨씬 빠르게 deployment가 가능하다

  • 다른 유형의 재사용과 마찬가지로, 신뢰할 수 있는 시스템의 더 빠른 배포(more rapid development of a reliable system)가 가능할 수 있습니다.
  • 응용 프로그램이 제공하는 기능을 볼 수 있기 때문에 이들이 적합한지 여부를 판단하기 더 쉽습니다(it is easier to judge whether or not they are likey to be suitable).
  • 기존 소프트웨어를 사용함으로써 '일부' 개발 리스크를 피할 수 있습니다('Some' development risks are avoided).
    • dependability를 일정 수준 이상으로 쉽게 확보할 수 있다. configuration으로 끝나기 때문에 개발 기간이 길어지거나 cost가 많이 드는 일이 적게 발생한다
  • 비즈니스는 IT 시스템 개발에 많은 자원을 할애하지 않고 핵심 활동에 집중(can focus on their core activity)할 수 있습니다.
    • 기존에 존재하는 system의 configuration을 통해서 사용하기 때문에, maintenance와 같은 요소를 신경 쓸 필요가 없다. Vendor하고 계약 관계를 잘 유지하면 된다.
  • 플랫폼이 발전함에 따라 기술 업데이트(technology updates)가 단순화될 수 있습니다. 이는 고객이 아닌 COTS 제품 공급업체의 책임(the responsibility of the COTS product vendor)입니다.
    • ex)어디에든 다 AI를 추가하는 현대 산업 트랜드를 생각해보자. application system 전체를 reuse 하는 상황에서 AI를 도입한다는 것은 application system을 개발하는 회사의 책임이다. 어떻게 도입하고 어떻게 개발할 지 고민할 필요가 없다. COTS product vendor가 알아서 개발, 광고, 판매할거다.

Problems of Application System Reuse

응용 시스템 재사용의 문제점 (Problems of application system reuse)

  • 요구 사항은 COTS 제품의 기능 및 운영 모드를 반영하도록 일반적으로 조정되어야 합니다(Requirements usually have to be adapted).
    • configuration의 범위를 넘어서면 Requirement는 타협을 해야 한다. 결국 Application system에 사람이 맞춰야 한다.
  • COTS 제품은 변경이 사실상 불가능한 가정에 기반할 수 있습니다.
  • 기업에 적합한 COTS 시스템을 선택(Chossing the right COTS system)하는 것은 특히 많은 COTS 제품이 잘 문서화되어 있지 않기 때문에 어려운 과정이 될 수 있습니다.(can be a difficult process)
    • 시스템을 구매하는 담당자가 전문가가 아니라, 시스템 적합성 평가가 쉽지 않은 문제임
  • 시스템 개발을 지원할 현지 전문 지식이 부족할 수 있습니다(a lack of local expertise to support systems development).
    • 우리가 사용하는 환경에 맞춰진 전문성이 떨어질 수 있다.
  • COTS 제품 공급업체가 시스템 지원 및 진화를 제어합니다.

Configurable Application Systems

구성 가능한 응용 시스템 (Configurable application systems)

 

어떤 특정 종류의 buisness process를 지원해준다(공통된 경우가 많기 때문)

  • 구성 가능한 응용 시스템은 특정 비즈니스 유형, 비즈니스 활동 또는 때로는 전체 비즈니스 엔터프라이즈를 지원하도록 설계될 수 있는 일반 응용 시스템입니다.
    • 예를 들어, 약속, 치과 기록, 환자 회상 등을 처리하는 치과 의사를 위한 응용 시스템이 제작될 수 있습니다.
    • ex) 식당 테이블 오더 시스템 : 메뉴만 설정해주면 됨
  • 비즈니스 기능(예: 문서 관리)을 지원하기 위한 도메인 특정 시스템은 잠재적 사용자 범위에 필요한 기능을 제공합니다.

ERP systems

  • ERP 시스템 (ERP systems)
    • 전사적 자원 관리 시스템 (Enterprise Resource Planning, ERP system)은 주문 및 송장 발행, 제조 등의 일반적인 비즈니스 프로세스를 지원하는 범용 시스템입니다.
    • 이러한 시스템은 대기업에서 매우 널리 사용되며, 소프트웨어 재사용의 가장 일반적인 형태를 나타냅니다.
      • 이는 더 이상 사실이 아닐 수 있습니다. 데이터 분석 및 머신러닝을 위한 클라우드 서비스의 급속한 성장 때문입니다.
    • 일반적인 코어는 모듈을 포함하고 비즈니스 프로세스 및 규칙에 대한 지식을 통합하여 적응됩니다.

여담)

독일의 SAP 사 : ERP 시스템을 개발하는 회사

SAP나 Salesforce 같은 회사는 재사용 가능한 SW를 판매한다.

Integrated application systems

통합 애플리케이션 시스템 (Integrated application systems)  

 

System Integration 여러 개를 모은 하나의 Application system이 원하는 기능을 모두 제공하지 않는다면 Application system을 재사용, 통합해서 거대한 시스템을 만들수 있다.

  • 통합 애플리케이션 시스템은 두 개 이상의 애플리케이션 시스템 제품 및/또는 레거시 애플리케이션 시스템을 포함하는 애플리케이션입니다.
  • 단일 애플리케이션 시스템이 모든 요구를 충족하지 못하거나, 이미 사용 중인 시스템과 새 애플리케이션 시스템을 통합하고자 할 때 이 접근 방식을 사용할 수 있습니다.

 

ex) 우리학교 통합정보 시스템을 생각해보자.

강의 계획서를 보여주거나 pdf로 보여주는 application system

학교 이메일 application system, 보고서 시스템, 통계 시스템, 프로파일 시스템, authentication 시스템

이런 application 시스템을 다 통합한다

Design choices

  • 디자인 선택 (Design choices)
    • 어떤 개별 애플리케이션 시스템이 가장 적합한 기능성을 제공하는가?
      • 일반적으로 여러 애플리케이션 시스템 제품이 제공되며, 이를 다양한 방식으로 결합할 수 있습니다.
    • 데이터는 어떻게 교환될 것인가?
      • 서로 다른 제품은 일반적으로 고유한 데이터 구조 및 형식을 사용합니다. 한 표현에서 다른 표현으로 변환하는 어댑터를 작성해야 합니다.
      • ex) 사용자 정보, 사용자가 작상한 게시글의 Data format이 조금씩 다를 수 있다. 시스템 간에 데이터 전송에 형식 변환을 해줘야 함
    • 제품의 어떤 기능이 실제로 사용될 것인가?
      • 개별 애플리케이션 시스템에는 필요 이상으로 더 많은 기능이 포함될 수 있으며, 기능성이 다양한 제품에 걸쳐 중복될 수 있습니다.
      • 전체 application system이 제공하는 기능의 전부를 사용하지 않고 70%만 사용한다고 해보자. 나머지를 다른 시스템에서 가져온다고 해도, 기존 시스템이랑 겹치기도 하고, 100%를 채우지 못하는 등 딱 맞아 떨어지는 시스템이 없을 수 있다. 조합을 할 때 최소 비용으로 최대 효과를 내야 한다. 일종의 knapsack problem 같은 것

Service-oriented interfaces

서비스 지향 인터페이스 (Service-oriented interfaces) 

 

ex) 프론트엔드와 백엔드를 생각해보자. 보통 프론트는 백엔드의 떠있는 형태로, api call을 통해서 화면을 구성한다

어떤 쇼핑몰에서 카카오페이, 네이버 페이를 사용하겠다는 것은, 페이가 떠있는 형태이다.

코드를 가져와서 쓸 수 있지만, 외부 서비스를 불러다가 사용할 수 있다. (ex. 지도, 페이)

또한 반대로 내가 직접 서비스를 만들어서 제공해줄 수 있따.

  • 서비스 지향 접근 방식을 사용하면 애플리케이션 시스템 통합이 단순화될 수 있습니다.
  • 서비스 지향 접근 방식은 표준 서비스 인터페이스를 통해 애플리케이션 시스템의 기능에 접근을 허용하며, 각 개별 기능 단위에 대한 서비스를 제공합니다.
    • 각각의 단위 기능을 제공해주는 서비스들을 호출하는 방식으로 연결해서 접근하는 형태
  • 일부 애플리케이션은 서비스 인터페이스를 제공할 수 있지만, 때로는 이 서비스 인터페이스를 시스템 통합자가 구현해야 합니다.
    • 애플리케이션을 숨기고 외부에서 볼 수 있는 서비스를 제공하는 래퍼를 프로그래밍해야 합니다.

Application wrapping

Application system이 legacy system인 경우 Service wrapper를 구성한다. Application System을 그대로 나두고, Service를 이용할 수 있는 새로운 Component를 붙이는 형태로 legacy system을 확장할 수 있다.

앱 개발의 경우에도, 네이티브로 처리해야 하는 부분은 남겨두고, 서버에서 처리할 수 있는 부분은 Application System을 두고 App에서 Application System을 부르는 형태로(클라이언트 서버 구조) 처리할 수 있다.

이런 식으로 Service-oriented가 구현된다.

  • 애플리케이션 래핑 (Application wrapping) 
    • (서비스 래퍼 (Service wrapper)가 애플리케이션 시스템을 둘러싸고 있습니다.)
    • (애플리케이션 시스템과 서비스 사이에 상호 작용이 있습니다.)

Application system integration problems

  • 애플리케이션 시스템 통합 문제 (Application system integration problems)
    • 기능 및 성능에 대한 제어 부족(Lack of control over functionality and performance)
      • 애플리케이션 시스템이 생각보다 덜 효과적일 수 있습니다.
    • 애플리케이션 시스템 상호 운용성 문제(Problems with application system inter-operability)
      • 서로 다른 애플리케이션 시스템이 통합을 어렵게 만드는 다른 가정을 할 수 있습니다.
      • 쉽게 말하면, 우리가 원하는 기능을 제공해주는 시스템 두 개를 선정했는데, 두 개가 호환이 안되서 상호작용을 제대로 못할 수 있다.
    • 시스템 진화에 대한 제어 부족(No control over system evolution)
      • 애플리케이션 시스템 벤더가 아닌 시스템 사용자가 시스템 진화를 제어합니다.
      • System vendor에서 evolution control을 하니까, 우리는 손 댈수가 없다.
    • 시스템 벤더의 지원(Support from system vendors)
      • 애플리케이션 시스템 벤더는 제품의 수명 동안 지원을 제공하지 않을 수 있습니다.
      • 단순히 AS 기간이라고 생각하면 됨

RESTful web services

RESTful 웹 서비스 (RESTful web services)

 

과거 웹 서비스에는 SOAP/WSDL을 사용했는데, heavyweight 해서 아무도 사용하지 않았다.

--> 요즘 REST라는 아키텍쳐 스타일로 서비스를 호출하고 접근한다.

  • 과거의 웹 서비스 표준은 '무거운(heavyweight)' 표준으로 비판받았으며, 이는 과도하게 일반적(over-general)이고 비효율적입니다.
  • REST (Representational State Transfer)는 클라이언트로부터 서버로 자원 표현을 전달하는 아키텍처 스타일입니다.
  • 이 스타일은 웹 전체를 기반으로 하며, 웹 서비스를 구현하는 데 SOAP/WSDL보다 단순합니다.
  • RESTful 서비스는 소위 '대규모 웹 서비스'보다 낮은 오버헤드를 가지며(+ 사용하기도 쉬움), 많은 조직에서 서비스 기반 시스템을 구현할 때 사용됩니다.

Resources

자원 (Resources)

== Data element

  • RESTful 아키텍처의 기본 요소는 자원입니다.
  • 본질적으로, 자원은 카탈로그, 의료 기록, 문서(예: 이 책 장)와 같은 데이터 요소일 뿐입니다.
  • 일반적으로, 자원은 여러 표현을 가질 수 있습니다.
    • 즉, 서로 다른 형식으로 존재할 수 있습니다.
    • RTF, DOCX, PDF, HWP?
    • JSON은 최근에 XML의 위치를 대체하는 인기 있는 형식입니다 (아마도 YAML?).

Resource operations

  • 자원 작업 (Resource operations)
    • 생성 (Create) – 자원을 생성합니다.
    • 읽기 (Read) – 자원의 표현을 반환합니다.
    • 업데이트 (Update) – 자원의 값을 변경합니다.
    • 삭제 (Delete) – 자원을 접근할 수 없게 만듭니다.
    • 이러한 작업은 종종 CRUD 작업이라고 불립니다.
      • 데이터베이스 관리 시스템의 기본 작업이기도 합니다.

Resources and actions

  • 자원과 동작 (Resources and actions)

READ : GET

UPDATE : PUT(자바 collection에 있는 map에 put 하는 것을 생각해보자)

CREATE : POST

DELETE : DELETE

 

위 4개는 반드시 알아야 하는 상식이라

Operation functionality(작업 기능)

  • POST는 자원을 생성하는 데 사용됩니다. 자원을 정의하는 관련 데이터가 포함되어 있습니다.
    • POST is used to create a resource. It has associated data that defines the resource.
  • GET는 자원의 값을 읽고 이를 XHTML과 같이 웹 브라우저에서 렌더링할 수 있는 지정된 표현으로 요청자에게 반환하는 데 사용됩니다.
    • GET is used to read the value of a resource and return that to the requestor in the specified representation, such as XHTML, that can be rendered in a web browser.
  • PUT는 자원의 값을 업데이트하는 데 사용됩니다.
    • PUT is used to update the value of a resource.
  • DELETE는 자원을 삭제하는 데 사용됩니다.
    • DELETE is used to delete the resource.

Resource access

Query results

Disadvantages of RESTful approach

WSAP나 SOAP는 Standard를 잘 작성해뒀기 때문에, 오히려 사용하기 어려웠다.

RESTful은 표준을 잘 따른다는 보장이 없기 때문에 인터에피스를 신경써야 한다.

ex) Request에 돌아오는 응답에 대해 Exception handling을 잘 처리해줘야 한다(Reliabiltiy Programming 관점에서 신경쓰자)

  • 서비스가 복잡한 인터페이스를 가지고 단순한 자원이 아닐 때, 이 RESTful 서비스를 설계하는 것은 어려울 수 있습니다.
  • RESTful 인터페이스 설명에 대한 표준이 없어서 서비스 사용자가 인터페이스를 이해하기 위해 비공식 문서에 의존해야 합니다.
    • There are no standards for RESTful interface description so service users must rely on informal documentation to understand the interface.
  • RESTful 서비스를 사용할 때, 서비스의 품질과 신뢰성을 관리하기 위한 자체 인프라를 구현해야 합니다.
    • When you use RESTful services, you have to implement your own infrastructure for monitoring and managing the quality of the service and the service reliability.

Safety

  • 안전(Safety)은 시스템이 정상적이든 비정상적이든 작동하면서 인간에게 상해나 사망을 초래하지 않고 시스템 환경에 손상을 주지 않는(the system's ability to operate without danger of causing human injury or death and witout damage to the system's environment) 시스템의 능력을 반영하는 속성입니다.
  • 소프트웨어 안전(software safety)을 고려하는 것이 중요합니다. 왜냐하면, 대부분의 장치들이 소프트웨어 기반 제어 시스템을 통합하고 있기 때문입니다.

Software in safety-critical systems

  • 시스템은 소프트웨어로 제어되어, 소프트웨어의 결정과 그에 따른 행동이 안전에 중요한 영향을 미칠 수 있습니다.
    • 따라서, 소프트웨어의 행동은 시스템의 전체 안전성과 직접적으로 관련이 있습니다.
  • 소프트웨어는 시스템의 다른 안전 중요 구성 요소를 검사하고 모니터링하는 데 광범위하게 사용됩니다.
    • 예를 들어, 모든 항공기 엔진 구성 요소는 소프트웨어를 통해 초기 고장 징후를 모니터링합니다.
    • 이 소프트웨어는 안전 중요(safety-critical)한데, 실패할 경우 다른 구성 요소들이 고장나 사고를 초래할 수 있기 때문입니다.
      • 2018~19년 Boeing 737 MAX 사고는 MCAS의 실패로 인한 것입니다.

Safety and reliability

reliability를 만족한다고해서 safety가 만족되는 것이 아니다

  • 안전(Safety)과 신뢰성(Reliability)은 관련이 있지만 서로 다릅니다.
    • 일반적으로, 신뢰성과 가용성(availability)은 시스템 안전을 위한 필요 조건이지만 충분 조건은 아닙니다.
    • 신뢰성은 주어진 명세와 서비스 제공에 대한 준수를 다룹니다.
  •  안전은 시스템이 명세에 부합하는지 여부와 상관없이 손상을 초래하지 않도록 보장하는 것과 관련이 있습니다.
    • 시스템 신뢰성(System reliability)은 안전에 필수적이지만 충분하지는 않습니다.
    • 신뢰할 수 있는 시스템도 안전하지 않을 수 있습니다.

Unsafe reliable systems

  • 시스템에 오랜 시간 동안 감지되지 않다가 드물게 나타나는 잠재적인 결함이 있을 수 있습니다.
  • 명세 오류(Specification errors)
    • 시스템 명세가 잘못된 경우, 시스템이 명세대로 작동하지만 여전히 사고를 일으킬 수 있습니다.
    • ex) 보잉 항공기 : 잘못된 데이터를 센서가 보내주더라도 diversity와 redundancy를 통해서 처리했어야 함
  • 하드웨어 고장이 잘못된 입력을 생성함
    • 명세에서 예측하기 어렵습니다.
  • 상황에 민감한 명령(Context-sensitive commands)
    • 즉, 올바른 명령을 잘못된 시점에 발행하는 경우입니다.
    • 종종 운영자의 실수로 인해 발생합니다.

Safety critical systems

  • 시스템 작동이 항상 안전해야 하는 시스템, 즉 시스템이 사람이나 시스템 환경에 손상을 주지 않아야 하는 시스템.
    • 예시
      • 항공기에서 제어 및 모니터링 시스템
      • 화학 제조의 공정 제어 시스템
      • 브레이크 및 엔진 관리 시스템과 같은 자동차 제어 시스템

Safety terminology

 

Accident (or mishap) 계획되지 않은 사건 또는 일련의 사건으로, 인명 사상, 재산 손상, 또는 환경 피해를 초래합니다. 인슐린 과다 복용이 예입니다.
Hazard 사고를 일으킬 가능성이 있는 잠재적인 조건입니다. 예를 들어, 혈당을 측정하는 센서의 고장은 하나의 위험 요소입니다.
Damage 사고로 인한 손실의 측정입니다. 손상은 중대 사고로 많은 사람들이 죽는 것부터 경미한 부상이나 재산 손상까지 다양합니다.

 

Hazard severity 특정 위험으로 인한 최악의 피해 평가입니다. 재난 수준에서 경미한 피해까지 다양할 수 있습니다.
Hazard probability 위험을 초래하는 사건이 발생할 확률입니다. 확률 값은 임의적일 수 있지만, 발생할 가능성은 '높음'에서 '불가능'까지 다양합니다.
Risk 시스템이 사고를 일으킬 확률의 측정입니다. 위험은 위험 확률, 위험 심각성, 사고로 이어질 확률(hazard probability, the harard severity, and the probability that hazard will lead to an accident)을 고려하여 평가됩니다.

 

Hazards

  • 사고로 이어질 수 있는 상황이나 사건
    • 원자로 제어 시스템에서 막힌 밸브
    • 내비게이션 시스템에서 소프트웨어의 잘못된 계산
    • 약물 처방 시스템에서 알레르기 감지 실패
  • 위험 요소(Hazards)는 필연적으로 사고로 이어지지 않습니다. 사고 예방 조치를 취할 수 있습니다.

Hazard-driven analysis

  • 위험 요소 식별 (Hazard identification)
  • 위험 요소 평가 (Hazard assessment)
  • 위험 요소 분석 (Hazard analysis)
  • 안전 요구 사항 명세 (Safety requirements specification)

Hazard identification

  • 시스템을 위협할 수 있는 위험 요소를 식별합니다.
  • 위험 요소 식별은 다양한 유형의 위험 요소를 기반으로 할 수 있습니다:
    • 물리적 위험 (Physical hazards)
    • 전기적 위험 (Electrical hazards)
    • 생물학적 위험 (Biological hazards)
    • 서비스 실패 위험 (Service failure hazards)
    • 기타 (Etc.)

Hazard assessment

  • 위험 확률(probability)과 위험 심각도(severity)를 추정합니다.
  • 이를 정확히 하는 것은 보통 불가능하므로 '희박함(unlikely)', '드뭄(rare)', '매우 높음(very high)' 등의 상대적인 값이 사용됩니다.
  • 목표는 발생 가능성이 높거나 심각도가 높은 위험을 배제하는 것입니다.

Social acceptability of risk

  • 위험의 수용 가능성은 인간, 사회, 정치적 고려에 의해 결정됩니다.
  • 대부분의 사회에서, 수용 가능/불가능한 영역 간의 경계는 시간이 지나면서 위로 밀려납니다.
    • 즉, 사회는 위험을 수용하려는 의지가 줄어듭니다.
    • 예를 들어, 오염 청소 비용이 예방 비용보다 적을 수 있지만 이는 사회적으로 수용되지 않을 수 있습니다.
    • ex) 지구의 기후변화에 대한 사회의 대응을 생각해보자
  • 위험 평가는 주관적입니다.
    • 위험은 '가능성 있음(probable)', '희박함(unlikely)' 등으로 식별됩니다.
    • 이는 평가를 수행하는 사람에 따라 다릅니다.

Hazard analysis

이런 방식이 있다 정도만 알아두자

  • 특정 시스템의 위험 근본 원인을 발견하는 데 중점을 둡니다.
  • 기술은 대부분 안전이 중요한 시스템에서 파생되었으며 다음과 같습니다:
    • 귀납적(Inductive, bottom-up) 기법
      • 제안된 시스템 고장으로 시작하여 그 고장으로 인한 위험을 평가합니다.
      • 예: 설계 실패 모드 및 영향 분석(Design Failure Modes and Effects Analysis, DFMEA)
    • 연역적(Deductive, top-down) 기법
      • 위험에서 시작하여 그 원인을 추론합니다.
      • 예: 고장수 분석(Fault Tree Analysis, FTA)

Risk Reduction

시험에 나오면, 아래중에서 주어진 상황에 납득할 수 있는 전략을 취하면 된다

  • 위험 회피(Hazard avoidance)
    • 시스템이 일부 유형의 위험이 발생할 수 없도록 설계됩니다.
    • ex) hazard 확률이 낮고, severity가 높은 경우?
  • 위험 감지 및 제거(Hazard detection and removal)
    • 시스템이 사고로 이어지기 전에 위험을 감지하고 제거하도록 설계됩니다.
  • 피해 제한(Damage limitation)
    • 시스템에는 사고로 인한 피해를 최소화하는 보호 기능이 포함됩니다.

Formal verification

수학적으로 specifiction을 세부적으로 정의

  • 수학적 명세가 작성될 때 형식적 기법(formal methods)을 사용할 수 있습니다.
  • 개발 과정의 다양한 단계에서 사용할 수 있는 궁극적인 정적 검증 기법입니다:
    • 형식적 명세를 개발하고 일관성을 수학적으로 분석할 수 있습니다.
      • 이는 명세 오류 및 누락을 발견하는 데 도움이 됩니다.
    • 프로그램이 수학적 명세에 부합하는지 여부를 확인하는 형식적 논증을 개발할 수 있습니다.
      • 이는 프로그래밍 및 설계 오류를 발견하는 데 효과적입니다.
  • 이는 매우 비용이 많이 들기 때문에 널리 사용되지는 않으며, 다른 방법으로도 유사한 수준의 신뢰성을 달성할 수 있습니다.

Model checking

  • 시스템의 확장된 final state model을 생성하고, 모델 검사기(model checker)를 사용하여 오류를 검사합니다.
  • 모델 검사기는 모델의 모든 가능한 경로를 탐색하고 사용자 지정 속성이 각 경로에 대해 유효한지 확인합니다.
  • 모델 검사는 테스트하기 어려운 동시성 시스템 검증(verifying concurrent systems)에 특히 유용합니다.
  • 모델 검사는 계산적으로 매우 비용이 많이 들지만, 이제는 소규모에서 중간 규모의 중요한 시스템 검증에 실용적으로 사용할 수 있습니다.

Static program analysis

  • 정적 분석기(static analysers)는 소스 텍스트 처리를 위한 소프트웨어 도구입니다.
  • 프로그램 텍스트를 구문 분석하고 잠재적으로 잘못된 조건을 발견하여 V&V 팀에 이를 알립니다.
  • 정적 분석기는 검사의 보조 수단으로 매우 효과적이며, 검사를 대체하는 것은 아닙니다.

Levels of static analysis

  • 특성 오류 검사(Characteristic error checking)
    • 정적 분석기는 특정 언어를 사용하는 프로그래머가 범하는 오류의 패턴을 코드에서 검사할 수 있습니다.
  • 사용자 정의 오류 검사(User-defined error checking)
    • 프로그래밍 언어의 사용자가 오류 패턴을 정의하여 감지할 수 있는 오류 유형을 확장합니다. 이를 통해 프로그램에 적용할 특정 규칙을 허용합니다.
  • 단언 검사(Assertion checking)
    • 개발자는 프로그램 내에 반드시 충족해야 하는 형식적 단언을 포함합니다. 정적 분석기는 코드를 상징적으로 실행하고 잠재적인 문제를 강조합니다.

Use of static analysis

  • C와 같이 약한 타입을 가진 언어가 사용되는 경우, 컴파일러에 의해 감지되지 않는 많은 오류가 있으므로 특히 유용합니다.
  • 보안 검사(security checking)에 특히 유용합니다.
    • 정적 분석기는 버퍼 오버플로우 또는 확인되지 않은 입력과 같은 취약성을 발견할 수 있습니다.
  • 정적 분석은 이제 많은 안전 및 보안 중요한 시스템 개발에 일상적으로 사용됩니다.
    • 예: Clang (C/C++), FindBugs (Java), ESLint (JavaScript), Pylint (Python), Coverity, SonarQube(한국에서 많이 씀) 등
    • 보통 ~Lint(er)가 static analysis나 program inspection을 해준다.



Software reliability

  • 일반적으로, 소프트웨어 고객은 모든 소프트웨어가 신뢰할 수 있기를 기대합니다.
    • 그러나, 비중요 응용 프로그램의 경우, 일부 시스템 실패를 수용할 수도 있습니다.
  • 일부 응용 프로그램(중요 시스템)은 매우 높은 신뢰성 요구 사항을 가지며, 이를 달성하기 위해 특별한 소프트웨어 공학 기술이 사용될 수 있습니다.
    • 의료 시스템
    • 통신 및 전력 시스템
    • 항공우주 시스템

Faults, errors and failures

용어설명

Human mistake 시스템에 결함을 도입하게 되는 인간 행동
System fault 시스템 오류로 이어질 수 있는 소프트웨어 시스템의 특성
System error 시스템 사용자가 예상하지 못한 시스템 상태
System failure 시스템이 기대한 서비스를 제공하지 못할 때 발생하는 이벤트

Faults and failures

  • 고장은 일반적으로 시스템의 결함(faults in the system)으로부터 파생된 시스템 오류(system errors)의 결과입니다.
  • 그러나, 결함이 반드시 시스템 오류를 초래하는 것은 아닙니다.(faults do not necessarily result in system errors)
    • 결함으로 인해 발생한 오류 상태는 일시적일 수 있으며, 오류가 발생하기 전에 '수정'될 수 있습니다.
    • 결함이 있는 코드가 실행되지 않을 수 있습니다.
  • 오류가 반드시 시스템 고장을 초래하는 것은 아닙니다.(Errors do not necessarily lead to system failures)
    • 오류는 내장된 오류 감지 및 복구 메커니즘에 의해 수정될 수 있습니다.
    • 고장은 내장된 보호 메커니즘에 의해 방지될 수 있습니다.

Fault management and Reliability Achievement

  • 결함 회피(Fault avoidance):
    • 시스템은 인간 오류를 방지하고 시스템 결함을 최소화하도록 개발됩니다.
    • 개발 프로세스는 시스템의 결함이 배포 전에 감지되고 수정되도록 조직됩니다.
  • 결함 감지(Falut detection):
    • 검증 및 검증 기술은 배포 전에 시스템의 결함을 발견하고 제거하는 데 사용됩니다.
  • 결함 허용(Fault tolerance):
    • 시스템은 전달된 소프트웨어의 결함이 시스템 고장을 초래하지 않도록 설계됩니다.

The increasing costs of residual fault removal

  • 잔여 결함 제거 비용의 증가 그래프

Availability and reliability

  • 신뢰성(Reliability):
    • 특정 환경에서 주어진 목적을 위해 지정된 시간 동안 시스템이 고장 없이 작동할 확률.
    • 예상하는 대로 작동하는 것을 말함.
  • 가용성(Availability):
    • 특정 시점에서 시스템이 운영 가능하고 요청된 서비스를 제공할 수 있는 확률.
    • ex) 서버가 터져서 접속하지 못하는 경우
  • 이 두 가지 속성 모두 정량적으로 표현될 수 있습니다.
    • 예: 0.999의 가용성은 시스템이 99.9%의 시간 동안 작동하고 있음을 의미합니다.

Reliability and specifications

  • Reliability는 시스템 Specification과 관련하여 formal하게 정의될 수 있습니다.
    • 즉, failure는 Specification에서 벗어나는 것입니다.
  • 그러나 많은 Specification이 불완전하거나 부정확할 수 있습니다. 따라서, Specification을 준수하는 시스템이 사용자 관점에서 'fail'할 수 있습니다.
  • 또한, 사용자는 Specification을 읽지 않기 때문에 시스템이 어떻게 작동해야 하는지 모릅니다.
    • 따라서 실제로는 인식된 신뢰성이 더 중요합니다(perceived reliability is more important in practice).

Perceptions of reliability

  • Reliability에 대한 formal definition은 항상 System's reliability에 대한 user's perception을 반영하지 않습니다.
  • 시스템이 사용될 환경에 대한 가정이 잘못될 수 있습니다.
    • 이 시스템을 개발하는 환경과, 사용하는 환경이 크게 다를 수 있음 
    • 붐비는 교통에서 사용되는 시스템의 사용은 집에서 동일한 시스템을 사용하는 것과 상당히 다른 환경을 제공합니다.
    • ex) 지옥철에서 사람이 엄청 많을 때, 인터넷 서비스가 원활하지 않음
    • ex) 티켓팅 시스템이 트래픽이 튀는 시간에 접속이 안됨 -> availability와 reliability에 문제가 있음
  • System failures의 결과는 reliability에 대한 perception에 영향을 미칩니다.
    • 심각한 결과를 초래하는 failures(예: 자동차 엔진 고장)은 사용자에게 불편함을 주는 failure보다 더 큰 비중을 차지합니다.

Availability perception

  • 가용성(Availability)은 일반적으로 시스템이 서비스를 제공할 수 있는 시간의 비율로 표현됩니다. 예: 99.95%.
    • 물론, 수치가 높다고 해서 Availability가 좋은게 아니다.
    • ex) Ticketing system에서 24시간중 4분만 접속이 제대로 되지 않더라도 availability가 좋지 않은 것.
  • 그러나 이는 두 가지 요소를 고려하지 않습니다:
    • 서비스 중단으로 영향을 받는 사용자 수(The number of users affected by the service outage): 많은 시스템에서 서비스 중단이 발생할 때, 한밤중의 서비스 중단은 피크 사용 기간 동안의 서비스 중단보다 덜 중요합니다.
    • 중단의 길이(The length of the outage): 중단이 길어질수록 혼란이 커집니다. 여러 번의 짧은 중단은 한 번의 긴 중단보다 덜 방해가 됩니다. 긴 수리 시간은 특별한 문제입니다.

Reliability in use

  • 시스템의 결함 X%를 제거한다고 해서 신뢰성이 X% 향상되는 것은 아닙니다.
  • 프로그램 결함(defection)은 드물게 실행되는 코드 부분에 있을 수 있어 사용자가 거의 만나지 않을 수 있습니다. 
    • 이를 제거해도 인식된 신뢰성에는 영향을 미치지 않습니다.
    • ex) 0.01% 정도의 defect --> 해결해도 reliability에 영향을 거의 주지 않음
  • 사용자는 실패할 수 있는 시스템 기능(feature)을 피하기 위해 행동을 적응시킵니다.
    • 결함이 있는 프로그램은 여전히 사용자에게 신뢰할 수 있다고 인식될 수 있습니다.

 

시스템 신뢰성 요구사항 (System reliability requirements)

  • 기능적 신뢰성 요구사항 (Functional reliability requirements)는 시스템과 소프트웨어 기능을 정의하며, 소프트웨어의 결함을 피하거나 탐지하거나 허용하여 이러한 결함(faults)이 시스템 실패(system failure)로 이어지지 않도록 합니다.
  • 소프트웨어 신뢰성 요구사항 (Software reliability requirements)에는 하드웨어 고장이나 운영자 오류를 대처하기 위한 내용도 포함될 수 있습니다.
    • 신뢰성 (Reliability)은 측정 가능한 시스템 속성이므로 비기능적 신뢰성 요구사항 (non-functional reliability requirements)은 정량적으로 명시될 수 있습니다(may be specified quantitatively).
    • 이는 시스템의 정상 사용 중 허용되는 실패 횟수 또는 시스템이 사용 가능해야 하는 시간을 정의합니다.

신뢰성 메트릭스 (Reliability metrics)

  • 신뢰성 메트릭스 (Reliability metrics)는 system reliability의 측정 단위입니다.
  • 시스템 신뢰성 (System reliability)은 운영 실패 횟수를 세고(measured by counting the number of operational failure), 적절할 경우 이를 시스템에 가해지는 요구와 시스템이 운영된 시간에 관련지어 측정합니다.
  • 중요한 시스템의 신뢰성을 평가하려면 장기적인 측정 프로그램이 필요합니다.
  • 메트릭스 (Metrics)
    • 요구 시 실패 확률 (Probability of failure on demand)
      • Perception과 관련됨
    • 실패 발생률/평균 고장 간격 (Rate of occurrence of failures/Mean time to failure)
    • 가용성 (Availability)

요구 시 실패 확률 (Probability of failure on demand, POFOD)

  • 이는 서비스 요청 시 시스템이 실패할 확률입니다.
    • 서비스 요청이 간헐적이고 비교적 드문 경우에 유용합니다(Useful when demans for service are intermittent and relatively infrequent)
    • ex) 100번 중 10번의 실패가 발생하면 10%
  • 서비스가 가끔 요구되며, 서비스가 제공되지 않으면 심각한 결과를 초래하는 보호 시스템에 적합합니다.
  • 예외 관리 구성요소(exception management component)를 포함하는 많은 안전-중요 시스템(safety-critical systems)에 관련이 있습니다.
    • 화학 공장의 비상 정지 시스템.

실패 발생률 (Rate of occurrence of failures, ROCOF)

  • 시스템에서 실패가 발생하는 비율을 반영합니다.
  • ROCOF 0.002는 1000 운영 시간 단위당 2번의 실패가 발생할 가능성이 있음을 의미합니다. 예: 1000 시간 운영당 2번의 실패.(time unit이 1 hour라면)
  •  단시간에 유사한 요청을 많이 처리해야 하는 시스템에 관련이 있습니다.(Relevant for systems where the system has to process a large number of similar request in a shor time)
    • 신용카드 처리 시스템, 항공사 예약 시스템.
  • ROCOF의 역수(Reciprocal of ROCOF)는 평균 고장 간격 (Mean time to Failure, MTTF)입니다.
    • MTTF : 얼마나 Failure 없이 오랫동안 서비스 할 수 있는지를 나타낸다 
    • 긴 트랜잭션이 있는 시스템에 관련이 있으며, 예를 들어 CAD 시스템과 같이 처리 시간이 오래 걸리는 시스템에 적합합니다.
    • MTTF는 예상 트랜잭션 길이보다 길어야 합니다.

가용성 (Availability, AVAIL)

  • 시스템이 사용 가능한 시간의 비율을 측정합니다.
  • 수리 및 재시작 시간을 고려합니다.
    • ex) 카카오톡 업데이트로 인해 장애가 발생하여, 서비스 복구가 6시간이 걸렸다.
      • 24시간 기준 availability는 75%, 365일 기준이라면 availability가 매우 높아짐 -->기준에 따라 달라진다
  • 가용성 0.998은 1000 시간 단위 중 998 시간 동안 소프트웨어가 사용 가능함을 의미합니다.
  •  비정지, 지속적으로 실행되는 시스템에 관련이 있습니다.(Relevant for non-stop, continuously running systems).
    • 전화 교환 시스템, 철도 신호 시스템.

비기능적 신뢰성 요구사항 (Non-functional reliability requirements)

  • 비기능적 신뢰성 요구사항 (Non-functional reliability requirements)은 시스템의 신뢰성과 가용성(Reliability and availability of system)에 필요한 Specification을 신뢰성 메트릭스 (POFOD, ROCOF 또는 AVAIL)를 사용하여 명시합니다.
  • 정량적 신뢰성(Quantitative reliability)과 가용성 명시(availability specification)는 안전-중요 시스템(safety-critical systems)에서 수년간 사용되어 왔으나, 비즈니스 중요 시스템에서는 드뭅니다.
  • 그러나 점점 더 많은 회사가 시스템의 24/7 서비스를 요구함에 따라, 신뢰성과 가용성 기대치(reliability and availability expectation)를 명확히 하는 것이 합리적입니다.

신뢰성 요구사항 명시 (Specifying reliability requirements)

  • 다양한 유형의 실패(different types of failure)에 대한 availability과 reliability requirements을 명시하십시오.
    • 심각한 결과를 초래하지 않는 실패보다 고비용 실패 확률이 낮아야 합니다
  • 다양한 유형의 시스템 서비스(different types of system service)에 대한 availability과 reliability requirements을 명시하십시오.
    • 중요한 시스템 서비스는 가장 높은 신뢰성을 가져야 하지만, 덜 중요한 서비스에서는 더 많은 실패를 용인할 수 있습니다.
  • 높은 수준의 신뢰성이 정말로 필요한지(whether a high level of reliability is really required) 고려하십시오.
    • 다른 메커니즘을 사용하여 신뢰할 수 있는 시스템 서비스를 제공할 수 있습니다.

기능적 신뢰성 요구사항 (Functional reliability requirements)

cf) metric : verifiable NFR로 정의

  • 잘못된 데이터가 실패로 이어지기 전에 이를 탐지하기 위한 체크를 확인하는 요구사항 (Checking requirements).
  • 실패 발생 후 시스템이 복구될 수 있도록 돕는 복구 요구사항 (Recovery requirements).
    • ex) 널포인터 Exception : 구글 플레이 스토어 crash 발생 원인 1위
  • 시스템에 포함될 중복 기능을 명시하는 중복 요구사항 (Redundancy requirements).
    • Redundancy와 Diversity를 잘 준비해야 한다(비용은 많이 듬).
  • 사용할 개발 프로세스를 명시하는 프로세스 요구사항 (Process requirements).
    • 이 시점에서는 이러한 것들이 준비되어야 한다.

신뢰할 수 있는 프로그래밍 (Dependable programming)

  • 프로그램 결함 발생을 줄이기 위해 좋은 프로그래밍 실천 방법을 채택할 수 있습니다.
  • 이러한 프로그래밍 실천 방법은 다음을 지원합니다:
    • 결함 회피 (Fault avoidance)
    • 결함 탐지 (Fault detection)
    • 결함 허용 (Fault tolerance)

신뢰할 수 있는 프로그래밍을 위한 모범 사례 지침 (Good practice guidelines for dependable programming)

  • 신뢰할 수 있는 프로그래밍 지침 (Dependable programming guidelines)
    1. 프로그램에서 정보의 가시성을 제한합니다.
    2. 모든 입력의 유효성을 검사합니다.
    3. 모든 예외에 대한 핸들러를 제공합니다.
    4. 오류 발생 가능성이 높은 구조체 사용을 최소화합니다.
    5. 재시작 기능을 제공합니다.
    6. 배열 경계를 검사합니다.
    7. 외부 구성요소 호출 시 타임아웃을 포함합니다.
    8. real-world 값을 나타내는 모든 상수를 이름 짓습니다.

1. 프로그램 내 정보의 가시성 제한 (Limit the visibility of information in a program)

ex) public/private으로 나누는 것

  • 프로그램 구성요소는 구현에 필요한 데이터에만 접근할 수 있어야 합니다.
  • 이는 이러한 구성요소로 인해 프로그램 상태의 일부가 우발적으로 손상되는 것을 불가능하게 합니다.
  • 추상 데이터 타입 (abstract data types)을 사용하여 데이터 표현을 비공개로 하고, get() 및 put()과 같은 사전 정의된 연산을 통해서만 데이터에 접근하도록 가시성을 제어할 수 있습니다.

2. 모든 입력의 유효성 검사 (Check all inputs for validity)

  • 모든 프로그램은 환경으로부터 입력을 받고 이 입력에 대한 가정을 합니다.
  • 그러나 프로그램 명세는 입력이 이러한 가정과 일치하지 않을 경우 어떻게 해야 할지를 거의 정의하지 않습니다.
  • 그 결과, 많은 프로그램이 비정상적인 입력을 받으면 예측할 수 없는 동작을 하며, 때로는 시스템 보안에 위협이 됩니다.
  • 따라서, 입력을 처리하기 전에 항상 입력의 유효성을 검사해야 합니다.
  • ex) array index 범위 조사, 인스턴스, 키 입력 조사

3. 모든 예외에 대한 핸들러 제공 (Provide a handler for all exceptions)

  • 프로그램 예외는 오류 또는 전력 실패와 같은 예상치 못한 이벤트입니다.
  • 예외 처리 구문은 이러한 이벤트를 탐지하기 위해 지속적인 상태 점검 없이 처리할 수 있도록 합니다.
  • 일반적인 제어 구문을 사용하여 예외를 탐지하려면 많은 추가 명령문을 프로그램에 추가해야 합니다.
    • 이는 상당한 오버헤드를 추가하고 잠재적으로 오류가 발생하기 쉽습니다.
  • 예외 처리는 일부 결함 허용 (fault tolerance)을 제공하는 메커니즘입니다.
  • ex) nullpointerException 등을 handling

4. 오류 발생 가능성이 높은 구문의 사용 최소화 (Minimize the use of error-prone constructs)

  • 프로그램 결함은 대개 사람의 실수로 인한 결과입니다.
    • 이는 프로그래머가 시스템의 다른 부분 간의 관계를 추적하지 못하기 때문입니다.
  • 이는 프로그래밍 언어에서 본질적으로 복잡하거나 실수를 확인하지 않는 오류 발생 가능성이 높은 구문에 의해 악화됩니다.
    • 예: goto, FP 숫자, 포인터, 동적 메모리 할당 등.
  • 따라서 프로그래밍할 때 이러한 오류 발생 가능성이 높은 구문의 사용을 피하거나 최소화해야 합니다.

5. 재시작 기능 제공 (Provide restart capabilities)

  • 긴 트랜잭션이나 사용자 상호작용이 포함된 시스템의 경우,
    • 실패 후 시스템을 재시작할 수 있는 재시작 기능을 항상 제공해야 합니다.
    • ex) error->failure라고 하더라도, autosave 등의 메커니즘을 넣어줘야 한다
    • 프로그램 state를 잘 파악하고 관리해줘야 함
    • 사용자가 이미 한 작업을 모두 다시 해야 하는 것을 방지합니다.
  • 재시작은 시스템의 유형에 따라 다릅니다.
    • 문제가 있을 경우 사용자가 양식을 다시 작성할 필요가 없도록 양식의 사본을 유지합니다.
    • 주기적으로 상태를 저장하고 저장된 상태에서 재시작합니다.

6. 배열 경계 검사 (Check array bounds)

  • C와 같은 일부 프로그래밍 언어에서는 배열 선언에서 허용된 범위 밖의 메모리 위치를 참조할 수 있습니다.
  • 이는 잘 알려진 '경계 버퍼' 취약점으로 이어집니다.
    • 공격자가 배열의 최상위 요소를 넘어 의도적으로 쓰기를 하여 실행 가능한 코드를 메모리에 작성하는 경우.
  • 만약 사용하는 언어에 경계 검사가 포함되지 않는다면,
    • 항상 배열 접근이 배열의 경계 내에 있는지 확인해야 합니다.

7. 외부 구성요소 호출 시 타임아웃 포함 (Include timeouts when calling external components)

  • 분산 시스템에서 원격 컴퓨터의 고장은 '침묵'할 수 있습니다.
    • 따라서 해당 컴퓨터로부터 서비스를 기대하는 프로그램이 그 서비스를 받지 못하거나 고장이 발생했다는 어떤 표시도 받지 못할 수 있습니다.
  • 이를 방지하려면 외부 구성요소에 대한 모든 호출에 타임아웃을 항상 포함해야 합니다.
    • ex) DB에 저장하는데 너무 시간이 오래걸리는 경우 timeout 설정
  • 정의된 시간 기간 내에 응답이 없으면,
    • 시스템은 고장을 가정하고 이를 복구하기 위해 필요한 조치를 취해야 합니다.

8. 실제 값을 나타내는 모든 상수에 이름 지정 (Name all constants that represent real-world values)

  • 항상 실제 값 (예: 세율)을 반영하는 상수에 이름을 지정하고 숫자 값을 사용하지 말고 항상 이름으로 참조하십시오.
    • 예: public static final PI = 3.14159;
  • 이름을 사용할 때는 값 대신 이름을 사용하는 경우 실수를 줄이고 잘못된 값을 입력할 가능성이 적습니다.
  • 이는 이러한 '상수'가 변경될 때 (실제로는 변경될 가능성이 있습니다),
    • 프로그램 내에서 한 번만 변경하면 됩니다.





System Dependability

  • 많은 컴퓨터 기반 시스템에서 가장 중요한 시스템 속성은 시스템의 신뢰성(dependability)이다.
  • 시스템의 신뢰성은 사용자가 해당 시스템에 대한 신뢰의 정도를 반영한다.(The dependability of a system relfects the user's degree of trust in that system)
    • 이는 사용자가 시스템이 사용자가 기대하는 대로 작동(it will operate as users expect)하고, 정상 사용 중에 '실패'하지 않을 것(it will not 'fail' in normal use)이라는 확신의 정도를 반영한다.
    • 사용자가 이 시스템을 얼마나 믿을 수 있는가?
    • 실패 예시) 과제 마감 2분 전 트래픽이 몰려서 제출하지 못함
  • 신뢰성은 신뢰성(reliability), 가용성(availability), 보안(security)과 같은 관련 시스템 속성을 포괄한다.
    • 이들은 모두 상호 의존적이다.

Importance of Dependability

  • 시스템 실패는 큰 수의 사람들에게 영향을 미치는 광범위한 영향을 미칠 수 있다.
  • 신뢰할 수 없고, 불안정하거나 안전하지 않은 시스템은 사용자에게 거부당할 수 있다.
  • 시스템 실패 비용은 실패가 경제적 손실이나 신체적 손상으로 이어지면 매우 높을 수 있다.
    • ex) 자율주행 시스템 -> physical damage 를 입을 수 있음.
  • 신뢰할 수 없는 시스템은 정보 손실을 초래하고, 이에 따른 회복 비용이 높을 수 있다.

The Principal Dependability Properties

  • 가용성(Availability): 요청 시 서비스를 제공할 수 있는 시스템의 능력
    • 원할 때 시스템을 사용할 수 있을까?
  • 신뢰성(Reliability): 지정된 대로 서비스를 제공할 수 있는 시스템의 능력
    • 원하는 대로 시스템이 작동하는가?
  • 안전성(Safety): 치명적인 실패 없이 작동할 수 있는 시스템의 능력
    • 이 시스템이 안전한가?
    • ex) 자율주행 시스템
  • 보안(Security): 의도적이거나 우발적인 침입으로부터 시스템을 보호할 수 있는 능력
  • 복원력(Resilience): 손상된 사건으로부터 저항하고 회복할 수 있는 시스템의 능력
  • 위에 4개가 중요함!

Other Dependability Properties

  • 복구 가능성(Repairability): 실패 시 시스템을 복구할 수 있는 정도를 반영한다.
    • 실패가 발생했을 때 얼마나 쉽게 복구할 수 있는가?
  • 유지보수성(Maintainability): 새로운 요구 사항에 맞게 시스템을 적응시킬 수 있는 정도를 반영한다.
  • 오류 허용성(Error Tolerance): 사용자 입력 오류를 피하고 허용할 수 있는 정도를 반영한다.
    • 에러가 발생했을 때 적절히 처리하여 system failure가 발생하지 않게 해주는 부분

Dependability Attribute Dependencies

시험에 나올 수 있는 중요한 부분!

  • 안전한 시스템 운영은 시스템이 가용하고 신뢰성 있게 작동하는지에 달려 있다.
    • 가용성, 신뢰성 → 안전성
    • ex) 자율 주행 시스템
      • Availability
        • 충돌 감지 시스템이 작동하지 않아, 자동으로 감속하는 기능이 작동하지 않음.
        • 자율 주행 시스템 자체가 죽어버리는 경우
      • Reliability
        • 시스템이 브레이크를 밟아야 하는데 Accelerator를 밟음
  • 시스템이 불안정할 수 있는 이유는 데이터가 외부 공격으로 손상되었기 때문이다.
    • 서비스 거부 공격(DDOS)은 시스템을 이용할 수 없게 만들려는 의도이다.
    • 또한, 시스템이 바이러스에 감염되면 신뢰성이나 안전성을 신뢰할 수 없다.
    • Security에 문제가 있어서 해킹을 당하는 경우
    • 보안 → 신뢰성, 가용성, 안전성
  • 신뢰성 속성들이 상호 의존적이라는 많은 다른 예들이 있다.
  • 발표 예시) 핵(미사일) 시스템, 원자로 시스템, 결제 시스템, 병원 시스템, 시스템 펌웨어

Dependability Achievement

  • 시스템 개발 시 실수 도입을 피한다.
  • 남은 오류를 발견하는 데 효과적인 검증 및 확인(V & V) 프로세스를 설계한다.
  • 오류 발생 시 계속 작동할 수 있도록 시스템을 내결함성으로 설계한다.
  • 외부 공격을 방어하는 보호 메커니즘을 설계한다.
    • ex) layered architecture
  • 시스템을 운영 환경에 맞게 올바르게 구성한다.
  • 사이버 공격을 인식하고 저항할 수 있는 시스템 기능을 포함한다.
  • 실패 후 정상 시스템 서비스 복구를 돕는 복구 메커니즘을 포함한다.

Dependability Costs

  • 높은 수준의 신뢰성이 요구됨에 따라 신뢰성 비용은 기하급수적으로 증가하는 경향이 있다.
  • 이 두 가지 이유가 있다:
    • 더 높은 수준의 신뢰성을 달성하기 위해 필요한 더 비싼 개발 기술 및 하드웨어의 사용(The use of more expensive development techniques and hardware).
    • 요구되는 신뢰성 수준이 달성되었음을 시스템 클라이언트와 규제 기관에게 입증하기 위한 증가된 테스트 및 시스템 검증(The increased testing and system validation).

Dependability Economics

  • 신뢰성 달성 비용이 매우 높기 때문에 신뢰할 수 없는 시스템을 수용하고 실패 비용을 지불하는 것(accept untrustworthy systems and pay for failure costs)이 더 비용 효과적일 수 있다.
    • ex) 시스템이 해킹당했을 때 법적으로 책임을 별로 묻지 않음
  • 그러나 이는 사회적, 정치적 요인에 따라 달라진다.
    • 신뢰할 수 없는 제품에 대한 평판은 미래의 비즈니스를 잃을 수 있다.
  • 시스템 유형에 따라 다르다.
    • 특히 비즈니스 시스템의 경우, 적당한 수준의 신뢰성으로 충분할 수 있다.

Systems and Software

  • 소프트웨어 공학은 고립된 활동이 아니라 더 넓은 시스템 공학 프로세스의 일부이다.
  • 따라서 소프트웨어 시스템은 고립된 시스템이 아니라 인간, 사회, 조직적 목적을 가진 더 넓은 시스템의 필수 구성 요소이다.

The Socio-Technical System (STS) Stack

  • 사회(Society)
  • 조직(Organization)
  • 비즈니스 프로세스(Business Processes)
  • 애플리케이션 시스템(Application System)
  • 통신 및 데이터 관리(Communications and Data Management)
  • 운영 체제(Operating System)
  • 장비(Equipment)

Holistic system design

전체적인 것을 고려해서 시스템 디자인을 하는게 중요하다.

ex) 리뷰(별점) 시스템의 어뷰징 문제 --> 결국에 비지니스 프로세스를 제대로 하지 않으면 쓸모 없어진다.

  • 시스템의 각 계층 간에는 상호작용과 의존성이 있으며, 한 계층에서의 변화가 다른 계층에 파급 효과를 미친다.
  • 신뢰성을 위해 시스템 관점이 필수적이다.
    • STS stack의 포괄적인 계층 내에서 소프트웨어 실패를 포함시킨다.
    • 인접 계층의 결함과 실패가 시스템 내 소프트웨어에 어떻게 영향을 미치는지 이해한다.
      • 예: 배달, 모빌리티, 콘텐츠 추천, 리뷰 등을 위한 앱

Regulation and compliance

  • 세계적으로 거의 보편화된 경제 조직의 일반 모델은 사유 기업이 상품과 서비스를 제공하고 이익을 내는 것이다.
  • 시민의 안전을 보장하기 위해 대부분의 정부는 사유 기업의 자유를 제한하여 제품이 안전하고 보안이 유지되도록 특정 기준을 준수하도록 규제한다.

Regulated systems

  • 많은 중요한 시스템들은 규제 시스템(Many critical systems are regulated systems)이며, 서비스에 들어가기 전에 외부 규제 기관의 승인을 받아야 한다.
    • 원자력 시스템
    • 항공 교통 관제 시스템
    • 의료 기기
  • 안전성과 신뢰성 사례는 규제 기관의 승인을 받아야 한다.
    • 따라서 중요한 시스템 개발은 시스템이 신뢰할 수 있고 안전하며 보안이 유지된다는 것을 규제 기관에 입증하기 위한 증거를 만들어야 한다.

Safety regulation

  • 규제 및 준수(룰을 따르는 것)는 시스템의 소프트웨어 요소가 아니라 전체 사회기술 시스템에 적용된다.
  • 안전 관련 시스템은 규제 기관에 의해 안전하다고 인증되어야 할 수 있다.
  • 인증을 받기 위해 안전 중요한 시스템을 개발하는 회사(companies that are developing safety-critical systems)는 규정과 규칙을 준수했음을 보여주는 포괄적인 안전 사례를 제시해야 한다. (have to produce an extensive safety case)
    • safety case : 안전함을 증명하는 문서
  • 인증을 위한 문서를 개발하는 것은 시스템 자체를 개발하는 것만큼 비용이 많이 들 수 있다.

Redundancy and diversity

  • Redundancy(중복성)
    • 중요한 구성 요소의 단일 버전 이상을 유지하여 하나가 실패하면 백업이 가능하게 한다.
    • ex) 클라우드 서비스에서 1, 2를 둬서 1이 죽으면 2로 복구
  • Diversity(다양성)
    • 서로 다른 구성 요소에서 동일한 기능을 다른 방식으로 제공하여 동일한 방식으로 실패하지 않도록 한다.
      • 완전히 동일한 꼴을 가진 기능을 제공하는데, 기능의 implementation 방식이 완전히 다름
      • ex) 하나는 bubble sort, 하나는 insertion sort, 하나는 merge sort
    • 중복되고 다양한 구성 요소는 독립적이어야 하므로 공통 모드('common-mode') 실패로부터 영향을 받지 않도록 한다.
      • 예: 다른 프로그래밍 언어로 구현된 구성 요소는 컴파일러 오류가 모두에게 영향을 미치지 않음을 의미한다.

Process diversity and redundancy

  • 검증과 같은 프로세스 활동은 시스템을 검증하기 위해 단일 접근 방식(예: 테스트)에 의존해서는 안 된다.
  • 중복되고 다양한 프로세스 활동은 특히 검증 및 확인을 위해 중요하다.
  • 상호 보완하는 여러 가지 다른 프로세스 활동은 교차 확인을 가능하게 하여 프로세스 오류를 피하고 소프트웨어 오류로 이어질 수 있는 상황을 방지한다.

Problems with redundancy and diversity

  • 시스템에 다양성과 중복성을 추가하면 시스템 복잡성이 증가한다.
  • 이는 중복 시스템 구성 요소 간의 예상치 못한 상호작용 및 의존성으로 인해 오류 가능성을 증가시킬 수 있다.
  • 따라서 일부 엔지니어는 단순성과 광범위한 검증 및 확인(V&V)을 소프트웨어 신뢰성 확보의 더 효과적인 경로로 옹호한다.
    • 예: Airbus FCS 아키텍처는 중복/다양성이 있지만 Boeing 777 FCS 아키텍처는 소프트웨어 다양성이 없다.
    • FCS(fly control system)의 경우 문제가 크게 발생할 수 있기 때문에 redundancy와 diversity를 확실히 신경써야 한다.

Dependable processes

  • 최소한의 소프트웨어 결함을 보장하기 위해 명확하게 정의된 반복 가능한 소프트웨어 프로세스가 중요하다.
    • 명확하게 정의된 반복 가능한 프로세스는 전적으로 개인의 기술에 의존하지 않으며(A well-defined repeatable process is one that does not depend entirely on individual skills), 다른 사람들이 실행할 수 있다.
    • 즉, 개인의 스킬이 부족해도, well-defined repeatable process를 사용하면 dependability를 확보할 수 있다.
  • 규제 기관은 프로세스에 대한 정보를 사용하여 좋은 소프트웨어 엔지니어링 관행이 사용되었는지 확인한다.
  • 결함 탐지를 위해 프로세스 활동에는 검증 및 확인에 상당한 노력을 기울여야 한다.

Dependable process characteristics

  • 명확하게 정의된(Explicitly defined)
    • 소프트웨어 생산 과정을 주도하는 정의된 프로세스 모델을 가진다.
    • 개발 팀이 프로세스 모델에 정의된 대로 프로세스를 따랐음을 입증하는 데이터를 수집해야 한다.
  • 반복 가능한(Repeatable)
    • 개인의 해석과 판단에 의존하지 않는 프로세스.
    • 개발에 누가 참여했는지와 관계없이 프로젝트 전반에 걸쳐 반복될 수 있는 프로세스.
    • 다른 SW를 개발할 때도 이 프로젝트의 프로세스가 반복되도록

Dependable process activities

  • 요구사항 검토(Requirements review): 요구사항이 가능한 한 완전하고 일관성(complete and consistent) 있는지 확인.
  • 요구사항 관리(Requirements management): 요구사항 변경이 통제되고 제안된 변경의 영향이 이해되도록 보장.
  • 정형 명세(Formal specification): 소프트웨어의 수학적 모델을 생성하고 분석.
  • 시스템 모델링(System modeling): 소프트웨어 설계가 명확히 문서화되어 그래픽 모델 세트로 요구사항과 이들 모델 간의 연결이 문서화됨.
  • 설계 및 프로그램 검토(Design and program inspections): 시스템의 다양한 설명을 서로 다른 사람들이 검사하고 확인하는 활동.
  • 정적 분석(Static analysis): 프로그램의 소스 코드에 대해 자동화된 검사를 수행하는 활동.
  • 테스트 계획 및 관리(Test planning and management): 포괄적인 시스템 테스트 세트를 설계하는 활동.
    • 테스트 프로세스는 이러한 테스트가 시스템 요구사항을 충족하고 테스트 과정에서 올바르게 적용되었음을 입증하기 위해 신중하게 관리되어야 한다.

Dependable processes and agility

  • 신뢰할 수 있는 소프트웨어는 종종 인증을 필요로 하며, 따라서 프로세스 및 제품 문서화(process and product documentation)가 작성되어야 한다.
  • 사전 요구사항 분석(Up-front requirements analysis)은 시스템의 안전성과 보안을 위협할 수 있는 요구사항 및 요구사항 간 충돌을 발견하는 데 필수적이다.
  • 이러한 요구는 요구사항과 시스템의 공동 개발 및 문서화를 최소화하는 애자일 개발(agile development)의 일반적인 접근 방식과 충돌한다.
    • Dependable process는 document를 필요로 하는데, 문서를 최소화 하는 애자일과 안맞는 부분이 있다.
  • 반복 개발(iterative development), 테스트 우선 개발(test-first development), 개발 팀의 사용자 참여(user involvement)와 같은 기술을 포함하는 애자일 프로세스가 정의될 수 있다.
  • 팀이 그 프로세스를 따르고 그들의 행동을 문서화하는 한(So long as the team follows that process and documents their actions), 애자일 방법론은 사용할 수 있다.
  • 그러나 추가 문서화 및 계획이 필수적이므로 순수 애자일(pure agile)은 신뢰할 수 있는 시스템 엔지니어링에는 실용적이지 않다.('pure agile' is impractical for dependable systems engineering.)
    • 애자일이 완전히 불가능한 것은 아니지만, 퓨어 에자일은 현실적이지 않다

 

Attribute 의미, 연관관계, Dependability를 확보하기 위해 어떤 전략을 취할 수 있는지를 중점적으로 보자

Software Evolution


Software change (소프트웨어 변경)

  • 소프트웨어 변경은 필연적입니다.
    • 소프트웨어를 사용할 때 새로운 요구사항(requirements)이 생겨납니다.
    • 비즈니스 환경(business environment)이 변합니다;
    • 오류(errors)는 수정되어야 합니다;
    • 시스템에 새로운 컴퓨터(computers)와 장비(equipment)가 추가됩니다;
    • 시스템의 성능(performance) 또는 신뢰성(reliability)이 향상되어야 할 수 있습니다.
  • 모든 조직에 있어 기존 소프트웨어 시스템에 대한 변경을 구현하고 관리하는 것이 주요 문제입니다.

Importance of evolution (진화의 중요성)

  • 조직은 소프트웨어 시스템에 큰 투자를 합니다 - 그것들은 중요한 비즈니스 자산(business assets)입니다.
  • 이 자산들의 가치를 유지하기 위해, 그것들은 변경되고 업데이트되어야 합니다.
  • 소프트웨어 예산의 대부분은 새 소프트웨어를 개발하는 것이 아니라 기존 소프트웨어를 변경하고 진화시키는 데 사용됩니다.
    • 소프트웨어 디버깅(debugging)만 해도 개발자들의 상당한 시간을 차지합니다.
    • 미국 개발자들은 소프트웨어 디버깅에 시간의 35%를 소비합니다.
    • 또 다른 연구에 따르면 디버깅은 약 50%의 시간을 차지하며, 소프트웨어 버그(software bugs)로 인한 비용은 연간 3120억 달러에 달합니다.

Evolution and servicing (진화와 서비스)

  • 시간에 따른 소프트웨어의 단계: 개발(development), 진화(evolution), 서비스(servicing), 퇴출(retirement).

A spiral model of development and evolution (개발 및 진화의 나선형 모델)

  • 나선형 모델에서는 명세(specification), 구현(implementation), 운영(operation), 검증(validation) 단계가 반복됩니다.

The software evolution process (소프트웨어 진화 과정)

  • 변경 요청(change requests)에서부터 영향 분석(impact analysis), 출시 계획(release planning), 변경 구현(change implementation), 시스템 출시(system release)로 이어지는 과정입니다.

Change implementation (변경 구현)

  • 개발 과정의 반복으로, 시스템의 수정이 설계, 구현 및 테스트됩니다.
  • 초기 단계에서는 프로그램 이해(program understanding)가 포함될 수 있으며(the first stage of change implementation may involve program understanding), 원래 시스템 개발자가 변경 구현을 담당하지 않는 경우가 많습니다.
  • 프로그램 이해 단계에서는 프로그램의 구조, 기능성, 제안된 변경이 프로그램에 미칠 영향(proposed change might affect the program)을 이해해야 합니다.

Agile methods and evolution (애자일 방법론과 진화)

  • 애자일 방법론(agile methods)은 점진적 개발에 기반을 두고 있어 개발에서 진화로의 전환은 매끄러운 것입니다.
    • 진화는 개발 과정의 지속적인 반복으로(Evolution is simply a continuation of the development process), 자주 시스템 출시를 기반으로 합니다.
  • 연속 통합(continuous integration) 동안 자동 회귀 테스트(automated regression testing)가 수행되며, 시스템에 변경이 이루어질 때 특히 가치가 있습니다.
  • 변경 사항은 추가적인 사용자 스토리(user stories)로 표현될 수 있습니다.

Legacy systems (레거시 시스템)

  • 레거시 시스템(Legacy systems)은 새로운 시스템에 사용되지 않는 언어와 기술에 의존하는 오래된 시스템(older systems)입니다.
    • e.g) Y2K issues and COBOL, Dismissal of ActiveX, Flash.
  • 레거시 소프트웨어는 종종 더 오래된 하드웨어에 의존하며, 관련 레거시 프로세스와 절차가 있을 수 있습니다.
  • 레거시 시스템은 소프트웨어 시스템뿐만 아니라(Legacy systems are not just software systems) 하드웨어, 라이브러리 및 기타 지원 소프트웨어, 비즈니스 프로세스를 포함한 더 넓은 사회 기술 시스템(but are boarder socio-technical systems)입니다.

Legacy system components (레거시 시스템 구성 요소)

  • System hardware(시스템 하드웨어): 레거시 시스템은 더 이상 사용할 수 없는 하드웨어용으로 작성되었을 수 있습니다.
  • Support software(지원 소프트웨어): 레거시 시스템은 더 이상 사용되지 않거나 지원되지 않을 수 있는 다양한 지원 소프트웨어에 의존할 수 있습니다.
  • Application software(응용 소프트웨어): 비즈니스 서비스를 제공하는 응용시스템은 일반적으로 다수의 응용프로그램으로 구성된다.
  • Application data(애플리케이션 데이터): 애플리케이션 시스템에서 처리되는 데이터입니다. 일관성이 없거나 중복되거나 다른 데이터베이스에 보관될 수 있습니다.
  • Business processes(비즈니스 프로세스): 일부 비즈니스 목표를 달성하기 위해 비즈니스에서 사용되는 프로세스입니다.
    • 비즈니스 프로세스는 레거시 시스템을 중심으로 설계되었으며 레거시 시스템이 제공하는 기능에 의해 제한될 수 있습니다.
  • Business polices and rules(비즈니스 정책 및 규칙): 비즈니스를 수행하는 방법과 비즈니스에 대한 제약 사항에 대한 정의입니다.
    • 레거시 애플리케이션 시스템의 사용이 이러한 정책 및 규칙에 포함될 수 있습니다.

Legacy system replacement (레거시 시스템 교체)

  • 레거시 시스템 교체는 위험(risky)하고 비용이 많이 드는(expensive) 일이므로 기업들은 이 시스템을 계속 사용하고 있습니다.
  • 시스템 교체는 다음과 같은 여러 가지 이유로 위험합니다.
    • 완전한 시스템 사양(system specification)이 부족
    • 시스템과 비즈니스 프로세스(business processes)의 긴밀한 통합
    • 레거시 시스템에 내장된 문서화되지 않은 비즈니스 규칙(undocumented business rules)
    • 새 소프트웨어(new software) 개발이 지연되거나 예산을 초과할 수 있음

Legacy system change (레거시 시스템 변경)

  • 레거시 시스템은 변경하기에 비용이 많이 들고(expensive) 다음과 같은 여러 이유로 인해 어렵습니다:
    • 일관되지 않은 프로그래밍 스타일(inconsistent programming style).
    • 사용되지 않는 프로그래밍 언어(obsolete programming languages) 사용, 해당 언어를 다룰 수 있는 사람이 적음.
    • 불충분한 시스템 문서화(inadequate system documentation).
    • 시스템 구조의 저하(system structure degradation).
    • 프로그램 최적화(program optimizations)로 인해 이해하기 어려움.
    • 데이터 오류(data errors), 중복(duplication), 불일치(inconsistency).

Legacy system management (레거시 시스템 관리)

  • 레거시 시스템에 의존하는 조직은 이 시스템을 진화시키기 위한 전략을 선택해야 합니다.
    • 시스템을 완전히 폐기(Scrap)하고 비즈니스 프로세스를 수정하여 더 이상 필요하지 않게 함.
    • 시스템을 계속 유지(maintaining)함.
    • 시스템을 재공학(re-engineering)하여 유지 관리성(maintainability)을 향상시킴.
      • Transfrom the system by re-engineering to improve its maintainability
    • 새 시스템으로 교체(Replace)함.

An example of a legacy system assessment (레거시 시스템 평가 예)

  • 선택된 전략은 시스템의 품질(system quality)과 비즈니스 가치(business value)에 따라 달라야 합니다.

Legacy system categories (레거시 시스템 분류)

시험에 나올 수 있는 부분이니 주의 깊게 보자

  • 낮은 품질(low quality), 낮은 비즈니스 가치(low business value)
    • 이러한 시스템은 폐기되어야 합니다.
  • 낮은 품질, 높은 비즈니스 가치(high business value)
    • 중요한 비즈니스 기여를 하지만 유지 관리 비용이 많이 든다
    • 적합한 시스템이 있을 경우 재공학(re-engineered)하거나 교체해야 합니다.
  • 높은 품질(high quality), 낮은 비즈니스 가치(Low-business value)
    • COTS로 교체하거나 완전히 폐기하거나 유지 관리합니다.
  • 높은 품질(high quality), 높은 비즈니스 가치(High business value)
    • 정상적인 시스템 유지 관리를 사용하여 계속 운영합니다.

Business value assessment (비즈니스 가치 평가)

  • The use of the system(시스템 사용)
    • 시스템이 가끔이나 소수의 사람들에 의해서만 사용된다면, 비즈니스 가치가 낮을 수 있습니다.
  • The business processes that are supported(지원되는 비즈니스 프로세스)
    • 시스템이 비효율적인 비즈니스 프로세스를 강제한다면 비즈니스 가치가 낮을 수 있습니다.
  • 시스템 의존성(system dependability)
    • 시스템이 믿을 수 없고 그 문제가 비즈니스 고객에게 직접적인 영향을 미친다면 비즈니스 가치가 낮습니다.
  • 시스템 출력(system outputs)
    • 비즈니스가 시스템 출력에 의존한다면, 시스템은 높은 비즈니스 가치를 가집니다.
    • 이 시스템이 우리에게 출력하고 있는게 무엇인가?

System quality assessment (시스템 품질 평가)

System quiality --> 이거 3개 기준으로 평가하자

  • 비즈니스 프로세스 평가(business process assessment)
    • 비즈니스 프로세스가 비즈니스의 현재 목표를 얼마나 잘 지원하는지?
    • 불필요한 것 때문에 비즈니스 프로세스가 방해받지 않아야 함
  • 환경 평가(environment assessment)
    • 시스템 환경이 얼마나 효과적이며 유지 관리하는 데 얼마나 비용이 드는지?
    • ex) 티켓팅 시스템의 서버
  • 응용 프로그램 평가(application assessment)
    • 응용 소프트웨어 시스템의 품질은 어떠한가?
    • 우리가 작성한 코드 자체가 얼마나 깔끔한가? 외부 라이브러리는 어떻게 사용하고 있는가? 보안은?...

Software maintenance (소프트웨어 유지 관리)

실제로 사용자에게 전달해서 사용하고 있을 때, 버그를 고치는 등의 maintenance를 말함(만들어서 전달하는 SW에 대한 maintenance)

  • 사용된 후 프로그램을 수정하는 것.
  • 이 용어는 주로 맞춤형 소프트웨어(custom software) 변경에 사용됩니다.
    • 일반 소프트웨어 제품은 새로운 버전을 만들기 위해 진화한다고 말해집니다.
  • 유지 관리는 일반적으로 시스템의 주요 구조 변경을 포함하지 않습니다.
    • 소소하게 바꾸지, 다 뜯어고치지 않는다
  • 변경은 시스템에 존재하는 구성 요소를 수정하거나 새로운 구성 요소를 추가함으로써 구현됩니다.
    • 시스템 아키텍처는 유지되는 상황에서 무언가가 추가됨

Types of maintenance (유지 관리 유형)

  • 결함 수리(fault repairs)
    • 버그/취약점을 수정하고 요구사항을 충족하는 방식에서의 결함을 수정하여 시스템을 변경합니다.
  • 환경 적응(environmental adaptation)
    • 소프트웨어를 다른 운영 환경으로 적응시키기 위한 유지 관리입니다.
    • 초기 구현과 다른 환경(컴퓨터, OS 등)에서 작동하도록 시스템을 변경하는 것입니다.
  • 기능 추가 및 수정(functionality addition and modification)
    • 새로운 요구사항을 충족시키기 위해 시스템을 수정합니다.
    • System enhancement에 해당하는 유형

Maintenance Effort Distribution (유지 관리 노력 분배)

  • 결함 수리(Fault repair): 24%
  • 환경적응(Environmental adaptation): 19%
  • 기능 추가 또는 수정(Functionality addition or modification): 58%
    • 애자일에서 자연스럽게 일어나는 과정임

Maintenance Costs (유지 관리 비용)

  • 개발 비용보다 훨씬 높음 (애플리케이션에 따라 2배에서 100배).
  • 기술적 및 비기술적 요인에 의해 영향을 받음.
  • 소프트웨어가 유지 관리됨에 따라 증가함.
    • 유지 관리는 소프트웨어 구조를 손상시켜 추가 유지 관리를 더 어렵게 만듦.
    • 개발하다 보면 구조가 복잡해짐 --> 비용 증가
  • 노화된 소프트웨어는 높은 지원 비용을 초래할 수 있음 (예: 구식 언어, 컴파일러 등).
    • 오래된 SW일수록 비용 증가
    • ex) ajax --> jquery --> nodejs, react

Software Reengineering (소프트웨어 재공학)

  • 레거시 시스템의 일부 또는 전체를 재구조화하거나 다시 작성하여 기능을 변경하지 않음.
    • 기능은 그대로 두고, maintenability를 올리기 위해 Reengineering을 한다
    • Refacoring 보다 큰 개념임
  • 일부 하위 시스템이 자주 유지 관리가 필요한 큰 시스템에 적용 가능.
  • 재공학은 유지 관리를 용이하게 하기 위해 노력을 추가함.
    • 시스템은 재구조화되고 재문서화될 수 있음.

Advantages of Reengineering (재공학의 장점)

  • Reduced risk(위험 감소)
    • 새로운 소프트웨어 개발에서는 높은 위험이 있음.
    • development problems, staffing problems and specification problems 가 있을 수 있다
  • Reduced cost(비용 감소)
    • 재공학 비용은 종종 새로운 소프트웨어 개발 비용보다 훨씬 적음.

Reengineering Process Activities (재공학 과정 활동)

  • 소스 코드 변환(Source code translation)
    • 코드를 새로운 언어로 변환.
  • 역공학(Reverse engineering)
    • 프로그램을 분석하여 이해.
  • 프로그램 구조 개선(Program structure improvement)
    • 이해를 돕기 위해 자동으로 구조를 재구성.
    • ex) 모듈화
  • 프로그램 모듈화(Program modularisation)
    • 프로그램 구조를 재정리.
  • 데이터 재공학(Data reengineering)
    • 시스템 데이터를 정리하고 재구조화.
    • Application data도 Legacy에서 중요한 컴포넌트임. 이 data를 새로운 format으로 바꿨는데 사용에 문제가 있다면 정리해주거나, 삭제하거나, 재구조화 해준다

Refactoring (리팩토링)

  • 프로그램에 개선을 통해 변화에 따른 퇴화를 늦추는 과정.
  • 리팩토링은 예방 유지 보수(preventative maintenance)로 생각할 수 있으며, 미래 변화의 문제를 줄임.
  • 리팩토링은 프로그램의 구조를 개선하고 복잡성을 줄이며 이해를 쉽게 하기 위해 프로그램을 수정함.
  • 리팩토링할 때 기능을 추가하는 것이 아니라 프로그램 개선에 집중해야 함.(you should not add functionality but rather concentrate on program improvement)
    • Root Canal vs Floss Refactoring
      • 이를 가는 것 vs 치실 
      • 치실은 매일 사용 --> 자잘한 작업 
      • Root Canal : 큰 작업, 자잘한 작업으로 커버가 안됨 

Refactoring and Reengineering (리팩토링 및 재공학)

  • 재공학은 시스템이 유지 보수되어 오랜 시간 동안 유지 관리 비용이 증가한 후에 이루어짐.
    • 크게 한 번 갈아 엎는 것, automated tool의 도움을 많이 받음 
    • 자동화 도구를 사용하여 처리하고 레거시 시스템을 재공학하여 더 유지 관리하기 쉬운 새 시스템을 만듦.
  • 리팩토링은 개발 및 진화 과정 전반에 걸쳐 지속적인 개선 과정임.
    • automated tool을 잘 쓰지 않는 경향이 있음(원하는 대로 잘 안되서)
    • 구조 및 코드의 퇴화를 방지하여 유지 관리 비용과 어려움을 증가시키는 것을 목표로 함.

‘Bad smells’ in program code (프로그램 코드의 ‘나쁜 냄새’)

  • 중복 코드(Duplicate code, 일명 코드 클론(Code Clones)):
    • 프로그램의 다양한 장소에서 동일하거나 매우 유사한 코드가 포함될 수 있습니다. 이는 제거되고 필요에 따라 호출되는 단일 메소드나 함수로 구현될 수 있습니다.
    • Code Clones : 중복된 코드가 문제가 되는 경우가 많음 (버그가 복사된다던지 등등)
    • 비슷한 코드가 여러 군데에 흩어져 있는 상황을 예로 들 수 있다.
      • 위의 경우 하나의 함수로 만들어 주는 방식 등으로 해결할 수 있다.
  • 긴 메소드(Long methods)
    • 메소드가 너무 길면, 여러 개의 더 짧은 메소드로 재설계될 수 있습니다.
    • 메서드 하나가 엄청나게 긴 경우(modularity가 낮음) 메서드 하나를 private 메서드로 분리할 수 있다.
      • private 메서드에 비해 public 메서드는 더 신경 써줘야 한다.
  • 스위치 문(Switch (case) statements)
    • 이들은 종종 중복을 포함하며, 스위치 문은 값의 유형에 따라 달라집니다.
    • switch 문은 프로그램 전반에 scattered 되어 있을 수 있다. 객체 지향 언어에서는 동일한 기능을 달성하기 위해 다형성을 사용할 수 있습니다.
    • 언제 if-else를 쓰고 Switch를 쓸 건지, 아니면 다른 방식으로 처리할 건지
  • 데이터 뭉치(Data clumping)
    • 동일한 데이터 항목 그룹(필드, 메소드의 매개변수)이 프로그램의 여러 곳에서 반복됩니다.
    • 이들은 종종 모든 데이터를 캡슐화하는 객체로 대체될 수 있습니다.
    • ex)
    • method1(int[] block, Block currBlock), method2(int[] block, Block currBlock), method(int[] block, Block currBlock)
    • --> 파라미터를 Board 클래스로 뽑아서, 클래스 인스턴스를 파라미터로 설정한다
  • 추측적 일반성(Speculative generality)
    • 개발자가 미래에 필요할 수 있는 일반성을 프로그램에 포함시키는 경우입니다.
    • 이는 종종 간단히 제거될 수 있습니다.
    • 과연 이걸 specific하게 작성하면 나중에 새로운 기능을 추가할 때 이 부분의 작업이 증가하지 않을까?
    • 너무 generality를 높이면 오히러 작업 시간이 증가하고, 구조가 안좋아질 수 있다.

 

실제 코드 refactoring 예시

  • IDE의 Refactor -> Rename 기능 사용하여 명확한 identifer 이름 사용
  • IDE extract method 기능으로 모듈화
  • 이너 클래스를 다른 파일로 추출
    • 이렇게 modulization을 함으로써 메서드가 어떤일을 하는지 확인할 수 있는 가독성도 늘어나고, 코드 라인도 줄어듬

 

Software Testing

 

Program Testing(프로그램 테스트)

  • 테스팅은 프로그램이 의도한 대로 작동하는지(a program does what it is intended to do), 사용 전에 프로그램 결함을 발견(to discover program defect)하기 위해 수행됩니다.
  • 소프트웨어를 테스트할 때, artificial data(인공 데이터)를 사용하여 프로그램을 실행합니다.
  • 테스트 결과를 검토하여 오류, 이상 현상 또는 프로그램의 비기능적 속성에 대한 정보를 확인합니다.
  • 오류의 존재만을 나타내며(the presence of error), 그 부재를 나타내지는 않습니다.(Not their absence)
  • 테스팅은 정적 검증 기법도 포함하는 보다 일반적인 검증 및 확인 과정의 일부입니다.

Program testing goals(프로그램 테스트 목표)

  • 개발자와 고객에게 소프트웨어가 요구 사항을 충족함을 보여줍니다.
    • 맞춤형 소프트웨어의 경우, 요구 사항 문서의 모든 요구 사항에 대해 적어도 하나의 테스트(at least one test for every requirement)가 있어야 합니다.
    • 일반 소프트웨어 제품의 경우, 시스템 기능의 모든 테스트와 이러한 기능의 조합(tests for all of the system features, plus combinations of these features) 이 제품 출시에 포함되어야 합니다.
  • 소프트웨어의 동작이 잘못되었거나 명세에 맞지 않는 상황을 발견합니다.
  • Validating Testing(검증 테스팅)
    • 개발자와 시스템 고객에게 소프트웨어가 요구 사항을 충족한다는 것을 보여줍니다.
    • 성공적인 테스팅은 의도한 대로 시스템이 작동하는 것(the system operates as intented)을 보여준다
  • Defect Testing(결함 테스팅)
    • 소프트웨어의 동작이 잘못되었거나, 명세와 일치하지 않는 소프트웨어의 결함을 발견합니다.
    • 성공적인 테스팅은 시스템이 잘못 동작하도록 하여 시스템의 결함을 노출시키는 것이다
  • 성공적인 테스트는 시스템이 의도한 대로 작동함을 보여줍니다.

An input-output model of program testing(프로그램 테스트의 입력-출력 모델)

  • 입력 테스트 데이터에서 시스템을 통해 출력 테스트 결과로 이어집니다.
  • 입력이 이상 동작을 일으킨다면, 출력은 결함의 존재를 드러냅니다.

Verification vs validation

  • Verification:
    • "우리가 제품을 올바르게 구축하고 있는가?"
    • 소프트웨어는 명세에 반드시 부합해야 한다
  • validation: "우리가 올바른 제품을 구축하고 있는가?"
    • 소프트웨어는 사용자의 실제 요구 사항을 충족해야 합니다.

Inspections and testing(검사 및 테스트)

  • Software inspections(소프트웨어 검사)는 정적 시스템 표현을 분석하여 문제를 발견하는 데 중점을 둡니다.(static verification)
    • tool-based document와 코드 분석을 통해서 수행된다
  • Software testing(소프트웨어 테스트)는 테스트 데이터로 시스템을 실행하고 동작을 관찰하는 데 중점을 둡니다.(dynamic verification)
    • 따라서 Software testing 의 경우 테스트 케이스 작성이 필요함
    • Software testing은 NFR 체크가 가능하다
  • 둘 다 IDE에서 많이 제공해준다
    • 코드 분석같은 소프트웨어 검사 / 실행 시간 분석, 디버깅과 같은 소프트웨어 테스트
  • Inspection and testing are complementary(검사와 테스팅은 보완적이며), verification에 어긋나지 않으며, V & V 과정 중 사용되어야 합니다.
  • Inspection(검사)는 명세에 대한 conformance(일치, 준수)를 확인할 수 있지만 고객의 실제 요구 사항 준수는 확인할 수 없습니다.
  • 검사는 성능, 사용성 등의 비기능적 특성을 확인할 수 없습니다.(Inspections cannot check non-fuctional characteristics)

Stages of testing(테스팅 단계)

  • 개발 중에 시스템을 테스트하여 버그와 결함을 발견하는 개발 테스팅(Development testing).
    • 제대로 코드를 작성했는지 test case를 가지고 testing
  • 사용자에게 출시되기 전에 시스템의 완전한 버전을 테스트하는 출시 테스팅(Release testing).
    • 유저에게 제공되기 전에 이 릴리즈에 문제가 없는지 체크
  • 사용자 또는 잠재 사용자가 자신의 환경에서 시스템을 테스트하는 사용자 테스팅(User testing).
    • 유저가 통제된 환경에서 실제 테스트를 해보는 것
    • ex) 게임 beta test

Development testing(개발 테스팅)

  • Development testing은 팀이 시스템 개발 중 수행하는 모든 테스팅 활동을 포함합니다.
  • 테스팅 활동은 테스트되는 구성 요소 수준에 따라 분류될 수 있습니다.
  • Unit testing은 개별 프로그램 단위 또는 객체 클래스를 테스트합니다.
    • Unit testing은 객체나 메서드의 기능성을 테스트하는데에 중점을 둬야 한다
  • Component testing(컴포넌트 테스팅)은 여러 개별 단위를 통합하여 복합 구성 요소를 생성합니다.
    • 따라서 이 단계에서는 Interface쪽 테스트를 많이 함
    • 보통 Unit이 모아지면 Component가 구성되고, 결국엔 Component, Unit testing이 System testing을 형성하게 됨
  • System testing은 시스템 일부 또는 전체 구성요소가 통합되어 시스템 전체가 테스트되는 테스트입니다.
    • System testing은 component interaction을 테스트하는 것에 중점을 둬야 한다

Unit testing

  • Unit testing은 개별 구성 요소를 독립적으로 테스트하는 과정입니다.
  • 결함 테스트 과정(defect testing process)입니다.
  • 테스트 단위는 다음과 같을 수 있습니다:
    • 객체 내의 개별 함수 또는 메서드(Individual functions or methods within an object)
    • 여러 속성 및 메서드를 가진 객체 클래스(Object classes with several attributes and methods)
      • 대부분 framework이 Individual --> Object 테스트에 집중되어 있음
    • 정의된 인터페이스를 사용하여 기능에 접근하는 복합 구성 요소(Composite components with defined interfaces used to access their functionality)

Object class testing(객체 클래스 테스트)

  • 클래스의 완전한 테스트 범위는 다음을 포함한다
    • 객체와 관련된 모든 operations을 테스트
      • --> 모든 메서드에 대해서 테스트가 필요하다
      • ex) Inspection 과정에서 특정 private 메서드가 사용되지 않는지 체크
    • 모든 객체 속성을 설정하고 및 조회하는 것
    • 가능한 모든 상태에서 객체를 운용하는 것
      • 위 두 개는 작성하기 쉬운데, 요거는 작성하는데 난이도가 있음
      • ex) View에 라이트모드와 다크 모드가 존재한다면, 테스트 해야 할 state가 2개 --> 테스트 해야하는 상황이 많아짐
  • 상속은 테스트 정보가 지역화되지 않기 때문에 객체 클래스 테스트 설계를 더 어렵게 만듭니다.

Automated testing(자동화된 테스트)

  • Test Framework이 반복되는 테스트에 대한 기능을 지원해줌
  • 가능한 경우, 단위 테스트는 수동 개입 없이 자동화되어 실행 및 확인되어야 합니다.
  • 자동화된 단위 테스트에서는 테스트 자동화 프레임워크(예: JUnit)를 사용하여 프로그램 테스트를 작성하고 실행합니다.
  • 단위 테스트 프레임워크는 특정 테스트 사례를 생성하기 위해 확장할 수 있는 일반적인 테스트 클래스를 제공합니다.
    • 이를 통해 구현한 모든 테스트를 실행하고, GUI를 통해 테스트의 성공 여부를 보고할 수 있습니다.

Automated test components(자동화된 테스트 구성 요소)

  • 초기화 부분(setup)에서 시스템을 테스트 케이스, 즉 입력 및 예상 출력과 함께 초기화합니다.
    • test input : 파라미터를 넘긴다던지, 클래스의 인스턴스를 만들어서 method invoke를 하는 등등
  • 호출(call) 부분에서 테스트할 객체 또는 메서드를 호출합니다.
    • test input 을 던져서 call -> output
  • assertion 부분에서 호출의 결과를 예상 결과와 비교합니다.
    • output이 expected result와 일치하는지
    • 테스트가 참으로 평가되면 성공한 것이고, 거짓이면 실패한 것입니다.
  • tear-down(in korean : 해체 단계)부분에서는 리소스 해제 또는 임시 파일 정리와 같이 시스템 상태를 원래 상태로 복원합니다.
  • 처음 두 part에서는 자동화된 테스트 연구에 더욱 주의를 기울인다

Types of Unit Test Cases(단위 테스트 사례 유형)

  • 테스트 사례는 예상대로 사용될 때 테스트하는 구성 요소가 의도한 대로 작동함을 보여줘야 합니다.
  • 구성 요소에 결함이 있는 경우(defects in the component), 이는 테스트 사례에 의해 드러나야 합니다.
  • 이는 두 가지 유형의 단위 테스트 사례로 이어집니다:
    • 첫 번째 유형은 프로그램의 정상 작동을 반영(reflect normal operation of a program)하고 구성 요소가 예상대로 작동함을 보여야 합니다(show that the component works as expected).
    • 다른 유형의 테스트 사례는 일반적인 문제가 발생하는 경험을 기반으로 한다
      • 비정상적인 입력을 사용하여 이러한 입력이 적절하게 처리되고 구성 요소를 충돌시키지 않는지 확인해야 합니다.(user abnormal inputs to check that these are properly processed and do not crash the component)
      • ex) 값이 NULL로 나오거나, A / B에서 B == 0일 때 문제 없이 작동하는지?

Testing strategies(테스팅 전략)

  • Partitioning testing(분할 테스트): 입력 그룹을 식별하고, 같은 방식으로 처리되어야 하는 공통 특성을 가집니다.
    • 각 그룹 내에서 테스트를 선택해야 한다.
    • 파티션을 나눠서 대표적인 값을 뽑고, 모든 파티션에 대해서 테스트 될 수 있도록 한다
  • (Guideline-based testing)가이드라인 기반 테스팅: 테스트 가이드라인을 사용하여 테스트 사례를 선택합니다.
    • 이러한 가이드라인은 구성 요소를 개발할 때 프로그래머가 자주 저지르는 오류를 반영합니다.
    • "이런 코드에 대한 이런 실수를 많이 하더라"를 바탕으로 체크하는 test case를 만든다.

Partition testing(분할 테스트)

  • 입력 데이터와 출력 결과는 종종 클래스의 모든 멤버가 서로 연관되어 있는 다른 클래스로 나뉩니다.
  • 각 클래스는 동등한 분할 또는 도메인으로, 프로그램이 각 클래스의 모든 멤버에 대해 동등하게 작동하는 곳입니다.
  • 각 분할에서 테스트 사례를 선택해야 합니다.
  • ex) int n의 input으로 올 수 있는 것 --> (0, 자연수, 음수) or (0 이상, 음수)
  • ex) 4 / 2 나 2 / 3의 경우에 대한 output group

Equivalence partitioning(동등 분할)

 

 

 

Testing guidelines(collections) / 테스팅 가이드라인 (컬렉션)

  • 단일 값만 포함하는 collections을 사용하여 소프트웨어를 테스트합니다.
    • 예) List list = new ArrayList(); list.add(0);
  • 다양한 크기의 컬렉션을 사용하여 다른 테스트를 수행합니다.
  • 첫 번째, 중간, 마지막 요소가 접근되도록 테스트를 구성합니다.
    • ex) index 0, list.size() - 1
  • 길이가 0인 컬렉션으로 테스트합니다.

General testing guidelines(일반 테스팅 가이드라인)

  • 시스템이 모든 오류 메시지를 생성하도록 입력을 선택합니다.
    • 예) Java try/catch. 모든 catch 블록을 고려합니다.
  • 입력 버퍼가 오버플로우되도록 입력을 설계합니다.
    • ex) int 형의 범위, floating point decision
  • 같은 입력이나 일련의 입력을 여러 번 반복합니다.
  • 유효하지 않은 출력이 생성되도록 강제합니다.
  • 계산 결과가 너무 크거나 작아지도록 강제합니다.
    • ex) int a * b 에서, a==2^16, b==2^16이면 int형의 범위를 넘는다
    • ex) DB 접속 : Connection 후 close 할 때 Try-catch에서 닫아줘야 함(finally절 사용), 이에 대한 Test case 작성

Component testing(컴포넌트 테스팅)

  • 소프트웨어 컴포넌트는 종종 여러 상호 작용하는 객체로 구성된 복합 컴포넌트입니다.
    • 예를 들어, 소프트웨어는 사용자 데이터를 읽고 데이터를 분석할 수 있는 별도의 부분을 가질 수 있으며, 다양한 출처에서 얻은 데이터를 동일한 기술로 분석할 수 있습니다.
  • 정의된 컴포넌트 인터페이스를 통해 이러한 객체의 기능에 접근합니다.
    • 메서드가 다른 메서드를 사용할 때 Interface 규약이 존재함(자바에서는 javdoc)
    • ex) Input parameter를 올바르게 넘기고 있는지 Check
      • div (a, b) -> a / b 가 아니라 b / a를 리턴하도록 코드를 작성했을 수도 있음
  • 복합 컴포넌트 테스팅은 컴포넌트 인터페이스가 그 명세에 따라 동작함을 보여줘야 합니다.
    • 컴포넌트 내 개별 객체에 대한 unit tests가 완료되었다고 가정할 수 있습니다.

Interface testing(인터페이스 테스팅)

  • 목표는 인터페이스 오류나 인터페이스에 대한 잘못된 가정으로 인한 결함을 탐지하는 것입니다.
  • 프로세스가 여러 개이거나, 멀티 쓰레드 환경에서 주로 발생하는 것들을 check
  • 인터페이스 유형:
    • Parameter interfaces(매개변수 인터페이스): 한 메서드나 프로시저에서 다른 것으로 데이터가 전달됩니다.
    • Shared memory interfaces(공유 메모리 인터페이스): 메모리 블록이 프로시저나 함수 간에 공유됩니다.
    • Procedural interfaces(절차 인터페이스): 하위 시스템이 다른 하위 시스템에 의해 호출될 일련의 절차를 캡슐화합니다.
      • ex) Deadlock 테스트
    • Message passing interfaces(메시지 전달 인터페이스): 하위 시스템이 다른 하위 시스템으로부터 서비스를 요청합니다.

Interface errors(인터페이스 오류)

  • Interface misuse(인터페이스 오용)
    • 호출 컴포넌트가 다른 컴포넌트를 호출하고 그 인터페이스 사용에서 오류를 범합니다.
    • 예) 매개변수 순서가 잘못되었습니다.
  • Interface misunderstanding
    • 호출 컴포넌트가 호출된 컴포넌트의 동작에 대한 잘못된 가정을 포함합니다.
    • 예) null 대신 비어 있거나 기본 객체를 반환합니다.
  • Timing errors(타이밍 오류)
    • 호출된 컴포넌트와 호출 컴포넌트가 다른 속도로 작동하고 시간 정보에 접근이 이루어질 때 오류가 발생합니다.
    • ex) Shared resource에 대한 raise condition

Interface testing guidelines(인터페이스 테스트 가이드라인)

  • 호출된 프로시저에 대한 매개변수가 그 범위의 극단적인 끝에 있을 때 테스트를 설계하세요.
    • 코너 케이스나 경계 케이스입니다.
  • 항상 null 포인터를 가진 포인터 매개변수를 테스트하세요.
  • 컴포넌트가 실패하도록 테스트를 설계하세요.
  • 메시지 전달 시스템에서 스트레스 테스트를 사용하세요.
  • 공유 메모리 시스템에서는 컴포넌트가 활성화되는 순서를 변경하세요.

System testing(시스템 테스트)

  • 개발 중 시스템 테스트는 컴포넌트를 통합하여 시스템 버전을 만든 다음 통합된 시스템을 테스트하는 것을 포함합니다.
  • 시스템 테스트의 초점은 컴포넌트 간의 상호작용을 테스트하는 것입니다(testing the interactions between components).
    • Component 테스트를 위해 testcode를 짜게 되는데, 시스템을 전부 돌려보는 등으로 체크함
  • 시스템 테스트는 컴포넌트가 올바르게 상호작용하고 인터페이스를 통해 적절한 시간에 올바른 데이터를 전송하는지 확인합니다.
  • 시스템 테스트는 시스템의 긴급 동작(the emergent behaviour of a system)을 테스트합니다.

System and component testing(시스템 및 컴포넌트 테스트)

  • 시스템 테스트 중에는 별도로 개발된 재사용 가능한 컴포넌트와 시판용(off-the-shelf) 시스템이 새로 개발된 컴포넌트와 통합될 수 있습니다.
    • 그런 다음 전체 시스템이 테스트됩니다.
  • 다른 팀 멤버 또는 하위 팀에 의해 개발된 컴포넌트는 이 단계에서 통합될 수 있습니다.
    • 여태까지 개발한 테스트를 모아서 System testing이 되는 것에 가까움 
    • 시스템 테스트는 개별적인 프로세스가 아닌 집단적인 프로세스입니다.
    • 일부 회사에서는 설계자 및 프로그래머의 참여 없이 별도의 시스템 테스트 팀이 관여할 수 있습니다.
      • ex) 회사 QA 팀에서 Component를 모아서 System testing을 한다

Use-case testing(유스케이스 테스트)

  • 시스템 상호작용을 식별하기 위해 개발된 use-cases는 시스템 테스트의 기초로 사용될 수 있습니다.
  • 각 use case는 일반적으로 여러 시스템 컴포넌트를 포함하므로 테스트 중에 이러한 상호작용이 발생하도록 합니다.
  • use case 에 연관된 순서 다이어그램은 테스트되고 있는 구성요소 및 상호작용을 설명할 수 있습니다.
  • ex) UML, 복잡한 코드의 메서드 호출 순서(A->B->C...)

Testing Policies(테스트 정책)

  • 철저한 시스템 테스트는 불가능하므로 필요한 시스템 테스트 커버리지를 정의할 수 있는 테스팅 정책이 개발될 수 있습니다.
    • 이 정도까지 테스트 하면 괜찮다 를 정의
  • 테스팅 정책 예시:
    • 메뉴를 통해 접근되는 모든 시스템 기능을 테스트해야 합니다.
    • 같은 메뉴를 통해 접근되는 기능 조합(예: 텍스트 포맷팅)을 테스트해야 합니다.
      • 각 기능을 조합했을 때 문제가 없는지 check
    • 사용자 입력이 제공되는 경우, 모든 기능은 정확한 입력과 잘못된 입력 모두에서 테스트되어야 합니다.
    • 원자로 시스템 같은 경우에는 더 엄격한 Testing Policy를 가짐

Test-driven Development

  • Test-driven development(테스트 주도 개발(TDD)은 테스트와 코드 개발을 교차 진행하는 프로그램 개발 방식입니다.
  • 테스트는 코드 작성 전에 작성되며, 테스트 통과가 개발의 주요 동인입니다.
  • Setup, call, assertion 단계 중에서 Setup에서 어려움을 주로 겪음
  • 코드를 점진적으로 개발하며, 그 단계에 맞는 테스트를 함께 개발합니다.
    • 다음 단계로 넘어가기 전에 개발된 코드가 그 테스트를 통과해야 합니다.
  • TDD는 익스트림 프로그래밍과 같은 애자일 방법의 일부로 소개되었습니다.
    • 하지만, 계획 주도 개발 과정에서도 사용될 수 있습니다.

Benefits of Test-driven Development

  • Code coverage(코드 커버리지)
    • 작성하는 모든 코드 세그먼트에는 적어도 하나의 테스트가 연결되어 모든 코드가 테스트를 받습니다.
    • 내가 작성한 코드에 대해서 test case를 가지고 있기 때문에, code Coverage가 올라감
  • Regression testing(회귀 테스트)
    • 새로운 코드를 작성해도 기존 코드가 잘 작동하는지 
    • 프로그램이 개발됨에 따라 점진적으로 회귀 테스트 모음(suite)이 개발됩니다.
  • Simplified debugging(디버깅 간소화)
    • 왜 오류가 발생하는지 하나씩 실행을 해야하는데, test를 돌려봄으로써 어떤 부분에 문제가 있는지 체크할 수 있고, 이 부분을 자동화 할 수 있음 
    • 테스트 실패 시 문제가 있는 위치가 명확해지며, 새로 작성된 코드를 확인하고 수정해야 합니다.
  • System documentation(시스템 문서화)
    • Agile에서는 documentation을 최소화해야하는데, test case가 Specification과 같은 역할을 해준다 
    • 테스트 자체가 코드가 수행해야 할 작업을 설명하는 문서 형태로 작용합니다.

Regression Testing

  • Regression Testing(회귀 테스트)는 시스템을 테스트하여 변경 사항이 이전에 작동하던 코드를 '깨트리지' 않았는지 확인합니다.
    • ex) method X를 수정할 때, X를 호출하는 다른 메서드에서 문제가 발생하지 않는지 확인한다
  • 수동 테스팅 과정에서 회귀 테스트는 비용이 많이 들지만, 자동화 테스팅을 사용할 경우 간단하고 직관적입니다.
    • 변경이 이루어질 때마다 모든 테스트를 다시 실행합니다.
  • 테스트는 변경 사항이 커밋되기 전에 '성공적으로' 수행되어야 합니다.
  • TDD는 회귀 테스트를 확보하는 좋은 방법입니다.

Code Coverage

  • Statement Coverage(or Line Coverage) / 구문 커버리지(또는 라인 커버리지)
    • statement가 실행되면 충족됩니다.
    • 일반적으로 Code Coverage라고 함은 Statement Coverage를 말함
  • Branch Coverage(or Decision Coverage)
    • 각 branch(분기)가 실행되면 충족됩니다.
    • 코드 상에서 Branch가 발생하는 경우 (실행 경로가 달라지는 경우)에 실행할 수 있는 서로 다른 경로가 잘 실행되는지
      • ex) if-else 문에서 실행 경로가 갈리짐
  • Condition Coverage(조건 커버리지)
    • branch(분기) 내 각 조건이 테스트되면 충족됩니다.
    • ex) (A && B) || C 에서 A, B, C의 T/F

Increasing Code Coverage

  • 테스트 케이스의 setup 부분과 call 부분을 신중하게 설계함으로써 코드 커버리지를 높일 수 있습니다.
  • 자바에서는 private 메소드가 public 메소드에 의해 호출되어야 합니다.
    • 테스트가 모든 public 메소드를 호출하고, 메소드 내의 모든 분기를 취하면 이론적으로 100% 라인/분기 커버리지를 달성할 수 있습니다.
    • 만약 private 메서드를 호출 안한다면 그냥 그 메서드를 지우고, 필요할 때 commit log를 확인해서 가져다 쓰자
  • 이를 위해 적절한 객체 인스턴스를 생성하는 것이 중요하며, 이는 메소드를 호출하는 데 사용될 수 있습니다.
    • 좋은 모듈화는 프로그램의 각 단위에 대한 테스트 케이스를 작성하기 쉽게 만듭니다.
  • Tip
    • 메서드가 100줄이라고 하면, Unit test에서는 input을 던져서 100줄 다 Cover 할 수 있도록 하자
    • 이를 위해서 if() A, else B라고 하면 A와 B를 다른 메서드로 분리해줄 수 있다(Clean-Code에 있는 내용인 듯)
    • java에서는 mockito의 Mock-up을 이용해서 커버리지를 올릴 수 있다
  • 테스트 스윗의 라인 커버리지가 99%라고 하더라도, 에러를 더 잘 발견한다고 보기 어렵다. 적절한 Input을 구성해야 함

 

Limitation of Code Coverage

  • 코드 커버리지는 테스트 스위트의 품질 또는 성능을 평가하는 데 사용됩니다.
    • 코드의 얼마나 많은 부분이 테스트 되었나요?
  • 자동화 테스트 연구는 종종 분기 커버리지를 사용합니다.
    • RandooP, EvoSuite 같은 도구가 JUnit 테스트 케이스 생성에 사용됩니다.
    • 물론, 이렇게 해서 커버리지를 올려도 실제로 오류 발견 확률이 올라가지 않을 수 있음
  • 최근 연구에 따르면 코드 커버리지만으로는 테스트 스위트 평가에 충분하지 않습니다.
    • 실제로 결함을 감지하는지에 대한 질문이 제기됩니다.
  • Mutation testing(돌연변이 테스트): 코드를 자동으로 변형하여 결함을 심고, 테스트가 결함을 감지할 수 있는지 확인합니다.
    • Java 돌연변이 테스트를 위한 PIT 도구가 사용됩니다.
    • 코드 일부를 변형한다면(ex. If문을 제거하거나, a = b와 같은 statement 제거) 에러가 발생해야 하는데, 이를 체크한다

 

TDD Example

 

 

 

 

 

 

// NFR test(계산 속도)
@Test
@Timeout(value = 1, unit = TimeUnit.SECONDS)
void testFibonnaci2() {
	assertTimeout(Duration.ofMillis(1), () —> {
		SimpleMath.fibonacci(50);
	});
}

// 메서드 구현 코드

public static int fibonacci(int n) {
	return fibonacci(n-1, 1, 1);
}

private static int fibonacci(int n, int pp, int p) {
	if (n <= 2) {
		return p;
	} else {
		return fibonacci(n-1, p, pp*p);
	}
}

 

 

Release Testing

  • 릴리즈 테스팅은 개발 팀 외부에서 사용하도록 의도된 특정 릴리즈의 시스템을 테스트(testing a particular release of a system that is intended for use outside of the development team)하는 과정입니다.
  • 릴리즈 테스팅의 주요 목표는 시스템 공급자에게 시스템이 사용에 충분히 좋다는 것을 확신시키는 것입니다.
    • 따라서, 릴리즈 테스팅은 시스템이 지정된 기능, 성능 및 신뢰성을 제공하며 정상 사용 중에 실패하지 않음을 보여야 합니다.
  • 릴리즈 테스팅은 일반적으로 블랙박스 테스팅 과정으로, 테스트는 시스템 명세에서만 파생됩니다.
    • 화이트박스 테스팅과 대조됩니다.

Release testing and system testing(릴리스 테스팅과 시스템 테스팅)

  • 릴리스 테스팅은 시스템 테스팅의 한 형태입니다.
  • 중요한 차이점:
    • 시스템 개발에 참여하지 않은 별도의 팀이 릴리스 테스팅을 담당해야 합니다.
    • 개발 팀에 의한 시스템 테스팅은 시스템 내 버그를 발견하는 데 중점을 둬야 합니다 (결함 테스팅) / focus on discovering bus in the system(defct testing).
    • 릴리스 테스팅의 목적은 시스템이 요구 사항을 충족하고 외부 사용에 충분히 좋은지 확인하는 것입니다 (검증 테스팅). / to check that the system meets its requirements and is good enough for external use(validation testing)

Requirements based testing(요구 사항 기반 테스팅)

  • 요구 사항 기반 테스팅(Requirements-based testing)은 각 요구 사항을 검토하고 이에 대한 테스트를 개발하는 것을 포함합니다.
  • 이미 중간 릴리스 목록에 대한 요구 사항 기반 테스팅 경험이 있습니다.
  • 개발된 테스트가 반드시 자동화된 테스트일 필요는 없습니다.
    • 단순히 시나리오를 정의하여 요구 사항이 충족되는지 확인할 수 있습니다.

Performance testing(성능 테스팅)

  • 릴리스 테스트의 일부에는 성능 및 안정성과 같은 시스템의 새로운 속성 테스트가 포함될 수 있습니다.
  • 테스트는 시스템 사용 프로필을 반영해야 합니다.
  • 성능 테스트는 일반적으로 시스템 성능이 수용할 수 없을 때까지 부하를 점진적으로 늘리는 일련의 테스트를 계획하는 것을 포함합니다.
  • 스트레스 테스트는 시스템을 고의로 과부하 상태로 만들어 그 실패 행동을 테스트하는 성능 테스트의 한 형태입니다.
  • ex) API request가 10000개 일 때, 5초 안에 return 해줘야 한다
  • 보통 Development 팀이 아니라 외부 team(ex. QA team)이 이런 것들을 test 함

User testing(사용자 테스팅)

  • 사용자 또는 고객 테스팅은 사용자 또는 고객이 시스템 테스팅에 대한 의견을 제공하는 테스트 과정의 단계입니다.
  • 사용자 테스팅은 포괄적인 시스템 및 릴리스 테스팅이 수행된 후에도 필수적입니다.
    • 이는 사용자의 작업 환경에서 발생하는 영향(influnces from the user's working environment have a major effect)이 시스템의 신뢰성, 사용성 및 견고성에 주요한 영향을 미치기 때문입니다.
      • target env랑, working env를 고려해야 한다.
      • ex) MAC의 Javadoc과 Linux의 Javadoc 차이 존재
    • 이러한 것들은 테스트 환경에서 재현할 수 없습니다.

Types of user testing(사용자 테스팅의 유형)

  • Alpha testing(알파 테스팅)
    • 소프트웨어의 사용자가 개발자 사이트에서 개발 팀과 함께 소프트웨어를 테스트합니다.
    • ex) 유저를 초청해서 Test하거나, 회사 내부에서 테스트를 진행하는 등
  • Beta testing(베타 테스팅)
    • 소프트웨어의 릴리스가 사용자에게 제공되어 시스템과 관련된 문제를 발견하고 제기할 수 있도록 합니다.
    • 불특정 다수를 대상으로 Release를 배포하여 feedback을 받는다
  • Acceptance testing(승인 테스팅)
    • 고객이 시스템을 테스트하여 시스템 개발자로부터 배포되고 고객 환경에서 사용할 준비가 되었는지를 결정합니다. 주로 맞춤형 시스템에 사용됩니다.

 

User Testing for Different Types of Software(다양한 소프트웨어 유형에 대한 사용자 테스팅)

  • 소프트웨어가 사용자 테스팅에 충분히 개발되었음에도 불구하고 아직 테스팅 단계에 있습니다.
  • 이 기간 동안 발견되지 않은 오류가 발생할 수 있습니다.
  • 따라서 다양한 소프트웨어 유형에 대해 사용자 테스팅을 설계하고 수행할 필요가 있습니다.
    • 예를 들어, 온라인 게임의 베타 테스팅은 자율 주행 소프트웨어나 금융 소프트웨어에 비해 더 쉽게 수행될 수 있습니다.

Agile methos and acceptance testing(애자일 방법론 및 승인 테스팅)

  • 애자일 방법에서 사용자/고객은 개발 팀의 일부이며 시스템의 수용성에 대한 결정을 내리는 책임이 있습니다.
  • 테스트는 사용자/고객에 의해 정의되며 변경이 이루어질 때 자동으로 실행되도록 다른 테스트와 통합됩니다.
  • 여기서 주요 문제는 내장된 사용자가 '전형적'이고 모든 시스템 이해관계자의 이익을 대표할 수 있는지 여부입니다.
  • Acceptance testing(ex. 계약맺고 개발하여 제공하고, 돈을 정산 받는 구조) --> Agile은 이런 과정이 아님

요약

  • Program testing은 verification 및 validation 과정에서 중요한 부분입니다.
    • 테스팅의 두 가지 주요 목표는 요구 사항 확인과 결함 발견입니다.
  • Software inspection는 문제를 발견하기 위한 static verification이며, software testing은 프로그램 동작을 관찰하기 위한 dynamic verification입니다.
  • 프로그램 테스팅은 development testing, release testing and user testing으로 구성됩니다.
  • TDD는 테스트와 코드 개발을 교차하여 진행하는 접근 방식으로, 개발된 프로그램이 통과해야 하는 테스트 케이스 작성부터 시작합니다.
  • 유닛테스트 / Partition Test는 꼭 기억하자

+ Recent posts