소프트웨어 공학

소프트웨어 공학(Software Engineering)은 신뢰할 수 있고 유지보수 가능한 소프트웨어를 경제적이고 체계적으로 개발·운영하기 위해 공학적 원리와 방법을 적용하는 학문이자 실무 분야이다. 개별 프로그램의 작성뿐만 아니라 문제와 요구사항의 분석, 시스템 구조의 설계, 구현, 시...

영문명Software Engineering
분류공학, 컴퓨팅
주요 대상소프트웨어 시스템과 개발·운영 과정
주요 활동요구사항 분석, 설계, 구현, 검증, 배포, 운영, 유지보수
관련 분야컴퓨터 과학, 시스템 공학, 프로젝트 관리, 품질 관리
용어 정착1968년 NATO 소프트웨어 공학 회의

소프트웨어 공학(Software Engineering)은 신뢰할 수 있고 유지보수 가능한 소프트웨어를 경제적이고 체계적으로 개발·운영하기 위해 공학적 원리와 방법을 적용하는 학문이자 실무 분야이다. 개별 프로그램의 작성뿐만 아니라 문제와 요구사항의 분석, 시스템 구조의 설계, 구현, 시험, 배포, 운영, 유지보수, 품질 관리와 프로젝트 관리에 이르는 소프트웨어의 전체 생명주기를 다룬다.

소프트웨어는 물리적인 제품과 달리 복제 과정에서 거의 마모되지 않지만, 요구사항과 실행 환경이 계속 변하고 구성 요소 사이의 관계가 복잡해지면서 설계 결함, 보안 취약점, 성능 저하와 유지보수 비용이 누적될 수 있다. 소프트웨어 공학은 이러한 복잡성을 통제하기 위해 명확한 요구사항, 모듈화된 구조, 추상화와 정보 은닉, 버전 관리, 코드 검토, 자동화된 시험, 지속적 통합, 운영 관찰과 같은 기술적·조직적 수단을 함께 사용한다.

소프트웨어 공학의 대상은 실행 코드에 한정되지 않는다. 요구사항 명세, 아키텍처와 설계 문서, 시험 자료, 빌드 및 배포 설정, 데이터 모델, 사용자 문서, 운영 절차와 변경 이력도 소프트웨어 시스템을 구성하고 유지하는 중요한 산출물로 다뤄진다. 개발자는 이러한 산출물과 소스 코드를 함께 관리하며, 시스템이 요구된 기능과 품질 속성을 충족하는지 지속적으로 확인한다.

소프트웨어 공학은 컴퓨터 과학과 밀접하지만 중심 관점에는 차이가 있다. 컴퓨터 과학이 계산의 원리, 알고리즘, 자료구조와 계산 가능성 등을 연구한다면, 소프트웨어 공학은 그러한 지식을 이용하여 실제 환경에서 장기간 사용되는 소프트웨어 시스템을 여러 사람이 계획하고 구축하며 변화시키는 과정에 초점을 둔다. 동시에 시스템 공학, 인간-컴퓨터 상호작용, 사이버 보안, 데이터베이스, 컴퓨터 네트워크, 프로젝트 관리와도 긴밀하게 연결된다.

“소프트웨어 공학”이라는 표현은 1960년대 대규모 소프트웨어 프로젝트에서 일정 지연, 예산 초과, 낮은 신뢰성과 유지보수의 어려움이 반복되던 상황에서 널리 주목받기 시작했다. 1968년 서독 가르미슈에서 열린 NATO 회의는 소프트웨어 개발 문제를 공학적 관점에서 논의하고 이 용어를 확산시킨 중요한 계기로 평가된다.[1]

오늘날 소프트웨어 공학은 하나의 고정된 개발 절차를 뜻하지 않는다. 순차적으로 단계를 진행하는 폭포수 모델, 반복과 점진적 전달을 강조하는 애자일 소프트웨어 개발, 개발과 운영을 연결하는 DevOps, 안전성과 규정 준수를 중시하는 고신뢰성 개발 등 서로 다른 접근이 시스템의 규모와 목적에 맞게 사용된다. IEEE Computer Society의 SWEBOK는 요구사항, 설계, 구축, 시험, 유지보수, 형상 관리, 관리, 프로세스, 모델과 방법, 품질, 보안과 운영 등을 소프트웨어 공학의 주요 지식 영역으로 정리한다.[2]

소프트웨어 공학에서 공학적이라는 말은 모든 프로젝트에 무거운 절차와 문서를 적용한다는 의미가 아니다. 필요한 수준의 증거와 통제 방법을 선택하고, 비용·일정·기능·품질·위험 사이의 균형을 측정 가능한 방식으로 관리한다는 의미에 가깝다. 개인이 만드는 작은 프로그램에서도 버전 관리와 자동화된 시험을 적용할 수 있으며, 항공·의료·금융·통신과 같은 대규모 또는 안전 필수 시스템에서는 더욱 엄격한 검증, 추적성, 독립적인 평가와 표준 준수가 요구된다.

역사

소프트웨어 공학의 역사는 소프트웨어 공학이라는 용어가 만들어진 1960년대부터 시작하지 않는다. 그보다 앞서 계산 절차를 표현하는 방법이 등장하고, 컴퓨터가 저장된 프로그램을 실행할 수 있게 되었으며, 운영체제와 프로그래밍 언어가 만들어지고, 소프트웨어가 하드웨어와 구별되는 독립적인 제품으로 발전한 과정 전체가 그 배경을 이룬다.

초기의 소프트웨어는 특정 기계에서 하나의 계산을 수행하기 위한 명령열에 가까웠다. 이후 소프트웨어 안에서 다른 소프트웨어를 실행하고 관리하는 운영체제, 프로그램을 작성하는 컴파일러와 개발 도구, 데이터를 관리하는 데이터베이스 관리 시스템, 사용자 작업을 수행하는 응용 프로그램이 차례로 발전했다. 개인용 컴퓨터와 인터넷이 보급된 뒤에는 소프트웨어가 일반 사용자의 일상과 산업 활동을 직접 구성하기 시작했고, 웹·모바일·클라우드 시대에는 여러 지역의 컴퓨터와 서비스를 계속 연결하고 갱신하는 분산 시스템으로 확장되었다.

이러한 변화에 따라 소프트웨어 개발은 한 사람이 기계 명령을 작성하는 작업에서 다수의 조직이 장기간 시스템을 설계·운영하는 활동으로 변했다. 소프트웨어 공학의 역사에는 프로그램과 운영체제, 프로그래밍 언어와 개발 도구의 발전뿐 아니라 소프트웨어를 생산하고 검증하며 배포하고 유지보수하는 방법의 변화도 함께 포함된다.

계산 절차와 프로그램 개념의 형성

컴퓨터가 등장하기 전에도 일정한 순서에 따라 계산이나 작업을 수행하게 하는 개념은 존재했다. 수학의 알고리즘, 자동 직기의 천공 카드, 자동 연주 장치와 기계식 계산기는 정보에 따라 기계의 동작을 바꿀 수 있다는 가능성을 보여 주었다. 그러나 이 시기의 절차는 특정 기계 장치나 물리적 배치에 직접 결합되어 있었으며, 현대적인 의미의 범용 소프트웨어와는 차이가 있었다.

19세기에 찰스 배비지가 구상한 해석기관은 저장 장치와 연산 장치, 조건에 따른 실행과 반복을 포함하는 범용 계산 기계의 구조를 제시했다. 에이다 러브레이스는 해석기관을 위해 베르누이 수를 계산하는 절차를 작성하고, 이러한 기계가 수치 계산을 넘어 기호를 조작할 가능성도 논의했다. 해석기관은 당시 완성되지 못했지만, 기계의 물리적 구조와 기계가 수행할 절차를 구별하는 관점을 발전시키는 데 중요한 역할을 했다.

1930년대에는 앨런 튜링튜링 기계알론조 처치의 람다 계산 등이 계산 가능한 절차를 수학적으로 설명했다. 이 이론들은 실제 소프트웨어 개발 방법을 직접 제공한 것은 아니지만, 하나의 범용 기계가 서로 다른 명령을 받아 여러 계산을 수행할 수 있다는 프로그램 개념의 이론적 기반을 마련했다.

1940년대 콘라트 추제는 기계와 독립적으로 계산 절차를 표현하기 위한 Plankalkül을 설계했다. Plankalkül은 당시에 널리 구현되거나 사용되지는 않았지만, 자료형과 배열, 제어 구조를 포함한 초기 고수준 프로그래밍 언어 설계로 평가된다.[3]

초기 전자식 컴퓨터와 물리적 프로그래밍

1940년대의 초기 전자식 컴퓨터에서는 프로그램과 기계의 구성이 명확히 분리되지 않았다. 계산 내용을 바꾸려면 배선을 다시 연결하거나 스위치와 플러그보드를 조정하고, 천공 카드나 종이테이프에 명령과 데이터를 기록해야 했다. 프로그램 작성은 수학적 절차를 설계하는 일인 동시에 기계의 신호 흐름과 기억 장치를 직접 구성하는 작업이었다.

ENIAC은 전자식으로 빠른 계산을 수행할 수 있었지만, 초기에는 현대적인 저장 프로그램 컴퓨터가 아니었다. 새로운 문제를 실행하려면 플러그보드의 케이블과 스위치를 물리적으로 다시 배치해야 했으며, 복잡한 프로그램의 준비에는 상당한 시간이 필요했다.[4]

이 시기의 프로그래머들은 기계가 수행할 계산을 작은 단계로 분해하고, 제한된 기억 공간과 연산 장치를 배치하며, 실행 결과를 수작업으로 확인했다. 프로그램에 오류가 발생하면 오늘날과 같은 디버거와 로그가 없었기 때문에 기계의 상태와 중간 결과를 직접 추적해야 했다. 따라서 초기 프로그래밍에서는 하드웨어 지식과 수학적 분석 능력이 긴밀하게 결합되어 있었다.

저장 프로그램 방식과 소프트웨어의 분리

프로그램을 데이터와 함께 기억 장치에 저장하는 저장 프로그램 방식은 소프트웨어 역사에서 결정적인 전환점이었다. 프로그램을 변경하기 위해 기계를 다시 배선하는 대신, 기억 장치에 저장된 명령을 교체하여 같은 컴퓨터가 전혀 다른 작업을 수행할 수 있게 되었기 때문이다.

1945년에 배포된 EDVAC 관련 보고서는 프로그램 명령과 데이터를 전자식 기억 장치에 저장하는 컴퓨터 구조를 설명했다. 이 구상은 이후 여러 저장 프로그램 컴퓨터의 설계에 영향을 주었다. 다만 저장 프로그램 개념은 여러 연구자와 프로젝트에서 점진적으로 형성되었으므로, 이를 한 사람이나 한 기계만의 발명으로 단순화하기는 어렵다.

1948년 6월 21일 영국 맨체스터 대학교의 Manchester Baby는 기억 장치에 저장된 프로그램을 실행했다. 실행된 프로그램은 수의 최대 약수를 찾는 17개 명령으로 구성되었으며, 전자식 디지털 저장 프로그램 컴퓨터에서 실제 프로그램이 실행된 초기의 중요한 사례로 기록된다.[5][6]

저장 프로그램 방식이 정착되면서 프로그램은 기계의 물리적 배선과 점차 분리되었다. 프로그램을 저장하고 복사하며 수정할 수 있게 되었고, 하나의 프로그램이 다른 프로그램을 읽거나 생성하는 것도 가능해졌다. 이후 등장한 어셈블러, 컴파일러, 운영체제는 모두 소프트웨어가 다른 소프트웨어의 작성과 실행을 지원한다는 구조에서 발전했다.

기계어, 어셈블리어와 초기 개발 도구

초기 저장 프로그램 컴퓨터의 프로그램은 숫자로 표현된 기계어 명령으로 작성되었다. 프로그래머는 각 명령의 코드와 기억 장치 주소를 직접 관리해야 했으며, 프로그램의 일부를 옮기면 여러 주소를 함께 수정해야 했다. 프로그램 규모가 커질수록 명령 번호를 잘못 기록하거나 분기 주소를 혼동하는 문제가 증가했다.

어셈블리어어셈블러는 기계 명령을 사람이 기억하기 쉬운 기호로 표현하고, 기호 이름을 실제 주소와 명령 코드로 변환했다. 이를 통해 프로그래머는 원시적인 숫자 명령 대신 연산 이름과 레이블을 사용하여 프로그램을 작성할 수 있었다.

서브루틴 라이브러리와 로더, 링커도 발전했다. 자주 사용하는 수학 함수나 입출력 절차를 매번 새로 작성하지 않고 별도의 코드로 저장한 뒤 다른 프로그램에서 결합할 수 있게 되었다. 이러한 도구는 프로그램을 여러 부분으로 나누고 기존 코드를 재사용하는 초기 소프트웨어 공학의 기반을 형성했다.

동시에 프로그램 코드와 사용 방법, 입출력 형식을 설명하는 문서가 중요해졌다. 프로그램이 작성자 한 사람의 기억에만 의존하지 않고 다른 사람에게 전달되기 시작하면서 명명 규칙, 주석, 설명서와 변경 기록이 소프트웨어의 일부로 취급되기 시작했다.

고수준 프로그래밍 언어와 컴파일러

1950년대에는 기계의 명령 체계보다 문제 영역에 가까운 표현을 사용하는 고수준 프로그래밍 언어가 본격적으로 등장했다. 고수준 언어는 사람이 작성한 프로그램을 기계어로 변환하는 컴파일러 또는 실행 중 해석하는 인터프리터를 필요로 했다. 컴파일러는 프로그램을 작성하는 소프트웨어이며, 소프트웨어가 다른 소프트웨어의 생산 과정 자체를 자동화한 대표적인 사례가 되었다.

FORTRAN은 수식과 반복문을 이용하여 과학·공학 계산을 표현할 수 있도록 설계되었다. IBM의 존 배커스 팀이 개발한 첫 FORTRAN 컴파일러는 1957년에 배포되었다. FORTRAN의 성공에는 언어 문법뿐 아니라 수작업으로 작성한 어셈블리 코드에 가까운 성능을 내는 기계어를 생성한 컴파일러의 품질이 중요한 역할을 했다.[7]

COBOL은 기업과 행정 기관의 자료 처리에 적합한 언어를 목표로 개발되었다. 서로 다른 제조사의 컴퓨터에서도 비교적 적은 수정으로 프로그램을 실행할 수 있도록 기계 독립성과 표준화가 강조되었다. ALGOL은 블록 구조와 재귀 호출, 형식적인 문법 기술을 통해 이후 많은 프로그래밍 언어의 설계에 영향을 미쳤다.[8]

고수준 언어는 프로그램을 더 짧고 읽기 쉽게 만들었지만, 소프트웨어 개발의 모든 문제를 해결하지는 않았다. 프로그램 규모가 커지면서 요구사항의 모호성, 구성 요소 사이의 의존성, 변경 관리, 시험과 일정 예측이 새로운 문제로 부각되었다. 프로그래밍 언어가 개별 명령의 복잡성을 줄였다면, 소프트웨어 공학은 시스템 전체와 개발 조직의 복잡성을 다루기 위해 발전했다.

운영체제와 소프트웨어 계층의 형성

초기의 컴퓨터는 한 번에 하나의 프로그램을 수동으로 준비해 실행했다. 작업이 끝날 때마다 운영자가 다음 프로그램과 데이터를 장착해야 했으며, 비싼 컴퓨터가 입출력을 기다리는 동안 사용되지 않는 시간이 많았다.

1950년대에는 여러 작업을 모아 순서대로 실행하는 일괄 처리 시스템이 등장했다. 1956년 General Motors Research와 North American Aviation이 IBM 704용으로 구현한 GM-NAA I/O 시스템은 초기 운영체제의 대표적인 사례다. 이러한 시스템은 입력과 출력, 프로그램 적재와 작업 전환을 자동화하여 컴퓨터의 가동률을 높였다.[9]

운영체제는 응용 프로그램과 하드웨어 사이에 새로운 소프트웨어 계층을 만들었다. 응용 프로그램은 저장 장치나 프린터를 직접 제어하는 대신 운영체제가 제공하는 입출력 기능을 호출할 수 있게 되었다. 운영체제는 여러 프로그램의 실행을 조정하고 기억 장치와 주변 장치를 관리하며 오류를 처리했다. 이후 프로그램은 하드웨어뿐 아니라 운영체제가 제공하는 인터페이스를 대상으로 작성되기 시작했다.

1960년대에는 여러 사용자가 하나의 컴퓨터를 대화식으로 공유하는 시분할 시스템이 발전했다. CTSSMultics는 사용자 계정, 파일 시스템, 보호, 다중 사용자 실행과 같은 개념을 발전시켰다. 일괄 처리 환경에서 프로그램 결과를 확인하려면 오랜 시간을 기다려야 했지만, 시분할 환경에서는 사용자가 터미널에서 명령을 입력하고 빠르게 결과를 확인할 수 있었다.[10]

1969년 Bell Labs에서 시작된 UNIX는 프로세스, 파일, 파이프와 작은 도구의 조합을 중심으로 비교적 단순하고 이식 가능한 운영 환경을 제공했다. UNIX는 이후 대학과 연구 기관, 워크스테이션, 서버와 인터넷 기반 시설에 널리 확산되었으며, BSD, Linux, 여러 상용 UNIX와 현대 운영체제 설계에 큰 영향을 미쳤다.[11]

운영체제가 발전하면서 소프트웨어의 실행 구조는 계층화되었다. 하드웨어 위에서 운영체제 커널이 실행되고, 그 위에서 시스템 라이브러리와 런타임, 개발 도구와 응용 프로그램이 실행되는 구조가 형성되었다. 따라서 운영체제도 소프트웨어이지만, 동시에 다른 소프트웨어가 실행될 자원과 규칙을 제공하는 기반 소프트웨어가 되었다.

대규모 시스템과 소프트웨어 위기

1950년대 말부터 컴퓨터가 군사, 우주 개발, 금융, 항공 예약, 통신과 행정 업무에 사용되면서 소프트웨어의 규모와 중요성이 빠르게 증가했다. 단순한 수치 계산 프로그램과 달리 이러한 시스템은 많은 사용자와 장치, 복잡한 데이터, 실시간 처리와 장기간의 운영을 지원해야 했다.

SAGE 방공 시스템, SABRE 항공 예약 시스템, IBM System/360과 그 운영체제 OS/360 같은 프로젝트는 소프트웨어가 대규모 조직과 사회 기반 시설을 직접 운영할 수 있음을 보여 주었다. 동시에 수백 명의 개발자가 참여하는 프로젝트에서는 설계 변경, 일정 지연, 결함, 문서 불일치와 구성 요소 통합 문제가 반복되었다.

하드웨어 제조 기술은 빠르게 발전했지만, 소프트웨어 생산성은 같은 속도로 증가하지 않았다. 더 빠르고 큰 컴퓨터가 등장할수록 이전에는 만들 수 없었던 복잡한 시스템이 요구되었고, 늘어난 자원은 더 큰 프로그램을 만드는 데 사용되었다. 프로젝트의 규모가 커지면서 개발 비용이 예상보다 증가하고, 완성된 시스템이 요구사항을 충족하지 못하거나 안정적으로 작동하지 않는 일이 발생했다.

이러한 상황은 흔히 소프트웨어 위기라고 불렸다. 소프트웨어 위기는 특정 시기에 발생해 끝난 단일 사건이라기보다, 소프트웨어의 복잡성과 사회적 의존도가 개발 능력보다 빠르게 증가하면서 나타난 문제를 가리킨다. 일정과 비용을 정확히 예측하기 어렵고, 프로그램의 정확성을 입증하기 어려우며, 수정할수록 새로운 결함이 발생하는 현상이 핵심 문제로 인식되었다.

소프트웨어 공학의 성립

1968년 NATO 과학위원회는 서독 가르미슈파르텐키르헨에서 소프트웨어 개발 문제를 논의하는 회의를 개최했다. 이 회의에서는 대규모 프로그램의 설계와 생산, 배포와 유지보수를 보다 체계적인 원칙에 따라 수행해야 한다는 의미로 소프트웨어 공학이라는 표현이 사용되었다. 1969년에는 이탈리아 로마에서 후속 회의가 열렸다.[12]

소프트웨어 공학이라는 명칭에는 프로그램 개발을 개인적인 기예에만 의존하지 않고, 명세와 설계, 검증, 측정과 관리가 가능한 공학 활동으로 만들려는 의도가 담겨 있었다. 다만 기계 공학이나 토목 공학의 절차를 그대로 소프트웨어에 적용한다는 의미는 아니었다. 소프트웨어는 물리적으로 마모되지 않으며, 수정이 비교적 쉬운 대신 변경으로 인한 논리적 영향이 시스템 전체에 퍼질 수 있다는 특성이 있었다.

당시의 논의에서는 대규모 시스템, 시분할, 프로그램 구조, 설계 과정, 시험, 관리와 교육 문제가 함께 다뤄졌다. 이후 요구사항 분석, 모듈화, 형상 관리, 품질 보증, 프로젝트 계획과 유지보수 등이 소프트웨어 공학의 독립적인 활동으로 발전했다.

1969년 IBM이 일부 프로그램을 하드웨어 가격에서 분리하여 별도의 제품과 서비스로 제공하기 시작한 것도 소프트웨어 산업의 형성에 중요한 영향을 주었다. 소프트웨어가 컴퓨터 구매에 부수적으로 포함되는 요소에서 독립적으로 개발·판매·지원되는 상품으로 변화하면서 전문 소프트웨어 기업과 패키지 소프트웨어 시장이 성장했다.[13]

구조적 프로그래밍과 개발 방법론

1960년대 말과 1970년대에는 프로그램의 제어 흐름과 구조를 명확하게 만들려는 구조적 프로그래밍이 확산되었다. 임의의 위치로 이동하는 복잡한 분기 대신 순차 실행, 조건문과 반복문을 중심으로 프로그램을 구성하고, 큰 문제를 여러 절차와 모듈로 분해하는 방법이 강조되었다.

에츠허르 데이크스트라, 토니 호어, 니클라우스 비르트 등을 비롯한 연구자들은 프로그램의 구조와 정확성, 추상화와 명세를 연구했다. Pascal, C, Modula, Ada와 같은 언어들은 구조적 프로그래밍, 모듈화, 시스템 프로그래밍 또는 고신뢰성 개발의 요구를 서로 다른 방식으로 반영했다.

구조적 분석과 구조적 설계는 프로그램 코드뿐 아니라 시스템의 입력, 처리와 데이터 흐름을 단계적으로 모델링하려 했다. 자료 흐름도, 구조도, 상태 전이와 데이터 사전 같은 표기법이 사용되었으며, 요구사항 분석에서 설계와 구현으로 이어지는 절차를 정형화하려는 여러 방법론이 등장했다.

이 시기에는 개발 단계를 요구사항, 분석, 설계, 구현, 시험과 유지보수로 구분하는 소프트웨어 생명주기 관점이 정착했다. 이후 흔히 폭포수 모델이라고 불린 순차적 개발 방식은 단계별 검토와 문서화를 강조했다. 실제 프로젝트에서는 이전부터 반복과 수정이 이루어졌지만, 순차적 모형은 계약과 관리, 군사·정부 프로젝트에서 작업과 산출물을 정의하는 기준으로 널리 사용되었다.

데이터베이스와 기업용 소프트웨어

기업과 공공 기관에서 처리하는 데이터가 증가하면서 여러 응용 프로그램이 공통 데이터를 저장하고 검색할 수 있는 데이터베이스 관리 시스템이 발전했다. 초기의 파일 중심 프로그램에서는 각 응용 프로그램이 자체 파일 형식과 검색 절차를 관리했기 때문에 데이터 중복과 불일치가 발생하기 쉬웠다.

1960년대의 계층형·네트워크형 데이터베이스는 복잡한 업무 데이터를 장기간 관리하는 기반을 제공했다. 1970년 에드거 F. 코드가 제안한 관계형 데이터베이스 모델은 데이터를 관계와 집합 연산으로 표현하고, 물리적인 저장 방식과 논리적인 데이터 구조를 분리하는 방향을 제시했다. 이후 SQL과 상용 관계형 데이터베이스가 확산되면서 데이터 관리는 응용 프로그램에서 독립된 소프트웨어 계층으로 발전했다.

회계, 급여, 재고, 생산, 금융과 행정 업무를 처리하는 기업용 소프트웨어도 성장했다. 조직의 여러 부서를 통합하는 전사적 자원 관리와 고객 관계 관리, 공급망 관리 시스템이 등장했으며, 소프트웨어는 단순히 기존 업무를 빠르게 처리하는 도구를 넘어 조직의 업무 절차 자체를 규정하는 기반이 되었다.

기업용 소프트웨어는 수십 년 동안 데이터를 유지하고 여러 시스템과 연동해야 했기 때문에 하위 호환성, 데이터 이전, 접근 제어, 감사 기록과 장기 유지보수가 중요한 소프트웨어 공학 문제로 자리 잡았다.

객체 지향과 그래픽 사용자 환경

1960년대의 Simula는 시뮬레이션 대상을 상태와 동작을 가진 객체로 표현하기 위해 클래스, 객체, 상속과 가상 절차 개념을 발전시켰다. 1970년대 Xerox PARC에서 개발된 Smalltalk은 거의 모든 대상을 객체로 다루고, 그래픽 환경 안에서 실행 중인 프로그램을 직접 수정하는 개발 방식을 제공했다.

객체 지향 프로그래밍은 1980년대와 1990년대에 C++, Objective-C, Java 등의 언어를 통해 널리 확산되었다. 데이터와 그 데이터를 처리하는 동작을 하나의 단위로 묶고, 인터페이스 뒤에 구현을 감추며, 기존 클래스를 확장하거나 여러 객체를 조합하는 방식이 대규모 응용 프로그램 개발에 적용되었다.

그래픽 사용자 인터페이스도 소프트웨어 구조를 변화시켰다. Xerox PARC의 연구 시스템에서 발전한 창, 아이콘, 메뉴와 포인터 기반 인터페이스는 Apple Lisa, Macintosh, Microsoft Windows 등을 통해 개인용 컴퓨터에 확산되었다. Apple Lisa는 1983년에 상용 그래픽 사용자 인터페이스를 갖춘 중요한 개인용 컴퓨터로 출시되었고, 1984년 Macintosh는 마우스 중심의 그래픽 환경을 대중화했다.[14]

그래픽 응용 프로그램은 사용자 입력, 창과 이벤트, 문서 상태, 화면 갱신을 동시에 관리해야 했다. 이에 따라 이벤트 기반 프로그래밍, 모델과 화면의 분리, 사용자 인터페이스 툴킷과 응용 프로그램 프레임워크가 발전했다. 운영체제는 단순한 작업 실행기를 넘어 그래픽, 오디오, 네트워크와 응용 프로그램 설치를 관리하는 사용자 플랫폼으로 변화했다.

개인용 컴퓨터와 패키지 소프트웨어 산업

1970년대 후반과 1980년대에는 마이크로프로세서의 발전으로 개인용 컴퓨터 시장이 형성되었다. 컴퓨터가 기업과 연구 기관의 중앙 시스템에서 개인이 직접 사용하는 장치로 확장되면서 소프트웨어의 사용자층과 유통 방식도 크게 달라졌다.

워드 프로세서, 스프레드시트, 데이터베이스, 그래픽 프로그램과 게임이 디스크와 패키지 형태로 판매되었다. VisiCalcLotus 1-2-3 같은 스프레드시트는 개인용 컴퓨터를 업무에 도입하게 만든 대표적인 응용 프로그램이었다. 프로그램은 특정 조직을 위해 한 번 개발하는 맞춤형 시스템뿐 아니라 다수의 사용자에게 같은 제품을 판매하고 지속적으로 버전을 갱신하는 패키지 소프트웨어가 되었다.

IBM PC와 호환 기종의 확산은 공통 하드웨어 플랫폼과 MS-DOS, 이후 Windows를 중심으로 거대한 소프트웨어 생태계를 형성했다. 한편 Macintosh는 그래픽 사용자 인터페이스와 데스크톱 출판, 그래픽 소프트웨어 시장을 확대했다. 운영체제 제조사와 응용 프로그램 개발사, 하드웨어 제조사 사이의 플랫폼 관계가 소프트웨어 산업의 핵심 구조가 되었다.

패키지 소프트웨어에서는 출시 시점과 시장 경쟁이 중요해졌다. 모든 기능을 완성한 뒤 한 번 배포하는 대신 버전별로 기능을 추가하고, 사용자의 오류 보고와 요구를 다음 버전에 반영하는 개발 방식이 확산되었다. 설치 프로그램, 라이선스 키, 업데이트와 기술 지원도 소프트웨어 제품의 일부가 되었다.

네트워크와 분산 소프트웨어

컴퓨터 네트워크가 발전하면서 소프트웨어는 한 컴퓨터 안에서만 실행되는 프로그램에서 여러 컴퓨터가 통신하는 시스템으로 확장되었다. 초기 네트워크에서는 원격 로그인, 파일 전송과 전자우편이 주요 응용 프로그램이었으나, 이후 데이터베이스와 업무 시스템, 프린터와 저장 장치를 여러 사용자가 공유하게 되었다.

ARPANET과 인터넷 프로토콜의 발전은 서로 다른 운영체제와 네트워크를 연결할 수 있는 기반을 마련했다. TCP/IP가 널리 채택되면서 응용 프로그램은 특정 물리 네트워크보다 표준화된 통신 프로토콜을 대상으로 개발될 수 있었다.

클라이언트-서버 모델에서는 사용자 컴퓨터의 클라이언트 프로그램이 네트워크를 통해 중앙 서버의 데이터와 기능을 요청했다. 파일 서버, 데이터베이스 서버, 전자우편 서버와 업무 응용 서버가 분리되면서 시스템은 여러 프로세스와 기계로 구성되기 시작했다.

분산 소프트웨어에서는 네트워크 지연, 부분적 장애, 동시 접근과 데이터 일관성 같은 문제가 중요해졌다. 하나의 프로그램 내부에서는 함수 호출이 성공하거나 실패하는 상황을 비교적 직접 판단할 수 있지만, 네트워크를 통한 요청에서는 응답 지연이 서버 장애인지 통신 장애인지 구분하기 어려웠다. 이에 따라 재시도, 타임아웃, 트랜잭션, 복제와 장애 복구가 소프트웨어 설계의 핵심 요소가 되었다.

자유 소프트웨어와 오픈소스 개발

초기 컴퓨터 공동체에서는 프로그램의 소스 코드를 사용자와 연구 기관이 공유하고 수정하는 일이 흔했다. 그러나 소프트웨어가 독립적인 상품으로 성장하고 라이선스와 비공개 소스 코드가 확산되면서 사용자가 프로그램을 수정하거나 재배포할 수 있는 범위가 제한되기 시작했다.

1983년 리처드 스톨먼은 자유롭게 사용·연구·수정·배포할 수 있는 UNIX 호환 운영체제를 만들기 위해 GNU 프로젝트를 발표했다. 1985년에는 자유 소프트웨어 재단이 설립되었고, 컴파일러와 편집기, 셸, 라이브러리 등 여러 GNU 소프트웨어가 개발되었다.[15][16]

1991년 리누스 토르발스Linux 커널을 공개한 뒤 인터넷을 통한 공동 개발이 빠르게 이루어졌다. Linux 커널과 GNU 도구, 여러 자유 소프트웨어를 결합한 운영체제 환경은 서버, 개발 환경, 임베디드 시스템과 이후의 모바일·클라우드 기반 시설에 널리 사용되었다.[17]

1998년에는 자유롭게 개발·배포되는 소프트웨어를 기업과 산업계에 설명하기 위한 오픈소스라는 표현이 만들어졌고, Open Source Initiative가 설립되었다. 오픈소스는 단순히 소스 코드를 볼 수 있다는 뜻이 아니라 재배포와 수정, 파생 저작물 등을 허용하는 라이선스 조건을 중심으로 정의되었다.[18][19]

자유 소프트웨어와 오픈소스 개발은 소프트웨어 생산 조직을 변화시켰다. 지리적으로 떨어진 개발자들이 메일링 리스트와 버전 관리 시스템, 이슈 추적기와 코드 검토를 통해 하나의 프로젝트에 참여했다. 소스 코드가 공개되면서 사용자가 결함을 보고하고 직접 수정안을 제출하는 개발 방식이 확산되었으며, 공개 라이브러리와 도구를 조합하여 새로운 소프트웨어를 만드는 생태계가 성장했다.

World Wide Web과 웹 소프트웨어

1989년 CERN의 팀 버너스리는 서로 다른 컴퓨터에 저장된 연구 문서를 연결하기 위한 분산 하이퍼텍스트 시스템을 제안했다. 1990년 말에는 HTML, HTTP, URL의 기본 개념과 최초의 웹 브라우저·편집기, 웹 서버와 웹사이트가 구현되었다.[20]

초기의 웹 페이지는 서버에 저장된 문서를 브라우저가 내려받아 표시하는 구조였다. 이후 CGI와 서버 측 프로그래밍, 데이터베이스 연동을 통해 사용자의 요청에 따라 페이지를 동적으로 생성하는 웹 응용 프로그램이 등장했다. 온라인 게시판, 검색 엔진, 전자상거래와 포털 서비스가 성장하면서 웹 서버는 문서 배포 도구에서 대규모 응용 프로그램 실행 환경으로 변화했다.

브라우저에서 실행되는 JavaScript가 발전하면서 사용자 인터페이스의 일부가 서버에서 클라이언트로 이동했다. 비동기 통신과 동적 문서 조작이 보편화되자 웹 페이지는 설치형 응용 프로그램과 비슷한 상호작용을 제공하기 시작했다. 이후 웹 브라우저는 문서 뷰어를 넘어 그래픽, 오디오, 영상, 실시간 통신과 로컬 저장소를 제공하는 범용 소프트웨어 플랫폼이 되었다.

웹 소프트웨어는 배포 방식도 변화시켰다. 사용자가 각 컴퓨터에 새 버전을 설치하지 않아도 서버를 갱신하면 모든 사용자가 새로운 기능을 이용할 수 있게 되었다. 반면 하나의 서버 변경이 전체 사용자에게 즉시 영향을 줄 수 있었기 때문에 자동화된 시험, 단계적 배포, 모니터링과 빠른 복구가 중요해졌다.

인터넷 서비스가 전 세계에서 계속 실행되는 형태로 바뀌면서 소프트웨어 개발과 운영의 경계도 약해졌다. 웹 서비스는 개발 완료 후 전달되는 고정된 제품이 아니라, 지속적으로 기능을 추가하고 데이터를 관리하며 장애와 보안 위협에 대응하는 운영 중인 시스템이 되었다.

애자일 개발과 지속적 통합

1990년대에는 무거운 문서와 장기 계획을 중심으로 한 개발 방식이 빠르게 변하는 요구사항에 적응하기 어렵다는 비판이 증가했다. 신속 응용 프로그램 개발, Scrum, 익스트림 프로그래밍, 반복적·점진적 개발 등 짧은 주기로 작동하는 소프트웨어를 제공하고 사용자 피드백을 반영하는 방법들이 발전했다.

2001년 여러 개발 방법론의 제안자들이 애자일 소프트웨어 개발 선언을 발표했다. 애자일은 계획과 문서를 없애는 방식이 아니라, 개발 과정에서 사람 사이의 협력, 실행 가능한 소프트웨어, 사용자와의 협업, 변화에 대한 대응에 더 높은 가치를 두었다.

애자일 개발에서는 큰 기능을 작은 단위로 나누고, 짧은 반복 주기마다 설계·구현·시험을 수행한다. 요구사항은 프로젝트 시작 시 완전히 고정되지 않으며, 실제 사용 결과와 우선순위에 따라 조정된다. 이러한 방식은 웹 서비스와 제품 소프트웨어처럼 시장과 사용자 요구가 자주 변하는 분야에서 널리 사용되었다.

지속적 통합은 여러 개발자의 변경을 자주 공유 저장소에 통합하고 자동으로 빌드와 시험을 실행하는 방식으로 발전했다. 변경 사항을 오랫동안 분리해 두었다가 한꺼번에 통합할 때 발생하는 충돌을 줄이고, 결함이 들어온 시점을 빠르게 찾는 것이 목적이었다.

버전 관리 시스템도 중앙 집중식 시스템에서 Git과 같은 분산 버전 관리 시스템으로 발전했다. 브랜치 생성과 병합, 변경 이력 추적이 쉬워지면서 대규모 오픈소스 프로젝트와 기업 개발 조직에서 코드 검토와 병렬 개발이 일상적인 작업이 되었다.

모바일 소프트웨어와 앱 생태계

휴대전화는 처음에는 통신 기능을 중심으로 제한된 내장 소프트웨어를 사용했으나, 처리 성능과 저장 공간, 네트워크 연결이 발전하면서 범용 응용 프로그램 플랫폼으로 변화했다. 개인용 정보 관리와 전자우편을 제공한 PDA와 초기 스마트폰은 이동 중에도 소프트웨어를 사용할 수 있는 환경을 만들었다.

2007년 iPhone과 2008년 App Store, Android 기반 기기의 등장은 모바일 앱 생태계를 빠르게 확대했다. 운영체제 제조사가 응용 프로그램 인터페이스와 개발 도구, 배포 시장, 결제와 보안 정책을 함께 제공하면서 개발자는 전 세계 사용자에게 소프트웨어를 직접 배포할 수 있게 되었다.

모바일 소프트웨어는 터치 입력, 작은 화면, 배터리, 무선 네트워크, 센서, 카메라와 위치 정보 등 개인용 컴퓨터와 다른 실행 환경을 다뤄야 했다. 앱이 운영체제의 보호된 환경에서 실행되고 권한을 요청하도록 설계되면서 샌드박스와 코드 서명, 앱 검토와 자동 업데이트가 일반적인 배포 구조가 되었다.

스마트폰 앱은 독립적으로 작동하는 프로그램이면서 동시에 인터넷 서버와 연결되는 클라이언트가 되었다. 메시징, 지도, 금융, 교통, 콘텐츠와 소셜 네트워크 서비스는 모바일 앱과 클라우드 서버, 데이터베이스와 알림 시스템이 결합된 분산 소프트웨어로 운영되었다.

클라우드 컴퓨팅과 서비스형 소프트웨어

웹 서비스가 성장하면서 기업은 자체 데이터 센터에서 서버를 구매하고 설치하는 대신 인터넷을 통해 계산·저장·데이터베이스 자원을 사용하는 방향으로 이동했다. 가상화 기술은 하나의 물리 서버에서 여러 격리된 운영체제와 응용 환경을 실행할 수 있게 했으며, 필요한 자원을 소프트웨어로 생성하고 제거하는 기반을 제공했다.

2006년 Amazon Web Services는 Amazon S3Amazon EC2를 공개하며 저장 공간과 계산 자원을 인터넷을 통해 필요할 때 사용하는 서비스를 대중화했다. 개발자는 물리 서버를 직접 구매하지 않고 API와 관리 도구를 통해 인프라를 구성할 수 있게 되었다.[21]

클라우드 컴퓨팅에서는 서버, 네트워크, 저장소와 접근 정책도 코드와 선언적 설정으로 관리된다. 코드형 인프라와 자동 확장, 관리형 데이터베이스, 메시지 큐와 서버리스 실행 환경이 등장하면서 응용 프로그램은 여러 클라우드 서비스의 조합으로 구성되기 시작했다.

소프트웨어를 설치 파일로 판매하는 대신 인터넷을 통해 지속적으로 제공하는 서비스형 소프트웨어도 확산되었다. 사용자는 웹 브라우저나 앱을 통해 서비스를 사용하고, 제공자는 중앙에서 기능과 보안 업데이트를 배포한다. 이 구조에서는 개발과 운영, 고객 지원과 데이터 관리가 하나의 지속적인 제품 활동으로 결합된다.

한편 클라우드는 시스템 구성을 더 쉽게 만들었지만, 분산된 서비스 사이의 의존성과 운영 복잡성도 증가시켰다. 서비스 검색, 부하 분산, 장애 격리, 데이터 복제, 비용 관리와 보안 설정이 새로운 소프트웨어 공학 영역으로 중요해졌다.

DevOps와 운영 중심 개발

전통적인 조직에서는 개발 팀이 프로그램을 작성하고 운영 팀이 완성된 프로그램을 배포·관리하는 방식으로 역할이 분리되는 경우가 많았다. 그러나 인터넷 서비스가 자주 배포되고 지속적으로 실행되면서 개발과 운영의 분리가 변경 지연과 책임 단절을 만들 수 있다는 문제가 제기되었다.

DevOps는 개발, 시험, 배포와 운영을 하나의 흐름으로 연결하고, 여러 역할이 시스템의 전체 생명주기에 공동으로 책임지는 방향으로 발전했다. 빌드와 시험, 배포, 인프라 구성과 모니터링을 자동화하고, 작은 변경을 자주 배포하여 변경 위험을 줄이는 방식이 중심이 되었다.

지속적 전달지속적 배포에서는 모든 코드 변경이 자동화된 빌드와 시험, 보안 검사와 배포 준비 과정을 거친다. 배포는 블루-그린 배포, 카나리 배포와 기능 플래그 등을 사용하여 일부 사용자나 서버부터 단계적으로 진행할 수 있다.

사이트 신뢰성 공학은 소프트웨어 공학의 원리를 운영에 적용하여 서비스 수준, 오류 예산, 자동화와 장애 대응을 관리한다. 운영자는 단순히 장애를 수동으로 처리하는 역할에서 시스템이 스스로 복구하고 관찰 가능하도록 소프트웨어를 설계하는 역할로 확장되었다.

로그와 메트릭, 분산 추적을 결합한 관찰 가능성도 중요해졌다. 현대의 소프트웨어 공학에서는 프로그램이 정상적으로 실행되는지뿐 아니라 실제 운영 환경에서 어떤 상태에 있으며 사용자가 어떤 문제를 경험하는지 파악할 수 있도록 시스템을 설계한다.

컨테이너와 클라우드 네이티브 소프트웨어

운영체제 수준 가상화를 이용한 컨테이너는 응용 프로그램과 필요한 라이브러리, 설정을 하나의 이식 가능한 실행 단위로 묶는 방식을 제공했다. 개발 환경과 운영 환경의 차이를 줄이고, 같은 응용 프로그램을 여러 서버와 클라우드 환경에 배포하기 쉬워졌다.

Docker의 확산과 Kubernetes 같은 컨테이너 오케스트레이션 시스템의 등장으로 대규모 서비스를 여러 컨테이너로 나누어 배포하고 관리하는 구조가 보편화되었다. 오케스트레이션 시스템은 컨테이너 배치, 장애 발생 시 재시작, 네트워크 연결, 비밀 정보와 설정, 확장과 업데이트를 자동으로 관리한다.

마이크로서비스 아키텍처는 하나의 큰 응용 프로그램을 독립적으로 배포 가능한 여러 서비스로 분리하는 방법으로 확산되었다. 각 서비스는 자체 데이터와 배포 주기를 가질 수 있지만, 서비스 간 통신과 데이터 일관성, 버전 호환성, 장애 전파와 운영 비용을 관리해야 한다.

클라우드 네이티브 소프트웨어는 개별 서버를 오래 유지하는 대신 서버와 컨테이너가 수시로 생성되고 제거되는 환경을 전제로 한다. 이에 따라 시스템 상태를 외부 저장소에 두고, 자동 복구와 수평 확장, 선언적 구성과 불변 인프라를 사용하는 설계가 중요해졌다.

소프트웨어 공급망과 보안의 확대

소프트웨어가 공개 라이브러리와 패키지, 운영체제 구성 요소, 빌드 도구와 클라우드 서비스를 조합하여 만들어지면서 하나의 제품에 포함되는 외부 의존성이 크게 증가했다. 개발 속도와 재사용성은 높아졌지만, 의존성 중 하나의 취약점이나 배포 계정 침해가 수많은 시스템으로 확산될 수 있게 되었다.

보안은 완성된 프로그램을 배포하기 전에 별도로 검사하는 활동에서 요구사항과 설계, 구현, 빌드와 운영 전체에 포함되는 활동으로 변화했다. 위협 모델링, 코드 분석, 의존성 검사, 비밀 정보 관리, 최소 권한, 코드 서명과 재현 가능한 빌드가 개발 과정에 통합되었다.

소프트웨어 구성 요소의 출처와 버전을 기록하는 소프트웨어 자재 명세서와 빌드 출처 증명, 공급망 보안 프레임워크도 발전했다. 현대의 소프트웨어 품질은 개발 조직이 직접 작성한 코드뿐 아니라 사용한 패키지와 도구, 빌드·배포 과정의 신뢰성까지 포함한다.

개인정보와 알고리즘의 사회적 영향도 주요 문제로 부상했다. 소프트웨어가 금융 거래, 의료, 교통, 통신, 행정과 의사결정에 사용되면서 오류와 편향, 데이터 유출이 개인과 사회에 직접적인 피해를 줄 수 있게 되었다. 이에 따라 보안과 안전, 개인정보 보호, 접근성과 전문 윤리가 소프트웨어 공학의 핵심 영역으로 확대되었다.

인공지능과 소프트웨어 개발의 변화

인공지능은 초기부터 소프트웨어의 주요 연구 분야였지만, 2010년대 이후 대규모 데이터와 그래픽 처리 장치, 딥 러닝의 발전으로 음성 인식, 번역, 영상 분석과 추천 시스템에 널리 적용되었다. 전통적인 소프트웨어가 개발자가 명시적으로 작성한 규칙을 중심으로 동작했다면, 기계학습 기반 소프트웨어는 학습 데이터와 모델 구조, 학습 과정이 동작을 결정한다.

이에 따라 소프트웨어 공학의 관리 대상도 소스 코드에서 데이터셋, 모델 가중치, 학습 설정과 평가 자료로 확장되었다. 같은 코드라도 데이터가 달라지면 결과가 달라질 수 있기 때문에 데이터 품질과 편향, 실험 재현성, 모델 버전 관리와 운영 중 성능 저하를 함께 관리해야 한다.

MLOps는 데이터 준비, 모델 학습, 평가, 배포와 감시를 자동화하고 소프트웨어 개발 과정과 연결한다. 모델이 실제 환경에서 예상과 다른 결과를 내거나 입력 데이터의 분포가 바뀌는 현상을 추적하기 위해 기존 서비스 모니터링과 다른 평가 체계가 필요해졌다.

2020년대에는 대규모 언어 모델을 이용한 코드 생성, 자동완성, 문서화, 시험 생성과 코드 분석 도구가 개발 과정에 빠르게 도입되었다. 이러한 도구는 개발자가 자연어로 요구를 설명하고 코드 초안을 생성하거나 기존 코드의 의미를 분석하는 새로운 작업 흐름을 제공한다.

그러나 생성된 코드도 다른 코드와 마찬가지로 요구사항 충족 여부, 정확성, 보안, 라이선스와 유지보수성을 검증해야 한다. 인공지능은 소프트웨어 공학을 대체하는 별도의 자동화 수단이라기보다, 소프트웨어 생산 과정에 추가된 새로운 도구이자 동시에 관리해야 할 소프트웨어 구성 요소로 자리 잡고 있다.

현대 소프트웨어 공학

현대의 소프트웨어는 개인용 컴퓨터에 설치되는 단일 프로그램부터 운영체제, 게임 엔진, 웹 서비스, 모바일 앱, 자동차 제어 시스템, 인공지능 모델과 전 세계 데이터 센터에서 실행되는 분산 플랫폼까지 다양한 형태로 존재한다.

하나의 현대적 서비스는 다음과 같은 여러 소프트웨어 계층으로 구성될 수 있다.

  • 장치를 제어하는 펌웨어
  • 자원과 프로세스를 관리하는 운영체제
  • 언어 실행을 제공하는 컴파일러, 인터프리터와 런타임 시스템
  • 데이터를 저장하는 데이터베이스와 분산 저장소
  • 업무 기능을 제공하는 서버 응용 프로그램
  • 웹 브라우저와 모바일 앱에서 실행되는 사용자 인터페이스
  • 네트워크 통신과 인증, 메시지 전달을 담당하는 기반 서비스
  • 빌드·시험·배포와 관찰을 자동화하는 개발 및 운영 도구
  • 데이터와 모델을 이용하여 결과를 생성하는 인공지능 구성 요소

따라서 소프트웨어 공학은 더 이상 프로그램의 코드를 올바르게 작성하는 방법만을 뜻하지 않는다. 여러 소프트웨어가 다른 소프트웨어 위에서 실행되고, 서로 통신하며, 지속적으로 변경되는 환경 전체를 설계하고 운영하는 분야가 되었다.

초기 프로그램은 하나의 기계에서 하나의 계산을 수행하기 위한 명령열이었지만, 현대 소프트웨어는 다른 프로그램을 작성하고 실행하며, 컴퓨터와 네트워크를 관리하고, 사회의 정보와 업무 흐름을 구성하는 기반이 되었다. 소프트웨어 공학은 이러한 소프트웨어의 규모와 역할이 확대되는 과정에서 발생한 복잡성, 품질, 협업과 유지보수 문제에 대응하며 함께 발전해 왔다.

핵심 개념과 원리

소프트웨어 공학의 핵심 목적은 소프트웨어를 단순히 실행 가능한 상태로 만드는 데 있지 않다. 소프트웨어가 요구된 기능을 정확히 수행하면서도 이해하고 수정하기 쉬우며, 장애와 공격에 대응하고, 실행 환경과 요구사항의 변화 속에서도 장기간 사용할 수 있도록 만드는 것이 중요하다.

소프트웨어는 물리적인 부품으로 이루어지지 않으므로 재료의 강도나 마모보다는 논리적 복잡성, 구성 요소 사이의 의존성, 상태 변화와 예외적인 실행 경로가 품질을 결정한다. 작은 프로그램에서는 전체 구조를 한 사람이 파악할 수 있지만, 운영체제·웹 서비스·게임 엔진·기업용 시스템처럼 규모가 커지면 모든 코드를 동시에 이해하는 것이 사실상 불가능해진다. 소프트웨어 공학은 이러한 복잡성을 사람이 다룰 수 있는 단위로 나누고, 각 단위의 책임과 관계를 명확히 하며, 변경의 영향을 제한하는 원리를 발전시켜 왔다.

이러한 원리는 특정 프로그래밍 언어나 개발 방법론에만 적용되지 않는다. 절차형 프로그램의 함수와 모듈, 객체 지향 프로그램의 클래스와 객체, 운영체제의 커널 하위 시스템, 웹 서비스의 서버 구성 요소, 분산 시스템의 서비스와 프로토콜에도 같은 기본 문제가 존재한다.

복잡성 관리

복잡성 관리는 소프트웨어 공학의 중심 문제이다. 소프트웨어의 규모가 커지면 코드의 양뿐 아니라 구성 요소 사이의 관계, 가능한 상태와 실행 경로, 처리해야 할 오류와 외부 환경의 수가 함께 증가한다. 각 부분이 단순하더라도 여러 부분이 결합되면 시스템 전체의 동작을 예측하기 어려워질 수 있다.

소프트웨어 복잡성은 여러 형태로 나타난다.

  • 시스템이 제공해야 하는 기능과 업무 규칙의 복잡성
  • 소스 코드의 제어 흐름과 자료 구조에서 발생하는 복잡성
  • 모듈과 서비스 사이의 의존 관계
  • 동시 실행과 비동기 처리에서 발생하는 상태 변화
  • 네트워크, 운영체제와 외부 서비스에서 발생하는 실패
  • 이전 버전 및 외부 시스템과의 호환성
  • 여러 개발자가 동시에 변경하면서 발생하는 조직적 복잡성
  • 배포 환경과 설정, 데이터 형식의 차이

복잡성을 완전히 제거할 수는 없다. 문제 자체에 포함된 복잡성은 소프트웨어가 해결해야 하며, 이를 없애면 필요한 기능까지 사라질 수 있다. 대신 소프트웨어 공학은 시스템의 복잡성을 작은 범위로 분리하고, 한 시점에 개발자가 고려해야 하는 정보의 양을 줄인다.

이 과정에는 추상화, 모듈화, 계층화, 명확한 인터페이스, 일관된 명명과 자동화된 검증이 사용된다. 각 구성 요소가 제한된 책임을 가지게 하고 내부 동작을 외부에서 직접 알 필요가 없도록 만들면, 개발자는 시스템 전체가 아니라 현재 작업하는 부분과 그 주변 관계에 집중할 수 있다.

복잡성을 관리한다는 것은 코드를 가능한 한 짧게 만드는 것과 같지 않다. 지나치게 압축된 코드는 줄 수는 적더라도 의미와 상태 변화를 이해하기 어려울 수 있다. 반대로 약간의 코드와 구조를 추가하여 책임과 경계를 명확하게 만들면 전체 시스템의 복잡성은 감소할 수 있다.

추상화와 정보 은닉

추상화는 대상의 모든 세부 사항을 한꺼번에 다루지 않고, 현재 문제를 해결하는 데 필요한 특성과 동작만을 표현하는 원리이다. 개발자는 추상화를 통해 하위 수준의 구현을 매번 다시 이해하지 않고도 상위 수준에서 시스템을 설계할 수 있다.

예를 들어 응용 프로그램은 저장 장치의 전기적 동작을 직접 제어하지 않고 운영체제가 제공하는 파일 인터페이스를 사용한다. 파일 시스템은 디스크 블록과 장치 명령을 파일과 디렉터리라는 추상적인 개념으로 표현한다. 네트워크 프로그램은 전송 매체의 신호 처리보다 소켓과 연결, 메시지라는 추상화를 사용한다.

소프트웨어에는 여러 수준의 추상화가 겹쳐 존재한다.

  • 기계 명령을 표현하는 어셈블리어
  • 자료형과 함수로 계산을 표현하는 고수준 프로그래밍 언어
  • 운영체제가 제공하는 프로세스, 파일과 가상 메모리
  • 라이브러리가 제공하는 컬렉션, 문자열과 입출력
  • 프레임워크가 제공하는 요청, 화면과 이벤트
  • 문제 영역을 표현하는 사용자, 문서, 계정과 주문 등의 모델

좋은 추상화는 사용자가 알아야 할 개념과 동작을 명확하게 보여 주면서 불필요한 구현 세부 사항을 감춘다. 추상화가 지나치게 낮으면 사용하는 쪽에서 내부 구조를 너무 많이 알아야 하고, 지나치게 일반적이면 실제 동작과 비용을 예측하기 어려워질 수 있다. 따라서 추상화 수준은 대상 사용자의 요구와 시스템에서 수행할 작업에 맞게 선택해야 한다.

정보 은닉은 구성 요소 내부에서 변경될 가능성이 있는 설계 결정과 데이터를 외부에서 직접 의존하지 못하게 감추는 원리이다. 외부 구성 요소는 공개된 인터페이스를 통해서만 기능을 사용하며, 내부 구현이 바뀌더라도 인터페이스의 계약이 유지되면 영향을 받지 않는다.

정보 은닉의 대상에는 다음과 같은 요소가 포함될 수 있다.

  • 자료 구조의 내부 표현
  • 파일과 데이터베이스의 저장 형식
  • 특정 알고리즘과 최적화 방법
  • 메모리와 자원 관리 방식
  • 동기화와 캐시 정책
  • 외부 서비스와 통신하는 구체적인 절차
  • 운영체제와 하드웨어에 종속된 코드

캡슐화는 정보 은닉을 구현하는 수단 가운데 하나이다. 객체 지향 언어에서는 클래스의 비공개 필드와 메서드를 사용할 수 있으며, 모듈 시스템에서는 외부로 공개할 이름과 내부에 둘 이름을 구분할 수 있다. 그러나 단순히 접근 제한자를 사용하는 것만으로 정보 은닉이 완성되는 것은 아니다. 공개 인터페이스가 내부 자료 구조나 처리 순서를 그대로 노출한다면 외부 코드는 여전히 내부 구현에 의존하게 된다.

모듈화와 관심사의 분리

모듈화는 소프트웨어 시스템을 명확한 책임과 경계를 가진 여러 구성 요소로 나누는 원리이다. 모듈은 함수, 파일, 패키지, 라이브러리, 프로세스, 서비스나 독립적으로 배포되는 프로그램 등 여러 형태로 구현될 수 있다.

모듈은 내부 구현을 포함하고 외부에 제한된 인터페이스를 제공한다. 이를 통해 각 모듈을 별도로 이해하고 구현하며 시험할 수 있고, 한 모듈의 내부 변경이 시스템 전체에 퍼지는 것을 줄일 수 있다.

모듈의 경계는 단순히 코드의 길이나 파일 수만으로 결정되지 않는다. 같은 목적을 위해 함께 변경되는 기능과 데이터를 묶고, 서로 다른 이유로 변경되는 요소는 분리하는 것이 일반적인 방향이다. 사용자 인증, 그래픽 렌더링, 파일 저장과 네트워크 통신처럼 서로 다른 책임을 하나의 모듈에 모으면 해당 모듈은 여러 종류의 변경을 동시에 받아들이게 된다.

관심사의 분리는 시스템이 다루는 서로 다른 문제를 가능한 한 독립적으로 표현하는 원리이다. 업무 규칙, 사용자 인터페이스, 데이터 저장, 네트워크 통신, 보안, 로깅과 오류 처리 등은 서로 관련되어 있지만 동일한 관심사는 아니다.

관심사가 적절히 분리되면 다음과 같은 작업이 쉬워진다.

  • 사용자 인터페이스를 변경하면서 업무 규칙을 유지한다.
  • 데이터베이스를 교체하면서 상위 기능의 변경을 줄인다.
  • 운영체제별 코드를 플랫폼 계층에 모은다.
  • 로깅과 인증 같은 공통 기능을 일관되게 적용한다.
  • 각 부분을 독립적으로 시험한다.
  • 특정 기능을 다른 프로그램에서 재사용한다.

그러나 모든 관심사를 완전히 분리할 수 있는 것은 아니다. 성능과 보안, 오류 처리처럼 시스템 여러 부분에 걸쳐 적용되는 관심사도 존재한다. 이러한 요소는 공통 계층이나 정책, 코드 생성, 미들웨어와 도구 지원 등을 이용하여 중복과 불일치를 줄인다.

모듈을 지나치게 세분하면 작은 변경을 위해 여러 파일과 인터페이스를 오가야 하고, 구성 요소 사이의 통신 비용이 증가할 수 있다. 반대로 너무 큰 모듈은 내부의 책임이 불명확하고 변경 영향이 커진다. 적절한 모듈 경계는 시스템의 기능, 변경 패턴, 개발 조직과 실행 비용을 함께 고려하여 정한다.

결합도와 응집도

결합도는 서로 다른 모듈이 얼마나 강하게 의존하는지를 나타내는 개념이다. 한 모듈이 다른 모듈의 내부 자료 구조, 전역 상태, 실행 순서와 구현 방식에 직접 의존하면 결합도가 높다. 반대로 제한되고 안정적인 인터페이스를 통해 필요한 정보만 주고받으면 결합도가 낮다.

결합도가 높은 시스템에서는 한 부분을 변경할 때 연결된 여러 부분을 함께 수정해야 한다. 독립적인 시험과 재사용이 어려워지고, 장애가 다른 구성 요소로 전파되기 쉽다. 따라서 일반적으로 모듈 사이의 직접적인 의존 관계와 공유 상태를 줄이고, 명확한 인터페이스와 데이터 계약을 사용하는 방향이 선호된다.

결합도를 낮추는 방법에는 다음과 같은 것들이 있다.

  • 내부 구현 대신 공개 인터페이스에 의존한다.
  • 전역 변수와 변경 가능한 공유 상태를 줄인다.
  • 필요한 데이터만 인자로 전달한다.
  • 구체적인 구현과 상위 정책 사이에 추상 인터페이스를 둔다.
  • 구성 요소의 생성과 연결을 외부에서 관리한다.
  • 네트워크 서비스에서는 명시적인 프로토콜과 버전 정책을 사용한다.
  • 실패와 지연이 다른 구성 요소로 무제한 전파되지 않도록 경계를 둔다.

결합도가 낮다고 해서 구성 요소 사이의 관계가 없어야 하는 것은 아니다. 소프트웨어는 여러 부분이 협력해야 기능을 수행할 수 있다. 중요한 것은 의존 관계의 존재 여부보다 그 관계가 명확하고 필요한 범위로 제한되며 변경 가능성을 고려하고 있는가이다.

응집도는 하나의 모듈 안에 포함된 요소들이 얼마나 밀접한 목적과 책임을 공유하는지를 나타낸다. 높은 응집도를 가진 모듈은 하나의 분명한 역할을 수행하며, 그 안의 함수와 데이터가 같은 목적을 위해 사용된다.

서로 관련 없는 기능을 하나의 유틸리티 모듈이나 관리자 객체에 계속 추가하면 응집도가 낮아진다. 이러한 모듈은 다양한 이유로 자주 변경되고, 다른 모듈이 필요하지 않은 기능까지 함께 의존하게 된다. 반대로 관련된 상태와 동작을 함께 두면 모듈의 역할을 이해하고 시험하기 쉬워진다.

일반적으로 낮은 결합도와 높은 응집도는 변경 범위를 제한하고 시스템의 구조를 이해하기 쉽게 만든다. 다만 결합도와 응집도는 단일한 수치만으로 설계의 품질을 결정하는 절대적인 규칙이 아니다. 시스템의 목적과 실행 환경, 성능 요구, 배포 구조를 함께 고려해야 한다.

인터페이스와 계약

모듈 사이의 협력은 인터페이스를 통해 이루어진다. 인터페이스는 단순한 함수 이름과 매개변수 목록뿐 아니라 호출 조건, 반환 결과, 발생 가능한 오류, 상태 변화와 성능 특성을 포함한다.

인터페이스가 제공하는 동작과 사용 조건을 계약으로 볼 수 있다. 계약에는 다음과 같은 내용이 포함될 수 있다.

  • 호출 전에 충족해야 하는 전제 조건
  • 정상 실행 뒤 보장되는 결과
  • 실패가 표현되는 방식
  • 입력과 출력 데이터의 형식
  • 함수나 요청이 상태를 변경하는지 여부
  • 여러 번 호출했을 때의 동작
  • 동시 호출의 허용 여부
  • 응답 시간과 자원 사용의 제한
  • 버전 간 호환성 규칙

명확한 계약이 있으면 모듈의 사용자는 내부 코드를 읽지 않고도 기능을 사용할 수 있고, 구현자는 계약을 유지하는 범위 안에서 내부 구조를 변경할 수 있다. 시험은 구현 세부 사항뿐 아니라 계약이 지켜지는지를 확인하는 수단이 된다.

인터페이스는 일단 널리 사용되면 변경 비용이 커질 수 있다. 공개 API, 파일 형식, 네트워크 프로토콜과 데이터베이스 구조는 외부 프로그램과 사용자가 의존할 수 있으므로 하위 호환성, 폐기 절차와 버전 관리가 필요하다.

변경 가능성과 유지보수성

소프트웨어는 완성된 뒤에도 계속 변경된다. 사용자의 요구가 달라지고, 결함과 보안 취약점이 발견되며, 운영체제와 하드웨어, 네트워크 프로토콜과 외부 서비스가 변화한다. 따라서 변경은 예외적인 작업이 아니라 소프트웨어 생명주기의 일반적인 부분이다.

변경 가능성은 새로운 요구나 환경 변화에 대응하여 시스템을 수정할 때 필요한 비용과 위험의 정도를 나타낸다. 유지보수성은 결함 수정, 기능 개선, 환경 적응과 내부 품질 개선을 얼마나 효과적으로 수행할 수 있는지를 나타내는 품질 특성이다. ISO/IEC 25010은 소프트웨어 및 ICT 제품의 품질을 명세·측정·평가하기 위한 제품 품질 모델을 정의한다.[22]

유지보수성이 높은 시스템은 일반적으로 다음과 같은 특성을 가진다.

  • 구성 요소의 책임과 경계가 명확하다.
  • 코드와 데이터의 중복이 통제되어 있다.
  • 의존 관계와 변경 영향 범위를 추적할 수 있다.
  • 자동화된 시험으로 기존 동작을 확인할 수 있다.
  • 빌드와 개발 환경을 재현할 수 있다.
  • 설계 결정과 공개 인터페이스가 문서화되어 있다.
  • 오류 원인을 찾을 수 있는 로그와 진단 수단이 있다.
  • 작은 단위로 변경하고 검토할 수 있다.

유지보수성을 높이기 위해 미래의 모든 변화를 미리 일반화할 필요는 없다. 발생 가능성이 낮은 변경까지 대비하면 추상화와 설정이 과도하게 늘어나 현재 시스템을 이해하기 어려워질 수 있다. 실제 변경 패턴과 중요한 품질 요구를 근거로 안정적인 부분과 변화할 부분을 구분하는 것이 중요하다.

변경 가능성은 구조만으로 결정되지 않는다. 시험의 품질, 개발 도구, 코드 검토 방식, 배포 자동화, 조직의 지식과 문서도 변경 비용에 영향을 준다. 구조적으로 수정 가능한 코드라도 실행 환경을 재현하거나 결과를 검증할 수 없다면 안전하게 변경하기 어렵다.

단순성과 일관성

단순성은 필요한 기능과 품질을 만족하는 범위에서 구조와 규칙을 이해하기 쉽게 유지하는 원리이다. 단순한 설계는 구성 요소 수가 무조건 적거나 코드가 짧다는 의미가 아니라, 각 요소가 존재하는 이유와 동작을 설명하기 쉽다는 의미에 가깝다.

불필요한 계층, 사용되지 않는 일반화, 중복된 상태와 여러 방식으로 표현되는 동일한 개념은 시스템을 복잡하게 만든다. 반대로 명확한 자료 모델과 제어 흐름, 제한된 인터페이스, 예측 가능한 오류 처리 방식은 개발자가 시스템의 동작을 추론하기 쉽게 한다.

일관성은 비슷한 문제가 시스템 안에서 비슷한 방식으로 해결되는 것을 뜻한다. 명명 규칙, 오류 표현, 자원 관리, 동시성 제어와 데이터 형식이 일관되면 개발자는 한 부분에서 배운 규칙을 다른 부분에도 적용할 수 있다.

일관성은 모든 구성 요소가 동일한 기술과 구조를 사용해야 한다는 뜻은 아니다. 서로 다른 문제에는 다른 해결 방법이 적합할 수 있다. 다만 차이가 생긴 이유와 적용 범위가 명확해야 하며, 우연한 중복과 개인별 관습 때문에 여러 방식이 공존하지 않도록 관리한다.

중복과 단일한 지식 표현

같은 규칙이나 정보가 여러 위치에 독립적으로 표현되면 한쪽만 수정되어 불일치가 발생할 수 있다. 이러한 문제를 줄이기 위해 하나의 중요한 지식이나 정책은 가능한 한 명확한 원천에서 관리하고, 다른 부분은 그 원천을 참조하거나 자동으로 생성하도록 구성한다.

중복은 동일한 코드가 복사된 경우에만 발생하지 않는다. 같은 업무 규칙이 서버와 클라이언트에 서로 다른 코드로 구현되거나, 데이터 구조가 소스 코드·데이터베이스·문서와 설정 파일에 각각 따로 정의되는 경우도 중복이 될 수 있다.

중복을 줄이면 변경 지점을 찾기 쉬워지지만, 모든 유사한 코드를 하나의 추상화로 합치는 것이 항상 적절한 것은 아니다. 현재 형태가 비슷하더라도 서로 다른 이유로 변화한다면 하나로 묶은 추상화가 오히려 결합도를 높일 수 있다. 중복 제거는 코드의 외형뿐 아니라 의미와 변경 원인을 기준으로 판단한다.

재사용과 일반화

재사용은 이미 구현하고 검증한 소프트웨어 요소를 새로운 시스템이나 기능에서 다시 사용하는 것이다. 함수와 클래스, 라이브러리, 프레임워크, 서비스, 운영체제 구성 요소와 공개 프로토콜 등이 재사용 단위가 될 수 있다.

재사용은 개발 시간을 줄이고 여러 시스템에서 일관된 동작을 제공할 수 있다. 널리 사용되고 충분히 시험된 구성 요소를 사용하면 개별 프로젝트에서 같은 기능을 반복해서 구현할 필요가 줄어든다.

재사용 가능한 구성 요소에는 일반적으로 다음과 같은 특성이 필요하다.

  • 책임과 사용 범위가 명확하다.
  • 외부에 노출하는 인터페이스가 안정적이다.
  • 특정 응용 프로그램의 내부 상태에 과도하게 의존하지 않는다.
  • 오류와 자원 사용 방식이 문서화되어 있다.
  • 독립적으로 시험하고 배포할 수 있다.
  • 호환성과 버전 정책이 존재한다.

일반화는 여러 구체적인 문제에서 공통되는 개념과 동작을 찾아 하나의 구조로 표현하는 과정이다. 적절한 일반화는 중복을 줄이고 다양한 요구를 같은 기반에서 처리할 수 있게 한다.

그러나 일반화에는 비용이 따른다. 확장 지점과 설정이 늘어나고, 실제로 사용되지 않는 기능을 지원해야 하며, 구체적인 문제에 최적화하기 어려워질 수 있다. 따라서 재사용 가능성을 이유로 모든 코드를 범용 프레임워크로 만들기보다, 반복되는 실제 요구와 안정된 공통점을 확인한 뒤 일반화하는 방향이 사용된다.

외부 라이브러리와 프레임워크의 재사용도 새로운 의존성을 만든다. 버전 변경, 보안 취약점, 라이선스, 지원 중단과 공급망 위험을 함께 관리해야 하므로 직접 구현과 외부 구성 요소 사용 사이의 선택은 전체 생명주기를 기준으로 이루어진다.

정확성과 검증 가능성

정확성은 소프트웨어가 정해진 명세와 요구사항에 맞게 동작하는 성질이다. 프로그램이 오류 없이 종료된다고 해서 반드시 정확한 것은 아니다. 구현이 처음부터 잘못된 요구를 따르거나 중요한 조건이 명세에서 빠져 있다면 실행은 성공해도 필요한 결과를 제공하지 못할 수 있다.

정확성을 판단하려면 기대되는 동작을 확인할 기준이 필요하다. 자연어 요구사항, 형식 명세, 인터페이스 계약, 시험 사례와 사용자 인수 조건 등이 기준으로 사용된다.

검증 가능성은 소프트웨어가 요구된 성질을 충족하는지 효과적으로 확인할 수 있는 정도를 의미한다. 입력과 출력, 상태 변화와 실패 조건이 명확할수록 시험과 분석이 쉬워진다. 반대로 전역 상태와 외부 환경에 강하게 의존하고 결과가 비결정적으로 달라지는 코드는 검증하기 어렵다.

검증에는 코드 검토, 정적 분석, 자동화된 시험, 형식 검증, 실행 중 감시와 사용자 평가 등이 사용된다. 하나의 방법으로 모든 결함을 찾을 수는 없으므로 시스템의 중요도와 위험에 따라 여러 방법을 결합한다.

신뢰성과 가용성

신뢰성은 소프트웨어가 정해진 조건에서 일정 기간 동안 요구된 기능을 올바르게 수행할 수 있는 정도이다. 가용성은 사용자가 필요로 할 때 시스템이 서비스를 제공할 수 있는 정도를 나타낸다.

신뢰성은 결함이 전혀 없다는 뜻으로만 이해되지 않는다. 현대의 복잡한 시스템에서는 하드웨어 고장, 네트워크 단절, 잘못된 입력과 외부 서비스 장애를 완전히 피하기 어렵다. 따라서 오류가 발생하더라도 이를 감지하고 피해를 제한하며 복구할 수 있도록 설계한다.

신뢰성과 가용성을 높이기 위한 방법에는 다음과 같은 것들이 있다.

  • 입력과 상태의 유효성 검사
  • 오류의 조기 감지와 명확한 전달
  • 처리 시간 제한과 취소
  • 장애가 다른 구성 요소로 번지는 것을 막는 격리
  • 중요 데이터의 복제와 백업
  • 실패한 작업의 안전한 재시도
  • 서비스와 프로세스의 자동 재시작
  • 성능과 상태에 대한 모니터링
  • 장애 대응 및 복구 절차의 시험

복제와 재시도 같은 기법은 신뢰성을 높일 수 있지만 시스템의 상태와 동시성 문제를 더 복잡하게 만들기도 한다. 예를 들어 결과를 이미 반영한 요청을 다시 실행하면 중복 처리가 발생할 수 있으므로, 작업의 멱등성이나 요청 식별자를 함께 고려해야 한다.

안전성

안전성은 소프트웨어의 동작이나 실패가 사람, 장비, 재산과 환경에 허용할 수 없는 피해를 일으키지 않도록 하는 성질이다. 항공기, 자동차, 의료 장비, 철도 신호와 산업 제어 시스템에서는 소프트웨어 결함이 물리적 피해로 이어질 수 있다.

안전 필수 소프트웨어에서는 정상 기능뿐 아니라 오작동과 비정상 상태를 체계적으로 분석한다. 위험 요소를 식별하고, 각 위험의 발생 가능성과 피해 규모를 평가하며, 위험을 제거하거나 허용 가능한 수준으로 낮추는 설계 수단을 적용한다.

안전성을 높이기 위해 다음과 같은 구조가 사용될 수 있다.

  • 위험한 동작을 기본적으로 허용하지 않는 안전한 초기 상태
  • 입력과 센서 값의 범위 검사
  • 독립적인 감시 장치와 중복 검사
  • 오류 발생 시 안전한 상태로 전환하는 실패 안전 설계
  • 중요 기능과 일반 기능의 격리
  • 실행 시간과 자원 사용의 제한
  • 요구사항부터 시험 결과까지 연결되는 추적성
  • 독립적인 검증과 인증

안전성과 가용성은 항상 같은 방향으로 작용하지 않는다. 이상 상태에서 기능을 중단하면 안전성은 높아질 수 있지만 서비스 가용성은 낮아질 수 있다. 시스템의 목적에 따라 계속 동작해야 하는 기능과 즉시 중단해야 하는 기능을 구분해야 한다.

보안과 개인정보 보호

보안은 소프트웨어와 데이터가 허가되지 않은 접근, 변경, 공개와 서비스 방해로부터 보호되는 성질이다. 보안은 완성된 프로그램에 마지막으로 추가하는 기능이 아니라 요구사항, 설계, 구현, 빌드, 배포와 운영 전체에서 다뤄야 한다.

NIST의 Secure Software Development Framework는 보안 개발 관행을 특정 생명주기 모델과 별개로 추가하는 것이 아니라 각 소프트웨어 생명주기 구현에 통합할 수 있는 공통 관행으로 제시한다.[23]

보안 설계의 기본 방향에는 다음과 같은 것들이 있다.

  • 사용자와 프로그램에 필요한 최소 권한만 부여한다.
  • 신뢰 경계를 넘는 모든 입력을 검증한다.
  • 인증과 권한 부여를 구분한다.
  • 중요한 데이터는 저장 및 전송 과정에서 보호한다.
  • 비밀 정보와 자격 증명을 소스 코드에서 분리한다.
  • 실패할 때 접근을 허용하는 대신 안전한 상태를 유지한다.
  • 보안 기능을 임의로 우회하기 어렵게 만든다.
  • 공격과 이상 동작을 추적할 수 있는 기록을 남긴다.
  • 외부 패키지와 빌드·배포 과정의 무결성을 관리한다.
  • 취약점 발견 이후 수정과 배포 절차를 마련한다.

개인정보 보호는 보안과 관련되지만 동일한 개념은 아니다. 데이터가 외부 공격자로부터 안전하게 보호되더라도 필요 이상으로 정보를 수집하거나 원래 목적과 다르게 사용한다면 개인정보 보호 문제가 발생할 수 있다.

개인정보를 다루는 시스템은 수집 목적과 범위를 명확히 하고, 필요한 정보만 보관하며, 접근과 보존 기간을 제한해야 한다. 데이터 삭제, 정정과 이동 같은 사용자의 권리를 지원하기 위해 데이터 구조와 시스템 경계를 설계 단계에서 고려해야 한다.

견고성과 복원력

견고성은 예상하지 못한 입력이나 비정상적인 실행 조건에서도 시스템이 통제되지 않은 방식으로 무너지지 않는 성질이다. 잘못된 파일, 손상된 네트워크 메시지, 자원 부족과 예외적인 호출 순서를 처리할 수 있어야 한다.

견고한 소프트웨어는 입력을 무조건 신뢰하지 않고, 오류를 명확하게 표현하며, 처리할 수 없는 상태에서는 무의미한 결과를 계속 생성하는 대신 작업을 중단하거나 상위 계층에 실패를 전달한다.

복원력은 장애와 공격, 자원 손실이 발생한 뒤에도 중요한 기능을 유지하거나 허용 가능한 시간 안에 복구할 수 있는 능력이다. 복원력은 장애를 예방하는 데서 끝나지 않고 장애가 실제로 발생한다는 전제에서 시스템을 설계한다.

복원력을 높이려면 단일 장애 지점을 줄이고, 상태를 복구할 수 있는 기록과 백업을 유지하며, 장애 범위를 제한하고, 복구 절차를 반복해서 시험해야 한다. 운영 환경의 장애 경험은 이후 설계와 시험에 다시 반영된다.

성능과 자원 효율성

성능은 시스템이 요청을 처리하는 시간, 일정 시간 동안 처리할 수 있는 작업량과 동시 사용자를 지원하는 능력 등을 포함한다. 자원 효율성은 요구된 기능을 수행하면서 처리 시간, 메모리, 저장 공간, 네트워크 대역폭과 에너지를 얼마나 효과적으로 사용하는지를 나타낸다.

성능은 구현을 완료한 뒤 일부 코드를 빠르게 만드는 문제에만 한정되지 않는다. 데이터 구조, 알고리즘, 구성 요소 경계, 통신 방식과 데이터 저장 구조 같은 초기 설계 결정이 성능의 상한을 결정할 수 있다.

성능 최적화는 실제 측정을 바탕으로 이루어져야 한다. 예상만으로 모든 코드를 복잡하게 최적화하면 유지보수성이 낮아지고 정작 중요한 병목은 남을 수 있다. 프로파일링과 부하 시험, 운영 메트릭을 이용하여 병목을 확인하고, 요구된 수준에 맞추어 개선한다.

성능과 다른 품질 속성 사이에는 상충 관계가 존재할 수 있다. 캐시는 응답 속도를 높이지만 데이터 일관성과 메모리 사용을 복잡하게 만들고, 암호화와 검증은 보안을 높이는 대신 처리 비용을 추가할 수 있다. 소프트웨어 아키텍처는 이러한 품질 목표 사이의 상호작용을 분석하고 중요한 위험을 조기에 확인하는 역할을 한다.[24]

이식성과 상호운용성

이식성은 소프트웨어를 서로 다른 운영체제, 하드웨어와 실행 환경으로 옮길 때 필요한 변경의 정도를 나타낸다. 플랫폼별 기능을 제한된 계층에 모으고 표준화된 언어와 인터페이스를 사용하면 핵심 기능을 여러 환경에서 공유할 수 있다.

이식성을 높이기 위해 다음과 같은 방법을 사용할 수 있다.

  • 플랫폼 종속 코드를 명확한 경계 안에 둔다.
  • 언어와 운영체제의 표준 인터페이스를 사용한다.
  • 자료형의 크기, 바이트 순서와 문자 인코딩을 명시한다.
  • 빌드와 의존성 설정을 자동화한다.
  • 지원하는 각 환경에서 자동화된 시험을 실행한다.
  • 특정 파일 경로와 로컬 설정을 코드에 고정하지 않는다.

상호운용성은 서로 다른 소프트웨어와 시스템이 정보를 교환하고 그 정보를 올바르게 사용할 수 있는 정도이다. 네트워크 프로토콜, 파일 형식, API와 데이터 스키마가 상호운용성의 기반이 된다.

형식이 같다는 것만으로 의미까지 일치하는 것은 아니다. 날짜와 시간, 통화, 단위, 문자 인코딩과 식별자의 의미가 시스템마다 다르면 데이터 교환 과정에서 오류가 발생할 수 있다. 따라서 구문 형식뿐 아니라 데이터의 의미와 오류 처리, 버전 호환성을 함께 정의해야 한다.

품질 속성과 상충 관계

소프트웨어의 품질은 하나의 특성으로 결정되지 않는다. 기능 적합성, 성능, 신뢰성, 보안, 사용성, 유지보수성, 이식성과 호환성 같은 여러 품질 속성이 함께 시스템의 가치를 결정한다. ISO/IEC 25010:2023은 소프트웨어와 ICT 제품에 적용할 수 있는 제품 품질 모델을 아홉 개의 상위 특성과 그 하위 특성으로 구성한다.[25]

품질 속성은 단순히 “높을수록 좋은” 독립적인 수치가 아니다. 특정 품질을 높이는 설계가 다른 품질에 비용을 줄 수 있다.

  • 중복 구성 요소는 가용성을 높이지만 비용과 운영 복잡성을 증가시킨다.
  • 강한 암호화와 검증은 보안을 높이지만 처리 시간과 자원을 사용한다.
  • 많은 추상화 계층은 변경 가능성을 높일 수 있지만 실행 흐름과 성능을 이해하기 어렵게 할 수 있다.
  • 엄격한 일관성은 데이터 정확성을 높이지만 분산 환경의 가용성과 응답 속도에 영향을 줄 수 있다.
  • 빠른 기능 제공은 단기적인 가치를 높이지만 시험과 구조 개선이 부족하면 장기 변경 비용이 증가할 수 있다.

따라서 소프트웨어 공학에서는 “좋은 구조”를 절대적인 형태로 정하기보다 시스템의 목적과 위험, 사용자와 운영 환경에 필요한 품질 속성을 먼저 정한다. 이후 이러한 목표를 달성할 수 있도록 구조를 설계하고, 시험과 측정을 통해 실제로 충족되는지 확인한다. 소프트웨어 아키텍처는 시스템이 변경 가능성, 가용성과 보안 같은 핵심 품질을 어떻게 달성할지를 이해하고 분석하는 기반이 된다.[26]

기술 부채

기술 부채는 단기적인 목적을 위해 선택한 설계나 구현이 이후 변경과 운영에 추가 비용을 발생시키는 상태를 설명하는 개념이다. 빠른 출시를 위해 임시 구조를 사용하거나 시험과 문서를 생략하고, 오래된 의존성을 계속 유지하는 경우 등이 기술 부채로 이어질 수 있다.

기술 부채는 항상 실수나 낮은 품질만을 뜻하지 않는다. 시장 검증이나 긴급한 장애 대응처럼 현재의 가치가 미래 비용보다 크다고 판단하여 의도적으로 부채를 감수할 수도 있다. 중요한 것은 그 선택과 예상 비용을 인식하고 이후 처리할 계획을 가지는 것이다.

기술 부채는 다음과 같은 형태로 나타날 수 있다.

  • 지나치게 강하게 결합된 코드
  • 중복된 업무 규칙과 데이터 정의
  • 자동화된 시험이 부족한 핵심 기능
  • 더 이상 지원되지 않는 라이브러리와 플랫폼
  • 수동으로만 수행할 수 있는 빌드와 배포
  • 실제 구조와 맞지 않는 문서
  • 임시 설정과 예외 처리의 누적
  • 책임이 불명확한 대규모 모듈
  • 보안 업데이트가 어려운 공급망과 의존성
  • 특정 개발자만 이해하는 운영 절차

기술 부채가 누적되면 새로운 기능을 추가하는 속도가 느려지고 작은 변경에서도 예상하지 못한 결함이 발생한다. 개발자는 기존 구조를 우회하기 위해 더 많은 임시 코드를 추가하게 되고, 그 결과 부채가 다시 증가할 수 있다.

기술 부채를 관리하려면 코드와 구조를 지속적으로 관찰하고, 변경 과정에서 발견된 문제를 기록하며, 위험과 비용에 따라 우선순위를 정해야 한다. 리팩터링, 시험 보강, 의존성 갱신, 문서화와 자동화는 기술 부채를 줄이는 수단이다.

모든 기술 부채를 즉시 제거하는 것이 항상 최선은 아니다. 곧 폐기될 기능이나 변화 가능성이 낮은 내부 도구에 대규모 재설계를 적용하는 것은 얻는 가치보다 비용이 클 수 있다. 기술 부채는 사업적 가치, 시스템의 수명, 장애 위험과 앞으로의 변경 가능성을 함께 고려하여 관리한다.

원리의 적용과 균형

소프트웨어 공학의 원리는 서로 분리된 규칙이 아니라 함께 작용하는 판단 기준이다. 추상화와 모듈화는 복잡성을 줄이고 변경 가능성을 높일 수 있지만, 계층과 인터페이스가 지나치게 많아지면 시스템을 추적하기 어려워질 수 있다. 재사용은 개발 비용을 줄일 수 있지만 외부 의존성과 호환성 관리 비용을 만든다. 보안과 신뢰성을 강화하는 검사는 성능과 개발 속도에 영향을 줄 수 있다.

따라서 모든 시스템에 동일한 구조와 절차를 적용하지 않는다. 시스템의 규모, 수명, 실패했을 때의 영향, 변경 빈도와 개발 조직의 특성에 따라 필요한 원리와 적용 강도를 정한다.

개인용 도구에서는 단순한 구조와 빠른 수정 가능성이 중요할 수 있으며, 오랫동안 운영되는 운영체제나 데이터베이스에서는 호환성과 변경 영향 관리가 중요하다. 웹 서비스에서는 배포 가능성과 관찰 가능성, 장애 복구가 중요하고, 의료·항공·교통 시스템에서는 안전성과 검증 가능성, 추적성이 우선될 수 있다.

소프트웨어 공학에서 좋은 설계란 특정 패턴이나 방법론을 많이 적용한 설계가 아니다. 시스템이 해결해야 하는 문제와 품질 목표를 분명하게 반영하고, 각 설계 결정의 이유와 비용을 설명할 수 있으며, 변화와 실패가 발생했을 때 그 영향을 통제할 수 있는 설계이다.

소프트웨어 생명주기와 개발 프로세스

소프트웨어 생명주기(Software Life Cycle)는 소프트웨어에 대한 필요가 인식되는 시점부터 계획, 개발, 배포, 운영, 유지보수를 거쳐 사용이 종료되고 폐기될 때까지 이어지는 전체 기간을 가리킨다. 소프트웨어 개발 프로세스는 이 생명주기 안에서 수행하는 활동과 작업, 역할, 산출물과 의사결정 방식을 조직한 체계이다.

두 개념은 서로 관련되지만 동일하지 않다. 생명주기는 소프트웨어가 존재하고 변화하는 전체 범위를 나타내며, 개발 프로세스는 그 안에서 사람들이 어떤 활동을 어떠한 순서와 방식으로 수행할지를 나타낸다. 하나의 소프트웨어는 여러 차례의 개발 프로젝트와 릴리스를 거칠 수 있고, 개발이 끝난 뒤에도 운영과 유지보수, 개선과 폐기 활동이 계속된다.

소프트웨어 생명주기는 흔히 요구사항, 설계, 구현, 시험, 배포와 유지보수 같은 단계로 설명된다. 그러나 실제 개발에서 이러한 활동이 항상 한 번씩 순서대로 수행되는 것은 아니다. 요구사항을 분석하다가 기술적 가능성을 확인하기 위해 프로토타입을 구현할 수 있고, 시험 과정에서 설계 문제를 발견하여 구조를 변경할 수도 있다. 운영 중 수집된 장애와 사용자 피드백은 새로운 요구사항과 다음 개발 주기로 이어진다.

따라서 생명주기 모델은 현실의 모든 작업을 고정된 단계에 가두는 규칙이라기보다, 복잡한 활동의 관계와 진행 방식을 이해하고 관리하기 위한 모형이다. 프로젝트는 제품의 목적과 규모, 위험, 규제, 변경 가능성, 개발 조직과 배포 환경에 따라 순차적·반복적·점진적·위험 중심 또는 지속적 개발 방식을 선택하고 조합한다.

ISO/IEC/IEEE 12207은 소프트웨어 시스템·제품·서비스의 구상, 개발, 운영, 지원과 폐기를 포함하는 전체 생명주기에 적용할 수 있는 공통 프로세스 체계를 제공한다. 이 표준의 프로세스는 하나의 고정된 개발 방법론을 뜻하지 않으며, 조직과 프로젝트는 필요한 프로세스와 활동을 목적과 상황에 맞게 선택하고 조정할 수 있다.[27]

생명주기와 프로세스의 구분

소프트웨어의 생명주기는 제품이나 서비스가 시간에 따라 거치는 전체 변화를 나타낸다. 반면 프로세스는 특정한 목적을 달성하기 위해 관련된 활동을 수행하고 입력을 산출물로 변환하는 방식을 나타낸다.

예를 들어 요구사항 공학 프로세스는 이해관계자의 요구와 제약을 분석하여 요구사항 명세와 검증 기준을 만든다. 구현 프로세스는 설계와 요구사항을 소스 코드와 실행 가능한 구성 요소로 변환한다. 배포 프로세스는 시험된 소프트웨어를 실제 운영 환경에 제공한다.

프로세스는 반드시 생명주기의 한 단계에만 속하지 않는다. 요구사항 관리는 개발 초기뿐 아니라 운영과 유지보수 중에도 수행되며, 시험은 구현 완료 후에만 이루어지는 것이 아니라 요구사항 검토, 설계 평가, 단위 시험과 운영 검증 등 여러 시점에 수행된다.

다음 개념들은 서로 구분할 필요가 있다.

  • 생명주기는 소프트웨어가 구상되어 폐기될 때까지의 전체 기간이다.
  • 생명주기 모델은 생명주기의 활동과 관계를 표현하는 추상적인 구조이다.
  • 프로세스는 특정한 목적을 달성하는 관련 활동의 집합이다.
  • 방법론은 프로세스를 실제로 수행하기 위한 원칙과 역할, 절차와 기법을 묶은 체계이다.
  • 방법은 분석, 설계, 구현이나 시험에 사용하는 구체적인 접근 방식이다.
  • 기법은 코드 검토, 프로토타이핑, 정적 분석과 같은 개별적인 수행 수단이다.
  • 도구는 버전 관리, 빌드, 시험, 배포와 추적 활동을 자동화하거나 지원한다.

같은 생명주기 모델도 서로 다른 방법론과 도구로 구현할 수 있다. 반대로 하나의 조직이 여러 생명주기 모델을 프로젝트나 구성 요소에 따라 함께 사용할 수도 있다.

계획과 타당성 분석

소프트웨어 개발은 코드를 작성하기 전에 해결할 문제와 개발의 목적을 확인하는 작업에서 시작된다. 새로운 소프트웨어가 필요한 이유, 예상 사용자, 제공할 가치, 필요한 자원과 주요 제약을 분석하여 개발을 시작할 것인지 결정한다.

타당성 분석은 제안된 소프트웨어가 실제로 개발하고 운영할 가치와 가능성이 있는지 평가하는 활동이다. 일반적으로 다음과 같은 측면을 검토한다.

  • 필요한 기술과 인력을 확보할 수 있는가
  • 예상 비용과 개발 기간이 허용 가능한가
  • 사용자의 문제와 조직의 목표를 실제로 해결하는가
  • 법률과 계약, 보안과 안전 요구를 충족할 수 있는가
  • 기존 시스템과 데이터, 업무 절차에 통합할 수 있는가
  • 개발 이후 운영과 유지보수를 지속할 수 있는가
  • 실패하거나 지연되었을 때 발생할 위험은 무엇인가
  • 직접 개발, 외부 구매, 오픈소스 도입과 서비스 이용 중 어떤 방식이 적합한가

계획에서는 프로젝트의 범위, 주요 산출물, 일정과 예산, 팀 구성, 의사소통 방식과 품질 목표를 정한다. 위험과 불확실성이 큰 부분을 식별하고, 이를 조기에 확인하기 위한 조사·실험·프로토타입과 검토 활동을 계획한다.

계획은 프로젝트 시작 시 한 번 작성하고 고정하는 문서가 아니다. 요구사항과 기술적 조건, 인력과 시장 환경이 변하면 계획도 갱신해야 한다. 반복적 개발에서는 각 반복과 릴리스 전에 범위와 우선순위를 다시 정하고, 실제 진행 결과를 이후 계획에 반영한다.

계획 단계에서 모든 세부 사항을 정확히 예측할 수는 없다. 따라서 초기 계획은 확정된 사실과 가정, 불확실성을 구분하고, 중요한 가정을 언제 어떻게 확인할지를 포함해야 한다.

요구사항에서 운영까지의 흐름

소프트웨어 생명주기는 일반적으로 다음과 같은 활동으로 구성된다.

  1. 문제와 기회를 식별한다.
  2. 이해관계자와 사용자의 요구를 확인한다.
  3. 시스템과 소프트웨어 요구사항을 정의한다.
  4. 전체 구조와 세부 설계를 결정한다.
  5. 소프트웨어 구성 요소를 구현한다.
  6. 구성 요소를 통합하고 요구사항 충족 여부를 시험한다.
  7. 운영 환경에 배포하고 사용자에게 제공한다.
  8. 실행 상태와 품질을 관찰하고 장애에 대응한다.
  9. 결함 수정, 환경 적응과 기능 개선을 수행한다.
  10. 다른 시스템으로 전환하거나 서비스를 종료하고 폐기한다.

이 흐름은 논리적인 관계를 보여 주지만 실제 시간 순서가 항상 일방향인 것은 아니다. 설계 과정에서 요구사항의 모순을 발견할 수 있고, 구현 과정에서 성능 목표가 현실적인지 다시 평가할 수 있다. 운영 데이터가 새로운 요구사항을 만들고, 폐기 계획이 데이터 형식과 시스템 구조에 영향을 주기도 한다.

각 활동은 다른 활동의 입력과 검토 기준을 제공한다.

  • 요구사항은 설계와 인수 시험의 기준이 된다.
  • 설계는 구현의 구조와 구성 요소 사이의 계약을 정의한다.
  • 구현과 빌드는 시험 가능한 소프트웨어를 만든다.
  • 시험 결과는 요구사항과 설계, 구현의 수정으로 이어진다.
  • 배포 결과와 운영 데이터는 다음 릴리스의 계획에 반영된다.
  • 유지보수 경험은 구조 개선과 프로세스 변경의 근거가 된다.

이러한 연결을 관리하기 위해 요구사항, 설계 결정, 코드 변경, 시험 사례와 배포 버전 사이의 추적성을 유지한다. 추적성은 특정 요구사항이 어디에 구현되었고 어떤 시험으로 검증되었는지 확인하고, 변경이 영향을 미칠 범위를 찾는 데 사용된다.

개발과 운영의 연속성

전통적인 설명에서는 개발과 운영을 별개의 단계로 구분하는 경우가 많았다. 개발 팀이 소프트웨어를 완성하여 운영 조직이나 사용자에게 전달하면 개발 프로젝트가 종료된다고 보는 방식이다.

그러나 대부분의 현대 소프트웨어는 배포 후에도 계속 변화한다. 운영 중 발견된 결함을 수정하고, 보안 취약점과 외부 의존성을 갱신하며, 사용자 요구와 데이터 규모의 변화에 대응해야 한다. 웹 서비스와 클라우드 소프트웨어에서는 기능 개발과 운영이 동시에 지속된다.

개발과 운영은 다음과 같은 순환 관계를 가진다.

  • 개발 과정에서 운영 환경과 배포 방식을 고려한다.
  • 배포 결과와 장애 정보를 개발 팀에 전달한다.
  • 로그와 메트릭, 사용자 피드백을 다음 요구사항에 반영한다.
  • 운영 절차를 코드와 자동화된 설정으로 관리한다.
  • 소프트웨어 변경과 인프라 변경을 함께 검증한다.
  • 장애 대응 후 원인을 분석하고 구조와 시험을 개선한다.

이러한 관점에서 생명주기는 개발 완료를 끝으로 보지 않는다. 소프트웨어가 실제 가치를 제공하는 기간은 대부분 운영 이후이며, 운영 가능성·관찰 가능성·복구 가능성도 설계와 구현 단계에서 함께 고려해야 한다.

순차적 개발

순차적 개발은 생명주기의 주요 활동을 일정한 순서로 진행하고, 각 단계의 산출물을 다음 단계의 입력으로 사용하는 방식이다. 요구사항을 정의한 뒤 설계하고, 설계에 따라 구현한 후 시험과 배포를 수행하는 구조가 대표적이다.

순차적 접근은 흔히 폭포수 모델과 연결되지만, 모든 순차적 프로젝트가 완전히 일방향으로만 진행되는 것은 아니다. 단계별 검토에서 문제가 발견되면 이전 단계로 돌아가 산출물을 수정할 수 있다. 핵심은 각 단계의 책임과 완료 기준, 전달할 산출물을 비교적 명확히 구분한다는 데 있다.

순차적 개발은 다음과 같은 환경에서 활용하기 쉽다.

  • 요구사항이 비교적 안정적이고 명확하다.
  • 계약과 규제에 따라 단계별 산출물이 필요하다.
  • 여러 조직이나 계약자가 명확한 인수 기준으로 작업을 전달한다.
  • 하드웨어 제작과 같이 뒤늦은 변경 비용이 매우 크다.
  • 검증과 인증에 필요한 문서와 추적성을 확보해야 한다.
  • 개발 중인 시스템을 부분적으로 배포하기 어렵다.

순차적 개발에서는 초기 분석과 설계에 많은 노력을 들여 이후 변경을 줄이려 한다. 단계별 기준선과 공식 검토를 통해 프로젝트 상태를 통제하고, 요구사항 명세와 설계 문서, 시험 계획을 주요 산출물로 관리한다.

이 방식은 범위와 책임을 명확히 관리하기 쉽지만, 요구사항이 실제 사용을 통해서만 드러나는 프로젝트에서는 피드백이 늦어질 수 있다. 실행 가능한 결과물이 개발 후반에 처음 완성되면 기술적 문제와 사용자 요구의 오해를 늦게 발견할 가능성이 있다.

따라서 순차적 구조를 사용하더라도 초기 위험 분석, 설계 검증, 시뮬레이션과 프로토타입을 함께 사용하여 불확실성을 줄일 수 있다.

반복적 개발

반복적 개발은 같은 소프트웨어를 여러 차례 설계·구현·시험하면서 각 반복에서 구조와 기능을 개선하는 방식이다. 처음부터 최종 형태를 완전하게 구현하기보다 초기 버전을 만든 뒤 평가 결과를 다음 반복에 반영한다.

각 반복은 일반적으로 다음 활동의 일부 또는 전부를 포함한다.

  • 목표와 범위 결정
  • 요구사항 분석
  • 설계와 구조 조정
  • 구현
  • 통합과 시험
  • 결과 평가
  • 다음 반복 계획

반복적 개발에서는 앞선 설계와 구현이 고정된 결과물이 아니라 학습과 개선의 대상이 된다. 사용자 피드백, 성능 측정과 기술적 발견을 바탕으로 요구사항과 구조를 변경할 수 있다.

반복은 단순히 같은 작업을 다시 수행하는 것이 아니다. 각 반복에는 확인하려는 가정이나 해결할 위험, 완성할 기능과 품질 목표가 있어야 한다. 반복의 결과를 평가하지 않고 코드만 계속 추가하면 변경 방향을 통제하기 어렵다.

점진적 개발

점진적 개발은 시스템의 기능을 여러 증분으로 나누어 각 증분마다 사용할 수 있는 기능을 추가하는 방식이다. 첫 번째 증분은 핵심 기능만 제공하고, 이후 증분에서 새로운 기능과 품질 개선을 더한다.

반복적 개발과 점진적 개발은 함께 사용되는 경우가 많지만 강조점에는 차이가 있다.

  • 반복적 개발은 기존 결과를 다시 검토하고 개선하는 데 초점을 둔다.
  • 점진적 개발은 완성된 기능의 범위를 단계적으로 늘리는 데 초점을 둔다.

예를 들어 문서 편집기를 개발할 때 첫 번째 증분에서 문서 생성과 저장을 제공하고, 다음 증분에서 검색을 추가하며, 이후 협업 편집과 버전 이력을 제공할 수 있다. 각 증분 내부에서는 설계와 구현을 여러 번 반복하여 품질을 개선할 수 있다.

점진적 개발은 다음과 같은 효과를 가진다.

  • 핵심 기능을 사용자에게 먼저 제공할 수 있다.
  • 실제 사용 결과를 이후 개발에 반영할 수 있다.
  • 중요한 기능과 위험을 우선 처리할 수 있다.
  • 대규모 통합을 작은 단위로 나눌 수 있다.
  • 일정이 변경되어도 이미 완성된 일부 가치를 제공할 수 있다.

기능을 증분으로 분리하려면 구성 요소의 경계와 의존성을 고려해야 한다. 데이터베이스, 인증과 공통 기반처럼 여러 기능이 의존하는 요소는 초기부터 일정 수준 마련해야 할 수 있다. 또한 부분적인 기능이 사용자에게 혼란이나 데이터 손상을 일으키지 않도록 각 증분의 완성 기준을 정해야 한다.

반복·점진적 개발

현대의 많은 개발 프로세스는 반복과 점진을 결합한다. 짧은 기간마다 작동하는 소프트웨어 증분을 만들고, 그 결과를 평가하여 기존 구조와 다음 기능을 조정한다.

각 반복 주기에서는 다음과 같은 흐름을 사용할 수 있다.

  1. 현재 목표와 우선순위를 선택한다.
  2. 필요한 요구사항과 수용 기준을 구체화한다.
  3. 설계와 구현을 수행한다.
  4. 자동화된 시험과 검토로 결과를 확인한다.
  5. 통합된 소프트웨어를 시연하거나 배포한다.
  6. 사용자와 운영 환경에서 피드백을 얻는다.
  7. 제품과 개발 과정에서 개선할 부분을 정한다.
  8. 다음 반복의 범위를 계획한다.

반복 주기의 길이는 프로젝트마다 다르다. 며칠 또는 몇 주 단위로 기능을 통합할 수도 있고, 안전 필수 시스템에서는 더 긴 주기와 공식 검토를 사용할 수 있다. 중요한 것은 일정한 주기로 실제 결과와 위험을 확인하고 그 정보를 이후 의사결정에 반영하는 것이다.

반복적 접근에서도 장기적인 구조와 계획은 필요하다. 현재 반복의 기능만 고려하여 설계하면 공통 기반이 불안정해지고 기술 부채가 빠르게 증가할 수 있다. 제품의 방향과 주요 품질 속성, 아키텍처 위험을 유지하면서 세부 범위와 구현을 점진적으로 조정한다.

프로토타이핑

프로토타이핑은 요구사항이나 설계, 사용자 경험과 기술적 가능성을 확인하기 위해 시스템의 일부 또는 단순화된 버전을 만드는 방법이다. 문서와 회의만으로 확인하기 어려운 가정을 실행 가능한 형태로 시험할 수 있다.

프로토타입은 목적에 따라 여러 형태로 나뉜다.

  • 사용자 인터페이스와 작업 흐름을 확인하는 화면 프로토타입
  • 알고리즘과 성능 가능성을 확인하는 기술 프로토타입
  • 외부 장치와 서비스의 연동을 확인하는 통합 프로토타입
  • 핵심 구조와 품질 속성을 검증하는 아키텍처 프로토타입
  • 제한된 기능을 실제 사용자에게 제공하는 시범 시스템
  • 요구사항을 이해한 뒤 폐기하는 탐색적 프로토타입
  • 점차 개선하여 실제 제품으로 발전시키는 진화적 프로토타입

폐기형 프로토타입은 특정 질문에 답하기 위한 실험으로 사용한 뒤 실제 제품 코드에 포함하지 않는다. 빠른 확인을 위해 품질과 구조를 단순화할 수 있지만, 이 코드를 그대로 제품으로 전환하면 시험·보안·유지보수 문제가 남을 수 있다.

진화적 프로토타입은 초기 구현을 계속 개선하여 최종 시스템으로 발전시킨다. 이 경우 처음부터 코드 구조, 시험, 데이터 이전과 확장 가능성을 어느 정도 고려해야 한다.

프로토타입을 만들기 전에 확인하려는 가정과 성공 기준을 정해야 한다. 목적이 불분명하면 제한된 실험에 지나치게 많은 시간을 사용하거나, 겉으로 동작하는 화면을 완성된 시스템으로 오해할 수 있다.

프로토타입은 요구사항을 완전히 대체하지 않는다. 프로토타입에서 확인된 사용자 행동과 기술적 결과를 요구사항, 설계 결정과 시험 기준으로 다시 기록해야 한다.

위험 중심 개발

위험 중심 개발은 실패했을 때 영향이 크거나 불확실성이 높은 문제를 조기에 식별하고, 개발 순서와 검증 활동을 위험 감소에 맞추는 방식이다.

위험은 다음과 같은 원인에서 발생할 수 있다.

  • 핵심 기술이 요구 성능을 충족할 수 있는지 불확실하다.
  • 사용자 요구와 업무 절차를 충분히 이해하지 못했다.
  • 외부 시스템과의 통합 방식이 검증되지 않았다.
  • 일정과 비용 추정의 근거가 부족하다.
  • 보안·안전·규제 요구를 충족하기 어렵다.
  • 특정 인력이나 공급자에게 의존한다.
  • 대량의 기존 데이터를 이전해야 한다.
  • 운영 환경의 규모와 장애 조건을 재현하기 어렵다.

위험 중심 접근에서는 단순히 구현하기 쉬운 기능부터 시작하지 않는다. 시스템의 성공 가능성을 결정하는 핵심 가정과 위험을 먼저 확인한다. 성능이 핵심 위험이라면 초기부터 부하 시험용 구조를 만들고, 사용자 경험이 위험이라면 프로토타입과 사용자 평가를 먼저 수행할 수 있다.

나선형 모델은 반복마다 목표와 대안을 정하고 위험을 분석한 뒤 개발과 평가를 진행하는 대표적인 위험 중심 생명주기 모델이다. 나선형 개발은 단순히 여러 번 반복하는 방식이 아니라 각 반복에서 위험을 식별하고 적극적으로 줄이는 것을 중심 원리로 삼는다.[28]

위험은 한 번 작성한 목록으로 관리되지 않는다. 개발과 운영 과정에서 새로운 정보가 생길 때마다 발생 가능성, 영향과 대응 상태를 갱신한다. 위험이 줄어들지 않거나 허용할 수 없는 수준이라면 기능 범위, 기술, 구조와 일정 자체를 변경할 수 있다.

검증과 확인의 지속적 수행

생명주기에서 검증확인은 마지막 시험 단계에만 수행되는 활동이 아니다. 요구사항, 설계, 코드, 데이터와 배포 환경이 각 시점의 목적과 기준을 충족하는지 계속 확인한다.

검증은 산출물이 정해진 명세와 이전 단계의 조건에 맞게 만들어졌는지를 확인한다. 확인은 완성된 시스템이 실제 사용자와 이해관계자의 필요를 충족하는지를 확인한다.

다음과 같은 활동이 생명주기 전체에 분포한다.

  • 요구사항의 완전성과 일관성을 검토한다.
  • 사용자와 프로토타입을 평가한다.
  • 설계가 품질 속성을 달성할 수 있는지 분석한다.
  • 코드 검토와 정적 분석을 수행한다.
  • 단위·통합·시스템 시험을 자동화한다.
  • 배포 전 운영 환경과 유사한 조건에서 검증한다.
  • 운영 중 서비스 수준과 실제 사용자 결과를 측정한다.
  • 장애와 변경 이후 기존 기능이 유지되는지 확인한다.

초기에 결함을 발견하면 이후 산출물과 코드에 잘못된 가정이 전파되는 것을 줄일 수 있다. 특히 요구사항과 아키텍처의 오류는 구현 후반에 발견될수록 수정 범위가 커질 수 있다.

기준선과 변경 관리

소프트웨어는 계속 변경되지만, 모든 산출물이 언제든지 임의로 바뀌면 프로젝트 상태와 검증 결과를 신뢰하기 어렵다. 특정 시점에 검토하고 승인한 요구사항, 설계, 소스 코드와 시험 결과를 기준선으로 관리할 수 있다.

기준선은 변경을 금지하는 것이 아니다. 이후 변경을 명시적으로 기록하고 영향과 승인 상태를 추적할 수 있도록 기준점을 제공한다.

변경 관리에서는 일반적으로 다음 내용을 다룬다.

  • 변경을 요청한 이유와 목적
  • 영향을 받는 요구사항과 구성 요소
  • 일정·비용·품질과 위험에 대한 영향
  • 대안과 우선순위
  • 승인 또는 거절 결정
  • 구현과 검토 담당자
  • 포함된 버전과 릴리스
  • 변경 이후 수행한 시험과 검증 결과

반복적 개발에서는 기준선이 순차적 프로젝트보다 자주 갱신될 수 있다. 각 반복과 릴리스에서 안정된 상태를 식별하고, 이후 작업이 어떤 버전을 기준으로 진행되는지 명확히 한다.

버전 관리와 이슈 추적, 자동화된 빌드와 시험 시스템은 변경된 코드뿐 아니라 변경의 이유와 검증 결과를 연결하는 기반이 된다.

지속적 통합

지속적 통합은 개발자의 변경을 공유 코드베이스에 자주 통합하고, 각 변경에 대해 자동화된 빌드와 시험을 수행하는 방식이다.

개발자가 오랫동안 서로 분리된 코드에서 작업하면 통합 시점에 충돌과 인터페이스 불일치가 한꺼번에 나타날 수 있다. 지속적 통합은 변경을 작게 유지하고 빠르게 통합하여 문제가 발생한 시점과 원인을 찾기 쉽게 한다.

일반적인 지속적 통합 흐름은 다음과 같다.

  1. 개발자가 작은 변경을 버전 관리 시스템에 제출한다.
  2. 빌드 시스템이 소스 코드를 컴파일하거나 패키징한다.
  3. 정적 분석과 자동화된 시험을 실행한다.
  4. 결과와 산출물을 기록한다.
  5. 실패하면 변경 담당자에게 알리고 빠르게 수정한다.
  6. 통과한 산출물을 이후 시험과 배포 단계에 전달한다.

지속적 통합이 효과적으로 작동하려면 빌드와 시험이 재현 가능하고 충분히 빠르게 실행되어야 한다. 실패한 빌드를 장기간 방치하면 이후 변경과 원인을 구분하기 어려워지므로 통합된 코드베이스를 정상 상태로 유지하는 규칙이 필요하다.

지속적 통합은 단순히 자동화 서버를 설치하는 것으로 완성되지 않는다. 변경 단위를 작게 유지하고, 자주 통합하며, 자동화된 검증 결과에 즉시 대응하는 개발 습관과 함께 사용해야 한다.

지속적 전달과 배포

지속적 전달은 코드 변경을 자동으로 빌드·시험하여 언제든지 운영 환경에 배포할 수 있는 상태로 유지하는 방식이다. 실제 운영 배포는 승인과 사업적 판단에 따라 수행할 수 있다.

지속적 배포는 자동화된 검증과 정책을 통과한 변경을 별도의 수동 배포 결정 없이 운영 환경까지 자동으로 제공하는 방식이다.

두 방식은 다음과 같이 구분할 수 있다.

  • 지속적 통합은 변경을 자주 합치고 자동으로 검증한다.
  • 지속적 전달은 검증된 변경을 언제든지 배포 가능한 상태로 만든다.
  • 지속적 배포는 검증된 변경을 운영 환경에 자동으로 배포한다.

지속적 전달 파이프라인에는 빌드, 단위 시험, 통합 시험, 보안 검사, 패키징, 환경 구성과 배포 검증 등이 포함될 수 있다. 안전 필수 또는 규제 대상 시스템에서는 자동화된 결과와 함께 공식 승인과 인증 절차를 유지할 수 있다.

배포 빈도가 높아질수록 한 번에 포함되는 변경을 작게 만들 수 있다. 작은 변경은 영향을 분석하고 문제가 생겼을 때 되돌리기 쉽지만, 실제로 안전하게 배포하려면 자동화된 시험과 모니터링, 버전 호환성과 복구 수단이 필요하다.

진화적 개발

진화적 개발은 소프트웨어가 실제 사용과 환경 변화에 따라 장기간 발전한다는 관점을 중심에 둔다. 시스템은 한 번 완성된 뒤 고정되는 것이 아니라 여러 버전과 릴리스를 통해 기능과 구조가 계속 변화한다.

진화적 개발에서는 초기부터 모든 요구사항과 구조를 확정하기보다 핵심 기능을 제공하고, 사용 결과와 새롭게 얻은 지식을 바탕으로 시스템을 확장한다. 반복·점진적 개발, 프로토타이핑과 지속적 전달이 진화적 개발을 구현하는 수단으로 사용될 수 있다.

소프트웨어가 진화할수록 기존 사용자와 데이터, 외부 시스템이 이전 동작에 의존하게 된다. 따라서 새로운 기능을 추가하는 일뿐 아니라 다음 요소를 함께 관리해야 한다.

  • 기존 인터페이스와 데이터의 호환성
  • 스키마와 저장 형식의 이전
  • 오래된 기능의 폐기 절차
  • 여러 버전이 동시에 존재할 때의 상호운용성
  • 사용자 설정과 문서의 갱신
  • 장기간 누적된 구조적 복잡성과 기술 부채
  • 지원 중인 버전과 보안 업데이트 범위

진화적 개발에서는 변경 가능성이 중요한 품질 속성이 된다. 구성 요소 경계와 시험, 버전 정책이 명확하지 않으면 작은 기능도 광범위한 수정과 장애를 일으킬 수 있다.

유지보수와 현대화

소프트웨어가 운영에 들어간 뒤 수행하는 변경 활동을 일반적으로 소프트웨어 유지보수라고 한다. 유지보수는 단순한 오류 수정에 한정되지 않는다.

유지보수는 목적에 따라 다음과 같이 구분할 수 있다.

  • 수정 유지보수는 발견된 결함을 바로잡는다.
  • 적응 유지보수는 운영체제, 하드웨어, 법률과 외부 시스템의 변화에 대응한다.
  • 완전 유지보수는 기능과 성능, 사용성을 개선한다.
  • 예방 유지보수는 미래의 결함과 변경 비용을 줄이기 위해 내부 구조와 시험을 개선한다.

운영 기간이 길어지면 소프트웨어의 구조와 사용 기술이 현재 요구에 맞지 않을 수 있다. 이때 전체 시스템을 즉시 새로 만드는 대신 부분적인 리팩터링, 구성 요소 교체, 데이터베이스 이전, 인터페이스 분리와 점진적인 재구축을 수행할 수 있다.

현대화는 오래된 시스템의 중요한 기능과 데이터를 유지하면서 구조, 실행 환경과 개발 방식을 현재 요구에 맞게 개선하는 활동이다. 레거시 시스템은 오래되었다는 이유만으로 가치가 없는 것이 아니라 오랜 기간 검증된 업무 규칙과 데이터를 포함할 수 있다.

현대화에서는 다음과 같은 선택지가 존재한다.

  • 기존 시스템을 유지하면서 필요한 부분만 수정한다.
  • 실행 환경과 플랫폼만 새로운 환경으로 이전한다.
  • 일부 구성 요소를 새로운 기술로 교체한다.
  • 외부에 API와 서비스 경계를 추가한다.
  • 데이터를 이전하고 전체 시스템을 재구축한다.
  • 상용 제품이나 외부 서비스로 대체한다.
  • 기능을 통합하거나 종료한다.

각 선택은 비용과 위험, 데이터 보존, 사용자 전환과 장기 유지보수성을 함께 고려해야 한다.

서비스 종료와 폐기

모든 소프트웨어가 영구적으로 운영되는 것은 아니다. 사용 목적이 사라지거나 다른 시스템으로 대체되고, 유지보수 비용과 보안 위험이 가치보다 커지면 서비스를 종료할 수 있다.

폐기는 단순히 서버와 프로그램을 끄는 작업이 아니다. 소프트웨어가 관리하던 데이터와 외부 시스템, 사용자와 업무 절차가 계속 존재할 수 있으므로 계획적인 전환이 필요하다.

폐기 과정에서는 다음 활동을 수행할 수 있다.

  • 대체 시스템과 전환 시점을 결정한다.
  • 기존 사용자와 연동 시스템에 종료 일정을 알린다.
  • 데이터의 보존·이전·내보내기와 삭제 방식을 정한다.
  • 법률과 계약에 따른 보존 의무를 확인한다.
  • 외부 API와 프로토콜의 사용 중단 절차를 제공한다.
  • 사용자와 운영자를 새로운 시스템으로 이전한다.
  • 라이선스와 클라우드 자원, 계정과 비밀 정보를 정리한다.
  • 저장 장치와 백업에서 민감한 데이터를 안전하게 삭제한다.
  • 소스 코드와 문서, 변경 이력을 보관한다.
  • 종료 후 발생할 수 있는 문의와 보안 문제에 대응한다.

운영 종료 가능성을 초기 설계에서 고려하면 특정 서비스와 데이터 형식에 대한 종속성을 줄이고, 사용자가 자신의 데이터를 이전할 수 있는 경로를 제공할 수 있다.

프로세스 측정과 개선

개발 프로세스는 실제 결과를 바탕으로 평가하고 개선해야 한다. 절차를 문서화했다는 사실만으로 품질과 생산성이 보장되지는 않는다.

프로세스 측정에는 다음과 같은 자료가 사용될 수 있다.

  • 요구사항과 기능의 완료 상태
  • 변경이 개발부터 배포까지 걸리는 시간
  • 빌드와 시험의 성공률 및 실행 시간
  • 발견된 결함의 수와 심각도
  • 결함을 발견하고 복구하는 데 걸린 시간
  • 배포 빈도와 배포 실패율
  • 코드 검토와 변경의 규모
  • 운영 중 서비스 수준과 장애 기록
  • 사용자 피드백과 실제 기능 사용
  • 재작업과 기술 부채에 사용된 노력

측정값은 팀과 개인을 단순히 비교하거나 숫자 자체를 목표로 삼기보다 병목과 위험, 개선 결과를 이해하기 위해 사용해야 한다. 측정 기준이 목표가 되면 실제 품질보다 숫자를 높이는 행동이 나타날 수 있다.

프로세스 개선은 큰 제도를 한 번에 도입하는 방식뿐 아니라 반복적으로 작은 문제를 찾아 수정하는 방식으로도 이루어진다. 자동화되지 않은 반복 작업, 늦게 발견되는 결함, 불명확한 책임과 긴 승인 대기 시간을 식별하고 개선 결과를 다시 측정한다.

IEEE Computer Society의 SWEBOK는 생명주기 정의와 모델, 프로세스 관리, 생명주기 조정, 프로세스 감시와 개선을 소프트웨어 공학 프로세스 지식의 주요 범위로 다룬다.[29]

프로세스 선택과 조정

모든 프로젝트에 가장 적합한 하나의 생명주기 모델이나 개발 프로세스는 존재하지 않는다. 조직은 프로젝트의 특성과 위험에 따라 필요한 활동, 순서, 반복 주기와 문서 수준을 선택하고 조정해야 한다.

프로세스를 선택할 때는 다음 요소를 고려한다.

  • 시스템의 규모와 예상 수명
  • 요구사항의 안정성과 불확실성
  • 사용자 피드백을 받을 수 있는 시점
  • 실패가 사람과 사회에 미치는 영향
  • 보안·안전·개인정보와 규제 요구
  • 여러 조직과 공급자 사이의 계약 관계
  • 하드웨어와 외부 시스템에 대한 의존성
  • 부분적인 배포와 되돌리기의 가능성
  • 개발 팀의 규모와 분산 정도
  • 운영과 유지보수 조직의 구조
  • 출시 일정과 시장 변화
  • 사용 가능한 도구와 자동화 수준

요구사항이 안정적이고 단계별 승인과 인증이 필요한 프로젝트에서는 순차적 구조와 명확한 기준선이 적합할 수 있다. 요구가 빠르게 변하고 사용자 피드백이 중요한 제품에서는 반복·점진적 개발과 지속적 전달이 적합할 수 있다. 기술적 불확실성과 실패 위험이 큰 시스템에서는 위험 중심 반복과 프로토타이핑을 강화할 수 있다.

하나의 프로젝트에서도 구성 요소에 따라 다른 프로세스를 사용할 수 있다. 웹 기반 관리 화면은 짧은 반복으로 개발하면서, 안전에 직접 영향을 주는 제어 구성 요소에는 엄격한 명세와 독립적인 검증을 적용할 수 있다. 상용 하드웨어의 제작 일정은 순차적으로 관리하면서 서버 소프트웨어는 지속적으로 배포할 수도 있다.

애자일 소프트웨어 개발은 초기 계획과 문서를 모두 없애는 방식이 아니다. 작동하는 소프트웨어를 조기에 지속적으로 전달하고, 변화하는 요구를 받아들이며, 개발자와 이해관계자의 협력을 통해 계획과 구현을 계속 조정하는 방향을 강조한다.[30][31]

프로세스를 조정할 때도 요구사항, 설계, 구현, 시험, 형상 관리와 품질 보증 같은 필요한 공학 활동 자체를 생략해서는 안 된다. 대신 각 활동의 형식과 깊이, 수행 시점과 산출물을 프로젝트에 맞게 정한다.

작은 프로젝트에서는 요구사항을 짧은 작업 항목과 시험 조건으로 관리할 수 있고, 대규모 안전 필수 시스템에서는 정형화된 명세와 승인 기록, 독립적인 평가가 필요할 수 있다. 중요한 것은 절차의 양이 아니라 시스템의 위험과 품질 목표를 통제하기에 충분한 정보를 만들고 검증하는 것이다.

소프트웨어 생명주기와 개발 프로세스는 소프트웨어를 일회성 결과물이 아니라 계속 변화하고 운영되는 시스템으로 다루기 위한 구조이다. 적절한 프로세스는 개발자를 제한하는 규칙의 집합이 아니라, 불확실성을 줄이고 필요한 피드백을 얻으며 변경의 영향을 통제하기 위한 공통 작업 체계를 제공한다.

요구사항 공학

요구사항 공학(Requirements Engineering)은 소프트웨어가 해결해야 할 문제와 제공해야 할 기능, 충족해야 할 품질과 제약을 식별하고 분석하여 명확하게 표현하며, 이해관계자와 합의하고 생명주기 동안 관리하는 활동이다. 요구사항 공학은 개발할 기능의 목록을 작성하는 작업에 그치지 않고, 왜 소프트웨어가 필요한지, 누가 어떤 환경에서 사용할지, 성공과 실패를 무엇으로 판단할지를 정의한다.

소프트웨어 개발에서 요구사항은 설계와 구현, 시험, 배포와 인수의 기준이 된다. 요구사항이 불명확하거나 서로 모순되면 개발자가 기술적으로 완성도 높은 시스템을 구현하더라도 실제 사용자의 문제를 해결하지 못할 수 있다. 반대로 요구사항이 구체적이고 검증 가능하며 우선순위와 근거가 명확하면 설계 대안을 평가하고 변경의 영향을 판단하기 쉬워진다.

ISO/IEC/IEEE 29148은 시스템과 소프트웨어 제품 및 서비스의 생명주기에서 요구사항을 만드는 공학 활동과 관련 프로세스, 그 과정에서 생성되는 정보 항목을 규정한다.[32] IEEE Computer Society는 요구사항 공학의 주요 활동을 요구사항 도출, 분석, 명세와 검증으로 설명한다.[33]

요구사항은 프로젝트 초기에 한 번 작성하고 고정하는 문서가 아니다. 개발 과정에서 새로운 이해관계자가 발견되거나 기술적 가능성, 법률, 시장과 운영 환경이 달라질 수 있다. 프로토타입과 시험, 실제 사용을 통해 처음에는 알지 못했던 요구가 드러나기도 한다. 따라서 요구사항 공학은 요구를 처음 발견하는 과정뿐 아니라 요구사항의 근거와 상태, 변경과 구현 결과를 지속적으로 관리하는 과정까지 포함한다.

문제와 요구사항의 구분

요구사항을 정의하기 전에 먼저 해결하려는 문제, 달성하려는 목표, 이를 위해 시스템이 충족해야 하는 요구사항을 구분해야 한다.

문제는 현재 상태에서 발생하는 불편, 위험, 비용이나 기회의 손실을 나타낸다. 목표는 문제를 해결한 뒤 기대하는 상태나 성과를 나타낸다. 요구사항은 그 목표를 달성하기 위해 시스템이나 개발 과정이 충족해야 하는 조건을 표현한다.

예를 들어 사용자가 중요한 문서를 자주 잃어버린다는 것은 문제이다. 문서를 안전하게 보존하고 이전 상태를 복구할 수 있게 한다는 것은 목표이다. 모든 저장된 문서의 변경 이력을 유지하고 사용자가 특정 시점의 버전을 복원할 수 있어야 한다는 것은 요구사항이 될 수 있다.

문제와 해결책을 구분하지 않으면 특정 구현 방식이 요구사항으로 고정될 수 있다. “데이터베이스로 저장해야 한다”는 문장은 실제로 데이터 보존과 검색이라는 목표를 달성하기 위한 하나의 설계 대안일 수 있다. 요구사항 단계에서 해결책을 지나치게 일찍 확정하면 더 단순하거나 적합한 설계 대안을 검토하기 어려워진다.

다만 법률, 계약, 기존 환경이나 조직 정책 때문에 특정 기술과 표준을 사용해야 하는 경우에는 구현 기술 자체가 실제 제약 요구사항이 될 수 있다. 중요한 것은 해당 결정이 사용자의 필요인지, 상위 시스템의 제약인지, 개발 조직이 선택한 설계인지 근거를 구분하는 것이다.

이해관계자

이해관계자는 소프트웨어의 개발, 사용, 운영이나 결과에 영향을 주거나 영향을 받는 개인과 조직이다. 요구사항 공학에서는 직접 소프트웨어를 사용하는 사람만이 아니라 시스템의 전체 생명주기에 관련된 이해관계자를 찾는다.

이해관계자에는 다음과 같은 주체가 포함될 수 있다.

  • 최종 사용자
  • 제품 또는 서비스의 구매자
  • 업무와 제품의 책임자
  • 소프트웨어 개발자와 시험 담당자
  • 시스템 운영자와 고객 지원 담당자
  • 보안과 개인정보 보호 담당자
  • 법무, 감사와 규제 기관
  • 외부 시스템과 API의 관리자
  • 하드웨어와 플랫폼 공급자
  • 유지보수와 데이터 이전 담당자
  • 시스템의 동작으로 간접적인 영향을 받는 사람
  • 서비스 종료 이후 데이터를 관리할 조직

이해관계자는 서로 다른 목표와 관점을 가진다. 사용자는 작업 속도와 편의성을 중시할 수 있고, 운영자는 장애 복구와 관리 가능성을 중시할 수 있다. 보안 담당자는 강한 접근 통제를 요구하고, 사용자는 로그인 절차가 간단하기를 원할 수 있다. 경영진은 빠른 출시를 원하지만 개발자는 구조 개선과 시험을 위한 시간을 필요로 할 수 있다.

요구사항 공학은 이러한 요구를 단순히 모두 받아 적는 과정이 아니다. 서로 충돌하는 요구와 제한된 비용·일정·기술 조건을 분석하고, 우선순위를 정하며, 결정의 이유를 이해관계자와 합의해야 한다.

이해관계자를 빠뜨리면 개발 후반이나 운영 단계에서 중요한 요구가 뒤늦게 나타날 수 있다. 직접 사용자에게만 집중하면 운영, 보안, 접근성, 데이터 보존과 폐기 요구가 누락될 수 있으므로 시스템의 전체 사용 환경과 생명주기를 기준으로 이해관계자를 식별한다.

요구사항의 수준

요구사항은 표현하는 대상과 상세 수준에 따라 여러 계층으로 구분할 수 있다.

사업 또는 임무 요구는 소프트웨어를 개발하는 이유와 조직이 달성하려는 성과를 설명한다. 매출 증가, 작업 시간 감소, 사고 위험 감소, 법적 의무 충족과 같은 목표가 여기에 포함될 수 있다.

이해관계자 요구사항은 사용자와 다른 이해관계자가 시스템을 통해 수행해야 하는 작업과 기대하는 결과를 표현한다. 이는 특정 구현 방식보다 사용자의 관점과 운영 상황에 초점을 둔다.

시스템 요구사항은 소프트웨어뿐 아니라 하드웨어, 사람, 업무 절차와 외부 시스템을 포함하는 전체 시스템이 충족해야 하는 조건을 정의한다.

소프트웨어 요구사항은 전체 시스템 요구사항 가운데 소프트웨어 구성 요소가 담당해야 할 기능, 품질과 인터페이스를 구체화한다.

구성 요소 요구사항은 상위 소프트웨어 요구사항을 모듈, 서비스, 라이브러리와 하위 구성 요소가 구현할 수 있는 수준으로 분해한다.

하위 요구사항은 상위 요구의 의미와 목적을 보존해야 한다. 구성 요소의 요구사항이 모두 구현되었더라도 상위 사용자의 목표가 충족되지 않는다면 요구사항 분해가 적절하지 않았을 수 있다. 따라서 하위 요구사항은 상위 요구와의 추적 관계를 유지하고, 전체 시스템 수준에서 다시 확인해야 한다.

요구사항 도출

요구사항 도출은 이해관계자와 업무 환경, 기존 시스템과 자료에서 요구를 발견하고 수집하는 활동이다. 요구사항은 처음부터 완성된 문장으로 존재하는 경우가 드물다. 사용자는 현재 작업 방식을 당연하게 여겨 중요한 조건을 말하지 않을 수 있고, 서로 다른 이해관계자가 같은 용어를 다른 의미로 사용할 수 있다.

도출 활동에서는 다음과 같은 방법을 사용할 수 있다.

  • 이해관계자 인터뷰
  • 설문 조사
  • 워크숍과 공동 설계 회의
  • 실제 작업과 사용 환경 관찰
  • 기존 업무 절차와 문서 분석
  • 현재 사용 중인 시스템과 데이터 분석
  • 법률, 표준, 계약과 조직 정책 검토
  • 사용자 시나리오와 유스 케이스 작성
  • 프로토타입과 화면 모형 평가
  • 경쟁 제품과 유사 시스템 분석
  • 장애, 문의와 사용자 행동 데이터 분석
  • 브레인스토밍과 아이디어 정리

인터뷰는 사용자의 목표와 문제를 깊이 이해하는 데 유용하지만, 질문 방식과 참여자의 기억에 영향을 받을 수 있다. 관찰은 실제 작업과 문서에 기록되지 않은 예외 절차를 발견할 수 있지만, 관찰 대상과 기간이 제한될 수 있다. 프로토타입은 추상적인 설명을 구체화하지만, 화면의 시각적 완성도가 실제 기능의 완성도로 오해될 수 있다.

따라서 하나의 도출 방법에만 의존하기보다 서로 다른 자료와 방법을 결합하여 요구를 교차 확인한다. 사용자의 설명과 실제 업무가 다르다면 어느 한쪽을 즉시 잘못된 것으로 판단하지 않고, 차이가 발생한 이유와 예외 조건을 조사한다.

도출 과정에서는 사용자가 요청한 기능만 묻지 않고 다음 내용을 함께 확인한다.

  • 현재 해결하려는 문제는 무엇인가
  • 현재 어떤 절차와 도구를 사용하는가
  • 누가 어떤 상황에서 작업하는가
  • 정상적인 작업 흐름과 예외 상황은 무엇인가
  • 가장 많은 시간과 비용이 드는 부분은 무엇인가
  • 어떤 오류와 실패가 허용될 수 없는가
  • 어떤 데이터가 생성되고 이동하는가
  • 성공 여부를 어떤 결과로 판단하는가
  • 앞으로 환경과 규모가 어떻게 변할 수 있는가
  • 시스템을 사용하지 않거나 우회하는 경우는 언제인가

도출 활동에서 얻은 발언과 자료는 그대로 최종 요구사항이 되지 않는다. 중복과 모순, 모호한 표현과 해결책 중심의 요청을 분석하고, 실제 목표와 검증 가능한 조건으로 정리해야 한다.

기능 요구사항

기능 요구사항은 시스템이 제공해야 하는 기능과 동작을 정의한다. 특정 입력이나 사건이 발생했을 때 시스템이 수행할 처리, 생성할 결과와 상태 변화를 설명한다.

기능 요구사항에는 다음과 같은 내용이 포함될 수 있다.

  • 사용자가 계정을 만들고 인증할 수 있다.
  • 문서를 생성·수정·삭제하고 검색할 수 있다.
  • 결제 요청을 처리하고 결과를 기록한다.
  • 센서 입력에 따라 장치를 제어한다.
  • 특정 조건에서 알림을 전송한다.
  • 외부 시스템과 데이터를 교환한다.
  • 사용자의 권한에 따라 접근을 제한한다.
  • 장애 이후 데이터를 복구한다.
  • 변경 이력과 감사 기록을 유지한다.

기능 요구사항은 단순히 화면에 보이는 기능만을 뜻하지 않는다. 자동 작업, 백그라운드 처리, 데이터 변환, 인증과 권한 검사, 오류 처리와 복구도 시스템의 기능이다.

기능 요구사항은 입력, 처리 조건, 결과와 실패 동작을 함께 설명해야 한다. “사용자는 파일을 업로드할 수 있어야 한다”는 문장만으로는 지원할 파일 형식과 크기, 중복 파일의 처리, 실패 시 결과와 권한 조건을 알기 어렵다.

모든 세부 사항을 한 문장에 넣을 필요는 없지만, 관련된 규칙과 예외 조건을 별도의 요구사항이나 수용 기준으로 연결하여 구현자와 시험 담당자가 같은 의미로 해석할 수 있도록 한다.

비기능 요구사항과 품질 요구사항

비기능 요구사항은 흔히 기능 자체가 아니라 시스템이 기능을 수행하는 품질과 조건을 나타내는 요구사항을 가리킨다. 성능, 신뢰성, 보안, 사용성, 유지보수성, 이식성과 접근성 등이 여기에 포함된다.

그러나 비기능이라는 표현은 해당 요구가 덜 중요하거나 기능과 분리되어 있다는 의미가 아니다. 사용자가 로그인할 수 있는 기능이 있더라도 응답에 지나치게 오래 걸리거나 인증 정보가 노출된다면 실제 요구를 충족했다고 보기 어렵다.

품질 요구사항에는 다음과 같은 것들이 있다.

  • 특정 요청의 응답 시간
  • 일정 시간 동안 처리할 수 있는 작업량
  • 동시에 지원해야 하는 사용자 수
  • 허용 가능한 장애 시간과 복구 시간
  • 데이터 손실의 허용 범위
  • 인증, 권한과 암호화 조건
  • 접근성 표준과 지원 보조 기술
  • 지원 운영체제와 하드웨어
  • 유지보수와 확장에 필요한 구조적 조건
  • 로그, 메트릭과 감사 기록
  • 설치와 업데이트에 걸리는 시간
  • 사용자가 작업을 완료할 수 있는 성공률

품질 요구사항은 가능하면 측정할 수 있는 조건으로 표현한다. “시스템은 빨라야 한다”보다 “정상 부하에서 검색 요청의 95%는 500밀리초 이내에 응답해야 한다”처럼 대상, 조건과 기준을 명시하는 편이 검증하기 쉽다.

하나의 품질 요구사항이 다른 품질에 영향을 줄 수도 있다. 강한 인증 절차는 보안을 높이지만 사용성을 낮출 수 있고, 대량 캐시는 성능을 높이지만 자원 사용과 데이터 일관성을 복잡하게 만들 수 있다. 따라서 품질 요구사항은 개별적으로만 정의하지 않고 우선순위와 상충 관계를 함께 분석한다.

제약 요구사항

제약 요구사항은 시스템이나 개발 과정에서 선택할 수 있는 범위를 제한하는 조건이다. 법률과 표준, 기존 환경, 계약, 예산과 일정, 사용 기술과 운영 정책 등이 제약이 될 수 있다.

제약에는 다음과 같은 내용이 포함될 수 있다.

  • 특정 운영체제와 장치에서 실행해야 한다.
  • 정해진 네트워크 프로토콜이나 파일 형식을 사용해야 한다.
  • 법률에 따라 데이터를 일정 기간 보존해야 한다.
  • 특정 국가나 지역 안에서만 데이터를 처리해야 한다.
  • 정해진 접근성 또는 안전 표준을 충족해야 한다.
  • 기존 데이터베이스와 하위 호환성을 유지해야 한다.
  • 제한된 메모리와 전력 안에서 동작해야 한다.
  • 특정 날짜 이전에 서비스를 전환해야 한다.
  • 승인된 라이선스의 구성 요소만 사용할 수 있다.
  • 독립적인 검증과 감사를 받아야 한다.

제약은 설계 선택의 폭을 줄이므로 근거와 적용 범위를 명확히 해야 한다. 과거에 선택한 기술이라는 이유만으로 제약이 유지되거나, 특정 담당자의 선호가 조직 전체의 요구로 표현될 수 있기 때문이다.

변경할 수 없는 제약과 협상을 통해 변경 가능한 제약을 구분하면 더 넓은 설계 대안을 검토할 수 있다.

인터페이스 요구사항

인터페이스 요구사항은 시스템이 사용자, 하드웨어, 외부 소프트웨어와 통신하는 경계와 조건을 정의한다.

인터페이스 요구사항에는 다음이 포함될 수 있다.

  • 사용자 인터페이스의 입력과 출력
  • 외부 API의 요청과 응답 형식
  • 파일과 데이터 교환 형식
  • 장치와 센서의 통신 방식
  • 네트워크 프로토콜과 포트
  • 인증과 권한 전달 방식
  • 오류 코드와 재시도 조건
  • 메시지 순서와 시간 제한
  • 지원하는 버전과 호환성 정책

인터페이스는 여러 조직과 시스템이 만나는 경계이므로 변경 비용이 크다. 인터페이스의 소유자, 버전 정책, 실패 처리와 폐기 절차를 요구사항 단계에서 정의하면 통합 과정의 불확실성을 줄일 수 있다.

인터페이스 요구사항은 데이터의 구문뿐 아니라 의미를 정의해야 한다. 같은 status라는 필드도 시스템마다 주문 상태, 통신 상태 또는 처리 결과를 뜻할 수 있다. 시간대, 측정 단위, 문자 인코딩과 누락된 값의 의미도 명시해야 한다.

데이터 요구사항

데이터는 소프트웨어의 입력과 출력일 뿐 아니라 시스템이 장기간 보존하고 다른 시스템과 공유하는 핵심 자산이 될 수 있다. 데이터 요구사항은 시스템이 다룰 데이터의 의미, 구조, 품질, 생명주기와 보호 조건을 정의한다.

데이터 요구사항에는 다음과 같은 내용이 포함된다.

  • 데이터 항목과 관계의 의미
  • 필수 값과 선택 값
  • 값의 범위와 유효성 규칙
  • 고유 식별자와 중복 처리
  • 데이터 생성, 수정과 삭제 권한
  • 보존 기간과 폐기 방식
  • 백업과 복구 조건
  • 개인정보와 민감 정보의 분류
  • 데이터 이전과 내보내기 형식
  • 출처와 변경 이력
  • 데이터 정확성, 완전성과 최신성
  • 분석과 감사에 필요한 기록

데이터 요구사항이 명확하지 않으면 서로 다른 구성 요소가 같은 정보를 다른 의미와 형식으로 저장할 수 있다. 이후 데이터 통합과 이전 과정에서 값의 의미를 복원하기 어려워지므로 초기부터 공통 용어와 데이터 정의를 관리한다.

운영 요구사항

운영 요구사항은 소프트웨어가 실제 환경에서 설치되고 실행되며 감시·복구되는 방식을 정의한다. 개발 환경에서 기능이 동작하더라도 운영자가 배포하거나 장애를 진단할 수 없다면 실질적으로 운영 가능한 시스템이 아니다.

운영 요구사항에는 다음이 포함될 수 있다.

  • 배포 가능한 시간과 중단 허용 범위
  • 서버와 장치, 운영체제와 네트워크 조건
  • 설정과 비밀 정보 관리
  • 로그와 메트릭, 분산 추적
  • 경고 조건과 통보 대상
  • 백업과 복구 절차
  • 장애 시 자동 또는 수동 복구 방식
  • 유지보수 창과 업데이트 정책
  • 용량과 자동 확장 조건
  • 운영 권한과 감사 기록
  • 고객 지원과 문제 보고 절차
  • 서비스 종료와 데이터 이전

운영 요구사항은 운영 담당자와 함께 도출해야 한다. 개발자가 필요한 로그와 진단 정보를 임의로 판단하면 실제 장애 상황에서 원인을 찾기 부족하거나, 반대로 불필요한 민감 정보를 기록할 수 있다.

요구사항 분석

요구사항 분석은 도출한 요구를 정리하고 관계와 충돌, 누락과 실현 가능성을 검토하여 설계와 검증에 사용할 수 있는 요구사항으로 발전시키는 활동이다.

분석 과정에서는 다음을 확인한다.

  • 요구가 실제 문제와 목표에 연결되는가
  • 같은 의미의 요구가 중복되어 있지 않은가
  • 서로 모순되거나 충돌하는 요구가 있는가
  • 의미가 여러 방식으로 해석될 수 있는가
  • 필요한 조건과 예외 상황이 빠져 있지 않은가
  • 기술과 비용, 일정 안에서 실현 가능한가
  • 다른 요구사항과 설계에 어떤 영향을 주는가
  • 검증할 수 있는 기준이 존재하는가
  • 우선순위와 중요도가 정해져 있는가
  • 요구사항의 출처와 책임자가 명확한가

요구사항 분석에서는 기능 목록뿐 아니라 사용자와 시스템의 상호작용, 데이터 흐름, 상태 변화, 업무 규칙과 예외 상황을 모델링할 수 있다.

사용되는 모델에는 다음과 같은 것들이 있다.

  • 사용자 시나리오
  • 유스 케이스
  • 사용자 스토리
  • 업무 흐름과 활동 모델
  • 상태 전이 모델
  • 데이터 흐름 모델
  • 개념과 데이터 모델
  • 시스템 경계와 문맥 모델
  • 인터페이스 모델
  • 결정표와 업무 규칙
  • 위협과 오용 사례

모델은 요구사항을 대체하는 장식물이 아니라 자연어만으로 파악하기 어려운 관계와 예외를 발견하는 분석 도구이다. 서로 다른 모델이 같은 동작을 다르게 표현한다면 불일치의 원인을 확인해야 한다.

시스템 경계

요구사항 분석에서는 개발할 시스템이 책임질 범위와 외부 환경을 구분하는 시스템 경계를 정의한다.

경계 안에는 시스템이 직접 제공하고 통제할 기능이 포함되며, 경계 밖에는 사용자, 외부 서비스, 하드웨어, 다른 조직의 업무 절차와 물리적 환경이 존재한다.

경계가 불명확하면 다음과 같은 문제가 발생할 수 있다.

  • 외부 시스템이 처리할 기능을 현재 프로젝트가 구현한다.
  • 반드시 필요한 통합 작업이 범위에서 빠진다.
  • 사용자나 운영자가 수동으로 해야 할 작업이 정의되지 않는다.
  • 외부 서비스의 장애와 변경 책임이 불분명해진다.
  • 프로젝트마다 전체 시스템의 범위를 다르게 이해한다.

시스템 문맥도와 외부 인터페이스 목록을 사용하면 시스템이 누구와 무엇을 주고받는지 명확히 표현할 수 있다. 외부 요소를 시스템이 통제할 수는 없지만, 예상되는 동작과 실패 조건을 요구사항에 반영해야 한다.

시나리오와 유스 케이스

시나리오는 사용자가 특정 목표를 달성하기 위해 시스템과 상호작용하는 구체적인 상황과 흐름을 설명한다. 정상적인 흐름뿐 아니라 실패, 취소와 예외 상황을 함께 표현할 수 있다.

유스 케이스는 외부 행위자와 시스템 사이의 상호작용을 목표 중심으로 구조화한 표현이다. 일반적으로 행위자, 시작 조건, 기본 흐름, 대안 흐름, 예외와 완료 조건을 포함한다.

시나리오와 유스 케이스는 시스템의 내부 구현보다 외부에서 관찰되는 동작에 집중한다. 이를 통해 이해관계자는 실제 작업의 관점에서 요구사항을 검토할 수 있고, 개발자는 기능 사이의 순서와 예외 조건을 파악할 수 있다.

하나의 기본 흐름만 작성하면 오류와 경계 조건을 놓치기 쉽다. 인증 실패, 중복 요청, 네트워크 단절, 권한 부족, 취소와 시간 초과 등 대안 흐름을 분석하여 필요한 요구사항과 시험 사례를 발견한다.

사용자 스토리와 수용 기준

사용자 스토리는 특정 사용자의 관점에서 원하는 기능과 그 목적을 짧게 표현하는 방식이다. 일반적으로 누가, 무엇을, 왜 원하는지를 나타낸다.

사용자 스토리는 대화를 시작하고 작업의 가치를 설명하는 데 유용하지만, 짧은 문장만으로 완전한 요구사항 명세가 되지는 않는다. 구체적인 동작과 예외, 품질 조건은 대화와 추가 자료, 수용 기준을 통해 보완한다.

수용 기준은 기능이 완료되었다고 판단할 수 있는 관찰 가능하고 시험 가능한 조건이다. 예를 들어 비밀번호 재설정 기능에는 다음과 같은 기준이 포함될 수 있다.

  • 등록된 계정에만 재설정 절차를 시작할 수 있다.
  • 사용자 존재 여부가 외부에 노출되지 않는다.
  • 재설정 링크는 한 번만 사용할 수 있다.
  • 정해진 시간이 지나면 링크가 만료된다.
  • 비밀번호 변경 후 기존 세션의 처리 정책이 적용된다.
  • 성공과 실패 결과를 감사 기록에 남긴다.

수용 기준은 요구사항과 시험 사이의 연결점이 된다. 다만 수용 기준만 통과했다고 해서 성능, 보안과 운영 요구까지 모두 충족되는 것은 아니므로 관련 품질 요구사항을 함께 관리한다.

프로토타입과 모형

요구사항이 추상적이거나 사용자 인터페이스와 상호작용이 중요한 경우 프로토타입과 모형을 사용하여 이해관계자의 요구를 구체화할 수 있다.

프로토타입은 다음과 같은 질문을 확인하는 데 사용된다.

  • 사용자가 작업 흐름을 이해할 수 있는가
  • 필요한 정보와 기능이 화면에 나타나는가
  • 장치와 외부 서비스가 기술적으로 연동되는가
  • 예상한 데이터와 입력을 실제로 얻을 수 있는가
  • 성능과 응답성이 사용 목적을 충족할 수 있는가
  • 새로운 개념이 사용자 업무에 맞는가

화면 모형은 구현 비용이 낮아 여러 대안을 빠르게 비교할 수 있다. 실행 가능한 프로토타입은 실제 상호작용과 기술적 위험을 확인할 수 있지만, 임시 코드와 제한된 데이터로 만들어졌다는 점을 명확히 해야 한다.

프로토타입에서 얻은 피드백은 요구사항과 수용 기준에 반영한다. 프로토타입 자체만 남기면 왜 특정 구조와 기능을 선택했는지 이후에 추적하기 어렵다.

요구사항 협상

여러 이해관계자의 요구는 비용, 일정, 기술과 품질 측면에서 충돌할 수 있다. 요구사항 협상은 충돌을 숨기거나 한쪽의 요구를 임의로 제거하는 대신, 각 요구의 목적과 영향을 분석하여 합의 가능한 결정을 만드는 활동이다.

협상에서는 다음과 같은 질문을 다룬다.

  • 각 요구가 해결하려는 문제는 무엇인가
  • 요구를 충족하지 않으면 어떤 영향이 발생하는가
  • 비용과 일정, 위험은 어느 정도인가
  • 일부만 제공하거나 단계적으로 제공할 수 있는가
  • 다른 방법으로 같은 목표를 달성할 수 있는가
  • 어떤 품질 속성이 우선되는가
  • 누가 최종 결정을 내릴 권한과 책임을 가지는가

예를 들어 사용자는 모든 검색 결과를 즉시 보고 싶어 할 수 있지만, 데이터 규모와 비용 때문에 제한이 필요할 수 있다. 이 경우 결과 수를 단순히 줄이기보다 페이지 처리, 점진적 로딩, 검색 조건과 사전 계산 등 여러 대안을 검토할 수 있다.

협상 결과에는 선택한 요구사항뿐 아니라 보류하거나 거절한 요구와 결정 이유도 기록한다. 그렇지 않으면 같은 논쟁이 반복되거나 이후 담당자가 과거의 제약을 알지 못한 채 결정을 뒤집을 수 있다.

요구사항 우선순위

모든 요구사항을 같은 시점과 수준으로 구현할 수는 없다. 우선순위 결정은 제한된 자원 안에서 어떤 요구를 먼저 구현하고 어떤 요구를 연기하거나 제외할지 판단하는 과정이다.

우선순위를 정할 때 다음 요소를 고려할 수 있다.

  • 사용자와 조직에 제공하는 가치
  • 안전과 보안에 미치는 영향
  • 법률과 계약상 의무
  • 기술적 위험과 불확실성
  • 다른 기능이 의존하는 정도
  • 구현 비용과 일정
  • 운영과 유지보수 비용
  • 시장과 배포 시점
  • 요구를 제공하지 않았을 때의 손실
  • 학습과 피드백을 얻을 가능성

우선순위는 중요도만을 뜻하지 않는다. 매우 중요한 기능이라도 상위 기반이나 외부 계약이 준비되지 않아 당장 구현할 수 없을 수 있다. 반대로 위험한 기술적 가정을 조기에 확인하기 위해 사용자 가치가 직접 나타나지 않는 기반 작업을 먼저 수행할 수도 있다.

우선순위는 고정된 숫자보다 의사결정의 근거로 사용해야 한다. 모든 이해관계자가 자신의 요구를 최우선으로 표시하면 구분의 의미가 사라지므로 상대적인 비교와 명확한 결정 권한이 필요하다.

요구사항 명세

요구사항 명세는 분석하고 합의한 요구사항을 개발, 시험과 관리에 사용할 수 있는 형태로 기록하는 활동이다. 결과물은 전통적인 소프트웨어 요구사항 명세서, 제품 백로그, 모델과 인터페이스 문서, 사용자 스토리와 수용 기준 등 여러 형태가 될 수 있다.

명세의 형식은 프로젝트 규모와 위험, 계약과 규제에 따라 달라진다. 작은 내부 도구는 짧은 작업 항목과 시험 조건으로 충분할 수 있지만, 여러 조직이 참여하거나 안전·보안에 중요한 시스템은 정형화된 문서와 추적성을 요구할 수 있다.

좋은 요구사항은 일반적으로 다음 특성을 지향한다.

  • 필요한 목적과 근거가 있다.
  • 하나의 명확한 요구를 표현한다.
  • 여러 방식으로 해석되지 않는다.
  • 다른 요구사항과 모순되지 않는다.
  • 기술과 비용 안에서 실현 가능하다.
  • 시험·분석·검사나 시연으로 확인할 수 있다.
  • 출처와 상위 목표를 추적할 수 있다.
  • 고유하게 식별되고 상태를 관리할 수 있다.
  • 필요한 조건과 범위가 충분히 설명되어 있다.
  • 구현 방법보다 필요한 결과를 중심으로 표현한다.

모든 요구사항을 완전히 독립된 한 문장으로 만드는 것은 현실적이지 않을 수 있다. 관련된 용어 정의, 모델, 표와 수용 기준을 함께 사용하여 전체 의미를 명확히 한다.

명세는 독자도 고려해야 한다. 사용자와 발주자, 개발자, 시험 담당자와 운영자가 같은 문서를 읽을 수 있으므로 전문 용어를 정의하고 문서의 구조와 상세 수준을 일관되게 유지한다.

요구사항 문장의 작성

요구사항 문장은 책임 주체와 필수 동작, 적용 조건과 결과를 명확하게 표현해야 한다.

예를 들면 다음과 같이 작성할 수 있다.

  • 시스템은 인증된 사용자가 자신이 소유한 문서를 삭제할 수 있도록 해야 한다.
  • 서버는 정상 부하에서 검색 요청의 95%에 500밀리초 이내로 응답해야 한다.
  • 재설정 토큰은 발급 후 30분이 지나거나 한 번 사용되면 무효화되어야 한다.
  • 감사 기록은 일반 사용자가 수정하거나 삭제할 수 없어야 한다.
  • 네트워크 연결이 끊기면 클라이언트는 저장되지 않은 변경을 로컬 임시 저장소에 보존해야 한다.

다음과 같은 표현은 추가적인 분석이 필요할 수 있다.

  • 빠르게 동작해야 한다.
  • 사용하기 쉬워야 한다.
  • 가능한 모든 환경을 지원해야 한다.
  • 적절한 보안을 제공해야 한다.
  • 필요하면 데이터를 저장한다.
  • 일반적인 오류를 처리한다.
  • 충분한 로그를 기록한다.

빠른, 쉬운, 적절한, 일반적인, 충분한과 같은 표현은 판단 기준이 사람마다 다르다. 대상 사용자와 실행 조건, 측정 방법과 허용 기준을 함께 정의해야 한다.

, 또는, 가능하면, 필요한 경우 같은 표현도 범위를 모호하게 만들 수 있다. 복수의 독립적인 조건을 한 문장에 넣었다면 요구사항을 분리하고 각 조건의 필수 여부를 명시한다.

요구사항 검증

요구사항 검증은 작성된 요구사항이 명세로서 충분한 품질을 가지고 있으며 이후 설계·구현과 시험의 기준으로 사용할 수 있는지 확인하는 활동이다.

검증에서는 다음을 확인한다.

  • 각 요구사항의 의미가 명확한가
  • 실제 이해관계자의 필요와 연결되는가
  • 필요한 요구가 빠져 있지 않은가
  • 서로 충돌하는 요구가 없는가
  • 측정하거나 시험할 수 있는가
  • 기술과 비용, 일정 안에서 실현 가능한가
  • 시스템 경계와 책임이 명확한가
  • 품질과 예외 조건이 포함되어 있는가
  • 용어와 데이터 정의가 일관적인가
  • 요구사항의 출처와 우선순위를 추적할 수 있는가

검증 방법에는 동료 검토, 이해관계자 회의, 체크리스트, 모델 분석, 프로토타입 평가, 시험 사례의 사전 작성과 형식 분석 등이 있다.

요구사항을 기준으로 시험 사례를 작성해 보면 입력과 기대 결과, 예외 조건이 빠져 있는지 발견하기 쉽다. 시험할 방법을 정할 수 없는 요구사항은 표현이 모호하거나 목표 수준에 머물러 있을 가능성이 있다.

요구사항 검증과 완성된 소프트웨어의 확인은 구분된다. 요구사항 검증은 요구사항 문서와 모델이 적절한지를 확인하고, 이후의 소프트웨어 확인은 구현된 시스템이 실제 이해관계자의 필요를 충족하는지 평가한다. NASA의 시스템 공학 지침도 제품의 검증을 요구사항 준수의 증거를 확인하는 활동으로 설명한다.[34]

요구사항 확인과 사용자 승인

요구사항이 문법적으로 명확하고 시험 가능하더라도 실제 문제를 올바르게 표현하지 못할 수 있다. 요구사항 확인은 정의된 요구사항이 이해관계자의 실제 목적과 사용 환경을 올바르게 반영하는지 확인한다.

확인에는 다음과 같은 활동이 사용될 수 있다.

  • 사용자가 시나리오와 업무 흐름을 검토한다.
  • 프로토타입을 실제 사용 환경에서 평가한다.
  • 대표적인 사용자와 수용 기준을 합의한다.
  • 운영자와 장애·복구 시나리오를 검토한다.
  • 보안·법무·안전 담당자가 관련 요구를 검토한다.
  • 기존 데이터와 실제 사례를 이용해 모형을 실행한다.
  • 시범 서비스를 제한된 사용자에게 제공한다.

공식 계약 프로젝트에서는 승인된 요구사항 명세가 이후 변경과 인수의 기준선이 될 수 있다. 반복적 개발에서는 전체 요구사항을 한 번에 승인하기보다 각 기능과 릴리스의 수용 기준을 점진적으로 합의할 수 있다.

승인은 요구사항이 영원히 변경되지 않는다는 뜻이 아니다. 해당 시점의 이해와 범위를 기준으로 합의했으며, 이후 변경은 정해진 절차로 관리한다는 의미이다.

추적성

요구사항 추적성은 요구사항의 출처와 근거, 상위 목표, 하위 요구사항, 설계, 구현, 시험과 릴리스 사이의 관계를 따라갈 수 있는 능력이다. INCOSE는 각 요구사항이 이해관계자의 필요로 연결되고 하위 요구사항이 상위 요구사항으로 연결되는 추적성을 강조한다.[35]

추적성에는 일반적으로 두 방향이 있다.

  • 후방 추적은 요구사항이 어디에서 왔고 어떤 목표와 필요를 근거로 하는지 확인한다.
  • 전방 추적은 요구사항이 어떤 설계와 코드, 시험 및 릴리스로 구현되었는지 확인한다.

추적성을 통해 다음과 같은 질문에 답할 수 있다.

  • 이 기능은 어떤 사용자 요구 때문에 존재하는가
  • 특정 요구사항은 어느 구성 요소에서 구현되는가
  • 이를 검증하는 시험은 무엇인가
  • 요구사항을 변경하면 어떤 설계와 코드가 영향을 받는가
  • 구현되지 않거나 시험되지 않은 요구사항이 있는가
  • 근거가 없는 기능과 코드가 존재하는가
  • 특정 릴리스에 어떤 요구사항이 포함되었는가

추적성은 요구사항 추적표 형태로 관리할 수 있지만, 현대 개발 환경에서는 이슈 추적기, 버전 관리, 코드 검토와 시험 관리 시스템의 연결로 구현하기도 한다.

모든 작은 코드 변경까지 수동으로 연결하면 관리 비용이 지나치게 커질 수 있다. 시스템의 위험과 규제, 변경 영향에 따라 필요한 추적 수준을 정하고 가능한 부분은 자동화한다.

요구사항 변경 관리

요구사항은 사업 목표와 사용자, 법률, 기술과 운영 환경이 변함에 따라 변경될 수 있다. 요구사항 변경 관리는 변경을 막는 활동이 아니라 변경의 이유와 영향을 이해하고 통제 가능한 방식으로 반영하는 활동이다.

변경 요청에는 일반적으로 다음 정보가 포함된다.

  • 변경을 요청한 주체
  • 변경하려는 요구사항
  • 변경 이유와 기대 가치
  • 적용 범위와 우선순위
  • 영향을 받는 기능과 품질 속성
  • 설계·코드·시험·데이터와 문서에 대한 영향
  • 비용과 일정, 위험
  • 호환성과 이전 문제
  • 승인 여부와 결정 근거
  • 적용할 버전과 릴리스

변경 영향 분석에서는 해당 요구사항과 연결된 설계·구현·시험을 추적하고, 직접적인 수정뿐 아니라 성능, 보안과 운영에 미치는 간접 영향도 검토한다.

모든 변경을 공식 위원회에서 승인할 필요는 없다. 작은 제품 팀에서는 제품 책임자와 개발 팀이 백로그의 우선순위를 조정할 수 있고, 안전 필수 시스템에서는 독립적인 검토와 공식 승인이 필요할 수 있다. 중요한 것은 변경 권한과 절차, 기록 수준을 프로젝트의 위험에 맞게 정하는 것이다.

기준선과 버전

검토와 합의를 마친 요구사항 집합은 특정 시점의 기준선으로 지정할 수 있다. 기준선은 이후의 설계와 시험, 계약과 일정이 참조하는 안정된 기준이다.

기준선 이후에도 요구사항을 변경할 수 있지만, 변경 전후의 차이와 영향을 기록해야 한다. 여러 릴리스가 동시에 개발·운영되는 경우 각 버전이 적용하는 요구사항 집합을 구분한다.

요구사항의 상태는 다음과 같이 관리할 수 있다.

  • 제안됨
  • 분석 중
  • 승인됨
  • 구현 중
  • 구현됨
  • 검증됨
  • 보류됨
  • 거절됨
  • 변경됨
  • 폐기됨

상태 이름은 조직마다 다를 수 있지만, 각 상태의 의미와 전환 권한을 명확하게 정의해야 한다.

애자일 개발의 요구사항 공학

반복적·애자일 개발에서도 요구사항 공학은 사라지지 않는다. 장문의 요구사항 명세를 프로젝트 초기에 완성하는 대신 제품 비전, 사용자 스토리, 제품 백로그, 수용 기준과 반복적인 대화를 통해 요구사항을 점진적으로 구체화한다.

상위 수준에서는 제품의 목표와 주요 사용자, 핵심 품질과 제약을 유지한다. 가까운 반복에서 구현할 기능은 상세하게 분석하고, 먼 미래의 기능은 불확실성을 인정한 채 상대적으로 높은 수준에서 관리할 수 있다.

애자일 환경의 요구사항 활동에는 다음이 포함될 수 있다.

  • 제품 목표와 사용자 문제 정의
  • 백로그 항목의 지속적인 도출과 정제
  • 사용자 스토리와 수용 기준 작성
  • 우선순위와 릴리스 범위 조정
  • 프로토타입과 사용자 평가
  • 반복 리뷰와 피드백
  • 완료된 기능의 검증과 승인
  • 새 정보에 따른 요구사항 변경

짧은 사용자 스토리만으로 보안, 성능, 데이터와 운영 요구가 자동으로 표현되지는 않는다. 여러 기능에 공통으로 적용되는 품질 요구사항과 규제 조건은 별도로 명시하고 각 기능의 완료 조건과 연결한다.

애자일 선언은 작동하는 소프트웨어와 변화 대응을 강조하지만 문서와 계획을 불필요하다고 선언하지 않는다. 프로젝트에 필요한 수준의 요구사항 정보와 추적성을 유지하면서 피드백에 따라 이를 지속적으로 조정하는 방향으로 적용한다.[36]

계약 및 규제 환경의 요구사항

발주자와 공급자가 분리된 프로젝트에서는 요구사항이 계약 범위와 인수, 비용 산정의 기준이 될 수 있다. 이러한 환경에서는 요구사항의 해석 차이가 법적·재정적 문제로 이어질 수 있으므로 책임과 산출물, 변경 절차를 명확히 정의한다.

안전·의료·항공·금융과 공공 시스템에서는 법률과 산업 표준에 따라 요구사항의 추적성, 검토, 독립적인 검증과 승인 기록이 필요할 수 있다.

규제 환경에서는 다음 사항이 특히 중요하다.

  • 적용할 법률과 표준의 정확한 식별
  • 규정 조항과 시스템 요구사항의 연결
  • 안전 및 보안 위험에서 도출된 요구사항
  • 요구사항 변경의 승인과 기록
  • 요구사항부터 시험 증거까지의 추적성
  • 독립적인 검토와 감사
  • 문서와 데이터의 보존 기간
  • 공급자와 외부 구성 요소의 요구사항 준수

규제 준수를 별도의 문서 작업으로만 다루면 실제 설계와 코드에 반영되지 않을 수 있다. 규정에서 도출한 요구사항도 다른 요구사항과 함께 설계, 구현과 시험으로 연결해야 한다.

요구사항 관리 도구

요구사항은 문서, 스프레드시트, 이슈 추적기, 전용 요구사항 관리 시스템과 모델 기반 도구 등 여러 방식으로 관리할 수 있다.

도구는 다음 기능을 제공할 수 있다.

  • 요구사항의 고유 식별과 버전 관리
  • 계층과 추적 관계 표현
  • 상태와 승인 흐름 관리
  • 변경 이력과 의견 기록
  • 우선순위와 릴리스 배정
  • 설계·코드·시험과의 연결
  • 중복과 누락 검사
  • 문서와 보고서 생성
  • 접근 권한과 전자 서명
  • 여러 기준선과 제품 변형 관리

도구를 도입한다고 요구사항의 품질이 자동으로 높아지는 것은 아니다. 불명확한 요구사항을 정교한 데이터베이스에 저장해도 의미는 여전히 불명확하다. 먼저 필요한 활동과 정보 구조, 책임을 정의하고 그 흐름을 지원하는 도구를 선택해야 한다.

작은 프로젝트에서는 버전 관리되는 일반 텍스트와 이슈 추적기로 충분할 수 있다. 대규모 시스템에서는 수천 개의 요구사항과 여러 제품 변형, 공급자와 인증 자료를 관리하기 위해 전용 도구가 필요할 수 있다.

요구사항 공학의 한계와 지속성

요구사항 공학을 철저하게 수행하더라도 미래의 모든 필요와 환경 변화를 예측할 수는 없다. 사용자도 실제 소프트웨어를 사용하기 전에는 자신의 요구를 완전히 설명하기 어려울 수 있으며, 개발 과정에서 새로운 기술적 가능성과 제약이 발견된다.

따라서 요구사항 공학의 목표는 처음부터 완전하고 변하지 않는 명세를 만드는 데 있지 않다. 현재의 지식과 불확실성을 명확하게 표현하고, 중요한 가정을 조기에 검증하며, 새로운 정보를 안전하게 반영할 수 있는 구조를 만드는 데 있다.

좋은 요구사항 공학은 다음 결과를 제공한다.

  • 개발해야 하는 이유와 목표가 분명하다.
  • 사용자와 시스템의 책임 범위가 명확하다.
  • 기능과 품질, 제약이 함께 정의되어 있다.
  • 이해관계자의 충돌과 우선순위가 관리된다.
  • 요구사항이 설계, 구현과 시험으로 이어진다.
  • 변경의 영향과 결정 근거를 추적할 수 있다.
  • 실제 운영과 사용자 결과를 통해 요구를 다시 평가할 수 있다.

요구사항은 소프트웨어 개발의 출발점이지만 동시에 설계, 구현, 시험과 운영에서 계속 검토되고 수정되는 생명주기 전체의 정보이다. 요구사항 공학은 무엇을 만들 것인지 기록하는 작업을 넘어, 무엇이 필요한지 이해하고 그것이 실제로 충족되었음을 입증하기 위한 공학적 과정이다.

소프트웨어 아키텍처와 설계

소프트웨어 설계(Software Design)는 요구사항을 구현 가능한 구조와 동작으로 변환하는 활동이다. 시스템을 어떤 구성 요소로 나눌지, 각 구성 요소가 어떤 책임과 데이터를 가질지, 서로 어떤 인터페이스로 통신할지, 상태와 오류를 어떻게 처리할지, 실제 실행 환경에 어떻게 배치할지를 결정한다.

소프트웨어 아키텍처(Software Architecture)는 소프트웨어 설계 가운데 시스템 전체의 구조와 주요 품질 속성, 장기간의 변경 비용과 운영 방식에 큰 영향을 미치는 결정을 다룬다. 주요 구성 요소와 그 관계, 외부 환경과의 경계, 실행 및 배포 구조, 데이터 소유권, 통신 방식, 중요한 설계 원칙과 제약 등이 아키텍처에 포함될 수 있다.

아키텍처는 단순한 기술 목록이나 구성도가 아니다. 어떤 프로그래밍 언어와 데이터베이스를 사용한다는 정보만으로는 각 요소가 맡는 책임과 상호작용, 실패와 변경의 영향이 드러나지 않는다. 상자와 화살표로 구성 요소를 표현하더라도 연결의 의미와 설계 결정의 근거가 없다면 시스템을 충분히 설명하기 어렵다.

ISO/IEC/IEEE 42010:2022는 소프트웨어와 시스템, 기업 등의 아키텍처를 기술하기 위한 개념과 관계를 정의하고, 아키텍처 기술 프레임워크, 아키텍처 기술 언어, 관점과 모델 종류에 관한 요구사항을 제공한다.[37]

IEEE Computer Society의 SWEBOK V4.0은 소프트웨어 아키텍처를 별도의 지식 영역으로 다루며 아키텍처의 문맥과 설계, 분석·종합·평가, 아키텍처 전술과 대규모 시스템의 아키텍처 등을 포함한다.[38]

아키텍처와 상세 설계

아키텍처와 상세 설계는 모두 소프트웨어 설계에 포함되지만 다루는 범위와 영향에 차이가 있다.

아키텍처 설계는 시스템 전체에 영향을 미치는 주요 구조와 결정을 다룬다.

  • 시스템을 어떤 하위 시스템과 구성 요소로 나눌지
  • 하나의 프로세스로 실행할지 여러 프로세스와 서비스로 분리할지
  • 상태와 데이터를 어느 구성 요소가 소유할지
  • 구성 요소가 함수 호출, 메시지, 공유 메모리나 네트워크로 통신할지
  • 장애와 보안 경계를 어디에 둘지
  • 어떤 단위로 배포하고 확장할지
  • 외부 시스템과 어떤 인터페이스로 연결할지
  • 성능, 가용성, 변경 가능성과 보안을 어떤 구조로 달성할지

상세 설계는 아키텍처에서 정한 구성 요소를 실제로 구현할 수 있는 수준으로 구체화한다.

  • 클래스와 함수의 책임
  • 자료 구조와 알고리즘
  • 상태와 상태 전이
  • 메모리와 자원 소유권
  • 오류와 예외 처리
  • 동시성과 동기화
  • 캐시와 성능 최적화
  • 직렬화와 데이터 변환
  • 내부 인터페이스
  • 시험을 위한 경계

아키텍처와 상세 설계를 구분하는 절대적인 기준은 없다. 같은 결정도 시스템의 규모와 중요도에 따라 다르게 취급될 수 있다. 작은 응용 프로그램에서는 데이터 저장 방식과 화면 상태 관리가 중요한 아키텍처 결정일 수 있지만, 대규모 플랫폼에서는 서비스 경계와 데이터 소유권, 배포 구조가 중심적인 아키텍처 결정이 될 수 있다.

아키텍처가 상세 설계보다 먼저 완성되어 고정되는 것도 아니다. 구현과 시험 과정에서 새로운 성능 문제나 기술적 제약이 발견되면 아키텍처를 수정할 수 있다. 반대로 상세 설계에서 반복적으로 발생하는 문제는 상위 구조나 구성 요소 경계가 적절하지 않음을 나타낼 수 있다.

아키텍처의 역할

소프트웨어 아키텍처는 요구사항과 구현 사이를 연결한다. 요구사항은 시스템이 제공해야 할 기능과 품질을 정의하지만, 여러 요구사항을 어떤 구조로 구현할지는 직접 결정하지 않는다.

아키텍처는 다음과 같은 역할을 한다.

  • 시스템의 주요 구성 요소와 책임을 정의한다.
  • 구성 요소 사이의 관계와 통신 규칙을 정한다.
  • 데이터와 상태의 소유권을 결정한다.
  • 주요 품질 속성을 시스템 구조에 반영한다.
  • 개발자와 운영자, 이해관계자가 공유할 시스템 모델을 제공한다.
  • 기술적 위험과 상충 관계를 조기에 분석한다.
  • 작업과 코드의 소유 범위를 나누는 기준을 제공한다.
  • 외부 시스템과 플랫폼의 통합 방식을 정한다.
  • 시험, 배포와 운영 구조를 개발 구조와 연결한다.
  • 이후의 변경이 영향을 미칠 범위를 제한한다.

아키텍처는 구현의 모든 세부 사항을 미리 정하는 계획이 아니다. 시스템의 성공과 장기적인 유지보수에 큰 영향을 주는 결정과 제약을 먼저 다루고, 구현 과정에서 일관된 판단을 내릴 수 있는 기반을 제공한다.

아키텍처적으로 중요한 요구사항

모든 요구사항이 아키텍처에 같은 정도로 영향을 주는 것은 아니다. 시스템의 주요 구조와 기술, 구성 요소 경계, 실행과 배포 방식에 큰 영향을 주는 요구를 아키텍처적으로 중요한 요구사항으로 다룬다.

다음과 같은 요구가 아키텍처적으로 중요할 수 있다.

  • 매우 낮은 응답 시간
  • 높은 처리량과 대규모 동시 사용자
  • 장시간 중단을 허용하지 않는 가용성
  • 안전 필수 기능과 장애 격리
  • 강한 인증과 접근 통제
  • 여러 지역과 데이터 센터에 걸친 배포
  • 대규모 데이터와 장기 보존
  • 제한된 메모리와 전력
  • 실시간 처리와 일정한 실행 시간
  • 다양한 운영체제와 장치 지원
  • 오래 유지해야 하는 공개 API와 파일 형식
  • 외부 시스템과 레거시 시스템의 통합
  • 독립적인 기능 배포와 확장
  • 법률과 산업 표준 준수

기능 요구사항도 아키텍처에 큰 영향을 줄 수 있다. 공동 문서 편집은 단순히 편집 화면을 추가하는 기능이 아니라 동시 수정, 변경 병합, 네트워크 지연, 오프라인 작업과 데이터 일관성을 처리하는 구조를 요구한다.

아키텍처 설계에서는 요구사항을 구성 요소에 그대로 배치하지 않는다. 각 요구가 데이터와 상태, 통신, 실패, 자원과 운영 환경에 어떤 의미를 갖는지 분석한 뒤 구조를 결정한다.

품질 속성

품질 속성은 시스템이 기능을 어떠한 수준과 조건으로 제공해야 하는지를 나타낸다.

대표적인 품질 속성은 다음과 같다.

  • 성능
  • 가용성
  • 신뢰성
  • 보안
  • 안전성
  • 변경 가능성
  • 유지보수성
  • 시험 가능성
  • 사용성
  • 상호운용성
  • 이식성
  • 확장성
  • 관찰 가능성

품질 속성은 구현이 끝난 뒤 추가하는 별도의 기능이 아니다. 구성 요소를 어떻게 나누고 상태를 어디에 저장하며 어떤 방식으로 통신하는지가 달성할 수 있는 품질의 범위를 결정한다.

높은 가용성을 요구하는 서비스에는 다음과 같은 설계가 필요할 수 있다.

  • 중요 구성 요소의 복제
  • 장애를 감지하는 상태 확인
  • 자동 재시작과 장애 조치
  • 단일 장애 지점의 제거
  • 데이터 백업과 복구
  • 장애 범위를 제한하는 격리
  • 일부 구성 요소가 실패해도 핵심 기능을 유지하는 저하 운전
  • 배포 중 서비스를 유지하는 점진적 전환

높은 변경 가능성을 요구하는 시스템에는 다음과 같은 설계가 필요할 수 있다.

  • 책임이 명확한 모듈 경계
  • 안정적인 인터페이스
  • 내부 구현의 정보 은닉
  • 외부 기술과 핵심 업무 규칙의 분리
  • API와 데이터의 버전 관리
  • 자동화된 시험
  • 의존성 방향의 통제

SEI는 가용성, 성능, 보안, 상호운용성과 변경 가능성처럼 아키텍처에 중요한 품질 속성을 사업 및 임무 목표에서 도출하고 구체화하는 방법으로 Quality Attribute Workshop을 제공한다.[39]

품질 속성 시나리오

“빠르게 동작해야 한다”, “높은 가용성을 제공해야 한다”와 같은 표현만으로는 설계를 평가하기 어렵다. 품질 속성은 구체적인 사건과 환경, 시스템의 반응과 측정 기준을 포함한 시나리오로 표현할 수 있다.

품질 속성 시나리오는 일반적으로 다음 요소로 구성된다.

  • 자극을 발생시키는 주체
  • 발생하는 사건이나 조건
  • 사건이 발생하는 환경
  • 영향을 받는 시스템 요소
  • 시스템이 수행해야 하는 반응
  • 반응을 평가하는 측정 기준

성능 요구는 다음과 같이 표현할 수 있다.

  • 정상 운영 환경에서
  • 인증된 사용자가 검색 요청을 전송하면
  • 검색 서비스는 인덱스와 저장소를 조회하여
  • 요청의 95%를 500밀리초 이내에 반환한다.

변경 가능성 요구는 다음과 같이 표현할 수 있다.

  • 외부 결제 서비스의 API가 변경되었을 때
  • 결제 어댑터와 설정만 수정하고
  • 주문 처리의 핵심 업무 코드를 변경하지 않은 상태로
  • 정해진 작업 시간 안에 새 API를 지원한다.

SEI는 변경 가능성, 성능, 가용성, 보안과 사용성 등의 품질 속성을 구체적인 시나리오로 표현하여 설계 결정을 분석할 수 있다고 설명한다.[40]

품질 속성의 상충 관계

품질 속성은 서로 독립적이지 않다. 하나의 속성을 높이는 결정이 다른 속성의 비용을 증가시킬 수 있다.

  • 데이터 복제는 가용성과 읽기 성능을 높일 수 있지만 일관성 관리와 운영 비용을 증가시킨다.
  • 강한 암호화와 검증은 보안을 높이지만 처리 시간과 자원 사용을 늘릴 수 있다.
  • 서비스를 세밀하게 분리하면 독립적인 배포가 가능하지만 네트워크 통신과 운영 복잡성이 증가한다.
  • 캐시는 응답 시간을 줄이지만 데이터 최신성과 메모리 사용을 복잡하게 만든다.
  • 엄격한 데이터 일관성은 정확성을 높이지만 네트워크 장애에서 가용성을 낮출 수 있다.
  • 많은 추상화 계층은 변경 가능성을 높일 수 있지만 실행 흐름과 성능을 이해하기 어렵게 만들 수 있다.

Architecture Tradeoff Analysis Method는 아키텍처가 품질 속성 목표를 얼마나 충족하는지 평가하고, 품질 속성이 서로 상호작용하는 지점과 아키텍처 위험을 발견하는 방법이다.[41]

따라서 아키텍처 설계에서는 모든 품질 속성을 최대화하려 하기보다 시스템의 목적과 위험에 따라 우선순위를 정하고 허용 가능한 균형을 결정한다.

아키텍처 분석과 종합

아키텍처 설계는 하나의 구조를 즉시 선택하는 작업이 아니다. 요구사항과 제약을 분석하고 여러 후보 구조를 만든 뒤, 각 구조의 장점과 위험을 평가하는 과정으로 진행할 수 있다.

아키텍처 분석에서는 다음을 확인한다.

  • 주요 기능과 품질 속성은 무엇인가
  • 시스템 경계와 외부 환경은 무엇인가
  • 중요한 데이터와 상태는 무엇인가
  • 실패했을 때 영향이 큰 부분은 어디인가
  • 기술적으로 검증되지 않은 가정은 무엇인가
  • 기존 시스템과 조직이 부과하는 제약은 무엇인가
  • 변경 가능성이 높은 부분은 무엇인가

아키텍처 종합에서는 분석 결과를 바탕으로 구성 요소와 책임, 연결 방식과 배포 구조를 만든다.

하나의 대안만 만들면 설계 결정이 실제 요구에 따른 것인지 단순한 관습이나 익숙한 기술에 따른 것인지 판단하기 어렵다. 중요한 문제에는 여러 대안을 비교하고 선택 이유를 기록한다.

SWEBOK V4.0은 아키텍처 설계를 분석, 종합과 평가가 연결되는 활동으로 분류한다.[42]

시스템 분해

시스템 분해는 전체 소프트웨어를 이해하고 구현할 수 있는 여러 부분으로 나누는 활동이다. 파일과 디렉터리를 나누는 작업이 아니라 책임과 데이터, 인터페이스와 의존성을 구분하는 설계 활동이다.

시스템은 다음과 같은 기준으로 분해할 수 있다.

  • 사용자에게 제공하는 기능
  • 업무 영역과 개념
  • 데이터 종류와 소유권
  • 실행 프로세스
  • 기술적인 계층
  • 변경되는 이유
  • 보안과 신뢰 경계
  • 배포와 확장 단위
  • 하드웨어와 플랫폼
  • 개발 팀의 책임

하나의 시스템에 여러 분해 구조가 동시에 존재할 수 있다. 소스 코드는 모듈과 패키지로 분리되고, 실행 시에는 프로세스와 스레드로 구성되며, 운영 환경에서는 여러 서버와 컨테이너에 배포될 수 있다.

좋은 분해는 각 구성 요소가 명확한 책임을 갖도록 하고, 다른 구성 요소의 내부 구현에 대한 의존을 줄인다. 한 부분의 변경과 장애가 시스템 전체로 확산되는 범위도 제한한다.

구성 요소가 지나치게 크면 많은 책임과 상태가 한곳에 모인다. 반대로 지나치게 작게 나누면 하나의 기능을 수행하기 위해 많은 구성 요소가 통신해야 하며, 호출과 데이터 변환, 배포와 운영 비용이 증가한다.

모듈과 구성 요소

모듈은 코드와 데이터를 논리적으로 묶고 외부에 제한된 인터페이스를 제공하는 설계 단위이다. 언어의 모듈과 패키지, 라이브러리, 프로젝트와 네임스페이스 등이 모듈을 구현할 수 있다.

구성 요소는 시스템 안에서 특정 책임을 수행하고 다른 요소와 명시적인 인터페이스로 연결되는 단위이다. 구성 요소는 하나의 모듈일 수도 있고 여러 모듈로 이루어진 프로세스나 서비스일 수도 있다.

구성 요소를 설계할 때는 다음을 정한다.

  • 구성 요소의 책임
  • 제공하는 기능
  • 소유하는 상태와 데이터
  • 공개 인터페이스
  • 필요로 하는 외부 기능
  • 초기화와 종료 방식
  • 오류와 실패 처리
  • 동시 실행 조건
  • 배포와 버전 관리 단위
  • 로그와 진단 정보
  • 시험과 대체 방법

구성 요소의 이름과 공개 인터페이스만으로 주요 역할을 이해할 수 있어야 한다. 여러 종류의 책임이 하나의 구성 요소에 계속 추가되면 응집도가 낮아지고 변경 이유가 증가한다.

책임과 데이터 소유권

각 기능과 데이터를 어느 구성 요소가 책임질지 결정해야 한다. 책임이 불분명하면 여러 구성 요소가 같은 데이터를 직접 수정하거나, 하나의 작업을 누가 완료해야 하는지 알기 어려워진다.

구성 요소가 가질 수 있는 책임은 다음과 같다.

  • 특정 데이터를 생성하고 관리한다.
  • 업무 규칙을 적용한다.
  • 외부 요청을 수신하고 검증한다.
  • 여러 구성 요소의 작업을 조정한다.
  • 운영체제와 외부 서비스를 추상화한다.
  • 자원과 객체의 생명주기를 관리한다.
  • 상태 변경을 기록하고 알린다.
  • 오류를 복구하거나 상위 계층에 전달한다.

데이터 소유권은 특히 분산 시스템에서 중요하다. 여러 서비스가 하나의 데이터베이스 표를 직접 수정하면 서비스 경계가 약해지고 독립적인 변경이 어려워진다.

구성 요소가 데이터를 소유한다는 것은 다른 부분이 데이터를 전혀 읽지 못한다는 뜻이 아니다. 데이터 변경 규칙과 일관성을 유지할 책임, 외부에 제공할 인터페이스를 소유 구성 요소가 관리한다는 의미이다.

인터페이스와 계약

구성 요소는 인터페이스를 통해 협력한다. 인터페이스에는 함수와 메서드, API, 메시지, 이벤트, 파일 형식, 명령행과 장치 프로토콜 등이 포함된다.

인터페이스는 이름과 매개변수 목록만을 뜻하지 않는다. 다음과 같은 계약을 함께 포함할 수 있다.

  • 입력과 출력의 의미와 형식
  • 호출 전제 조건
  • 실행 후 보장되는 결과
  • 상태 변경 여부
  • 발생 가능한 오류
  • 호출 순서
  • 시간 제한과 취소
  • 동시 호출 가능 여부
  • 권한과 보안 조건
  • 버전과 호환성
  • 자원과 성능 비용

인터페이스가 내부 자료 구조를 그대로 노출하면 구성 요소의 구현을 변경하기 어렵다. 반대로 너무 일반적인 인터페이스는 사용 방법과 실패 조건을 알기 어렵게 만든다.

외부에 공개된 API와 파일 형식은 내부 인터페이스보다 변경 비용이 크다. 여러 사용자와 외부 프로그램이 기존 계약에 의존할 수 있으므로 버전, 폐기와 이전 정책을 함께 설계해야 한다.

의존성 관리

구성 요소는 다른 모듈과 라이브러리, 운영체제, 하드웨어와 외부 서비스에 의존한다. 설계에서는 의존성의 존재뿐 아니라 방향과 범위를 통제한다.

의존성을 관리하는 방법에는 다음이 있다.

  • 다른 모듈의 공개 인터페이스만 사용한다.
  • 내부 상태와 구현 자료 구조에 직접 접근하지 않는다.
  • 상위 정책이 특정 하위 기술에 직접 의존하지 않도록 한다.
  • 구체적인 구현을 교체 가능한 인터페이스 뒤에 둔다.
  • 객체와 서비스의 생성 및 연결을 별도의 구성 계층에서 처리한다.
  • 외부 시스템 접근을 어댑터나 게이트웨이에 모은다.
  • 순환 의존성을 줄인다.
  • 의존성 버전과 호환 범위를 명시한다.
  • 빌드와 분석 도구로 의존성 규칙을 검사한다.

모든 의존성을 별도의 추상화로 감쌀 필요는 없다. 변경 가능성이 낮고 내부에서만 사용하는 단순한 기능까지 인터페이스와 어댑터로 분리하면 코드의 양과 이해 비용이 늘어난다. 추상화의 비용과 실제 변경 가능성을 함께 고려한다.

계층화

계층형 아키텍처는 시스템을 책임과 추상화 수준에 따라 여러 계층으로 분리한다. 상위 계층은 하위 계층이 제공하는 기능을 사용하며, 하위 계층은 상위의 구체적인 업무를 알지 않도록 구성할 수 있다.

일반적인 정보 시스템은 다음과 같은 계층으로 나눌 수 있다.

  • 사용자 인터페이스와 표현
  • 응용 흐름과 유스 케이스
  • 업무 규칙과 도메인
  • 데이터 접근과 외부 시스템 통합
  • 운영체제와 인프라

계층화는 사용자 인터페이스, 업무 논리와 저장 기술을 분리하고 각 계층을 독립적으로 시험하기 쉽게 한다. 하위 기술이 변경되어도 상위 정책에 미치는 영향을 줄일 수 있다.

그러나 모든 요청이 여러 계층을 통과하면 단순한 기능에도 전달 코드와 데이터 변환이 많이 필요할 수 있다. 계층 자체를 유지하는 것보다 각 경계가 해결하는 문제와 책임이 명확한지가 중요하다.

실행 구조

소스 코드의 모듈 구조와 실제 실행 구조는 같지 않을 수 있다. 여러 모듈이 하나의 프로세스에서 실행되거나 같은 모듈이 여러 프로세스와 장치에서 사용될 수 있다.

실행 구조에서는 다음을 결정한다.

  • 프로세스와 스레드의 수
  • 작업과 자원의 소유권
  • 동시성과 병렬 처리 단위
  • 프로세스 간 통신
  • 공유 상태와 메시지 전달
  • 시작과 종료 순서
  • 시간 제한과 작업 취소
  • 장애 격리 범위
  • 스케줄링과 우선순위
  • 실시간 제약
  • 교착 상태와 경쟁 조건 방지

하나의 프로세스 안에서 함수 호출로 연결하면 통신 비용이 낮고 디버깅하기 쉽다. 여러 프로세스로 분리하면 보안과 장애 경계를 강화하고 독립적으로 확장할 수 있지만, 프로세스 간 통신과 부분적 실패를 처리해야 한다.

네트워크를 통한 호출은 로컬 함수 호출과 다르다. 요청이 실제로 처리되었는지 알 수 없는 상태, 지연과 중복, 메시지 순서와 연결 단절을 고려해야 한다.

배포 구조

배포 구조는 소프트웨어 구성 요소가 실제 하드웨어와 운영체제, 가상 머신, 컨테이너, 장치와 네트워크에 어떻게 배치되는지를 나타낸다.

배포 설계에서는 다음을 고려한다.

  • 실행할 서버와 장치
  • 지역과 데이터 센터
  • 각 구성 요소의 자원 요구
  • 네트워크 지연과 대역폭
  • 보안 영역과 접근 정책
  • 데이터의 물리적 저장 위치
  • 복제와 장애 조치
  • 부하 분산과 자동 확장
  • 업데이트와 되돌리기
  • 서로 다른 버전의 공존
  • 운영 비용과 용량

배포 구조는 운영 단계에서 나중에 결정하는 부가적인 문제가 아니다. 구성 요소 사이의 거리가 멀어지면 통신 지연과 실패 가능성이 증가하고, 여러 지역에 데이터를 저장하면 일관성과 규제 문제가 발생할 수 있다.

소프트웨어 구조와 배포 구조를 함께 설계해야 성능과 가용성, 보안과 비용 목표를 현실적으로 평가할 수 있다.

데이터 설계

데이터 설계는 시스템이 어떤 정보를 다루고, 그 정보를 어떻게 표현·저장·조회·변경하며 구성 요소 사이에서 어떻게 이동시킬지를 정한다.

데이터 설계의 주요 대상은 다음과 같다.

  • 개체와 값, 관계
  • 식별자와 참조
  • 데이터의 소유 구성 요소
  • 유효성 규칙과 불변 조건
  • 저장 형식과 스키마
  • 검색과 색인
  • 트랜잭션
  • 동시 수정
  • 캐시와 파생 데이터
  • 복제와 일관성
  • 변경 이력과 감사 기록
  • 보존과 삭제
  • 개인정보와 접근 권한
  • 데이터 이전

데이터 모델은 저장 기술의 구조보다 문제 영역의 의미를 중심으로 설계해야 한다. 데이터베이스 표의 형태가 그대로 시스템 전체의 인터페이스가 되면 저장 구조를 변경할 때 여러 구성 요소를 함께 수정해야 한다.

같은 데이터가 여러 위치에 복제되면 읽기 성능과 가용성을 높일 수 있지만 어느 데이터가 기준인지, 변경이 어떤 순서로 전파되는지, 일시적인 불일치를 허용할지를 정해야 한다.

저장된 데이터는 소스 코드보다 오래 유지될 수 있다. 따라서 스키마와 형식의 버전, 이전과 하위 호환성을 생명주기 전체에서 관리해야 한다.

상태 설계

소프트웨어의 동작은 현재 상태와 입력에 따라 달라진다. 상태가 여러 구성 요소에 흩어지고 변경 규칙이 명확하지 않으면 동작을 추론하고 결함을 찾기 어려워진다.

상태 설계에서는 다음을 정의한다.

  • 어떤 상태가 존재하는가
  • 상태를 누가 소유하는가
  • 어떤 동작이 상태를 변경할 수 있는가
  • 항상 유지해야 하는 불변 조건은 무엇인가
  • 허용되는 상태 전이는 무엇인가
  • 여러 상태를 원자적으로 변경해야 하는가
  • 실패한 변경을 되돌릴 수 있는가
  • 변경 이력을 기록해야 하는가
  • 여러 상태 복사본을 어떻게 동기화하는가

예를 들어 주문은 생성, 결제 대기, 결제 완료, 배송, 취소 상태를 가질 수 있다. 허용되는 전이를 정의하면 이미 취소된 주문이 배송 상태로 변경되는 것과 같은 잘못된 동작을 막을 수 있다.

상태를 제한된 범위에서 소유하고 명확한 연산을 통해 변경하면 시스템의 동작을 이해하고 시험하기 쉬워진다.

오류와 실패 설계

오류 처리는 개별 함수에서 예외를 잡는 작업에만 한정되지 않는다. 어떤 실패를 어느 구성 요소에서 처리하고, 어디까지 복구하며, 사용자와 운영자에게 무엇을 알려야 하는지를 시스템 수준에서 설계한다.

소프트웨어가 처리해야 하는 실패에는 다음이 있다.

  • 잘못된 사용자 입력
  • 권한 부족과 인증 실패
  • 내부 불변 조건 위반
  • 파일과 데이터 손상
  • 네트워크 지연과 단절
  • 외부 서비스 실패
  • 메모리와 저장 공간 부족
  • 하드웨어와 운영체제 오류
  • 부분적으로 완료된 작업
  • 시간 초과
  • 작업 취소

오류 설계에서는 다음을 정한다.

  • 실패를 반환 값, 예외, 오류 코드나 메시지 중 무엇으로 표현할지
  • 호출자가 복구 가능한 오류와 프로그램 결함을 어떻게 구분할지
  • 어느 계층에서 오류를 변환하거나 복구할지
  • 재시도할 수 있는 작업은 무엇인지
  • 중복 실행을 허용할 수 있는지
  • 실패 뒤 데이터와 자원을 어떤 상태로 유지할지
  • 사용자용 메시지와 내부 진단 정보를 어떻게 분리할지
  • 로그와 메트릭에 무엇을 기록할지

재시도는 일시적인 네트워크 오류에 대응할 수 있지만 이미 처리된 요청을 다시 실행하여 중복 결과를 만들 수 있다. 작업의 멱등성, 요청 식별자와 중복 검사 등을 함께 설계해야 한다.

보안 설계

보안은 별도의 인증 모듈 하나만으로 달성되지 않는다. 사용자와 서비스의 신원, 권한, 데이터, 네트워크, 실행 환경과 소프트웨어 공급망 전체에 영향을 준다.

보안 아키텍처에서는 다음을 고려한다.

  • 보호해야 하는 자산
  • 신뢰할 수 있는 영역과 신뢰할 수 없는 영역
  • 사용자와 서비스의 인증
  • 권한과 역할
  • 데이터의 저장 및 전송 보호
  • 암호 키와 비밀 정보 관리
  • 외부 입력 검증
  • 네트워크와 프로세스 격리
  • 감사 기록
  • 이상 행위 탐지
  • 업데이트와 코드 서명
  • 외부 구성 요소와 빌드 공급망
  • 보안 사고의 차단과 복구

위협 모델링은 시스템의 자산과 공격자, 공격 경로, 신뢰 경계를 분석하여 필요한 보안 요구와 구조를 발견하는 데 사용된다.

최소 권한에 따라 각 구성 요소는 필요한 데이터와 기능에만 접근해야 한다. 하나의 서비스나 계정이 침해되더라도 시스템 전체가 노출되지 않도록 권한과 네트워크 경계를 분리한다.

관찰 가능성과 운영 설계

운영 중인 시스템의 상태를 파악할 수 없다면 장애와 성능 문제를 진단하기 어렵다. 관찰 가능성은 시스템의 외부 출력과 기록을 이용하여 내부 상태와 동작을 이해할 수 있도록 설계하는 성질이다.

관찰 가능성을 위해 다음 요소를 설계할 수 있다.

  • 구조화된 로그
  • 요청과 작업의 식별자
  • 처리량과 지연 시간
  • 오류율
  • CPU와 메모리, 저장소 사용량
  • 분산 추적
  • 상태 및 준비 확인
  • 감사 이벤트
  • 운영 대시보드와 경고
  • 진단 정보
  • 현재 설정과 기능 플래그 상태

로그의 양이 많다고 관찰 가능성이 높아지는 것은 아니다. 중요한 상태 변화와 실패를 일관된 형식으로 기록하고, 하나의 요청이 여러 구성 요소를 지나가는 흐름을 연결할 수 있어야 한다.

로그와 추적 데이터에 개인정보와 인증 정보가 기록되지 않도록 해야 하며, 운영 데이터에도 접근 권한과 보존 정책이 필요하다.

아키텍처 스타일

아키텍처 스타일은 구성 요소의 종류와 관계, 책임 분배와 통신 방식에 관한 일반적인 구조를 나타낸다. 하나의 시스템은 여러 스타일을 서로 다른 영역에서 함께 사용할 수 있다.

계층형 아키텍처

시스템을 추상화 수준과 책임에 따라 여러 계층으로 나눈다. 사용자 인터페이스, 업무 논리와 데이터 접근을 분리하는 데 사용할 수 있다.

계층은 책임과 의존 방향을 명확하게 만들 수 있지만 요청이 지나치게 많은 계층을 통과하면 전달 코드와 변환 비용이 증가할 수 있다.

파이프와 필터

데이터를 여러 처리 단계가 순서대로 변환하며, 각 단계는 입력을 받아 새로운 출력을 만든다.

컴파일러, 데이터 처리 파이프라인, 미디어 처리와 명령행 도구 조합 등에 사용된다. 단계를 독립적으로 시험하고 조합하기 쉽지만 공유 상태와 복잡한 상호작용이 많은 시스템에는 적합하지 않을 수 있다.

클라이언트-서버

서버가 데이터와 기능을 제공하고 클라이언트가 네트워크를 통해 요청한다. 웹 서비스, 데이터베이스와 파일 서비스에서 널리 사용된다.

데이터와 정책을 중앙에서 관리할 수 있지만 서버의 장애와 확장, 네트워크 지연과 단절을 고려해야 한다.

이벤트 중심 아키텍처

구성 요소가 상태 변화를 이벤트로 발행하고 다른 구성 요소가 이를 구독하여 처리한다.

발행자와 소비자의 직접적인 결합을 줄이고 비동기 처리를 지원하지만 이벤트 순서와 중복, 전달 실패, 전체 처리 상태를 추적하기 어려워질 수 있다.

저장소 중심 아키텍처

여러 구성 요소가 공통 데이터 저장소를 중심으로 정보를 교환한다. 데이터베이스 중심 업무 시스템과 컴파일러의 중간 표현 등에 사용될 수 있다.

데이터를 일관되게 관리하기 쉽지만 저장소 구조와 가용성에 시스템 전체가 강하게 의존할 수 있다.

플러그인 아키텍처

안정적인 핵심과 선택적으로 추가할 수 있는 확장 기능을 분리한다. 편집기, 개발 도구, 브라우저와 게임 엔진 등에 사용할 수 있다.

확장 API와 버전 정책을 명확히 해야 하며, 플러그인의 오류와 보안 문제를 핵심 시스템에서 격리할 필요가 있다.

서비스 지향 아키텍처

업무 기능을 명시적인 서비스 계약으로 제공하고 여러 응용 프로그램이 이를 조합한다.

조직과 시스템 사이의 기능 재사용과 통합을 지원할 수 있지만 서비스 계약, 데이터 의미와 운영 거버넌스가 필요하다.

마이크로서비스 아키텍처

응용 프로그램을 독립적으로 개발하고 배포할 수 있는 여러 서비스로 구성한다. 서비스마다 업무 책임과 데이터 소유권을 가질 수 있다.

서비스를 독립적으로 변경하고 확장할 수 있지만 네트워크 통신, 분산 데이터, 인증, 배포, 관찰과 장애 처리의 복잡성이 증가한다.

마이크로서비스는 모든 시스템에 적용해야 하는 기본 구조가 아니다. 독립적인 배포와 팀별 소유, 서로 다른 확장 요구가 실제로 필요한 경우 선택할 수 있는 구조이다.

마이크로커널 아키텍처

최소한의 핵심 기능을 커널에 두고 추가 기능을 독립된 서버나 확장으로 분리한다. 운영체제와 확장 가능한 개발 도구, 제품군 등에 사용할 수 있다.

핵심의 안정성과 기능 확장에 유리하지만 구성 요소 간 통신 비용과 기능 배치가 복잡해질 수 있다.

단일체와 분산 시스템

단일체 아키텍처는 여러 기능을 하나의 배포 단위로 구성한다. 내부적으로는 명확한 모듈로 분리할 수 있지만 빌드와 배포는 함께 이루어진다.

단일체는 다음과 같은 특성을 가질 수 있다.

  • 로컬 함수 호출로 통신한다.
  • 하나의 프로세스에서 디버깅하기 쉽다.
  • 데이터 트랜잭션을 관리하기 쉽다.
  • 배포 구성 요소가 적다.
  • 소규모 팀이 빠르게 개발할 수 있다.

규모가 커지면 하나의 변경과 배포가 많은 기능에 영향을 주고 일부 기능만 독립적으로 확장하기 어려울 수 있다. 그러나 이러한 문제는 단일 배포 단위보다 내부 모듈 경계가 불명확해서 발생할 수도 있다.

모듈식 단일체는 명확한 내부 모듈과 인터페이스를 유지하면서 하나의 프로그램으로 배포한다. 실제로 독립적인 배포가 필요한 부분이 나타나면 해당 모듈을 별도의 서비스로 분리할 수 있다.

분산 시스템은 여러 프로세스와 서버, 장치가 네트워크로 협력한다. 독립적인 확장과 장애 격리, 지역별 배포가 가능하지만 다음 문제를 추가로 처리해야 한다.

  • 네트워크 지연과 연결 단절
  • 부분적 실패
  • 메시지 중복과 순서
  • 데이터 일관성
  • 서비스 검색
  • 서비스 간 인증과 권한
  • 여러 구성 요소의 버전 호환성
  • 분산된 로그와 추적
  • 배포와 운영 비용

로컬 함수 호출과 원격 요청을 동일하게 취급하면 분산 환경에서 실패를 올바르게 처리하기 어렵다.

설계 패턴

설계 패턴은 반복적으로 나타나는 설계 문제와 해당 문맥에서 사용할 수 있는 해결 구조를 정리한 것이다. 패턴은 그대로 복사하는 코드가 아니라 문제와 적용 조건, 구조, 장점과 비용을 설명한다.

패턴은 다음과 같은 범위에 사용될 수 있다.

  • 객체와 구성 요소의 생성
  • 인터페이스 변환과 구조 조합
  • 이벤트와 상태 변화
  • 업무 논리와 데이터 저장
  • 사용자 인터페이스
  • 동시성과 비동기 처리
  • 네트워크 통신
  • 장애 복구
  • 배포와 운영

패턴의 이름은 개발자가 구조와 의도를 짧게 논의할 수 있는 공통 어휘를 제공한다. 그러나 알려진 패턴이라는 이유만으로 적용하면 불필요한 추상화와 구성 요소가 늘어날 수 있다.

생성 패턴

생성 패턴은 객체와 구성 요소를 만드는 책임을 사용 코드에서 분리한다.

  • 팩토리는 구체적인 생성 절차를 한곳에 모은다.
  • 빌더는 복잡한 객체를 여러 단계로 구성한다.
  • 프로토타입은 기존 객체를 복제하여 새 객체를 만든다.

실행 환경이나 설정에 따라 생성할 구현이 달라지거나 객체의 생명주기를 통제해야 할 때 사용할 수 있다.

구조 패턴

구조 패턴은 기존 객체와 구성 요소를 조합하고 인터페이스를 변환한다.

  • 어댑터는 기존 인터페이스를 필요한 형태로 변환한다.
  • 퍼사드는 복잡한 하위 시스템에 단순한 인터페이스를 제공한다.
  • 데코레이터는 기존 객체를 감싸 기능을 추가한다.
  • 프록시는 접근 제어, 원격 호출과 지연 로딩 등을 제공한다.

이러한 구조를 지나치게 중첩하면 실제 호출 대상과 실행 흐름을 파악하기 어려워질 수 있다.

행위 패턴

행위 패턴은 객체와 구성 요소 사이의 책임과 상호작용을 다룬다.

  • 옵저버는 상태 변화를 여러 구독자에게 알린다.
  • 전략은 교체 가능한 알고리즘과 정책을 표현한다.
  • 명령은 작업을 객체나 메시지로 표현한다.
  • 상태는 현재 상태에 따라 달라지는 동작을 분리한다.

행위를 여러 객체로 분리하면 조건문의 복잡성을 줄일 수 있지만 전체 흐름이 여러 위치에 흩어질 수 있다.

사용자 인터페이스 구조

사용자 인터페이스는 화면 표현, 입력, 업무 상태와 비동기 작업을 함께 처리한다. 화면 코드에 업무 규칙과 데이터 접근을 직접 넣으면 기능을 다른 인터페이스에서 재사용하고 독립적으로 시험하기 어렵다.

사용자 인터페이스 구조에는 다음과 같은 방식이 사용될 수 있다.

  • Model-View-Controller
  • Model-View-Presenter
  • Model-View-ViewModel
  • 단방향 데이터 흐름
  • 상태 기반 선언형 사용자 인터페이스
  • 프레젠테이션 모델

이러한 방식은 화면 표현과 상태, 사용자 입력 처리와 업무 규칙을 구분하기 위한 구조이다.

프레임워크에서 정한 폴더 이름을 따르는 것만으로 책임이 자동으로 분리되지는 않는다. 상태를 누가 소유하고 화면과 업무 논리가 어느 방향으로 의존하는지를 명확히 해야 한다.

도메인 설계

업무 규칙이 복잡한 시스템에서는 실제 문제 영역의 개념과 규칙을 코드 구조에 반영할 수 있다.

도메인 모델은 업무의 개체와 값, 관계, 상태와 규칙을 표현한다. 개발자와 업무 전문가가 같은 용어를 사용하면 요구사항과 구현 사이의 의미 차이를 줄일 수 있다.

도메인은 다음과 같은 기준으로 여러 경계로 나눌 수 있다.

  • 서로 다른 업무 목적
  • 독립적인 규칙과 용어
  • 데이터 소유권
  • 변경과 배포의 독립성
  • 조직과 팀의 책임

같은 단어가 영역마다 다른 의미를 가질 수도 있다. 예를 들어 사용자는 인증 영역에서는 로그인 계정을 뜻하지만 결제 영역에서는 청구 대상 고객을 뜻할 수 있다.

모든 응용 프로그램에 복잡한 도메인 모델이 필요한 것은 아니다. 단순한 데이터 입력과 조회가 중심인 프로그램에서는 직접적인 구조가 더 적합할 수 있다.

API 설계

API는 다른 소프트웨어와 개발자가 기능을 사용할 수 있도록 제공하는 계약이다.

API 설계에서는 다음을 고려한다.

  • 기능과 자원의 경계
  • 용어와 데이터의 의미
  • 입력과 출력 형식
  • 동기 및 비동기 호출
  • 오류와 상태 코드
  • 인증과 권한
  • 페이지 처리
  • 대량 작업
  • 멱등성과 중복 요청
  • 시간 제한과 취소
  • 버전과 폐기 정책
  • 호출 제한
  • 문서와 예제

API는 데이터베이스 표와 내부 객체 구조를 그대로 외부에 노출하기보다 사용자의 작업과 안정적인 개념을 중심으로 설계한다.

오류 응답은 호출자가 재시도, 입력 수정, 인증이나 권한 요청 중 어떤 대응을 해야 하는지 판단할 수 있도록 표현해야 한다.

버전과 호환성

소프트웨어는 여러 버전이 동시에 실행될 수 있다. 서버와 클라이언트, 데이터베이스, 파일과 플러그인이 서로 다른 시점에 업데이트되면 호환성 문제가 발생한다.

설계에서는 다음을 고려한다.

  • 새 프로그램이 이전 형식의 데이터를 읽을 수 있는가
  • 새 서버가 이전 클라이언트의 요청을 처리할 수 있는가
  • 일부 서비스만 먼저 업데이트되어도 통신할 수 있는가
  • 스키마 이전 중 이전 코드와 새 코드가 함께 동작할 수 있는가
  • 폐기된 기능을 언제 제거할 수 있는가
  • 사용자가 데이터를 새로운 형식으로 이전할 수 있는가

호환성을 유지하기 위해 선택적인 필드, 기본값, 기능 협상, 버전 명시와 단계적인 읽기·쓰기 전환 등을 사용할 수 있다.

이전 버전을 무기한 유지할 수는 없으므로 지원 기간과 폐기 경고, 이전 도구와 종료 일정을 제공한다.

자원과 생명주기 설계

소프트웨어는 메모리와 파일, 네트워크 연결, 스레드, 그래픽 자원, 장치 핸들과 같은 자원을 사용한다.

자원 설계에서는 다음을 정한다.

  • 누가 자원을 생성하는가
  • 누가 자원을 소유하는가
  • 언제 해제하는가
  • 여러 구성 요소가 공유할 수 있는가
  • 실패와 취소 중에도 정리할 수 있는가
  • 자원 사용 한도는 무엇인가
  • 누수와 장기 보유를 어떻게 감지하는가
  • 종료 순서는 어떻게 되는가

가비지 컬렉션을 사용하는 언어도 파일과 네트워크 연결, 잠금과 장치 자원은 별도로 정리해야 할 수 있다. 자원의 생명주기를 객체나 작업 범위와 연결하면 정상 경로와 오류 경로에서 일관되게 관리하기 쉽다.

시험 가능성을 위한 설계

시험 가능성은 구성 요소의 입력과 상태를 제어하고 결과를 관찰하여 요구사항 충족 여부를 확인하기 쉬운 정도이다.

시험 가능성이 높은 구조는 다음과 같은 특성을 가진다.

  • 책임과 인터페이스가 명확하다.
  • 구성 요소를 작은 단위로 실행할 수 있다.
  • 외부 서비스와 장치를 대체할 수 있다.
  • 시간과 난수, 운영체제 상태에 대한 숨겨진 의존성이 적다.
  • 상태 변화와 오류를 관찰할 수 있다.
  • 오류 상황을 의도적으로 발생시킬 수 있다.
  • 전역 상태가 제한되어 있다.
  • 시험 환경과 데이터를 재현할 수 있다.

시험을 위해 운영과 전혀 다른 경로를 만들면 시험 결과가 실제 동작을 대표하지 못할 수 있다. 실제 인터페이스와 구성 경계를 유지하면서 필요한 대체와 진단 지점을 제공한다.

아키텍처 전술

아키텍처 전술은 특정 품질 속성에 영향을 주기 위해 적용하는 비교적 작은 설계 결정이다. 하나의 아키텍처 스타일 안에서도 여러 전술을 조합할 수 있다.

가용성 전술에는 다음이 포함될 수 있다.

  • 상태 감지
  • 하트비트
  • 복제
  • 장애 조치
  • 자동 재시작
  • 체크포인트와 롤백
  • 장애 격리
  • 저하 운전

성능 전술에는 다음이 포함될 수 있다.

  • 캐시
  • 작업 우선순위
  • 병렬 처리
  • 자원 풀
  • 요청 일괄 처리
  • 데이터 지역성
  • 부하 분산
  • 불필요한 작업 제거

보안 전술에는 다음이 포함될 수 있다.

  • 인증
  • 권한 검사
  • 최소 권한
  • 입력 검증
  • 암호화
  • 네트워크 분리
  • 감사 기록
  • 이상 행위 탐지

변경 가능성 전술에는 다음이 포함될 수 있다.

  • 모듈 경계
  • 정보 은닉
  • 어댑터
  • 설정과 정책의 분리
  • 플러그인 인터페이스
  • 의존성 역전
  • API 버전 관리

하나의 전술은 다른 품질 속성에 비용을 줄 수 있으므로 적용 전후의 영향을 함께 분석한다.

아키텍처 프로토타입

중요한 기술적 가정과 구조는 전체 시스템을 구현하기 전에 프로토타입으로 검증할 수 있다.

아키텍처 프로토타입으로 다음을 확인할 수 있다.

  • 목표 처리량과 응답 시간을 달성할 수 있는가
  • 선택한 통신 방식의 지연이 허용 가능한가
  • 외부 장치와 서비스가 실제로 연동되는가
  • 데이터 저장과 복제가 필요한 규모를 처리하는가
  • 운영체제와 런타임이 자원 제한을 충족하는가
  • 장애 격리와 복구가 예상대로 작동하는가
  • 배포와 업데이트를 실제 환경에서 수행할 수 있는가
  • 보안 경계와 인증 흐름이 실현 가능한가

프로토타입을 만들기 전에 검증할 가정과 성공 기준을 정한다. 제한된 환경에서 한 번 동작했다는 사실만으로 제품 수준의 품질과 운영 가능성이 입증되지는 않는다.

아키텍처 평가

아키텍처 평가는 전체 구현을 완료하기 전에 구조가 중요한 요구사항과 품질 속성을 충족할 가능성을 분석하는 활동이다.

평가에서는 다음을 확인한다.

  • 주요 품질 속성이 구체적인 시나리오로 정의되었는가
  • 설계 결정이 어떤 요구사항을 해결하는가
  • 장애와 변경에 어떻게 반응하는가
  • 단일 장애 지점은 어디인가
  • 성능 병목은 어디에 생길 수 있는가
  • 신뢰 경계와 권한이 적절한가
  • 검증되지 않은 기술적 가정은 무엇인가
  • 특정 기술과 공급자에 얼마나 종속되는가
  • 실제로 시험하고 배포하며 운영할 수 있는가
  • 구조의 복잡성과 비용이 허용 가능한가

평가에는 문서와 설계 검토, 시나리오 분석, 프로토타입, 성능 모델, 부하 시험, 위협 모델링과 장애 시험 등을 사용할 수 있다.

ATAM은 품질 속성 목표에 영향을 주는 아키텍처 결정과 위험을 찾고, 서로 다른 품질 목표 사이의 상충 관계를 분석한다.[43]

민감 지점과 상충 지점

민감 지점은 특정 값이나 설계 결정이 조금만 달라져도 품질 속성에 큰 영향을 미치는 부분이다.

예를 들어 다음과 같은 요소가 민감 지점이 될 수 있다.

  • 연결 풀 크기
  • 캐시 유효 기간
  • 복제본 수
  • 메시지 대기열 크기
  • 작업 스레드 수
  • 동기와 비동기 통신 선택
  • 데이터 일관성 정책

상충 지점은 하나의 결정이 여러 품질 속성에 서로 다른 방향으로 영향을 주는 부분이다.

데이터를 여러 지역에 동기적으로 복제하면 데이터 일관성을 높일 수 있지만 네트워크 지연과 장애에 따라 응답 시간과 가용성에 영향을 줄 수 있다.

민감 지점과 상충 지점을 찾으면 시스템 전체를 같은 수준으로 분석하는 대신 위험이 집중된 부분에 측정과 시험을 우선할 수 있다.

아키텍처 결정 기록

아키텍처는 여러 결정의 결과이다. 최종 구성도만 남기면 이후 개발자는 왜 특정 구조와 기술이 선택되었는지 알기 어렵다.

중요한 결정에는 다음을 기록할 수 있다.

  • 해결하려는 문제
  • 관련 요구사항과 품질 속성
  • 검토한 대안
  • 선택한 결정
  • 선택 이유
  • 예상되는 장점과 비용
  • 적용 범위
  • 남아 있는 위험과 가정
  • 다시 검토해야 하는 조건
  • 관련 구현과 문서

Architecture Decision Record와 같은 짧은 형식을 사용하여 결정을 개별적으로 관리할 수 있다.

결정이 변경되었을 때 이전 기록을 삭제하지 않고 새 결정이 이전 결정을 대체했다는 관계를 남기면 구조의 변화와 이유를 추적할 수 있다.

모든 클래스와 라이브러리 선택을 기록할 필요는 없다. 시스템 전체와 장기 변경 비용에 영향을 주거나 여러 대안 사이에 중요한 상충 관계가 있었던 결정을 중심으로 기록한다.

이해관계자와 관심사

소프트웨어 아키텍처는 개발자만을 위한 정보가 아니다. 시스템의 개발과 사용, 운영과 관리에 참여하는 이해관계자는 서로 다른 관심사를 가진다.

  • 사용자는 기능과 사용성에 관심을 가진다.
  • 개발자는 모듈과 인터페이스, 변경 가능성에 관심을 가진다.
  • 운영자는 배포와 관찰, 장애 복구에 관심을 가진다.
  • 보안 담당자는 신뢰 경계와 데이터 흐름에 관심을 가진다.
  • 시험 담당자는 검증 가능한 경계와 환경에 관심을 가진다.
  • 제품 책임자는 비용과 일정, 사업 목표에 관심을 가진다.
  • 감사와 규제 기관은 추적성과 준수 증거에 관심을 가진다.

하나의 아키텍처 표현으로 모든 관심사를 충분히 설명하기 어렵다. 따라서 여러 관점과 뷰를 사용하여 같은 시스템을 서로 다른 측면에서 표현한다.

관점과 뷰

관점은 특정 이해관계자의 관심사를 다루기 위해 사용할 모델과 표기, 분석 규칙을 정의한다. 는 해당 관점을 특정 시스템에 적용하여 만든 실제 표현이다.

아키텍처는 다음과 같은 뷰로 표현할 수 있다.

  • 시스템 문맥과 외부 요소
  • 모듈과 소스 코드 구조
  • 주요 구성 요소와 인터페이스
  • 실행 프로세스와 통신
  • 데이터와 저장 구조
  • 배포 노드와 네트워크
  • 보안 경계와 데이터 흐름
  • 운영과 관찰 구조
  • 빌드와 배포 파이프라인

ISO/IEC/IEEE 42010:2022는 이해관계자와 관심사, 관점, 뷰와 아키텍처 모델 사이의 관계를 아키텍처 기술의 중심 개념으로 다룬다.[44]

여러 뷰는 같은 시스템을 설명하므로 서로 일관되어야 한다. 모듈 뷰에서는 하나의 구성 요소로 표현하지만 배포 뷰에서는 여러 프로세스로 나뉜다면 그 관계와 이유를 설명해야 한다.

다이어그램과 모델링

다이어그램은 구조와 관계를 빠르게 전달하지만 각 요소와 연결의 의미가 명확해야 한다.

다이어그램에는 다음을 표현할 수 있다.

  • 구성 요소의 이름과 책임
  • 시스템과 모듈 경계
  • 연결 방향
  • 함수 호출과 메시지 전달
  • 데이터와 제어 흐름
  • 동기 및 비동기 통신
  • 외부 시스템과 사용자
  • 실행 및 배포 위치
  • 보안과 신뢰 경계

화살표가 단순히 “관련되어 있음”만을 의미하면 독자마다 다르게 해석할 수 있다. 호출, 데이터 흐름, 의존성과 배포 관계를 구분하고 범례를 제공해야 한다.

UML은 소프트웨어와 시스템의 구조와 동작을 시각화·명세·구성·문서화하기 위한 그래픽 언어이다. 클래스, 구성 요소, 배포, 시퀀스, 상태와 활동 등 여러 종류의 모델을 제공한다.[45]

UML을 사용한다고 설계 품질이 자동으로 높아지는 것은 아니다. 프로젝트와 독자가 이해하고 유지할 수 있는 표기와 상세 수준을 선택해야 한다.

아키텍처 문서화

아키텍처 문서는 구현 세부 사항을 모두 복제하는 문서가 아니다. 시스템을 이해하고 변경하며 평가하는 데 필요한 구조와 설계 의도를 전달해야 한다.

아키텍처 문서에는 다음과 같은 내용이 포함될 수 있다.

  • 시스템의 목적과 범위
  • 이해관계자와 관심사
  • 아키텍처적으로 중요한 요구사항
  • 시스템 문맥
  • 주요 구성 요소와 책임
  • 외부 인터페이스
  • 데이터 소유권과 저장 구조
  • 실행과 배포 구조
  • 품질 속성을 달성하는 방법
  • 중요한 결정과 대안
  • 제약과 가정
  • 위험과 알려진 한계
  • 장애와 복구 방식
  • 용어 정의
  • 관련 코드와 운영 문서의 위치

코드에서 자동으로 확인할 수 있는 파일과 함수 목록을 수동으로 복제하면 문서가 쉽게 오래된 상태가 된다. 자동 생성할 수 있는 정보는 도구로 생성하고, 사람이 기록해야 하는 이유와 제약, 상충 관계에 집중한다.

설계 검토

설계 검토는 여러 사람이 구조의 요구사항 충족 여부와 위험을 확인하는 활동이다.

검토에서는 다음과 같은 질문을 다룬다.

  • 각 구성 요소의 책임이 명확한가
  • 데이터와 상태의 소유자가 분명한가
  • 요구사항과 품질 속성이 구조에 반영되었는가
  • 불필요한 결합과 순환 의존성이 있는가
  • 오류와 장애가 적절히 격리되는가
  • 외부 시스템의 변경과 실패에 대응할 수 있는가
  • 보안 경계와 권한이 적절한가
  • 시험과 운영이 가능한가
  • 배포와 되돌리기가 가능한가
  • 더 단순한 대안이 있는가
  • 설계의 비용이 제공하는 가치에 비해 적절한가

설계 검토는 설계자의 능력을 평가하는 과정이 아니라 시스템의 위험과 검증되지 않은 가정을 공동으로 발견하는 과정이다. 의견은 개인적 취향보다 요구사항과 품질 속성, 실제 운영 조건을 기준으로 제시한다.

구현과 아키텍처의 일치

문서에 표현된 아키텍처와 실제 코드 및 배포 구조는 시간이 지나면서 달라질 수 있다. 임시 의존성과 예외 경로가 누적되고 구성 요소가 원래 책임을 벗어나면 아키텍처의 경계가 약해진다.

이를 줄이기 위해 다음과 같은 방법을 사용할 수 있다.

  • 언어와 빌드 시스템으로 모듈 접근 범위를 제한한다.
  • 공개 인터페이스 이외의 접근을 막는다.
  • 의존성 규칙을 정적 분석과 시험으로 검사한다.
  • 코드 검토에서 아키텍처 영향을 확인한다.
  • 실제 배포 구성을 자동으로 수집한다.
  • 중요한 변경과 함께 결정 기록을 갱신한다.
  • 의존성 그래프와 순환 관계를 주기적으로 검토한다.
  • 임시 통합과 사용하지 않는 경로를 정리한다.

아키텍처를 유지한다는 것은 최초의 구조를 변경하지 않는다는 뜻이 아니다. 구조를 의도적으로 변경하고 코드와 문서, 배포 환경에 일관되게 반영한다는 의미이다.

진화적 아키텍처

소프트웨어 아키텍처는 개발 초기에 한 번 완성하고 고정하는 구조가 아니다. 사용자 요구와 실행 환경, 운영 경험과 기술이 변하면 아키텍처도 함께 진화한다.

진화적인 아키텍처에서는 다음을 중요하게 다룬다.

  • 명확하고 변경 가능한 모듈 경계
  • 작은 단위의 구조 개선
  • 자동화된 시험
  • API와 데이터의 호환성
  • 구조 규칙의 자동 검사
  • 품질 속성의 지속적인 측정
  • 중요한 가정과 결정의 재평가
  • 운영 결과의 설계 반영

초기에 미래의 모든 기능을 예상하여 지나치게 일반적인 구조를 만들면 현재 시스템이 필요 이상으로 복잡해질 수 있다. 현재의 중요한 요구와 위험을 해결하면서 변화 가능성이 높은 부분에 경계를 둔다.

반대로 현재 기능만 빠르게 추가하면 구성 요소 경계가 무너지고 기술 부채가 쌓일 수 있다. 기능 개발과 구조 개선을 같은 생명주기의 작업으로 관리해야 한다.

리팩터링과 재구조화

리팩터링은 외부에서 관찰되는 동작을 유지하면서 내부 구조를 개선하는 활동이다.

리팩터링에는 다음이 포함될 수 있다.

  • 함수와 클래스 분리
  • 이름과 인터페이스 개선
  • 중복 제거
  • 책임 이동
  • 의존 방향 수정
  • 전역 상태 제거
  • 외부 기술을 어댑터 뒤로 이동
  • 조건과 정책 분리
  • 시험 경계 개선

아키텍처 수준의 재구조화는 모듈 분리와 통합, 데이터 소유권 변경, 프로세스와 서비스의 분할, 배포 구조 변경처럼 더 넓은 범위를 다룬다.

전체 시스템을 한 번에 교체하기보다 새 구조를 기존 구조 옆에 추가하고 기능과 데이터를 점진적으로 이전할 수 있다. 기존 인터페이스를 유지한 채 내부 구현을 단계적으로 대체하는 방식도 사용할 수 있다.

아키텍처와 조직

소프트웨어 구조와 개발 조직은 서로 영향을 준다. 여러 팀이 하나의 구성 요소를 반복해서 함께 수정하면 조정 비용이 증가하고, 하나의 기능 변경에 여러 팀의 승인이 필요하면 배포 속도가 느려질 수 있다.

업무 책임과 데이터의 경계를 팀의 소유권과 맞추면 구성 요소를 더 독립적으로 개발하고 운영할 수 있다.

그러나 현재 조직의 부서 구조를 그대로 시스템 구조로 옮기면 사용자 기능과 데이터의 자연스러운 경계가 깨질 수 있다. 업무 개념과 데이터, 변경 흐름과 조직의 책임을 함께 고려해야 한다.

하나의 구성 요소에 대한 최종 책임을 명확히 하되, 조직이 바뀌더라도 시스템의 핵심 개념과 계약이 유지될 수 있도록 설계한다.

기술 선택

프로그래밍 언어와 프레임워크, 데이터베이스, 운영체제와 클라우드 서비스는 아키텍처 구현에 영향을 준다. 그러나 기술 목록 자체가 아키텍처는 아니다.

기술을 선택할 때는 다음을 고려한다.

  • 기능과 품질 요구사항
  • 지원 플랫폼
  • 성능과 자원 사용
  • 안정성과 장기 지원
  • 개발 및 디버깅 도구
  • 시험 가능성
  • 팀의 경험
  • 학습과 채용 비용
  • 라이선스와 사용 비용
  • 보안 업데이트
  • 외부 공급자와 생태계
  • 데이터와 API 종속성
  • 운영과 관찰 도구
  • 다른 기술로 이전할 가능성

유행하거나 익숙하다는 이유만으로 기술을 선택하기보다 해결할 문제와 품질 목표, 위험을 기준으로 비교한다. 중요한 가정은 프로토타입과 측정으로 검증할 수 있다.

외부 기술에 대한 종속을 완전히 없애려 하면 많은 추상화와 비용이 필요하다. 교체 가능성이 높거나 핵심 업무 논리를 보호해야 하는 경계에 선택적으로 적용한다.

설계의 적합성과 단순성

좋은 설계는 패턴과 계층, 구성 요소가 가장 많은 설계가 아니다. 요구된 기능과 품질을 충족하면서 구조와 의도를 설명하고 변경할 수 있는 설계이다.

적합한 설계는 다음과 같은 특성을 가진다.

  • 각 구성 요소가 존재하는 이유가 분명하다.
  • 책임과 데이터 소유권을 설명할 수 있다.
  • 의존성이 필요한 범위로 제한된다.
  • 실행 흐름과 상태 변화를 추적할 수 있다.
  • 오류와 장애의 영향 범위가 정해져 있다.
  • 불필요한 계층과 일반화가 적다.
  • 품질 요구사항을 측정할 수 있다.
  • 시험과 배포, 운영을 고려한다.
  • 중요한 결정의 근거가 남아 있다.

단순성은 모든 기능을 하나의 구성 요소에 넣는 것과 같지 않다. 복잡한 문제에는 여러 구성 요소와 계층이 필요할 수 있지만, 각각의 복잡성은 실제 요구사항과 위험을 해결하는 이유를 가져야 한다.

설계의 지속적 검증

설계는 문서와 회의만으로 완전히 검증되지 않는다. 구현과 시험, 실제 운영 결과를 통해 설계의 가정을 계속 확인해야 한다.

다음 자료를 사용할 수 있다.

  • 기능 시험
  • 성능과 부하 시험
  • 장시간 실행 시험
  • 장애 주입과 복구 시험
  • 보안 분석과 침투 시험
  • 의존성 및 구조 분석
  • 배포 시간과 실패율
  • 운영 로그와 메트릭
  • 사용자 오류와 행동
  • 기능 변경에 필요한 시간과 수정 범위
  • 장애 원인과 복구 시간
  • 기술 부채와 유지보수 비용

예상보다 변경 범위가 크거나 성능과 가용성이 목표를 충족하지 못한다면 개별 코드뿐 아니라 구성 요소 경계와 통신, 데이터 구조와 배포 방식을 다시 검토해야 한다.

소프트웨어 아키텍처와 설계는 요구사항을 코드로 옮기기 전에 한 번 수행하고 끝나는 단계가 아니다. 요구사항과 운영 환경이 변하는 동안 구조를 계속 평가하고 수정하며, 중요한 품질과 변경의 영향을 통제하는 생명주기 전체의 공학 활동이다.

구현과 소프트웨어 구성 관리

소프트웨어 구현은 요구사항과 설계를 실제로 실행 가능한 소프트웨어 구성 요소로 변환하는 활동이다. 소스 코드 작성뿐 아니라 자료 구조와 알고리즘의 구체화, 외부 구성 요소의 통합, 코드 검토, 정적 분석, 빌드, 디버깅과 단위 수준의 검증을 포함한다.

소프트웨어 구성 관리(Software Configuration Management, SCM)는 소프트웨어와 관련 산출물의 구성을 식별하고, 그 변경과 버전을 통제하며, 특정 시점의 상태를 기록·검증하고, 일관된 제품과 릴리스를 재현할 수 있도록 관리하는 활동이다.

구성 관리에서 말하는 구성은 프로그램 설정 파일만을 뜻하지 않는다. 소프트웨어 제품을 정의하거나 다시 만들기 위해 필요한 소스 코드, 요구사항, 설계 자료, 시험 코드, 빌드 스크립트, 의존성, 데이터 스키마, 배포 설정과 문서 등이 모두 구성의 일부가 될 수 있다.

구현과 구성 관리는 밀접하게 연결된다. 개발자가 코드를 변경하면 해당 변경은 버전 관리 시스템에 기록되고, 코드 검토와 자동화된 빌드·시험을 거쳐 다른 변경과 통합된다. 검증된 상태는 기준선과 릴리스 후보가 되며, 최종 산출물은 버전·출처·의존성과 함께 배포된다.

IEEE Computer Society의 SWEBOK V4.0은 소프트웨어 구축과 소프트웨어 구성 관리를 각각 독립된 지식 영역으로 다룬다. 소프트웨어 구축은 코딩, 검증, 단위 시험, 통합과 관련된 활동을 포함하며, 구성 관리는 구성 식별, 통제, 상태 기록, 감사와 릴리스 관리를 다룬다.[46][47]

구현의 역할

구현은 설계 문서를 기계적으로 코드로 옮기는 작업이 아니다. 설계에서 정한 구조와 계약을 실제 프로그래밍 언어와 실행 환경의 규칙으로 구체화하고, 구현 과정에서 발견된 제약과 문제를 다시 설계와 요구사항에 반영하는 활동이다.

구현 과정에서는 다음과 같은 결정을 내린다.

  • 사용할 자료형과 자료 구조
  • 알고리즘과 처리 순서
  • 함수와 객체의 구체적인 책임
  • 메모리와 자원의 소유권
  • 동시성과 비동기 처리 방식
  • 오류와 예외의 표현
  • 입력과 상태의 유효성 검사
  • 외부 라이브러리와 운영체제 기능의 사용
  • 로그와 진단 정보
  • 성능 최적화
  • 단위 시험과 시험 경계
  • 플랫폼별 구현과 공통 코드의 분리

상세 설계가 구현 전에 모두 확정되는 것은 아니다. 실제 코드로 표현하면서 인터페이스가 지나치게 복잡하거나 자료 구조가 요구 성능을 충족하지 못한다는 사실이 드러날 수 있다. 이 경우 구현을 임시 코드로 우회하기보다 관련 설계와 요구사항을 함께 검토한다.

구현 결과는 소스 코드에 한정되지 않는다. 생성 코드, 데이터베이스 이전 파일, 빌드 설정, 패키지 명세, 컨테이너 이미지 정의, 시험 자료와 사용자에게 배포되는 실행 파일도 구현 활동의 산출물이 될 수 있다.

프로그래밍 언어와 실행 환경

프로그래밍 언어는 소프트웨어의 동작과 구조를 표현하는 주요 수단이다. 언어의 타입 체계와 메모리 모델, 오류 처리, 동시성 기능, 모듈 시스템과 실행 방식은 구현 구조에 영향을 준다.

언어를 선택하거나 사용할 때는 다음과 같은 조건을 고려할 수 있다.

  • 대상 운영체제와 하드웨어
  • 요구되는 실행 성능과 지연 시간
  • 메모리와 전력 제한
  • 안전성과 보안 요구
  • 기존 코드 및 라이브러리와의 연동
  • 개발 도구와 디버깅 지원
  • 컴파일과 배포 방식
  • 장기적인 언어 및 구현체 지원
  • 팀의 경험과 학습 비용
  • 외부 패키지 생태계
  • 라이선스와 공급망 관리

하나의 시스템에서도 서로 다른 언어가 사용될 수 있다. 운영체제 커널과 장치 드라이버에는 하드웨어 제어에 적합한 언어를 사용하고, 관리 도구에는 개발 생산성이 높은 언어를 사용할 수 있다. 웹 서비스의 서버와 브라우저 클라이언트, 모바일 앱도 서로 다른 언어와 런타임으로 구성될 수 있다.

여러 언어를 사용하면 각 영역에 적합한 기능을 선택할 수 있지만, 빌드·디버깅·데이터 변환과 인력 관리가 복잡해진다. 언어 사이의 경계에서는 호출 규약, 자료형, 메모리 소유권, 오류와 문자 인코딩을 명확히 정의해야 한다.

개발 환경

개발 환경은 소스 코드를 편집하는 프로그램 하나만을 뜻하지 않는다. 코드를 작성하고 빌드·실행·시험·분석하며 변경을 공유하기 위해 사용하는 도구와 설정 전체를 포함한다.

개발 환경에는 다음과 같은 요소가 포함될 수 있다.

  • 텍스트 편집기와 통합 개발 환경
  • 컴파일러와 인터프리터
  • 링커와 로더
  • 디버거와 프로파일러
  • 빌드 시스템
  • 패키지 관리자
  • 버전 관리 시스템
  • 코드 분석과 형식화 도구
  • 시험 프레임워크
  • 컨테이너와 가상 환경
  • 로컬 데이터베이스와 외부 서비스 대체 환경
  • 지속적 통합 시스템

팀 구성원이 서로 다른 도구를 사용할 수는 있지만, 코드의 형식과 빌드·시험 결과가 개인의 로컬 환경에 따라 달라지지 않도록 공통 규칙과 자동화된 명령을 제공해야 한다.

새 개발자가 프로젝트를 내려받은 뒤 필요한 도구와 의존성을 설치하고, 빌드와 시험을 실행할 수 있는 절차도 개발 환경의 일부이다. 이 과정이 개인의 기억과 수동 설정에만 의존하면 환경 차이로 인한 결함과 작업 지연이 증가한다.

코딩 규칙

코딩 규칙은 소스 코드의 구조와 표현, 오류 처리와 자원 관리에 적용하는 공통 기준이다. 코드의 외형뿐 아니라 특정 언어 기능을 언제 어떻게 사용할지 정의할 수 있다.

코딩 규칙에는 다음과 같은 내용이 포함될 수 있다.

  • 이름과 파일 구조
  • 들여쓰기와 코드 형식
  • 공개 인터페이스의 작성 방식
  • 오류와 예외 처리
  • 메모리 및 자원 관리
  • 동시성 기능의 사용
  • 입력과 정수 연산의 검증
  • 로그와 진단 정보
  • 보안에 민감한 함수의 사용 제한
  • 주석과 문서화
  • 시험 코드의 구조
  • 사용을 금지하거나 제한하는 언어 기능

일관된 형식은 개발자가 의미 없는 표현 차이보다 코드의 동작과 설계에 집중하도록 돕는다. 자동 형식화 도구를 사용하면 사람마다 형식에 관한 의견을 반복해서 조정하는 비용을 줄일 수 있다.

코딩 규칙은 가능한 한 정적 분석기, 컴파일러 경고와 형식화 도구로 자동 검사하는 편이 좋다. 사람이 모든 규칙을 코드 검토에서 반복해서 확인하면 중요한 설계와 오류 검토에 사용할 시간이 줄어든다.

모든 규칙을 절대적인 형태로 적용할 필요는 없다. 성능이나 플랫폼 제약 때문에 예외가 필요하다면 적용 범위와 이유를 코드 또는 관련 결정 기록에 남긴다.

읽을 수 있는 코드

소스 코드는 컴퓨터가 실행하기 위한 명령이면서 개발자가 시스템을 이해하고 변경하기 위한 주요 문서이다. 읽기 쉬운 코드는 실행 결과를 바꾸지 않더라도 결함 발견과 유지보수 비용에 영향을 준다.

읽을 수 있는 코드는 일반적으로 다음과 같은 특성을 가진다.

  • 이름이 역할과 의미를 설명한다.
  • 함수와 모듈의 책임이 명확하다.
  • 제어 흐름과 상태 변화가 추적 가능하다.
  • 숨겨진 부작용이 제한되어 있다.
  • 관련된 코드와 데이터가 가까이 배치되어 있다.
  • 오류 조건이 정상 흐름과 구분된다.
  • 불필요한 추상화와 중복이 적다.
  • 언어와 프로젝트의 일반적인 관습을 따른다.
  • 중요한 가정과 이유가 기록되어 있다.

코드의 줄 수를 줄이는 것이 항상 가독성을 높이는 것은 아니다. 하나의 표현 안에 여러 연산과 상태 변경을 압축하면 짧더라도 의미를 파악하기 어려울 수 있다.

반대로 모든 작은 동작을 여러 계층과 함수로 나누면 실제 실행 흐름을 따라가기 어려워질 수 있다. 코드의 분해는 표현의 길이보다 책임과 변경 이유를 기준으로 결정한다.

주석과 코드 문서

주석은 코드에서 직접 드러나지 않는 의도와 제약을 설명하는 데 사용한다.

다음과 같은 내용은 주석으로 남길 가치가 있다.

  • 특정 알고리즘과 방식이 선택된 이유
  • 외부 시스템과 플랫폼의 제약
  • 직관적이지 않은 성능 최적화
  • 안전성과 보안을 위한 중요한 조건
  • 수학적 근거와 참고 자료
  • 임시 대응의 제거 조건
  • 다른 코드와 유지해야 하는 불변 관계
  • 공개 API의 사용 조건과 오류

코드의 동작을 같은 표현으로 반복하는 주석은 코드가 변경될 때 불일치하기 쉽다. 복잡한 코드가 주석 없이는 이해되지 않는다면 먼저 이름과 구조를 개선할 수 있는지 검토한다.

공개 함수와 타입, 라이브러리와 API에는 사용자가 내부 구현을 읽지 않고도 사용할 수 있는 문서가 필요하다. 입력과 출력, 오류, 상태 변경, 스레드 안전성, 자원 소유권과 예제가 포함될 수 있다.

코드에서 문서를 생성할 수 있는 도구를 사용하면 공개 인터페이스와 문서를 연결할 수 있다. 그러나 자동 생성된 함수 목록만으로 시스템의 개념과 올바른 사용 방법이 충분히 설명되지는 않는다.

방어적 구현

방어적 구현은 외부 입력과 상태, 다른 구성 요소가 항상 예상대로 동작한다고 가정하지 않고 잘못된 조건을 감지하고 제한하는 방식이다.

방어적 구현에는 다음과 같은 방법이 포함된다.

  • 외부 입력의 형식과 범위를 검증한다.
  • 배열과 버퍼의 경계를 확인한다.
  • 정수 오버플로와 변환 손실을 고려한다.
  • 널 참조와 초기화되지 않은 상태를 제한한다.
  • 반환 값과 오류를 무시하지 않는다.
  • 외부 자원의 시간 제한과 취소를 설정한다.
  • 자원 부족과 부분적인 실패를 처리한다.
  • 불변 조건을 검사한다.
  • 실패 시 안전한 상태를 유지한다.
  • 민감한 정보를 오류 메시지에 노출하지 않는다.

모든 내부 호출에서 같은 검증을 반복하면 코드와 실행 비용이 증가할 수 있다. 신뢰 경계에서 입력을 검증하고, 내부에서는 타입과 명확한 계약으로 올바른 상태를 유지하는 구조를 사용할 수 있다.

단언은 개발 중 프로그램의 잘못된 내부 상태를 빠르게 발견하는 데 유용하다. 그러나 사용자가 제공한 잘못된 입력이나 운영 중 발생 가능한 오류를 단언만으로 처리하면 적절한 복구와 오류 전달이 이루어지지 않을 수 있다.

오류 처리

구현에서는 설계에서 정한 오류 정책을 실제 언어와 인터페이스에 반영한다.

오류는 다음과 같이 구분할 수 있다.

  • 사용자가 수정할 수 있는 잘못된 입력
  • 일시적인 네트워크와 외부 서비스 오류
  • 권한과 인증 실패
  • 존재하지 않는 자원
  • 자원 부족과 시간 초과
  • 손상된 데이터와 상태
  • 호출 계약과 불변 조건의 위반
  • 프로그램 내부의 결함

함수와 API는 호출자가 실패의 종류와 대응 방법을 판단할 수 있도록 오류를 표현해야 한다. 모든 실패를 하나의 일반 오류로 바꾸면 재시도, 사용자 입력 수정, 관리자 개입과 프로그램 수정 중 어떤 처리가 필요한지 알기 어렵다.

오류를 여러 계층에서 반복해서 기록하면 같은 실패가 로그에 중복될 수 있다. 오류를 처리하거나 충분한 문맥을 추가할 수 있는 계층에서 기록하고, 하위 계층에서는 구조화된 오류 정보를 전달할 수 있다.

오류를 무시하고 기본값이나 성공 결과를 반환하면 문제가 더 멀리 전파되어 원인을 찾기 어려워질 수 있다. 반대로 복구할 수 있는 오류 때문에 전체 프로세스를 즉시 종료하면 시스템의 가용성이 불필요하게 낮아질 수 있다.

자원 관리

구현에서는 메모리와 파일, 네트워크 연결, 스레드, 잠금, 그래픽 자원과 장치 핸들의 실제 생명주기를 관리한다.

자원 관리에서는 다음이 명확해야 한다.

  • 자원을 누가 생성하고 소유하는가
  • 다른 구성 요소로 소유권을 이전할 수 있는가
  • 여러 사용자가 공유할 수 있는가
  • 언제 반환하고 해제하는가
  • 오류와 취소 중에도 정리되는가
  • 중복 해제와 해제 후 사용을 어떻게 방지하는가
  • 자원 사용 한도를 어떻게 적용하는가
  • 누수와 장기 보유를 어떻게 감지하는가

언어가 메모리 관리를 자동화하더라도 파일과 연결, 잠금과 운영체제 자원은 명시적인 종료가 필요할 수 있다. 범위 기반 자원 관리, 지연 실행, 구조화된 정리 구문 등을 사용하면 여러 반환 경로에서 자원을 일관되게 해제할 수 있다.

자원 풀과 캐시는 생성 비용을 줄일 수 있지만 자원을 예상보다 오래 유지하고 한도를 초과하게 만들 수 있다. 사용량과 대기 시간, 누수를 관찰할 수 있는 지표를 함께 제공한다.

동시성과 비동기 구현

여러 작업이 동시에 실행되는 프로그램에서는 공유 상태와 실행 순서를 명확히 관리해야 한다.

동시성 구현에서 다루는 문제에는 다음이 있다.

  • 경쟁 상태
  • 교착 상태
  • 라이브락과 기아
  • 메모리 가시성과 연산 순서
  • 작업 취소
  • 시간 초과
  • 스레드와 작업의 생명주기
  • 비동기 오류의 전달
  • 과도한 병렬 실행과 자원 고갈
  • 종료 중인 프로그램의 작업 정리

공유되는 변경 가능한 상태를 줄이고 소유권을 명확히 하면 가능한 실행 순서를 줄일 수 있다. 메시지 전달, 불변 데이터, 작업 대기열과 행위자 모델 같은 방식도 사용할 수 있다.

잠금은 공유 상태를 보호할 수 있지만 잠금 순서와 범위가 복잡해지면 교착 상태와 성능 문제가 발생한다. 잠금을 잡은 상태에서 외부 호출이나 오래 걸리는 작업을 수행하지 않도록 경계를 설계할 수 있다.

비동기 작업을 생성한 뒤 완료와 실패를 추적하지 않으면 오류와 자원이 유실될 수 있다. 작업은 가능한 한 명확한 상위 범위에 속하고, 취소와 종료가 구조적으로 전파되도록 구현한다.

외부 구성 요소의 사용

현대 소프트웨어는 표준 라이브러리와 외부 패키지, 프레임워크, SDK와 서비스에 크게 의존한다. 외부 구성 요소를 사용하면 검증된 기능을 재사용하고 개발 시간을 줄일 수 있지만 새로운 기술적·법적·보안 의존성이 생긴다.

외부 구성 요소를 선택할 때는 다음을 검토할 수 있다.

  • 필요한 기능과 품질
  • 유지보수 상태와 릴리스 주기
  • 알려진 취약점과 보안 대응
  • 라이선스와 재배포 조건
  • 지원 플랫폼과 언어 버전
  • API 안정성과 호환성 정책
  • 전이 의존성의 수와 성격
  • 패키지의 출처와 배포 경로
  • 대체 가능성과 기술 종속
  • 프로젝트와 조직의 신뢰 수준

패키지의 이름과 버전만 같다고 항상 같은 코드가 제공된다고 가정해서는 안 된다. 신뢰할 수 있는 저장소와 암호학적 해시, 서명과 출처 정보를 이용하여 실제로 가져온 구성 요소를 확인할 수 있다.

외부 서비스에 대한 의존은 패키지 의존성과 다르다. 서비스 제공자가 API와 가격, 정책을 변경하거나 서비스를 종료할 수 있으므로 계약과 시간 제한, 오류 처리, 데이터 이전과 대체 방식을 함께 고려한다.

의존성 관리

의존성 관리는 소프트웨어가 사용하는 외부 패키지와 내부 구성 요소의 이름, 버전, 출처와 관계를 관리하는 활동이다.

패키지 관리자는 의존성을 내려받고 설치하며, 필요한 경우 전이 의존성을 해결한다. 그러나 버전 범위를 너무 넓게 지정하면 같은 소스 코드에서도 설치 시점에 따라 서로 다른 의존성이 선택될 수 있다.

잠금 파일과 고정된 버전은 특정한 의존성 집합을 기록하여 빌드와 개발 환경의 재현성을 높인다. 다만 버전을 고정한 뒤 갱신하지 않으면 보안 수정과 호환성 개선을 받지 못할 수 있다.

의존성 관리에서는 다음을 수행할 수 있다.

  • 직접 및 전이 의존성 식별
  • 버전과 출처 고정
  • 잠금 파일의 버전 관리
  • 사용되지 않는 의존성 제거
  • 취약점과 라이선스 검사
  • 업데이트의 자동 제안과 시험
  • 조직 내부 저장소와 캐시 관리
  • 패키지 무결성 확인
  • 지원 종료 상태 추적
  • 개발 전용과 운영 의존성 구분

외부 패키지의 코드를 프로젝트 저장소에 직접 포함할 수도 있다. 이 경우 수정 내역과 원본 버전, 라이선스와 향후 업데이트 방식을 명확히 관리해야 한다.

코드 생성

스키마와 인터페이스 정의, 문법과 모델에서 소스 코드를 자동 생성할 수 있다. 생성 코드는 반복 작업과 사람의 입력 오류를 줄이고 여러 언어의 구현을 일관되게 만들 수 있다.

코드 생성에서는 다음을 관리해야 한다.

  • 기준이 되는 원본 정의
  • 생성 도구와 버전
  • 생성 명령과 설정
  • 생성 결과를 저장소에 포함할지 여부
  • 생성 코드의 수정 가능 여부
  • 생성 결과의 형식과 시험
  • 도구 변경에 따른 대규모 차이
  • 빌드 환경에서의 재생성 가능성

생성된 코드를 사람이 직접 수정하면 다음 생성 과정에서 변경이 사라질 수 있다. 사용자 작성 코드와 생성 코드를 명확히 분리하거나 확장 지점을 제공한다.

생성 결과를 저장소에 포함하면 도구 없이도 코드를 확인하고 사용할 수 있지만 원본과 결과가 불일치할 수 있다. 빌드 과정에서 생성하면 일관성을 유지할 수 있지만 생성 도구와 환경을 재현해야 한다.

컴파일과 링크

컴파일 언어에서는 소스 코드가 컴파일러에 의해 목적 코드나 중간 표현으로 변환되고, 링커가 여러 코드와 라이브러리를 결합하여 실행 파일이나 라이브러리를 만든다.

컴파일과 링크 과정에는 다음 요소가 영향을 준다.

  • 컴파일러와 링커의 종류 및 버전
  • 대상 아키텍처와 명령어 집합
  • 최적화와 디버그 설정
  • 전처리기와 기능 플래그
  • 정적 및 동적 링크
  • 외부 라이브러리의 검색 경로
  • 기호의 공개 범위
  • 호출 규약과 ABI
  • 런타임 라이브러리
  • 링크 시간 최적화

같은 소스 코드도 컴파일러와 옵션, 대상 환경에 따라 다른 동작과 성능을 가질 수 있다. 지원하는 도구 체인과 빌드 설정을 명시하고 지속적 통합에서 실제 대상 환경을 검증한다.

ABI를 외부에 제공하는 라이브러리는 자료형의 크기와 배치, 기호 이름과 호출 규약을 장기간 유지해야 할 수 있다. 소스 코드 수준의 호환성과 바이너리 호환성은 별도로 관리한다.

빌드 시스템

빌드 시스템은 소스 코드와 자원, 생성 규칙과 의존 관계를 이용하여 실행 파일·라이브러리·패키지와 기타 산출물을 만드는 과정을 자동화한다.

빌드 시스템은 다음과 같은 작업을 수행할 수 있다.

  • 코드 생성
  • 컴파일과 링크
  • 자원 변환과 묶기
  • 의존성 해결
  • 시험 실행
  • 정적 분석
  • 문서 생성
  • 패키징
  • 서명
  • 설치 이미지와 컨테이너 이미지 생성
  • 빌드 메타데이터 기록

빌드 규칙은 어떤 입력이 어떤 출력에 영향을 주는지 명확히 표현해야 한다. 의존 관계가 누락되면 변경된 파일이 다시 빌드되지 않아 오래된 산출물이 포함될 수 있다.

증분 빌드는 변경된 부분만 다시 처리하여 시간을 줄인다. 그러나 완전한 새 빌드와 결과가 다르지 않은지 주기적으로 확인해야 한다. 개발자의 로컬 환경에서만 존재하는 파일이나 설정에 암묵적으로 의존해서도 안 된다.

빌드는 가능한 한 하나의 문서화된 명령이나 자동화된 진입점으로 수행할 수 있어야 한다. 사람이 여러 도구를 정해진 순서로 직접 실행해야 한다면 누락과 환경 차이가 발생하기 쉽다.

빌드 구성

같은 코드베이스에서도 목적과 환경에 따라 여러 빌드 구성을 사용할 수 있다.

대표적인 구성에는 다음이 있다.

  • 개발용 빌드
  • 디버그 빌드
  • 시험 및 분석용 빌드
  • 성능 측정용 빌드
  • 배포용 최적화 빌드
  • 플랫폼별 빌드
  • 기능과 제품 변형별 빌드
  • 주소·메모리·스레드 분석기가 적용된 빌드

빌드 구성마다 전혀 다른 코드 경로가 사용되면 개발 환경에서 검증되지 않은 코드가 배포될 수 있다. 가능한 한 동일한 소스와 구조를 사용하고 최적화·진단과 포함 기능만 명시적으로 변경한다.

조건부 컴파일은 플랫폼과 기능별 코드를 분리할 수 있지만 조건이 많아지면 가능한 조합이 급격히 증가한다. 지원할 조합을 정의하고 자동화된 빌드 행렬에서 검증한다.

재현 가능한 빌드

재현 가능한 빌드는 같은 소스 코드와 빌드 지침, 정의된 빌드 환경을 사용했을 때 다른 주체가 비트 단위로 동일한 지정 산출물을 다시 만들 수 있는 빌드이다.[48]

재현 가능한 빌드는 배포된 바이너리가 공개되거나 검토된 소스와 빌드 절차에서 만들어졌는지 독립적으로 확인할 수 있는 기반을 제공한다.

빌드의 재현성을 방해하는 요소에는 다음이 있다.

  • 현재 시각과 임의의 타임스탬프
  • 파일과 디렉터리의 비결정적인 순서
  • 임의 값과 생성 식별자
  • 절대 경로와 사용자 이름
  • 지역 및 문자 인코딩 설정
  • 도구와 의존성 버전의 차이
  • 병렬 실행 순서
  • 파일 시스템과 운영체제의 차이
  • 네트워크에서 변경 가능한 자료를 가져오는 작업

재현 가능한 빌드를 위해 빌드 환경과 도구 버전을 정의하고, 비결정적인 입력을 제거하거나 고정하며, 산출물에 포함되는 메타데이터를 통제한다.

모든 프로젝트가 즉시 완전한 비트 단위 재현성을 달성하지 못하더라도 빌드 입력과 환경을 기록하고, 깨끗한 환경에서 반복적으로 빌드하며, 산출물과 출처를 연결하는 과정은 구성 관리와 공급망 보안을 개선한다.

정적 분석

정적 분석은 프로그램을 실행하지 않고 소스 코드나 중간 표현, 바이너리를 분석하여 결함과 규칙 위반을 찾는 방법이다.

정적 분석기는 다음과 같은 문제를 탐지할 수 있다.

  • 초기화되지 않은 값
  • 도달할 수 없는 코드
  • 잘못된 형 변환
  • 자원 누수
  • 널 참조 가능성
  • 버퍼와 배열 경계 문제
  • 정수 오버플로
  • 경쟁 상태의 가능성
  • 보안에 취약한 API 사용
  • 정의되지 않은 동작
  • 프로젝트의 코딩 규칙 위반

컴파일러 경고도 정적 분석의 한 형태로 활용할 수 있다. 경고 수준을 높이고 새 경고가 무시되지 않도록 관리하면 결함을 조기에 발견할 수 있다.

정적 분석은 실행 가능한 모든 경로를 정확히 판단하기 어려우므로 실제 문제가 아닌 경고나 발견하지 못하는 결함이 존재할 수 있다. 결과의 심각도와 근거를 검토하고, 반복되는 오탐은 분석 규칙과 코드 구조를 조정하여 관리한다.

NIST의 Secure Software Development Framework는 이전에 발견되지 않은 취약점을 확인하기 위해 코드를 검토·분석하거나 시험하는 활동을 보안 개발 관행에 포함한다.[49]

동적 분석과 진단 도구

동적 분석은 실행 중인 프로그램의 동작을 관찰하여 메모리 오류와 성능 문제, 동시성 결함을 찾는다.

사용할 수 있는 도구와 방법에는 다음이 있다.

  • 메모리 접근과 누수 검사
  • 정의되지 않은 동작 검사
  • 스레드 경쟁 탐지
  • 코드 커버리지 측정
  • 프로파일링
  • 시스템 호출과 네트워크 추적
  • 힙과 자원 사용 분석
  • 퍼징
  • 장시간 및 스트레스 실행
  • 오류와 장애 주입

분석 도구는 실행 성능과 타이밍을 크게 바꿀 수 있으므로 일반 빌드에서 나타나는 동시성 문제를 재현하지 못하거나 새로운 시간 조건을 만들 수 있다. 여러 도구와 실제 운영에 가까운 빌드를 함께 사용한다.

개발 빌드에는 추가 검사와 진단 정보를 포함하고, 배포 빌드에는 필요한 성능을 유지하면서 최소한의 오류 기록과 보호 기능을 남길 수 있다.

디버깅

디버깅은 관찰된 실패의 원인을 찾고 수정하며, 수정 결과가 문제를 해결했는지 확인하는 활동이다.

디버깅은 오류가 발생한 코드 줄을 찾는 작업에만 한정되지 않는다. 요구사항의 오해, 설계의 상태 모델, 데이터와 배포 설정, 외부 서비스의 동작이 원인일 수 있다.

일반적인 디버깅 흐름은 다음과 같다.

  1. 문제를 재현하고 관찰 가능한 증상을 기록한다.
  2. 기대 결과와 실제 결과를 구분한다.
  3. 문제가 발생하는 최소 조건과 범위를 줄인다.
  4. 로그와 디버거, 추적과 이력을 이용하여 가설을 만든다.
  5. 가설을 확인할 실험이나 추가 관찰을 수행한다.
  6. 근본 원인을 수정한다.
  7. 기존 문제를 재현하는 시험을 추가한다.
  8. 관련 기능과 품질에 회귀가 없는지 확인한다.
  9. 필요한 경우 설계와 운영 절차를 개선한다.

재현할 수 없는 오류도 시간과 환경, 입력, 버전과 시스템 상태를 충분히 기록하면 원인 범위를 줄일 수 있다. 운영 환경에서 빌드 식별자, 설정, 요청 식별자와 오류 정보를 수집하는 구조가 중요하다.

표면적인 증상만 수정하면 같은 원인이 다른 경로에서 다시 나타날 수 있다. 실패를 가능하게 한 구조와 누락된 검증·시험도 함께 분석한다.

단위 시험과 구현

구현과 단위 시험은 별개의 마지막 단계가 아니라 함께 수행될 수 있다. 단위 시험은 함수와 클래스, 모듈 같은 작은 구성 요소가 계약에 맞게 동작하는지 확인한다.

단위 시험은 다음을 검증할 수 있다.

  • 정상적인 입력과 결과
  • 경계값
  • 잘못된 입력
  • 상태 전이
  • 오류와 예외
  • 자원 정리
  • 중복 호출
  • 알고리즘의 알려진 사례
  • 수정된 결함의 재발 방지

시험은 구현 세부 사항보다 공개 동작과 계약을 중심으로 작성하는 편이 구조 변경에 강하다. 내부 함수와 호출 순서를 지나치게 고정하면 동작은 같아도 리팩터링할 때 많은 시험이 깨질 수 있다.

반대로 공개 인터페이스의 결과만 확인해서 내부의 중요한 안전 조건과 알고리즘 분기를 검증하기 어렵다면 더 작은 단위나 속성 기반 시험을 사용할 수 있다.

코드 검토

코드 검토는 작성자 이외의 개발자가 코드 변경과 관련 자료를 확인하는 활동이다. 설계와 요구사항의 반영 여부, 정확성, 보안, 가독성과 시험을 검토한다.

코드 검토에서는 다음을 확인할 수 있다.

  • 변경 목적과 요구사항이 명확한가
  • 구현이 설계와 인터페이스 계약을 따르는가
  • 정상·오류·경계 조건이 처리되는가
  • 상태와 자원 소유권이 명확한가
  • 동시성 문제가 발생할 수 있는가
  • 보안과 개인정보 요구를 충족하는가
  • 필요한 시험이 포함되어 있는가
  • 불필요한 복잡성과 중복이 있는가
  • 공개 API와 호환성이 바뀌는가
  • 문서와 설정의 변경이 필요한가

검토 가능한 변경은 목적과 범위가 작고 명확한 편이 좋다. 여러 기능과 대규모 형식 변경이 한 변경에 섞이면 실제 동작의 차이를 파악하기 어려워진다.

자동화 도구가 확인할 수 있는 형식과 단순 규칙은 검토 전에 처리한다. 사람의 검토는 설계 의도, 요구사항과 예외 조건처럼 자동화하기 어려운 판단에 집중한다.

검토 의견은 개인의 취향이 아니라 프로젝트 규칙과 요구사항, 실제 위험을 근거로 한다. 중요한 논쟁이 반복된다면 공통 규칙이나 아키텍처 결정으로 정리할 수 있다.

변경 단위와 커밋

버전 관리 시스템에서 커밋은 특정 시점의 변경 집합과 메타데이터를 기록하는 단위이다.

좋은 커밋은 일반적으로 하나의 논리적인 목적을 가진다. 관련된 구현과 시험, 필요한 문서를 함께 포함하되 서로 독립적인 기능과 대규모 형식 변경을 섞지 않는다.

커밋 메시지에는 다음이 포함될 수 있다.

  • 변경한 내용
  • 변경한 이유
  • 해결한 문제 또는 요구사항
  • 이전 동작과 호환성의 변화
  • 추가 검토가 필요한 위험
  • 관련 이슈와 결정

커밋은 단순한 작업 백업이 아니라 변경 이력과 원인을 추적하는 자료가 된다. 문제가 발생했을 때 어느 변경에서 시작되었는지 찾고, 특정 변경을 다른 버전에 적용하거나 되돌리는 데 사용된다.

공유된 이력을 임의로 다시 작성하면 다른 개발자의 작업과 참조가 깨질 수 있다. 개인 작업 영역에서는 정리할 수 있지만 공유 이후의 이력 변경 정책은 팀이 명확히 정해야 한다.

버전 관리

버전 관리는 파일과 프로젝트의 변경 이력을 기록하여 과거 상태를 확인하고 복원하며, 여러 개발자의 변경을 통합할 수 있도록 하는 체계이다.

버전 관리 대상에는 소스 코드뿐 아니라 다음과 같은 자료가 포함될 수 있다.

  • 빌드와 배포 설정
  • 데이터베이스 스키마와 이전 코드
  • 시험 코드와 자료
  • API와 데이터 명세
  • 문서
  • 인프라 정의
  • 생성 규칙
  • 프로젝트 설정

Git의 공식 문서는 버전 관리를 파일 집합의 시간에 따른 변경을 기록하여 이후 특정 버전을 다시 불러올 수 있게 하는 시스템으로 설명한다.[50]

대형 바이너리와 비밀 정보, 빌드로 다시 생성할 수 있는 산출물은 일반 소스 저장소에 적합하지 않을 수 있다. 별도의 아티팩트 저장소와 대형 파일 관리 도구를 사용하고, 소스 이력에는 위치와 버전·무결성 정보를 기록할 수 있다.

중앙 집중식과 분산 버전 관리

중앙 집중식 버전 관리에서는 중앙 서버가 주요 저장소와 이력을 관리하며 사용자는 작업 복사본을 통해 변경한다. 접근 권한과 단일 기준 저장소를 관리하기 쉽지만 서버 연결과 가용성에 의존할 수 있다.

분산 버전 관리에서는 각 개발자가 전체 또는 대부분의 저장소 이력을 가진 로컬 복제본을 사용한다. 로컬에서 커밋과 분기, 이력 조회를 수행한 뒤 원격 저장소와 변경을 교환할 수 있다.

분산 방식에서도 프로젝트는 공식적인 기준 원격 저장소와 통합 정책을 둘 수 있다. 분산이라는 말은 모든 저장소가 같은 권한과 역할을 가져야 한다는 뜻이 아니다.

저장소 구조는 제품과 조직에 따라 하나의 대규모 저장소, 여러 구성 요소별 저장소 또는 이를 결합한 형태를 선택할 수 있다.

분기와 통합

분기는 주 개발선에서 독립된 개발 이력을 만들어 변경을 진행하는 방식이다. Git은 분기를 주 개발선에서 갈라져 기존 개발에 직접 영향을 주지 않고 작업하는 기능으로 설명한다.[51]

분기는 다음과 같은 목적으로 사용할 수 있다.

  • 개별 기능 개발
  • 결함 수정
  • 실험과 프로토타입
  • 장기 지원 버전 유지
  • 릴리스 준비
  • 긴급 수정
  • 제품과 고객별 변형

분기에서 발생한 변경은 병합이나 재배치 등의 방식으로 다른 개발선과 통합된다. 같은 코드를 서로 다르게 수정했다면 충돌을 사람이 해결해야 한다.

분기가 오랫동안 주 개발선과 분리되면 변경 차이가 커지고 통합 위험이 증가한다. 작은 변경을 자주 통합하고 자동화된 빌드와 시험으로 공통 개발선을 검증하면 대규모 통합 문제를 줄일 수 있다.

하나의 분기 전략이 모든 프로젝트에 맞는 것은 아니다. 지속적으로 배포하는 서비스는 짧은 기능 분기와 안정된 주 개발선을 사용할 수 있고, 여러 장기 지원 버전을 제공하는 제품은 릴리스별 유지보수 분기가 필요할 수 있다.

병합과 충돌

병합은 서로 다른 개발 이력의 변경을 하나의 결과로 결합하는 작업이다.

텍스트 수준에서 서로 다른 줄을 수정했다면 자동 병합할 수 있지만, 자동 병합이 성공했다고 프로그램의 의미까지 올바르게 결합된 것은 아니다. 서로 다른 개발자가 같은 자료 구조의 가정이나 인터페이스를 독립적으로 변경했다면 문법적 충돌 없이 논리적 오류가 발생할 수 있다.

병합 후에는 다음을 확인해야 한다.

  • 코드가 빌드되는가
  • 자동화된 시험이 통과하는가
  • 인터페이스와 데이터 구조가 일치하는가
  • 두 변경의 목적이 모두 유지되는가
  • 설정과 문서가 함께 갱신되었는가
  • 새 의존성과 보안 조건이 충돌하지 않는가

충돌이 자주 발생하는 파일은 여러 책임과 변경이 한곳에 모여 있거나 코드 소유와 모듈 경계가 불명확하다는 신호일 수 있다.

주 개발선과 통합 정책

프로젝트는 공식적인 개발의 기준이 되는 주 개발선을 정할 수 있다. 주 개발선은 항상 배포 가능한 상태로 유지하거나, 다음 릴리스를 위한 통합 상태로 사용할 수 있다.

통합 전에 다음 조건을 요구할 수 있다.

  • 코드 검토 승인
  • 빌드 성공
  • 단위 및 통합 시험 통과
  • 정적 분석 통과
  • 보안 및 의존성 검사 통과
  • 필요한 문서와 변경 기록 포함
  • 서명된 커밋 또는 검증된 작성자
  • 특정 담당자나 구성 요소 소유자의 승인

통합 조건이 지나치게 느리고 수동적이면 개발자는 큰 변경을 한꺼번에 제출하거나 검사를 우회할 수 있다. 자동화와 병렬 실행을 활용하여 빠른 피드백과 필요한 품질 통제를 함께 제공한다.

주 개발선에 직접 변경을 허용할지, 검토된 병합 요청만 허용할지는 팀의 규모와 위험에 따라 정한다.

형상 항목

형상 항목(Configuration Item)은 구성 관리의 대상으로 식별하고 독립적으로 버전과 변경 상태를 관리하는 산출물 또는 산출물 집합이다.

형상 항목에는 다음이 포함될 수 있다.

  • 요구사항 명세
  • 아키텍처와 설계 문서
  • 소스 코드
  • 외부 라이브러리
  • 빌드 스크립트와 도구 체인
  • 시험 코드와 시험 자료
  • 데이터베이스 스키마
  • API와 프로토콜 명세
  • 배포 설정
  • 펌웨어와 하드웨어 설정
  • 사용자 및 운영 문서
  • 실행 파일과 패키지
  • 컨테이너 이미지

모든 개별 파일을 같은 수준의 형상 항목으로 관리할 필요는 없다. 변경과 릴리스, 감사에서 독립적으로 식별해야 하는 단위를 프로젝트의 위험과 구조에 맞게 정한다.

각 형상 항목에는 고유 식별자와 버전, 소유자, 상태, 관련 기준선과 저장 위치를 연결할 수 있다.

구성 식별

구성 식별은 관리할 형상 항목과 그 구조, 버전·이름 지정 규칙을 정하는 활동이다.

구성 식별에서는 다음을 정할 수 있다.

  • 어떤 산출물을 관리 대상으로 삼을지
  • 각 항목을 어떤 단위로 나눌지
  • 버전과 변형을 어떻게 식별할지
  • 항목 사이의 관계를 어떻게 기록할지
  • 공식 저장소와 책임자는 누구인지
  • 어떤 상태를 기준선과 릴리스로 지정할지
  • 외부 구성 요소를 어떻게 식별할지

구성 식별이 명확하지 않으면 같은 이름의 파일과 패키지가 서로 다른 내용을 가리키거나, 실행 중인 제품이 어떤 소스와 설정에서 만들어졌는지 알기 어려워진다.

산출물에는 버전 번호뿐 아니라 소스 커밋 식별자, 빌드 번호, 대상 플랫폼과 빌드 설정을 포함한 고유 식별 정보를 부여할 수 있다.

기준선

기준선은 공식적으로 검토하고 합의하여 이후 개발과 변경 관리의 기준으로 사용하는 특정한 구성 상태이다.

기준선에는 다음과 같은 종류가 있을 수 있다.

  • 승인된 요구사항 기준선
  • 아키텍처와 설계 기준선
  • 개발 통합 기준선
  • 시험 기준선
  • 릴리스 기준선
  • 운영 환경 기준선

기준선은 이후의 변경을 금지하지 않는다. 변경 전후의 차이와 승인 상태를 식별하고, 특정 시험과 릴리스가 어떤 구성을 기준으로 수행되었는지 확인할 수 있게 한다.

반복적 개발에서는 기준선이 짧은 주기로 자주 만들어질 수 있다. 각 빌드와 배포를 자동으로 식별 가능한 불변 산출물로 저장하면 모든 성공한 통합 상태가 잠재적인 기준선 역할을 할 수 있다.

변경 통제

변경 통제는 형상 항목의 변경을 제안·평가·승인·구현·검증하고 그 결과를 기록하는 과정이다.

변경 통제에서는 다음을 확인한다.

  • 변경의 목적과 요청자
  • 영향을 받는 형상 항목
  • 요구사항과 설계에 미치는 영향
  • 호환성과 데이터 이전
  • 비용과 일정
  • 보안과 안전 위험
  • 필요한 검토와 승인
  • 구현과 시험 결과
  • 포함할 기준선과 릴리스
  • 되돌리기와 복구 방법

모든 코드 변경을 공식 위원회에서 승인할 필요는 없다. 작은 팀과 낮은 위험의 제품은 코드 검토와 자동화된 검사로 통제할 수 있고, 안전 필수·규제 대상 시스템은 별도의 변경 심의와 독립적인 승인이 필요할 수 있다.

변경 통제의 목적은 변경을 느리게 만드는 데 있지 않다. 누가 무엇을 왜 변경했으며, 어떤 상태가 검증되고 배포되었는지를 알 수 있게 하는 것이다.

구성 상태 기록

구성 상태 기록은 형상 항목과 변경 요청, 기준선, 빌드와 릴리스의 현재 상태와 이력을 수집하고 제공하는 활동이다.

다음과 같은 정보를 기록할 수 있다.

  • 각 형상 항목의 버전과 상태
  • 승인 및 구현된 변경
  • 아직 처리되지 않은 변경 요청
  • 특정 기준선에 포함된 항목
  • 빌드에 사용된 소스와 의존성
  • 시험과 검토 결과
  • 릴리스와 배포 환경
  • 알려진 결함과 제한
  • 담당자와 승인 기록

버전 관리, 이슈 추적, 빌드 시스템과 아티팩트 저장소를 연결하면 상태 정보를 자동으로 수집할 수 있다.

상태 기록이 여러 도구에 흩어져 서로 연결되지 않으면 특정 실행 파일이 어떤 요구사항과 소스, 시험 결과에 해당하는지 추적하기 어렵다. 공통 식별자와 자동 링크를 사용하여 관계를 유지한다.

구성 감사

구성 감사는 제품과 기준선이 정의된 요구사항과 구성 기록에 맞는지 확인하는 활동이다.

감사에서는 다음을 확인할 수 있다.

  • 승인된 변경만 포함되었는가
  • 요구된 형상 항목이 모두 존재하는가
  • 문서와 코드, 시험 결과의 버전이 일치하는가
  • 빌드와 릴리스 절차가 정해진 방식으로 수행되었는가
  • 제품이 승인된 요구사항과 기능을 구현하는가
  • 실제 산출물의 내용이 구성 기록과 일치하는가
  • 외부 구성 요소와 라이선스 정보가 정확한가
  • 서명과 무결성 정보가 유효한가

감사는 제품의 기능을 확인하는 활동과 물리적인 구성의 완전성을 확인하는 활동으로 나눌 수 있다. 프로젝트의 규제와 위험 수준에 따라 독립된 담당자가 수행할 수 있다.

자동화된 파이프라인에서도 정책과 기록이 실제로 일치하는지 정기적으로 검토해야 한다. 자동화 스크립트 자체가 잘못되거나 우회될 수 있기 때문이다.

버전 번호

버전 번호는 소프트웨어의 서로 다른 상태와 호환성, 릴리스 순서를 사용자와 도구에 전달한다.

버전 체계에는 다음 요소가 사용될 수 있다.

  • 주 버전
  • 부 버전
  • 수정 버전
  • 시험판 식별자
  • 빌드 번호
  • 날짜
  • 소스 커밋 식별자
  • 제품과 플랫폼 변형

유의적 버전은 공개 API의 호환성 변화에 따라 주.부.수정 버전을 증가시키는 규칙을 제공한다. 호환되지 않는 API 변경은 주 버전, 하위 호환 기능 추가는 부 버전, 하위 호환 오류 수정은 수정 버전에 반영한다.[52]

모든 소프트웨어가 유의적 버전을 사용해야 하는 것은 아니다. 운영체제와 웹 서비스, 내부 도구는 날짜나 릴리스 열차, 빌드 번호 등 다른 체계를 사용할 수 있다.

중요한 것은 같은 버전이 항상 같은 산출물을 가리키고, 버전 번호의 의미와 지원 정책이 일관되는 것이다.

태그와 릴리스 식별

버전 관리의 태그는 특정 커밋이나 객체에 안정적인 이름을 부여하는 데 사용할 수 있다. Git의 공식 문서는 일반적인 개발 분기와 달리 태그는 프로젝트의 같은 버전을 계속 가리킬 것으로 기대된다고 설명한다.[53]

릴리스 태그에는 다음과 같은 정보를 연결할 수 있다.

  • 제품 버전
  • 릴리스 날짜
  • 변경 기록
  • 빌드와 시험 결과
  • 산출물 위치와 해시
  • 서명
  • 알려진 문제
  • 지원 플랫폼
  • 의존성과 SBOM

이미 공개된 릴리스 태그를 다른 커밋으로 이동하면 같은 버전 이름이 서로 다른 코드를 가리키게 된다. 수정이 필요하다면 새로운 버전과 태그를 만드는 것이 추적성과 캐시, 패키지 관리에 더 적합하다.

빌드 산출물 관리

빌드 결과로 만들어진 실행 파일과 라이브러리, 패키지, 컨테이너 이미지와 디버그 기호는 아티팩트 저장소에 보관할 수 있다.

각 산출물에는 다음 정보를 연결할 수 있다.

  • 제품과 버전
  • 소스 커밋
  • 빌드 번호와 파이프라인
  • 대상 플랫폼과 아키텍처
  • 빌드 구성
  • 사용한 도구와 의존성
  • 생성 시각
  • 암호학적 해시
  • 서명과 출처 증명
  • 시험과 승인 상태
  • 보존 기간

동일한 버전의 산출물을 나중에 다시 빌드하여 기존 파일을 덮어쓰면 내용과 검증 결과가 달라질 수 있다. 배포 가능한 산출물은 불변으로 저장하고 새로운 빌드는 별도의 식별자를 부여한다.

운영 환경에는 소스에서 다시 빌드한 산출물이 아니라 검증된 파이프라인을 통과한 동일한 산출물을 승격하여 배포하는 방식이 사용될 수 있다.

패키징

패키징은 실행 파일과 라이브러리, 자원, 설정 템플릿과 메타데이터를 사용자가 설치하거나 배포할 수 있는 형태로 구성하는 과정이다.

패키지는 다음 내용을 포함하거나 참조할 수 있다.

  • 프로그램 파일
  • 런타임 의존성
  • 기본 설정
  • 서비스 및 권한 정보
  • 설치와 제거 절차
  • 데이터베이스 이전
  • 라이선스와 저작권 정보
  • 버전과 호환성
  • 서명과 무결성 정보
  • 변경 기록
  • 디버그 기호의 위치

플랫폼의 표준 패키지 형식을 사용하면 설치와 업데이트, 의존성 해결과 제거를 운영체제 또는 배포 시스템과 통합할 수 있다.

패키지 설치가 시스템의 기존 파일과 설정을 변경한다면 업데이트와 제거, 실패 시 복구 방식을 명확히 해야 한다.

릴리스 관리

릴리스 관리는 검증된 소프트웨어 버전을 사용자와 운영 환경에 제공하기 위해 범위와 일정, 산출물과 승인 상태를 관리하는 활동이다.

릴리스에서는 다음을 결정한다.

  • 포함할 기능과 수정
  • 대상 사용자와 플랫폼
  • 버전 번호와 지원 기간
  • 빌드 및 시험 기준선
  • 알려진 문제
  • 데이터와 설정의 이전
  • 배포와 되돌리기 절차
  • 사용자 및 운영 문서
  • 보안 수정과 공개 시점
  • 이전 버전과의 호환성
  • 릴리스 이후의 지원 책임

릴리스 후보는 최종 릴리스와 같은 방식으로 빌드하고 가능한 한 같은 산출물을 사용하여 시험하는 편이 좋다. 시험 이후 코드를 다시 빌드하면 도구와 환경 차이로 실제 배포 파일이 달라질 수 있다.

릴리스는 정해진 날짜에 여러 기능을 묶어 제공할 수도 있고, 기능이 준비될 때마다 지속적으로 제공할 수도 있다. 배포 빈도와 별개로 어떤 변경과 산출물이 사용자에게 제공되었는지 식별할 수 있어야 한다.

릴리스 노트와 변경 기록

릴리스 노트는 새 버전이 사용자와 운영자에게 어떤 변화를 가져오는지 설명한다.

다음과 같은 내용이 포함될 수 있다.

  • 새 기능
  • 변경된 동작
  • 수정된 주요 결함
  • 보안 수정
  • 호환되지 않는 변경
  • 폐기 예정 기능
  • 설치와 데이터 이전 절차
  • 알려진 문제와 우회 방법
  • 지원 플랫폼과 요구 환경
  • 이전 버전으로 되돌릴 때의 제한

개발자의 커밋 메시지를 그대로 나열하는 것만으로는 사용자가 변화의 의미를 이해하기 어려울 수 있다. 사용자와 운영자의 관점에서 영향을 설명한다.

자동화된 변경 기록 생성은 누락을 줄일 수 있지만 각 변경에 분류와 사용자 영향 정보를 일관되게 기록해야 한다.

제품 변형과 구성

하나의 코드베이스에서 여러 플랫폼과 고객, 기능 조합의 제품을 만들 수 있다. 이러한 제품 변형은 조건부 컴파일, 빌드 설정, 플러그인, 기능 플래그와 별도 모듈로 구현될 수 있다.

제품 변형 관리에서는 다음을 고려한다.

  • 지원하는 공식 조합
  • 공통 코드와 변형별 코드
  • 기능 사이의 의존성과 충돌
  • 각 변형의 시험 범위
  • 라이선스와 지역별 조건
  • 배포와 업데이트 경로
  • 설정의 기본값과 유효성
  • 더 이상 지원하지 않는 변형의 폐기

가능한 기능 조합이 늘어나면 모든 조합을 시험하기 어렵다. 실제 지원하는 구성과 호환 규칙을 제한하고, 대표 조합과 위험이 큰 상호작용을 자동화된 시험으로 검증한다.

고객별 코드가 주 개발선에서 장기간 분리되면 공통 변경을 통합하기 어려워질 수 있다. 가능한 경우 설정과 확장 인터페이스로 변형을 표현하고, 별도 포크가 필요하다면 변경 교환과 지원 정책을 정한다.

비밀 정보와 구성 데이터

암호 키와 비밀번호, API 토큰과 인증서는 소스 코드와 일반 설정 파일에 포함하지 않아야 한다. 버전 관리 이력에서 삭제하더라도 이전 커밋과 복제본에 남을 수 있다.

비밀 정보 관리에서는 다음을 수행할 수 있다.

  • 전용 비밀 관리 시스템 사용
  • 개발·시험·운영 환경의 자격 증명 분리
  • 최소 권한과 짧은 유효 기간
  • 자동 교체와 폐기
  • 접근 및 사용 기록
  • 저장과 전송 중 암호화
  • 소스 저장소와 빌드 로그의 비밀 검사
  • 유출 시 즉시 무효화할 절차

일반 구성 데이터도 버전과 변경 이력을 관리해야 한다. 운영 환경에서 수동으로만 변경된 설정은 코드와 문서에 기록된 상태와 달라질 수 있다.

환경별 값과 공통 구조를 분리하고, 설정 스키마와 유효성 검사를 제공하며, 실제 배포된 설정의 버전을 추적할 수 있다.

소프트웨어 자재 명세서

소프트웨어 자재 명세서(Software Bill of Materials, SBOM)는 소프트웨어 제품을 구성하는 구성 요소와 관계를 식별하는 구조화된 목록이다.

SBOM에는 다음과 같은 정보가 포함될 수 있다.

  • 구성 요소 이름
  • 버전
  • 공급자와 출처
  • 패키지 식별자
  • 암호학적 해시
  • 라이선스
  • 구성 요소 사이의 의존 관계
  • 알려진 보안 정보와 외부 참조

SBOM은 새 취약점이 공개되었을 때 영향을 받는 제품과 버전을 찾고, 라이선스와 공급망을 관리하는 데 사용할 수 있다.

SPDX는 SBOM을 비롯한 소프트웨어 구성 요소의 출처·라이선스·보안 정보를 교환하기 위한 공개 표준이며 ISO/IEC 5962:2021로 국제 표준화되었다.[54]

SBOM은 목록을 생성하는 것만으로 완성되지 않는다. 실제 릴리스에 포함된 의존성과 일치해야 하며, 빌드마다 자동으로 생성·검증하고 산출물과 함께 보관해야 한다.

빌드 출처와 공급망

소프트웨어 공급망에는 개발자가 작성한 코드뿐 아니라 소스 저장소, 외부 패키지, 빌드 도구, 지속적 통합 실행기, 아티팩트 저장소와 배포 시스템이 포함된다.

공격자가 소스 코드 대신 빌드 시스템이나 배포 계정을 침해하면 검토되지 않은 코드를 정상 릴리스에 포함할 수 있다. 따라서 코드 검토만으로 공급망 전체를 보호할 수 없다.

공급망 관리에서는 다음과 같은 통제를 적용할 수 있다.

  • 소스와 빌드 시스템의 접근 권한 분리
  • 다중 인증과 짧은 수명의 자격 증명
  • 보호된 분기와 승인 규칙
  • 격리된 깨끗한 빌드 환경
  • 빌드 입력과 도구 버전 기록
  • 산출물의 해시와 서명
  • 빌드 출처 증명
  • 의존성의 출처와 무결성 검증
  • 아티팩트 저장소의 불변성
  • 배포 권한과 승인 분리
  • 감사 로그와 이상 행위 탐지

NIST SSDF는 소프트웨어의 모든 형태를 변조와 무단 접근으로부터 보호하고, 릴리스의 무결성을 확인하며, 각 릴리스의 출처 자료를 수집·보호하는 관행을 제시한다.[55]

서명과 무결성

암호학적 해시는 파일과 산출물의 내용이 변경되었는지 확인하는 데 사용할 수 있다. 그러나 해시 목록 자체가 공격자에 의해 바뀔 수 있으므로 신뢰할 수 있는 경로와 디지털 서명을 함께 사용할 수 있다.

서명은 다음 대상에 적용할 수 있다.

  • 소스 커밋과 태그
  • 패키지와 실행 파일
  • 컨테이너 이미지
  • 업데이트 메타데이터
  • SBOM과 출처 증명
  • 설치 프로그램
  • 펌웨어

서명을 검증하려면 서명자의 공개키를 신뢰할 수 있는 방식으로 배포하고, 키의 생성·보관·교체·폐기 절차를 관리해야 한다.

유효한 서명은 산출물이 서명 후 변경되지 않았고 특정 키로 서명되었다는 사실을 보여 준다. 해당 코드가 안전하거나 결함이 없다는 사실까지 보장하지는 않는다.

지속적 통합과 구현 흐름

지속적 통합은 구현과 구성 관리를 자동화된 흐름으로 연결한다.

일반적인 변경 흐름은 다음과 같다.

  1. 개발자가 요구사항이나 결함을 기준으로 코드를 변경한다.
  2. 로컬 빌드와 시험, 정적 분석을 실행한다.
  3. 논리적인 변경 단위로 버전 관리 시스템에 기록한다.
  4. 변경을 공유 저장소에 제출한다.
  5. 자동화된 시스템이 깨끗한 환경에서 빌드와 시험을 수행한다.
  6. 다른 개발자가 코드와 설계, 보안을 검토한다.
  7. 정해진 통합 조건을 통과한 변경을 주 개발선에 병합한다.
  8. 통합된 상태에서 다시 전체 빌드와 시험을 수행한다.
  9. 산출물과 메타데이터를 아티팩트 저장소에 보관한다.
  10. 검증된 산출물을 릴리스와 배포 과정으로 전달한다.

자동화된 파이프라인은 개발자의 로컬 검사보다 더 넓은 플랫폼과 시험을 실행할 수 있다. 그러나 모든 결함을 탐지하지는 못하므로 코드 검토와 설계 평가, 운영 관찰을 함께 사용한다.

파이프라인 설정 자체도 소프트웨어이므로 버전 관리와 코드 검토, 시험의 대상이 된다.

구성 관리 계획

프로젝트는 구성 관리 활동과 책임, 도구와 절차를 구성 관리 계획으로 정리할 수 있다.

계획에는 다음 내용이 포함될 수 있다.

  • 관리할 형상 항목
  • 저장소와 디렉터리 구조
  • 이름과 버전 규칙
  • 분기와 병합 정책
  • 변경 요청과 승인 절차
  • 기준선의 종류와 생성 시점
  • 빌드와 릴리스 절차
  • 구성 상태 기록
  • 감사와 검토
  • 외부 공급자와 구성 요소 관리
  • 백업과 복구
  • 접근 권한
  • 사용 도구와 책임자
  • 보존 기간과 폐기 정책

SWEBOK V4.0의 구성 관리 지식 영역은 조직적 문맥, 제약과 지침, 계획, 조직과 책임, 자원과 일정, 도구 선택, 공급자 통제, 인터페이스 통제와 구성 관리의 감시를 포함한다.[56]

작은 프로젝트에서는 저장소 규칙과 자동화된 파이프라인이 계획의 대부분을 표현할 수 있다. 대규모·규제 대상 프로젝트에서는 공식 문서와 역할, 승인 및 감사 절차가 필요할 수 있다.

공급자와 외부 개발 관리

외부 업체와 오픈소스 프로젝트, 다른 조직이 제공하는 소프트웨어도 전체 제품 구성의 일부이다.

외부 공급자에게 다음 정보를 요구할 수 있다.

  • 제공할 소프트웨어와 버전
  • 소스 또는 바이너리 제공 방식
  • 라이선스와 사용 권한
  • 지원 플랫폼과 인터페이스
  • 보안 개발 관행
  • SBOM과 취약점 정보
  • 빌드와 릴리스 출처
  • 오류 수정과 업데이트 정책
  • 지원 종료 일정
  • 데이터와 시스템의 이전 방법

외부 구성 요소를 도입한 뒤에도 새 버전과 취약점, 라이선스와 지원 상태를 계속 추적해야 한다.

공급자가 제공한 바이너리를 내부 빌드와 같은 저장소에 넣는 경우에도 출처·버전·해시와 승인 상태를 기록하여 임의 파일과 구분한다.

저장소와 산출물의 백업

분산 버전 관리 시스템을 사용하더라도 공식 저장소와 이슈, 코드 검토 기록, 빌드 산출물과 서명 키가 자동으로 안전하게 보존되는 것은 아니다.

백업 대상에는 다음이 포함될 수 있다.

  • 소스 저장소와 전체 이력
  • 이슈와 검토 기록
  • 빌드 및 배포 설정
  • 패키지와 릴리스 산출물
  • SBOM과 출처 증명
  • 문서와 요구사항
  • 데이터베이스 스키마
  • 서명과 키 관리 자료
  • 외부 의존성의 내부 복사본

백업은 생성 여부뿐 아니라 실제 복원 가능성을 시험해야 한다. 저장소와 아티팩트가 손상되거나 서비스 제공자가 중단되었을 때 다른 환경에서 개발과 릴리스를 재개할 수 있는지 확인한다.

비밀키와 민감한 자료는 일반 백업과 다른 보호·복구 절차가 필요할 수 있다.

구성 정보의 장기 보존

소프트웨어를 장기간 지원하려면 현재 소스 코드만 보관해서는 충분하지 않을 수 있다. 과거 버전을 빌드하고 분석하려면 당시의 도구 체인과 외부 의존성, 문서와 환경 정보가 필요하다.

장기 보존 대상에는 다음이 포함될 수 있다.

  • 릴리스별 소스 기준선
  • 컴파일러와 빌드 도구
  • 외부 패키지와 해시
  • 빌드 지침과 환경
  • 데이터 스키마와 이전 코드
  • 디버그 기호
  • 시험 자료와 결과
  • 사용자 및 운영 문서
  • 라이선스와 공급자 정보
  • 서명과 검증 자료

외부 패키지 저장소에서 오래된 버전이 제거되거나 도구가 현재 운영체제에서 실행되지 않을 수 있다. 필요한 구성 요소를 내부 보관소와 가상화된 환경으로 보존할 수 있다.

장기 보존은 모든 중간 빌드를 영구히 저장한다는 뜻은 아니다. 법률과 계약, 제품 수명과 장애 분석 필요성에 따라 보존 등급과 기간을 정한다.

구현과 설계의 일치

구현 과정에서 편의를 위해 모듈 경계를 우회하거나 내부 상태에 직접 접근하는 코드가 추가되면 실제 구조가 설계와 달라질 수 있다.

이를 줄이기 위해 다음 방법을 사용할 수 있다.

  • 언어와 빌드 시스템으로 접근 범위를 제한한다.
  • 모듈 사이의 허용 의존성을 자동 검사한다.
  • 코드 검토에서 아키텍처 영향을 확인한다.
  • 공개 인터페이스와 내부 구현을 구분한다.
  • 임시 예외의 제거 조건을 기록한다.
  • 실제 의존성 그래프를 주기적으로 검토한다.
  • 구조 변경과 함께 설계 문서와 결정 기록을 갱신한다.

설계를 그대로 유지하기 위해 필요한 변경을 억제하는 것도 적절하지 않다. 구현과 운영에서 얻은 정보가 기존 설계의 한계를 보여 준다면 구조를 의도적으로 변경하고 새로운 기준선을 만든다.

구현 중 리팩터링

구현이 진행되면서 코드의 책임과 공통 구조가 더 명확해질 수 있다. 리팩터링은 외부 동작을 유지하면서 내부 구조를 개선한다.

구현 중 수행할 수 있는 리팩터링에는 다음이 있다.

  • 이름과 함수 경계 개선
  • 중복 제거
  • 지나치게 큰 모듈 분리
  • 관련된 상태와 동작 이동
  • 전역 상태 축소
  • 의존성 방향 변경
  • 오류 처리 통합
  • 외부 기술을 어댑터 뒤로 분리
  • 시험하기 어려운 코드의 경계 개선
  • 사용하지 않는 코드와 기능 제거

리팩터링은 별도의 대규모 정리 기간에만 수행하는 작업이 아니다. 기능 변경 과정에서 영향을 받는 영역을 이해하기 쉬운 상태로 개선할 수 있다.

그러나 기능 변경과 광범위한 리팩터링을 하나의 커밋에 섞으면 동작 변화와 구조 변화를 구분하기 어려울 수 있다. 가능한 경우 검증 가능한 단계로 나누어 진행한다.

구현 완료의 기준

코드가 작성되고 개발자의 환경에서 실행된다는 사실만으로 구현이 완료되었다고 보기 어렵다.

프로젝트는 완료 기준에 다음 조건을 포함할 수 있다.

  • 요구사항과 수용 기준을 충족한다.
  • 코드 검토가 완료되었다.
  • 필요한 단위·통합 시험이 존재하고 통과한다.
  • 지원 플랫폼에서 빌드된다.
  • 정적 분석과 보안 검사를 통과한다.
  • 오류와 운영 진단 정보가 포함되어 있다.
  • API와 데이터의 호환성 영향이 검토되었다.
  • 문서와 변경 기록이 갱신되었다.
  • 의존성과 라이선스가 확인되었다.
  • 배포와 되돌리기 방법이 준비되었다.
  • 구성 상태와 산출물을 추적할 수 있다.

완료 기준은 모든 변경에 같은 수준으로 적용할 필요는 없다. 작은 내부 수정과 공개 API 변경, 안전 필수 기능은 서로 다른 검토와 증거를 요구할 수 있다.

중요한 것은 완료를 개인의 판단이나 코드 작성 종료 시점이 아니라 검증 가능한 공통 상태로 정의하는 것이다.

구현과 구성 관리의 지속성

구현과 구성 관리는 개발 초기부터 서비스 종료까지 계속된다. 운영 중 결함을 수정하고 의존성을 갱신하며, 오래된 버전을 지원하거나 긴급 보안 릴리스를 제공할 때도 정확한 구성과 이력이 필요하다.

소프트웨어가 폐기된 이후에도 법률과 계약, 보안 분석을 위해 특정 버전의 소스와 산출물, 의존성과 승인 기록을 보존해야 할 수 있다.

구현은 실행 가능한 코드를 작성하는 활동이지만, 그 코드가 어느 요구사항과 설계에서 나왔으며 어떤 검토와 시험을 거쳐 어떤 산출물로 배포되었는지 확인할 수 있어야 한다.

소프트웨어 구성 관리는 변경을 제한하는 행정 절차가 아니라, 많은 개발자와 도구가 지속적으로 소프트웨어를 변경하는 환경에서 제품의 정체성과 무결성, 재현성과 추적성을 유지하기 위한 공학 활동이다.

소프트웨어 시험과 품질 보증

소프트웨어 시험(Software Testing)은 소프트웨어와 관련 산출물을 실행하거나 분석하여 기대한 동작과 실제 결과의 차이, 결함과 품질상의 위험을 발견하고, 요구사항과 사용 목적을 충족하는지 평가하는 활동이다.

소프트웨어 품질 보증(Software Quality Assurance, SQA)은 소프트웨어 제품과 이를 만드는 프로세스가 정해진 요구사항, 품질 목표, 표준과 절차를 충족하도록 계획·감시·평가하고 개선하는 활동이다. 품질 보증에는 시험뿐 아니라 요구사항과 설계 검토, 프로세스 보증, 정적 분석, 감사, 측정, 결함 관리와 개선 활동이 포함된다.

시험과 품질 보증은 서로 관련되지만 동일하지 않다. 시험은 특정한 소프트웨어와 산출물에서 결함을 발견하고 품질을 평가하는 데 초점을 두며, 품질 보증은 결함이 만들어지고 누락되는 원인을 줄이기 위해 개발 과정과 관리 체계까지 다룬다.

소프트웨어가 일부 시험을 통과했다는 사실만으로 전체 품질이 보장되지는 않는다. 시험하지 않은 입력과 실행 경로가 남아 있을 수 있고, 기능은 정상적으로 동작하지만 성능·보안·사용성·유지보수성 요구를 충족하지 못할 수도 있다. 반대로 결함이 발견되었다고 해서 시험 활동이 실패한 것은 아니다. 결함을 사용자와 운영 환경에 도달하기 전에 발견하고 수정할 수 있게 하는 것이 시험의 중요한 목적이다.

ISO/IEC/IEEE 29119-1:2022는 ISO/IEC/IEEE 29119 소프트웨어 시험 표준군에서 사용하는 일반 개념과 핵심 용어를 정의한다.[57] ISO/IEC/IEEE 29119 표준군은 조직과 생명주기 모델에 관계없이 여러 형태의 소프트웨어 시험에 적용할 수 있는 국제적으로 합의된 시험 표준을 제공한다.[58]

IEEE Computer Society의 SWEBOK는 소프트웨어 시험과 소프트웨어 품질을 별도의 지식 영역으로 다루며, 소프트웨어 품질 영역에는 프로세스 보증, 제품 보증, 정적·동적·형식 분석, 시험, 기술 검토와 감사가 포함된다.[59]

품질의 의미

소프트웨어 품질은 단순히 결함 수가 적다는 뜻이 아니다. 소프트웨어가 명시된 요구사항과 암묵적인 필요를 정해진 사용 조건에서 충족하고, 이해관계자에게 필요한 가치를 제공하는 정도를 포함한다.

품질은 여러 관점에서 평가할 수 있다.

  • 사용자는 원하는 작업을 정확하고 쉽게 수행할 수 있는지를 본다.
  • 운영자는 배포·감시·복구와 장애 대응이 가능한지를 본다.
  • 개발자는 코드를 이해하고 안전하게 변경할 수 있는지를 본다.
  • 조직은 비용과 일정, 사업 목표를 충족하는지를 본다.
  • 보안 담당자는 데이터와 기능이 공격으로부터 보호되는지를 본다.
  • 규제 기관은 안전·법률·표준 요구를 충족하는지를 본다.
  • 외부 시스템의 개발자는 인터페이스와 호환성이 안정적인지를 본다.

하나의 관점에서 높은 품질을 가진 소프트웨어가 다른 관점에서도 반드시 높은 품질을 갖는 것은 아니다. 응답 속도가 빠른 프로그램이라도 데이터가 잘못되면 기능적 품질이 낮고, 기능이 정확하더라도 사용자가 작업을 완료할 수 없을 정도로 인터페이스가 복잡하면 실제 사용 품질이 낮다.

ISO/IEC 25010:2023은 ICT 제품과 소프트웨어 제품의 품질을 명세·측정·평가하기 위한 제품 품질 모델을 정의하며, 아홉 개의 상위 품질 특성과 그 하위 특성으로 구성한다.[60]

품질 목표는 프로젝트마다 다르다. 게임에서는 입력 지연과 그래픽 안정성이 중요할 수 있고, 금융 시스템에서는 데이터 정확성·감사 가능성과 보안이 중요하다. 운영체제에서는 자원 격리와 하드웨어 호환성, 장기간의 안정성이 중요할 수 있으며, 의료 장비에서는 안전성과 검증 가능성이 우선될 수 있다.

따라서 모든 품질 특성을 최대화하려 하기보다 제품의 목적과 위험에 따라 중요한 특성과 허용 기준을 정하고, 이를 요구사항과 시험으로 연결한다.

품질 보증과 품질 통제

품질 보증은 적절한 프로세스와 기준을 정의하고 이를 지키는지 확인하여 품질 문제를 예방하는 활동이다. 품질 통제는 만들어진 산출물과 제품을 검사·시험하고 결함을 발견하여 품질 수준을 확인하는 활동이다.

품질 보증에는 다음과 같은 활동이 포함될 수 있다.

  • 품질 목표와 계획 수립
  • 개발 및 시험 프로세스 정의
  • 표준과 코딩 규칙 수립
  • 요구사항과 설계 검토
  • 프로세스 준수 확인
  • 코드 검토와 정적 분석 정책
  • 구성 관리와 변경 통제 확인
  • 공급자와 외부 구성 요소 평가
  • 결함과 품질 지표 분석
  • 기술 검토와 품질 감사
  • 개선 활동의 계획과 추적

품질 통제에는 다음과 같은 활동이 포함될 수 있다.

  • 정적 분석
  • 코드 검토
  • 단위·통합·시스템 시험
  • 성능과 보안 시험
  • 사용자 수용 시험
  • 산출물과 릴리스 검사
  • 시험 결과와 결함 판정
  • 제품 품질 측정

실제 조직에서는 품질 보증과 통제를 완전히 분리하기 어렵다. 코드 검토는 제품 결함을 발견하는 통제 활동이면서 개발 과정의 일관성을 높이는 보증 활동이기도 하다.

품질 보증의 목적은 문서와 절차를 늘리는 데 있지 않다. 위험이 큰 부분에서 결함을 예방하고, 필요한 검증이 누락되지 않으며, 제품이 어떤 근거로 배포되었는지 설명할 수 있는 체계를 만드는 것이다.

시험의 목적

시험은 프로그램이 정상적으로 작동하는 사례를 보여 주는 것뿐 아니라 결함과 위험을 발견하고 의사결정에 필요한 정보를 제공한다.

시험의 목적에는 다음이 포함될 수 있다.

  • 구현이 요구사항과 설계를 충족하는지 확인한다.
  • 예상한 입력과 예외 상황에서 동작을 평가한다.
  • 기존 기능의 변경으로 발생한 회귀를 발견한다.
  • 품질 속성이 목표 수준을 충족하는지 측정한다.
  • 배포와 운영에 남아 있는 위험을 파악한다.
  • 결함의 재현 조건과 영향 범위를 확인한다.
  • 사용자가 실제 목표를 달성할 수 있는지 평가한다.
  • 릴리스와 인수 여부를 결정할 증거를 제공한다.
  • 설계와 개발 프로세스의 약점을 발견한다.
  • 법률·계약·안전과 보안 요구의 준수 근거를 만든다.

시험의 목적은 모든 결함이 없다는 사실을 증명하는 것과 다르다. 가능한 입력과 상태, 실행 순서가 매우 많은 소프트웨어에서는 모든 경우를 실행해 보는 것이 현실적으로 불가능하다.

시험은 선택한 조건에서 결함이 존재함을 보여 줄 수 있고, 일정 수준의 신뢰를 제공할 수 있다. 그러나 시험에서 결함이 발견되지 않았다는 사실만으로 시험하지 않은 모든 조건에서 결함이 없다고 단정할 수는 없다.

따라서 시험에서는 전체 경우를 무작위로 조금씩 확인하기보다 위험과 사용 빈도, 경계 조건과 과거 결함을 기준으로 중요한 사례를 체계적으로 선택한다.

시험과 디버깅

시험과 디버깅은 서로 연결되지만 목적이 다르다.

시험은 소프트웨어를 평가하여 실패와 품질 문제를 발견하고 기록하는 활동이다. 디버깅은 발견된 실패의 원인을 추적하고 결함을 수정하는 활동이다.

일반적인 흐름은 다음과 같다.

  1. 시험이나 운영 중 기대 결과와 다른 실패를 발견한다.
  2. 실패의 입력과 환경, 실행 절차를 기록한다.
  3. 개발자가 문제를 재현한다.
  4. 로그와 디버거, 코드 이력을 이용하여 원인을 분석한다.
  5. 결함을 수정한다.
  6. 같은 실패를 다시 발생시키는 회귀 시험을 추가한다.
  7. 수정된 버전에서 시험을 다시 실행한다.
  8. 관련 기능에 새로운 문제가 생기지 않았는지 확인한다.

시험 담당자가 발견한 증상과 개발자가 수정할 코드 위치는 같지 않을 수 있다. 화면의 잘못된 메시지가 실제로는 서버의 데이터 처리나 요구사항의 모순에서 발생할 수 있으므로 관찰된 실패와 추정 원인을 구분하여 기록한다.

결함, 오류와 실패

소프트웨어 시험에서는 결함의 원인과 결과를 구분할 필요가 있다.

  • 사람이 요구사항·설계·코드나 설정을 잘못 작성하는 행위를 오류라고 할 수 있다.
  • 그 결과 산출물 안에 들어간 잘못된 부분을 결함 또는 고장 원인으로 볼 수 있다.
  • 결함이 실행되어 시스템이 기대한 서비스를 제공하지 못한 외부 결과를 실패라고 할 수 있다.

코드에 결함이 있어도 해당 경로가 실행되지 않으면 실패가 관찰되지 않을 수 있다. 반대로 사용자가 관찰한 실패의 원인이 소스 코드가 아니라 잘못된 데이터·설정·인프라·외부 서비스일 수도 있다.

시험에서는 관찰된 결과를 정확히 기록하고, 원인 분석 전에는 특정 코드가 결함이라고 단정하지 않는 편이 좋다.

검증과 확인

검증(Verification)은 소프트웨어와 산출물이 정해진 요구사항·설계·계약에 맞게 만들어졌는지를 확인한다. 확인(Validation)은 만들어진 시스템이 실제 사용자와 이해관계자의 필요, 사용 목적을 충족하는지를 평가한다.

검증에서는 다음과 같은 질문을 다룬다.

  • 요구사항이 올바른 형식과 품질로 작성되었는가
  • 설계가 요구사항을 반영하는가
  • 코드가 설계와 인터페이스 계약을 따르는가
  • 구현된 기능이 명세에 정의된 결과를 제공하는가
  • 산출물과 구성 기록이 일치하는가

확인에서는 다음과 같은 질문을 다룬다.

  • 실제 사용자의 문제를 해결하는가
  • 실제 환경에서 사용 가능한가
  • 필요한 업무와 목표를 달성할 수 있는가
  • 사용자의 기대와 운영 절차에 맞는가
  • 정의된 요구사항 자체가 올바른 필요를 표현했는가

명세와 정확히 일치하는 소프트웨어라도 잘못된 문제를 해결한다면 확인에는 실패할 수 있다. 따라서 요구사항 검토와 프로토타입, 사용자 평가와 수용 시험이 필요하다.

검증과 확인은 개발 마지막에 한 번 수행하는 단계가 아니다. 요구사항·설계·구현·배포와 운영 전반에서 반복적으로 수행한다.

정적 시험과 동적 시험

정적 시험은 프로그램을 실행하지 않고 요구사항·설계·소스 코드와 기타 산출물을 분석한다.

정적 시험에는 다음이 포함될 수 있다.

  • 요구사항 검토
  • 설계 검토
  • 코드 검토
  • 정적 코드 분석
  • 형식 검증
  • 문서 검사
  • 인터페이스와 스키마 분석
  • 구성 및 배포 설정 검사

정적 활동은 실행 가능한 프로그램이 완성되기 전에도 수행할 수 있으므로 결함을 조기에 발견할 수 있다. 요구사항의 모순과 설계 누락은 실행 시험만으로 원인을 찾기 어려울 수 있다.

동적 시험은 소프트웨어를 실제로 실행하고 입력·상태·환경에 따른 결과와 품질을 관찰한다.

동적 시험에는 다음이 포함될 수 있다.

  • 기능 시험
  • 단위 및 통합 시험
  • 시스템 시험
  • 성능과 부하 시험
  • 보안 동적 시험
  • 사용자 인터페이스 시험
  • 장애와 복구 시험
  • 호환성 시험
  • 장시간 실행 시험

정적 시험은 실행되지 않는 코드와 구조적 문제를 찾을 수 있고, 동적 시험은 실제 실행 중의 상태와 환경 상호작용을 확인한다. 두 방식은 서로 대체하지 않으며 함께 사용한다.

SWEBOK의 소프트웨어 품질 지식 영역은 정적·동적·형식 분석, 품질 통제와 시험, 기술 검토 및 감사를 함께 다룬다.[61]

시험 수준

시험은 대상과 통합 범위에 따라 여러 수준으로 구분할 수 있다.

일반적으로 다음과 같은 수준이 사용된다.

  • 단위 시험
  • 구성 요소 시험
  • 통합 시험
  • 시스템 시험
  • 수용 시험

각 수준은 서로 다른 종류의 결함을 발견한다. 단위 시험이 통과하더라도 구성 요소 사이의 데이터 형식과 통신, 운영 환경의 설정에서 문제가 발생할 수 있다.

시험 수준은 반드시 시간 순서와 일치하지 않는다. 단위·통합·시스템 시험을 지속적 통합 과정에서 반복 실행할 수 있으며, 시스템 시험을 준비하면서 단위 시험을 함께 보강할 수도 있다.

단위 시험

단위 시험은 함수·클래스·모듈과 같은 비교적 작은 구현 단위를 독립적으로 평가한다.

단위 시험에서는 다음과 같은 내용을 확인할 수 있다.

  • 정상 입력의 결과
  • 경계값
  • 잘못된 입력
  • 상태 전이
  • 오류와 예외
  • 자원 획득과 해제
  • 알고리즘의 알려진 사례
  • 동일 입력에 대한 반복 호출
  • 수정한 결함의 재발 여부

단위 시험은 실행 속도가 빠르고 결함의 위치를 좁히기 쉬우므로 개발자가 코드 변경 직후 자주 실행할 수 있다.

외부 데이터베이스와 네트워크·시간·파일 시스템에 직접 의존하면 단위 시험의 속도와 재현성이 낮아질 수 있다. 인터페이스와 대체 구현, 고정된 시험 데이터를 사용하여 대상의 동작을 제한된 범위에서 확인할 수 있다.

그러나 모든 의존성을 모의 객체로 대체하면 실제 구성 요소와의 계약 불일치를 놓칠 수 있다. 단위 시험과 실제 통합 시험의 역할을 구분해야 한다.

시험이 내부 함수 이름과 호출 순서를 지나치게 고정하면 동작은 같아도 리팩터링 과정에서 많은 시험이 깨질 수 있다. 가능한 경우 단위의 공개 계약과 관찰 가능한 결과를 중심으로 작성한다.

구성 요소 시험

구성 요소 시험은 여러 단위가 결합된 모듈·라이브러리·서비스나 하위 시스템을 하나의 대상으로 평가한다.

구성 요소 시험은 내부 단위의 상호작용과 공개 인터페이스를 확인한다. 외부 의존성은 실제 구현이나 시험용 대체 환경으로 연결할 수 있다.

다음과 같은 문제를 발견할 수 있다.

  • 내부 모듈 사이의 데이터 변환 오류
  • 초기화와 종료 순서
  • 내부 상태와 캐시의 불일치
  • 공개 API의 계약 위반
  • 구성 요소 내부의 동시성 문제
  • 오류가 경계를 넘어 전달되는 방식
  • 외부 의존성 대체와 설정 오류

구성 요소 시험은 단위 시험보다 넓은 범위를 확인하지만 전체 시스템 시험보다 결함의 원인을 좁히기 쉽다.

통합 시험

통합 시험은 둘 이상의 구성 요소와 시스템을 연결하여 인터페이스와 상호작용을 평가한다.

통합 과정에서는 개별 구성 요소가 정상적으로 동작하더라도 다음과 같은 문제가 발생할 수 있다.

  • 데이터 형식과 의미의 불일치
  • API와 프로토콜 버전 차이
  • 호출 순서와 상태 관리 오류
  • 인증과 권한 전달 문제
  • 트랜잭션 경계의 불일치
  • 시간 제한과 재시도 정책 충돌
  • 중복 또는 누락된 메시지
  • 문자 인코딩과 시간대·단위 차이
  • 시작과 종료 순서
  • 오류 코드와 예외 처리의 불일치

통합 시험은 모든 구성 요소를 한 번에 연결하는 방식만을 뜻하지 않는다. 위험과 의존 관계에 따라 점진적으로 통합할 수 있다.

상향식 통합은 하위 구성 요소부터 연결하고, 하향식 통합은 상위 흐름에서 시작해 아직 구현되지 않은 하위 부분을 대체한다. 기능이나 서비스 흐름을 따라 수직적으로 통합할 수도 있다.

외부 결제·메일·지도와 같은 서비스는 시험 전용 환경이나 계약 기반 대체 서버를 사용할 수 있다. 실제 외부 서비스에 대한 제한된 시험도 필요하지만 비용과 속도, 데이터 보호와 실패 재현 가능성을 고려해야 한다.

계약 시험

계약 시험은 구성 요소나 서비스 사이의 인터페이스 계약이 제공자와 소비자 양쪽에서 유지되는지 확인한다.

계약에는 다음과 같은 내용이 포함될 수 있다.

  • 요청과 응답 스키마
  • 필수 및 선택 필드
  • 상태 코드와 오류 형식
  • 이벤트와 메시지 구조
  • 인증 방식
  • 호출 순서
  • 버전 호환성
  • 시간 제한과 재시도 조건

분산 시스템에서는 모든 서비스를 함께 실행하는 대규모 통합 시험만으로 인터페이스 호환성을 확인하면 피드백이 느려질 수 있다. 계약을 기계가 읽을 수 있는 형태로 정의하고 각 서비스의 빌드 과정에서 확인할 수 있다.

계약 시험이 통과해도 실제 네트워크·인증·배포 환경에서의 통합 문제가 남을 수 있으므로 전체 통합 시험을 완전히 대체하지 않는다.

시스템 시험

시스템 시험은 완전히 통합된 소프트웨어 시스템을 전체 요구사항과 실제에 가까운 환경에서 평가한다.

시스템 시험에서는 다음을 확인할 수 있다.

  • 주요 사용자 흐름
  • 기능 요구사항
  • 전체 데이터 흐름
  • 외부 시스템과의 통합
  • 권한과 보안 경계
  • 성능과 용량
  • 장애 및 복구
  • 설치·업데이트와 제거
  • 운영 로그와 모니터링
  • 지원 플랫폼과 장치
  • 데이터 이전과 호환성

시스템 시험 환경은 운영 환경과 가능한 한 유사해야 하지만, 개인정보·비용·안전과 외부 시스템 제약 때문에 완전히 같게 만들기 어려울 수 있다.

운영 환경과 시험 환경의 차이는 명시적으로 관리하고, 시험할 수 없는 조건은 운영 단계의 점진적 배포와 감시·복구 절차로 보완한다.

수용 시험

수용 시험은 소프트웨어가 사용자·고객과 발주자의 요구와 수용 기준을 충족하며 실제 사용이나 인도가 가능한지를 평가한다.

수용 시험에는 다음과 같은 형태가 있을 수 있다.

  • 사용자 수용 시험
  • 고객 또는 발주자 인수 시험
  • 운영 수용 시험
  • 계약상 수용 시험
  • 규제 및 인증 시험
  • 알파·베타 시험
  • 제한된 실제 사용자 대상 시범 운영

수용 시험은 개발자가 정의한 기능 시험을 반복하는 데 그치지 않는다. 실제 업무 절차와 데이터, 사용자 역할, 운영·지원과 이전 과정을 포함해야 한다.

수용 기준은 요구사항 단계에서 가능한 한 미리 정의한다. 개발이 끝난 뒤 기준을 처음 협의하면 이해관계자마다 완료의 의미를 다르게 해석할 수 있다.

수용 시험 통과는 모든 결함이 없다는 뜻이 아니라, 합의된 기준과 알려진 위험을 바탕으로 시스템을 사용할 수 있다고 판단했다는 의미이다.

회귀 시험

회귀 시험은 변경으로 인해 이전에 정상적으로 동작하던 기능이 손상되지 않았는지 확인한다.

회귀는 다음과 같은 변경에서 발생할 수 있다.

  • 결함 수정
  • 새 기능 추가
  • 리팩터링
  • 성능 최적화
  • 외부 라이브러리 갱신
  • 운영체제와 컴파일러 변경
  • 데이터베이스 스키마 변경
  • 배포와 설정 변경
  • 보안 패치

수정된 결함에는 가능하면 같은 문제가 다시 발생하는지를 확인하는 시험을 추가한다. 이를 통해 동일한 실패가 이후 변경에서 재발하는 것을 탐지할 수 있다.

전체 회귀 시험이 너무 오래 걸리면 개발자는 실행을 미루거나 결과를 무시할 수 있다. 시험을 수준과 위험에 따라 분류하고, 빠른 시험은 모든 변경에서 실행하며, 무거운 시험은 통합·릴리스·정기 실행으로 나눌 수 있다.

변경된 코드와 의존성, 관련 요구사항을 이용해 영향받을 가능성이 높은 시험을 우선 선택할 수도 있다. 다만 영향 분석이 완전하지 않을 수 있으므로 정기적으로 전체 시험을 실행한다.

스모크 시험과 건전성 시험

스모크 시험은 새 빌드와 배포가 더 깊은 시험을 수행할 수 있을 정도로 기본 기능과 환경을 갖추었는지 빠르게 확인한다.

다음과 같은 항목을 확인할 수 있다.

  • 프로그램이 시작되는가
  • 필수 서비스와 데이터베이스에 연결되는가
  • 사용자가 인증할 수 있는가
  • 핵심 요청이 기본 결과를 반환하는가
  • 치명적인 설정 오류가 없는가
  • 배포된 버전과 상태 정보를 확인할 수 있는가

스모크 시험에 실패한 빌드에서 긴 시스템 시험을 계속 실행하는 것은 효율적이지 않을 수 있다.

건전성 시험은 특정 수정이나 제한된 변경이 의도한 부분에서 정상적으로 동작하는지를 빠르게 확인하는 의미로 사용되기도 한다. 두 용어의 범위는 조직마다 다를 수 있으므로 프로젝트 안에서 의미를 명확히 정의한다.

탐색적 시험

탐색적 시험은 시험자가 제품을 학습하고 시험을 설계하며 실행하는 활동을 긴밀하게 연결하는 방식이다.

미리 작성된 시험 절차만 반복하는 대신 시험 중 발견한 동작과 위험에 따라 새로운 질문과 경로를 탐색한다.

탐색적 시험은 다음과 같은 문제를 발견하는 데 유용할 수 있다.

  • 명세에 없는 예외적인 사용자 행동
  • 기능 사이의 예상하지 못한 상호작용
  • 사용성 문제
  • 오류 메시지와 복구 흐름의 문제
  • 자동화된 시험이 고정한 범위 밖의 결함
  • 실제 데이터와 복잡한 상태 조합
  • 요구사항의 모호성과 누락

탐색적 시험은 무계획한 임의 조작과 같지 않다. 시험 목표·범위·시간을 정하고 관찰 결과와 발견한 결함, 추가 질문을 기록할 수 있다.

반복 가능한 검증이 필요한 핵심 사례는 이후 자동화된 시험이나 정식 시험 절차로 전환한다.

확인 시험

결함을 수정한 뒤 동일한 실패가 해결되었는지 확인하는 시험을 확인 시험 또는 재시험이라고 할 수 있다.

확인 시험은 해당 결함의 재현 절차와 기대 결과를 중심으로 한다. 회귀 시험은 수정이 다른 기능에 미친 영향을 더 넓게 확인한다.

두 활동은 함께 수행되는 경우가 많지만 목적이 다르다.

  • 확인 시험은 보고된 결함이 실제로 수정되었는지를 확인한다.
  • 회귀 시험은 수정으로 다른 동작이 손상되지 않았는지를 확인한다.

블랙박스 시험

블랙박스 시험은 내부 코드 구조보다 요구사항·인터페이스·입력과 출력에 따라 시험 사례를 설계한다.

대표적인 설계 기법에는 다음이 있다.

  • 동등 분할
  • 경계값 분석
  • 결정표 시험
  • 상태 전이 시험
  • 유스 케이스와 시나리오 기반 시험
  • 조합 시험
  • 원인-결과 분석
  • 오류 추정

동등 분할에서는 비슷한 동작을 할 것으로 예상되는 입력 영역을 여러 집합으로 나누고 대표 값을 선택한다.

경계값 분석에서는 허용 범위의 최소·최대와 그 바로 안팎을 시험한다. 많은 결함이 비교 연산과 배열 크기, 날짜와 수량의 경계에서 나타난다.

결정표는 여러 조건의 조합에 따라 다른 결과가 발생하는 업무 규칙을 표로 표현한다. 상태 전이 시험은 현재 상태와 사건에 따른 다음 상태와 동작을 확인한다.

블랙박스 시험은 구현이 바뀌어도 외부 계약이 유지되면 재사용하기 쉽지만, 내부에서 실행되지 않은 경로와 숨겨진 상태를 직접 확인하기 어렵다.

ISO/IEC/IEEE 29119-4는 시험 설계와 구현 과정에서 사용할 수 있는 시험 설계 기법을 정의한다.[62]

화이트박스 시험

화이트박스 시험은 소스 코드와 제어 흐름, 자료 흐름과 내부 구조를 바탕으로 시험 사례를 설계한다.

확인할 수 있는 구조에는 다음이 있다.

  • 문장과 분기
  • 조건의 참·거짓 조합
  • 반복문의 0회·1회·여러 회 실행
  • 함수와 호출 관계
  • 정의된 값과 사용되는 위치
  • 예외와 오류 경로
  • 동시성 및 잠금 경로

화이트박스 시험은 내부에서 실행되지 않은 부분과 복잡한 제어 흐름을 찾을 수 있다. 그러나 코드에 구현되지 않은 요구사항은 내부 구조를 아무리 많이 시험해도 발견하기 어려울 수 있다.

따라서 요구사항 기반의 블랙박스 시험과 구조 기반의 화이트박스 시험을 함께 사용한다.

코드 커버리지

코드 커버리지는 시험 실행 중 소스 코드의 특정 구조가 얼마나 실행되었는지를 측정한다.

대표적인 지표에는 다음이 있다.

  • 문장 커버리지
  • 분기 커버리지
  • 조건 커버리지
  • 함수 커버리지
  • 경로 커버리지

커버리지는 시험하지 않은 코드를 찾는 데 유용하다. 새 코드가 한 번도 실행되지 않았다면 시험 범위가 부족할 가능성이 있다.

그러나 높은 커버리지가 높은 시험 품질을 보장하지는 않는다. 코드를 실행했지만 결과를 검증하지 않았거나, 잘못된 기대값을 사용했거나, 중요한 입력 조합이 빠져 있을 수 있다.

모든 실행 경로를 시험하는 경로 커버리지는 분기와 반복이 증가할수록 현실적으로 달성하기 어렵다. 따라서 위험과 복잡성을 기준으로 적절한 커버리지 목표를 정한다.

커버리지 수치를 팀이나 개인의 단순 성과 지표로 사용하면 의미 없는 시험이 늘어날 수 있다. 커버리지는 누락된 시험과 위험을 찾는 보조 정보로 사용한다.

변이 시험

변이 시험은 프로그램의 연산자·조건·상수 등을 의도적으로 조금 변경한 여러 변이체를 만들고, 기존 시험이 이러한 잘못된 변경을 탐지하는지 확인한다.

시험이 변이된 프로그램에서도 모두 통과한다면 해당 동작을 충분히 검증하지 못했을 가능성이 있다.

변이 시험은 코드 커버리지만으로 알기 어려운 시험의 판별 능력을 평가할 수 있다. 그러나 많은 변이체를 빌드하고 시험해야 하므로 실행 비용이 크다.

실제 동작과 동일한 변이체가 생성되거나 중요하지 않은 변경이 포함될 수 있으므로 결과를 해석하고 대상 범위를 선택해야 한다.

속성 기반 시험

속성 기반 시험은 개별 입력과 예상 결과를 하나씩 작성하기보다 다양한 입력에서 항상 유지되어야 하는 성질을 정의하고 많은 입력을 자동 생성하여 확인한다.

예를 들어 다음과 같은 속성을 정의할 수 있다.

  • 정렬 결과는 원래 입력과 같은 원소를 포함한다.
  • 정렬 결과는 비감소 순서이다.
  • 직렬화한 뒤 다시 역직렬화하면 원래 값과 동일하다.
  • 암호화한 값을 올바른 키로 복호화하면 원문이 복원된다.
  • 같은 요청을 여러 번 실행해도 멱등한 연산의 최종 상태는 같다.

실패가 발견되면 도구는 문제를 일으키는 입력을 더 작은 사례로 축소할 수 있다.

속성 기반 시험은 사람이 예상하지 못한 경계 조합을 발견할 수 있지만, 올바른 속성을 정의하지 못하면 잘못된 구현과 시험이 같은 가정을 공유할 수 있다.

퍼징

퍼징은 프로그램 인터페이스에 많은 수의 비정상적이거나 변형된 입력을 자동으로 제공하여 충돌·무한 반복·메모리 오류와 잘못된 상태를 찾는 시험 방법이다.

퍼징은 다음과 같은 대상에 사용할 수 있다.

  • 파일 파서
  • 네트워크 프로토콜
  • 이미지·영상과 문서 형식
  • 컴파일러와 인터프리터
  • API와 명령행
  • 직렬화와 역직렬화
  • 시스템 호출 경계

퍼저는 완전히 임의의 입력을 만들거나 기존 유효 입력을 변형하고, 코드 커버리지 같은 실행 정보를 이용하여 새로운 경로를 탐색할 수 있다.

퍼징에서 발견된 충돌은 입력·빌드·환경과 함께 보존하고, 수정 뒤 회귀 시험으로 추가한다.

프로그램이 충돌하지 않았다는 사실만으로 결과가 논리적으로 올바르다는 뜻은 아니다. 필요한 경우 출력의 의미와 불변 조건을 검사하는 오라클을 함께 제공한다.

NIST의 개발자 검증 지침은 코드 기반 분석·검토와 동적 시험을 함께 다루며 퍼징을 포함한 검증 기법을 설명한다.[63]

성능 시험

성능 시험은 소프트웨어가 정해진 작업 부하와 환경에서 응답 시간·처리량·자원 사용과 확장성 목표를 충족하는지 평가한다.

성능 시험에는 다음과 같은 형태가 있다.

  • 부하 시험
  • 스트레스 시험
  • 용량 시험
  • 확장성 시험
  • 장시간 실행 시험
  • 급격한 부하 증가 시험
  • 지연과 처리량 측정
  • 자원 사용 및 병목 분석

부하 시험은 예상되는 정상 또는 최대 작업량에서 동작을 평가한다. 스트레스 시험은 설계 한계를 넘는 조건에서 시스템이 어떻게 저하되고 복구되는지 확인한다.

성능 시험에서는 평균값만 보지 않고 백분위 지연과 최악 조건, 오류율과 자원 사용을 함께 확인할 수 있다. 일부 매우 느린 요청은 평균 응답 시간에 드러나지 않을 수 있다.

실제 사용자 행동과 다른 단순 요청만 반복하면 시험 결과가 운영 성능을 대표하지 못한다. 읽기·쓰기 비율, 데이터 크기, 캐시 상태와 동시 사용자의 작업 흐름을 실제에 가깝게 모델링한다.

시험 환경의 하드웨어·네트워크·데이터와 설정도 결과에 큰 영향을 주므로 함께 기록한다.

부하와 용량 시험

용량 시험은 시스템이 품질 기준을 유지하면서 지원할 수 있는 데이터량·사용자 수·요청 수와 자원 한도를 확인한다.

다음과 같은 기준을 찾을 수 있다.

  • 동시에 지원 가능한 사용자 수
  • 초당 처리 가능한 요청
  • 데이터베이스 크기에 따른 검색 성능
  • 대기열과 연결 풀의 한도
  • 메모리와 저장 공간 사용
  • 자동 확장이 시작되는 시점
  • 추가 자원에 따른 성능 증가
  • 병목이 이동하는 지점

용량 시험 결과는 운영 환경의 자원 계획과 경고 기준, 자동 확장 정책에 반영한다.

한계에 도달했을 때 무작위 오류와 데이터 손상이 발생하기보다 요청 제한과 명확한 실패, 점진적인 성능 저하가 나타나는지도 확인한다.

장시간 실행 시험

장시간 실행 시험은 시스템을 오랜 기간 동작시켜 짧은 기능 시험에서 나타나지 않는 누적 문제를 찾는다.

발견할 수 있는 문제에는 다음이 있다.

  • 메모리와 자원 누수
  • 파일과 로그의 무제한 증가
  • 캐시와 연결 풀의 고갈
  • 타이머와 작업의 누적
  • 장기 실행 후의 성능 저하
  • 날짜와 시간 경계
  • 인증서와 토큰 만료
  • 주기 작업의 충돌
  • 데이터 정리와 보존 정책의 실패

시험 기간을 실제 운영 기간만큼 길게 만들기 어렵다면 시간을 가속하거나 만료 시점을 조정하고, 자원 사용 추세를 분석할 수 있다.

신뢰성과 가용성 시험

신뢰성과 가용성 시험은 소프트웨어가 오류와 장애 조건에서도 요구된 서비스를 유지하거나 정해진 시간 안에 복구하는지 평가한다.

시험할 수 있는 상황에는 다음이 있다.

  • 프로세스와 서버 종료
  • 네트워크 단절과 지연
  • 데이터베이스 연결 실패
  • 저장 공간 부족
  • 외부 서비스의 느린 응답과 오류
  • 복제본 손실
  • 메시지 중복과 순서 변경
  • 잘못된 설정 배포
  • 일부 지역과 데이터 센터 장애

평가할 수 있는 결과에는 다음이 있다.

  • 장애 감지 시간
  • 자동 복구 시간
  • 허용되는 데이터 손실
  • 서비스 중단 시간
  • 저하된 상태에서 유지되는 기능
  • 재시도와 중복 처리
  • 경고와 운영자 통보
  • 복구 이후 데이터 일관성

장애 복구 절차가 문서에 존재하더라도 실제로 반복 시험하지 않으면 필요한 권한·도구와 데이터가 부족할 수 있다.

장애 주입과 혼돈 시험

장애 주입은 시스템에 의도적으로 오류와 장애를 발생시켜 감지·격리·복구 동작을 평가하는 방법이다.

혼돈 시험 또는 혼돈 공학은 분산 시스템의 실제 운영과 유사한 환경에서 구성 요소 장애와 네트워크 문제 등을 주입하고, 시스템이 중요한 정상 상태를 유지하는지 실험하는 접근이다.

장애 주입은 다음 대상에 적용할 수 있다.

  • 함수와 API의 오류 반환
  • 디스크와 메모리 부족
  • 네트워크 지연·손실과 분할
  • 프로세스와 컨테이너 종료
  • 외부 서비스 장애
  • 시간과 시계의 변화
  • 메시지 중복과 재정렬
  • 잘못된 구성과 인증서 만료

운영 환경에서 수행하는 실험은 사용자 피해를 제한할 안전장치가 필요하다. 대상 범위·중단 조건·감시와 복구 절차를 정하고 작은 범위부터 수행한다.

보안 시험

보안 시험은 소프트웨어가 보안 요구를 충족하고 공격과 오용에 적절히 대응하는지 평가한다.

보안 시험에는 다음이 포함될 수 있다.

  • 인증과 세션 관리 시험
  • 권한 및 접근 통제 시험
  • 입력 검증
  • 암호화와 키 관리 확인
  • 정적 애플리케이션 보안 분석
  • 동적 애플리케이션 보안 시험
  • 의존성 및 취약점 검사
  • 퍼징
  • 침투 시험
  • 비밀 정보와 설정 검사
  • 보안 로그와 탐지 확인
  • 공급망과 산출물 무결성 검증

기능 시험에서 정상적인 인증 흐름만 확인하면 권한 우회와 다른 사용자의 데이터 접근, 만료된 토큰과 중복 요청 같은 문제를 놓칠 수 있다.

보안 시험은 공격 도구를 한 번 실행하는 것으로 끝나지 않는다. 위협 모델과 보안 요구사항을 기준으로 공격 경로와 보호 수단, 탐지와 복구까지 평가한다.

NIST SSDF는 이전에 발견되지 않은 취약점을 식별하기 위해 사람이 읽을 수 있는 코드를 검토·분석하고 실행 가능한 코드를 시험하는 관행을 소프트웨어 생명주기에 통합하도록 제시한다.[64]

안전성 시험

안전 필수 시스템에서는 소프트웨어의 실패가 사람·장비·환경에 피해를 일으키지 않는지를 평가해야 한다.

안전성 시험은 위험 분석과 안전 요구사항을 기준으로 설계한다.

다음과 같은 상황을 확인할 수 있다.

  • 센서 값의 오류와 불일치
  • 통신 단절
  • 제어 명령의 지연과 손실
  • 자원 부족
  • 구성 요소의 예상하지 못한 종료
  • 허용 범위를 벗어난 입력
  • 전원 중단과 재시작
  • 잘못된 상태 전이
  • 중복되고 충돌하는 명령
  • 감시 장치와 비상 정지

시험에서는 위험한 조건에서 시스템이 안전한 상태로 이동하는지, 경고와 수동 개입이 가능한지, 안전 기능 자체의 결함을 감지할 수 있는지를 확인한다.

실제 장비에서 위험한 상황을 모두 시험하기 어려우면 시뮬레이터와 하드웨어 인더루프 환경, 형식 분석을 함께 사용할 수 있다.

사용성 시험

사용성 시험은 대표 사용자가 실제 또는 유사한 환경에서 시스템을 사용하여 목표를 효과적이고 효율적으로 달성할 수 있는지 평가한다.

측정할 수 있는 요소에는 다음이 있다.

  • 작업 성공률
  • 작업 완료 시간
  • 오류와 되돌리기 횟수
  • 도움 요청과 학습 시간
  • 사용자의 이해와 만족도
  • 중요한 정보의 발견 가능성
  • 오류 메시지와 복구 가능성
  • 반복 작업의 피로와 효율성

개발자와 숙련 사용자는 시스템의 개념과 위치를 이미 알고 있으므로 초보 사용자의 문제를 놓칠 수 있다. 실제 대상 사용자와 환경을 대표하는 참여자가 필요하다.

사용성 시험은 인터페이스의 시각적 선호만을 평가하는 활동이 아니다. 작업 흐름과 정보 구조, 오류 예방과 복구를 포함한다.

접근성 시험

접근성 시험은 장애와 다양한 사용 조건을 가진 사용자가 소프트웨어의 기능과 정보를 이용할 수 있는지 평가한다.

시험 대상에는 다음이 포함될 수 있다.

  • 키보드만을 사용한 조작
  • 화면 읽기 프로그램
  • 초점 이동과 순서
  • 이름·역할·상태의 접근성 정보
  • 색상과 명암 대비
  • 확대와 글자 크기
  • 자막과 대체 텍스트
  • 시간 제한과 동작 효과
  • 음성 입력과 스위치 장치
  • 오류 식별과 수정 안내

자동화 도구는 누락된 이름과 대비 같은 일부 문제를 찾을 수 있지만 실제 보조 기술과 사용자의 작업 흐름을 모두 평가하지는 못한다.

접근성은 개발 마지막에 별도로 수정하기보다 사용자 인터페이스 구성 요소와 디자인 시스템, 완료 기준에 포함하여 지속적으로 시험한다.

호환성 시험

호환성 시험은 소프트웨어가 지원하기로 한 운영체제·하드웨어·브라우저·장치·네트워크와 다른 소프트웨어 버전에서 올바르게 동작하는지 평가한다.

시험할 수 있는 조합에는 다음이 있다.

  • 운영체제와 버전
  • CPU와 명령어 집합
  • 화면 크기와 입력 장치
  • 그래픽 드라이버
  • 브라우저와 웹 엔진
  • 데이터베이스와 외부 서비스
  • 언어와 지역 설정
  • 파일 및 프로토콜 버전
  • 이전 및 새 클라이언트와 서버
  • 설치와 업데이트 경로

가능한 모든 조합을 시험하기 어렵기 때문에 공식 지원 범위와 사용 비율, 위험을 기준으로 시험 행렬을 만든다.

가상 머신과 컨테이너, 장치 팜과 클라우드 환경을 사용하여 여러 조합을 자동화할 수 있지만 실제 하드웨어와 드라이버에서만 나타나는 문제도 남을 수 있다.

이식성 시험

이식성 시험은 소프트웨어를 다른 환경으로 옮기거나 설치할 때 필요한 변경과 동작을 평가한다.

다음과 같은 문제를 확인할 수 있다.

  • 운영체제별 파일 경로와 권한
  • 바이트 순서와 자료형 크기
  • 문자 인코딩과 지역 설정
  • 시스템 호출과 라이브러리 차이
  • 빌드 도구와 컴파일러
  • 설치와 제거
  • 설정과 데이터 이전
  • 성능과 자원 사용
  • 플랫폼별 기능의 저하

공통 코드가 빌드된다는 사실만으로 해당 플랫폼을 지원한다고 보기 어렵다. 설치·사용·업데이트·오류 처리와 운영 진단까지 확인해야 한다.

설치와 업데이트 시험

설치·업데이트·제거 과정도 소프트웨어 제품의 일부이다.

다음과 같은 상황을 시험할 수 있다.

  • 새 설치
  • 이전 버전에서의 업데이트
  • 여러 단계의 장기 버전 업그레이드
  • 설치 중 중단과 재시도
  • 저장 공간 부족
  • 권한 부족
  • 설정과 사용자 데이터 보존
  • 데이터베이스 스키마 이전
  • 이전 버전으로 되돌리기
  • 제거 후 남는 파일과 서비스
  • 자동 업데이트와 서명 검증

업데이트가 프로그램 파일만 교체하고 데이터 형식은 변경하지 않는다고 가정하면 실제 사용자 데이터가 손상될 수 있다.

이전 도구와 스키마 변경은 실제에 가까운 대규모 데이터와 오래된 버전의 복사본을 사용하여 시험한다.

복구 시험

복구 시험은 장애·잘못된 배포·데이터 손상 이후 시스템과 데이터를 정상 상태로 복원할 수 있는지 확인한다.

시험 대상에는 다음이 포함될 수 있다.

  • 백업에서 데이터 복원
  • 데이터베이스 시점 복구
  • 이전 버전으로 롤백
  • 새 환경에서 서비스 재구성
  • 손상된 노드의 교체
  • 계정과 비밀 정보 복구
  • 재해 복구 지역으로의 전환
  • 서비스 의존성의 재연결
  • 복구 이후 데이터 일관성 확인

백업 파일이 존재한다는 사실과 실제로 시스템을 복원할 수 있다는 사실은 다르다. 백업의 무결성, 필요한 도구와 키, 복원 시간과 운영 절차를 함께 시험한다.

데이터 시험

데이터 중심 시스템에서는 코드와 함께 데이터의 품질과 처리 결과를 시험해야 한다.

확인할 수 있는 내용에는 다음이 있다.

  • 필수 값과 범위
  • 고유성과 참조 무결성
  • 중복과 누락
  • 날짜·시간과 단위
  • 데이터 변환
  • 스키마 변경과 이전
  • 집계와 계산 결과
  • 데이터 보존과 삭제
  • 개인정보 마스킹
  • 대량 데이터 처리
  • 손상된 데이터에 대한 대응

시험 데이터는 정상 사례뿐 아니라 경계값·오래된 형식·누락·중복과 손상된 사례를 포함해야 한다.

운영 데이터를 시험 환경에 복사할 때는 개인정보와 비밀 정보를 제거하거나 합성 데이터로 대체해야 한다.

인공지능 기반 소프트웨어의 시험

기계학습과 인공지능 기반 시스템은 소스 코드뿐 아니라 데이터와 모델이 동작을 결정한다.

시험 대상에는 다음이 포함될 수 있다.

  • 학습·검증·시험 데이터의 분리
  • 데이터 품질과 대표성
  • 모델의 정확도와 오류 유형
  • 특정 집단과 조건에서의 성능 차이
  • 입력 변화에 대한 견고성
  • 재현성과 모델 버전
  • 운영 데이터 분포의 변화
  • 설명 가능성과 사용자 개입
  • 안전하지 않은 출력과 오용
  • 모델과 일반 소프트웨어 구성 요소의 통합

평균 정확도 하나만으로 실제 품질을 판단하기 어렵다. 중요한 오류의 비용과 사용자 집단·환경별 성능, 거짓 양성과 거짓 음성을 함께 분석한다.

확률적인 모델은 같은 종류의 입력에서도 일정하지 않은 결과를 생성할 수 있으므로 허용 범위와 통계적 기준, 반복 평가 방법을 정의해야 한다.

ISO/IEC TR 29119-11:2020은 복잡하고 대규모 데이터에 기반할 수 있는 AI 기반 시스템의 시험을 소개한다.[65]

시험 환경

시험 결과를 신뢰하려면 시험 환경을 식별하고 통제해야 한다.

시험 환경에는 다음이 포함될 수 있다.

  • 운영체제와 하드웨어
  • 프로그램과 의존성 버전
  • 데이터베이스와 스키마
  • 설정과 기능 플래그
  • 네트워크 조건
  • 시간과 지역 설정
  • 외부 서비스와 대체 서버
  • 시험 계정과 권한
  • 데이터와 초기 상태
  • 빌드 및 배포 방식

같은 시험이 개발자 컴퓨터에서는 통과하고 지속적 통합이나 운영 환경에서는 실패할 수 있다. 환경의 차이를 줄이고 필요한 구성을 코드와 자동화된 설정으로 관리한다.

시험 실패 시 사용한 빌드·설정·데이터와 환경 정보를 함께 기록하면 재현하기 쉽다.

시험 환경을 여러 시험이 공유하면 상태와 데이터가 서로 영향을 줄 수 있다. 시험마다 초기 상태를 격리하거나 실행 전후에 환경을 복원해야 한다.

시험 데이터

시험 데이터는 시험하려는 조건과 위험을 표현한다.

다음과 같은 종류를 사용할 수 있다.

  • 일반적인 정상 데이터
  • 최소·최대와 경계값
  • 빈 값과 누락 값
  • 잘못된 형식
  • 중복과 충돌 데이터
  • 매우 큰 데이터
  • 이전 버전의 데이터
  • 손상된 파일과 메시지
  • 다양한 언어와 문자
  • 시간대와 날짜 경계
  • 권한과 사용자 역할별 데이터

시험 데이터는 반복 실행에서 같은 결과를 얻을 수 있도록 버전과 생성 방법을 관리한다.

운영 데이터를 사용하는 경우 개인정보·기밀·계약 조건을 준수해야 한다. 단순히 이름만 바꾸어도 다른 필드 조합으로 개인을 다시 식별할 수 있으므로 익명화와 합성 데이터 정책이 필요하다.

시험 오라클

시험 오라클은 특정 입력과 상황에서 올바른 결과가 무엇인지 판단하는 기준이다.

오라클에는 다음이 사용될 수 있다.

  • 요구사항과 수용 기준
  • 알려진 정답
  • 이전의 검증된 구현
  • 수학적 성질과 불변 조건
  • 다른 독립적인 구현과 비교
  • 사용자와 전문가의 판단
  • 통계적 범위
  • 규정과 표준

복잡한 계산과 인공지능, 시뮬레이션에서는 정확한 기대 결과를 미리 알기 어려울 수 있다. 이 경우 보존되어야 하는 관계와 불변 조건을 확인하거나 서로 다른 구현 결과를 비교할 수 있다.

기존 구현을 오라클로 사용하면 기존 결함도 올바른 동작으로 고정할 수 있으므로 독립적인 기준과 요구사항을 함께 검토한다.

시험 자동화

시험 자동화는 시험 환경 준비, 입력 제공, 결과 확인과 보고를 도구로 수행하는 방식이다.

자동화에 적합한 시험에는 다음과 같은 특성이 있다.

  • 자주 반복한다.
  • 결과를 명확하게 판정할 수 있다.
  • 많은 데이터와 조합을 처리한다.
  • 여러 플랫폼에서 같은 검증이 필요하다.
  • 사람이 반복하면 오류가 발생하기 쉽다.
  • 회귀 위험이 높다.

자동화의 장점은 시험을 한 번 빠르게 실행하는 데만 있지 않다. 같은 시험을 모든 변경과 여러 환경에서 일관되게 반복하고 결과와 이력을 기록할 수 있다.

모든 시험을 자동화하는 것이 항상 효율적인 것은 아니다. 사용자 경험과 새로운 기능의 탐색처럼 사람의 관찰과 판단이 중요한 활동도 있다.

자동화된 시험 코드도 유지보수 대상이다. 중복과 숨겨진 의존성을 줄이고, 실패 원인을 알 수 있는 메시지와 구조를 제공해야 한다.

시험 피라미드와 시험 구성

시험 자동화 전략을 설명할 때 빠르고 작은 시험을 많이 두고, 느리고 넓은 범위의 시험은 상대적으로 적게 두는 시험 피라미드 개념이 사용되기도 한다.

일반적인 구성은 다음과 같다.

  • 많은 단위 시험
  • 적절한 수의 구성 요소와 통합 시험
  • 핵심 사용자 흐름을 확인하는 제한된 종단 간 시험

단위 시험은 빠르고 원인 파악이 쉽지만 실제 통합 문제를 확인하지 못한다. 종단 간 시험은 전체 흐름을 확인하지만 느리고 환경 변화에 민감하며 실패 원인을 찾기 어렵다.

따라서 시험의 수보다 위험과 피드백 속도, 실제 결함 유형을 기준으로 수준별 균형을 정한다. 분산 서비스에서는 계약 시험과 구성 요소 시험을 강화할 수 있고, 그래픽 프로그램과 장치 소프트웨어에서는 시스템 및 실제 장치 시험의 비중이 커질 수 있다.

종단 간 시험

종단 간 시험은 사용자의 시작 행동부터 여러 구성 요소와 외부 시스템을 거쳐 최종 결과가 나타날 때까지 전체 흐름을 평가한다.

예를 들어 전자상거래 시스템에서는 다음 흐름을 확인할 수 있다.

  • 사용자가 로그인한다.
  • 상품을 검색하고 장바구니에 넣는다.
  • 주문과 결제를 수행한다.
  • 재고와 주문 상태가 변경된다.
  • 알림이 전송된다.
  • 사용자가 주문 결과를 조회한다.

종단 간 시험은 시스템 전체의 연결을 확인하지만 많은 외부 상태와 환경에 의존하므로 느리고 불안정할 수 있다.

모든 세부 조건을 종단 간 시험으로 검증하지 않고, 핵심 사용자 흐름과 배포 확인에 집중하며 세부 규칙은 더 작은 시험 수준에서 다룬다.

불안정한 시험

같은 코드와 환경에서 실행했는데도 간헐적으로 성공과 실패가 달라지는 시험을 불안정한 시험이라고 할 수 있다.

원인에는 다음이 있다.

  • 비동기 작업과 고정 대기 시간
  • 실행 순서에 대한 의존
  • 공유 데이터와 환경
  • 시간대와 현재 시각
  • 네트워크와 외부 서비스
  • 임의 값과 난수 시드
  • 자원 부족과 병렬 실행
  • 시험 정리 실패
  • 실제 동시성 결함

불안정한 시험을 단순히 반복하여 성공할 때까지 실행하면 실제 결함을 숨기고 시험 결과에 대한 신뢰를 떨어뜨린다.

실패 정보를 보존하고 원인을 찾아 수정하며, 필요한 경우 격리하되 담당자와 해결 기한을 정한다.

지속적 통합의 시험

지속적 통합에서는 코드 변경이 공유 개발선에 통합되기 전에 자동화된 시험과 분석을 실행한다.

일반적인 흐름은 다음과 같다.

  1. 변경된 코드를 빌드한다.
  2. 코드 형식과 정적 분석을 실행한다.
  3. 빠른 단위 시험을 실행한다.
  4. 구성 요소와 통합 시험을 실행한다.
  5. 필요하면 보안·호환성·패키지 검사를 수행한다.
  6. 결과와 커버리지, 산출물을 기록한다.
  7. 실패한 변경의 통합을 차단하거나 담당자에게 알린다.

빠른 피드백을 위해 시험을 병렬 실행하고, 변경과 관련된 시험을 먼저 수행할 수 있다.

주 개발선에서는 더 넓은 회귀 시험과 여러 플랫폼의 빌드를 실행하고, 릴리스 후보에는 성능·보안·시스템과 수용 시험을 추가할 수 있다.

파이프라인이 통과했다는 사실만으로 제품이 배포에 적합하다고 단정하지 않는다. 자동화되지 않은 위험과 운영 상태, 승인 조건을 함께 확인한다.

지속적 전달과 배포 시험

지속적 전달에서는 같은 산출물을 여러 환경으로 승격하며 각 단계에서 필요한 시험을 수행한다.

예를 들어 다음과 같은 단계를 사용할 수 있다.

  • 빌드와 단위 시험
  • 구성 요소 및 통합 시험
  • 시험 환경 배포
  • 시스템 및 보안 시험
  • 준비 환경 검증
  • 제한된 사용자 또는 서버에 배포
  • 운영 지표 관찰
  • 전체 배포

배포 직후에는 스모크 시험과 상태 확인, 핵심 지표를 통해 새 버전이 정상적으로 작동하는지 확인한다.

카나리 배포와 점진적 배포에서는 일부 사용자와 인스턴스에 새 버전을 적용하고 오류율·지연·사업 지표를 이전 버전과 비교할 수 있다.

자동 롤백 기준은 명확해야 한다. 단순한 일시적 지표 변화로 반복 롤백이 발생하거나, 심각한 데이터 오류가 평균 지표에 가려지지 않도록 여러 신호를 사용한다.

운영 환경의 시험

일부 품질과 통합 문제는 실제 운영 환경에서만 드러난다. 따라서 사용자 피해를 제한하는 범위에서 운영 환경 검증을 수행할 수 있다.

방법에는 다음이 있다.

  • 기능 플래그
  • 내부 사용자와 제한된 그룹
  • 카나리 배포
  • 미러링과 그림자 트래픽
  • A/B 시험
  • 합성 모니터링
  • 실제 사용자 모니터링
  • 운영 스모크 시험
  • 제한된 장애 실험

운영 시험은 개발 전 시험을 생략하기 위한 수단이 아니다. 사전 검증으로 위험을 줄인 뒤 시험 환경에서 재현하기 어려운 실제 규모와 사용자 행동을 확인하는 보완 활동이다.

개인정보와 사용자 동의, 서비스 약관과 안전을 고려해야 하며, 실험 결과가 사용자에게 미치는 영향을 감시하고 중단할 수 있어야 한다.

시험 계획

시험 계획은 무엇을 왜 어떤 방법과 자원으로 시험할지 정의한다.

시험 계획에는 다음이 포함될 수 있다.

  • 시험 대상과 범위
  • 관련 요구사항과 품질 속성
  • 시험하지 않을 범위와 이유
  • 시험 수준과 유형
  • 사용할 기법과 도구
  • 시험 환경과 데이터
  • 역할과 책임
  • 일정과 의존성
  • 시작과 종료 조건
  • 결함 보고와 우선순위
  • 자동화 범위
  • 위험과 완화 방법
  • 산출물과 보고
  • 중단과 재개 조건

계획은 프로젝트 초기에 한 번 작성한 뒤 고정하지 않는다. 요구사항과 위험, 결함과 운영 정보가 바뀌면 시험 범위와 우선순위를 조정한다.

작은 프로젝트에서는 별도의 긴 문서보다 작업 백로그와 자동화 설정, 완료 기준으로 계획을 표현할 수 있다. 대규모·규제 대상 시스템에서는 공식 시험 계획과 승인·추적성이 필요할 수 있다.

위험 기반 시험

모든 기능과 입력을 같은 깊이로 시험할 수 없으므로 위험에 따라 시험 우선순위와 강도를 정할 수 있다.

위험은 다음 요소를 기준으로 평가할 수 있다.

  • 실패 발생 가능성
  • 실패의 피해와 비용
  • 사용 빈도
  • 코드와 구조의 복잡성
  • 변경 규모
  • 과거 결함 이력
  • 외부 시스템과 공급자 의존성
  • 시험과 복구의 어려움
  • 안전·보안·법률 영향
  • 데이터 손실 가능성

위험이 높은 영역에는 더 많은 시험 수준과 독립적인 검토, 장애와 경계 조건 시험을 적용할 수 있다.

위험이 낮은 내부 도구의 단순 기능에는 가벼운 자동화와 수동 확인만으로 충분할 수 있다. 그러나 위험이 낮다고 판단한 근거와 변경 조건을 확인해야 한다.

위험 기반 시험은 중요하지 않은 기능을 전혀 시험하지 않는다는 뜻이 아니다. 제한된 자원을 사용자와 조직에 가장 큰 영향을 주는 영역에 우선 배분하는 방식이다.

시험 사례

시험 사례는 특정 목적을 평가하기 위한 입력·사전 조건·절차·기대 결과와 사후 조건을 정의한다.

시험 사례에는 다음 정보가 포함될 수 있다.

  • 고유 식별자
  • 시험 목적
  • 관련 요구사항
  • 초기 상태와 사전 조건
  • 입력 데이터
  • 실행 절차
  • 기대 결과
  • 정리와 사후 조건
  • 우선순위
  • 적용 환경
  • 자동화 여부
  • 실제 결과와 판정

자동화된 단위 시험에서는 코드 자체가 절차와 기대 결과를 표현할 수 있다. 규제·수용 시험에서는 별도의 명세와 증거가 필요할 수 있다.

시험 사례는 서로 독립적으로 실행할 수 있는 편이 좋다. 실행 순서와 이전 시험의 상태에 의존하면 원인 분석과 병렬 실행이 어려워진다.

시험 절차와 시험 묶음

관련 시험 사례를 특정 목적과 순서로 모은 것을 시험 묶음으로 구성할 수 있다.

예를 들어 다음과 같이 나눌 수 있다.

  • 빠른 커밋 시험
  • 전체 회귀 시험
  • 보안 시험 묶음
  • 플랫폼별 호환성 시험
  • 릴리스 수용 시험
  • 데이터 이전 시험
  • 장애 복구 시험

시험 절차는 환경 준비와 데이터 설정, 실행 순서와 정리 방식을 포함한다.

자동화 환경에서는 태그와 분류·위험 수준을 이용하여 상황에 맞는 시험 묶음을 선택할 수 있다.

시험 결과와 증거

시험 결과는 단순한 성공과 실패 표시만으로 충분하지 않을 수 있다.

다음 정보를 기록할 수 있다.

  • 시험한 제품과 빌드 버전
  • 실행한 시험과 버전
  • 환경과 설정
  • 시작·종료 시간
  • 입력과 데이터
  • 실제 결과
  • 로그·화면과 진단 자료
  • 성공·실패·차단 판정
  • 관련 결함
  • 재시험 결과
  • 담당자와 승인 정보

실패한 시험이 제품 결함 때문인지 시험 코드·환경·데이터 문제 때문인지 판정해야 한다.

규제와 계약 환경에서는 시험 결과와 요구사항, 사용한 도구와 산출물의 추적성을 유지해야 할 수 있다.

결함 보고

결함 보고서는 다른 사람이 문제를 이해하고 재현하며 영향과 우선순위를 판단할 수 있는 정보를 제공해야 한다.

포함할 수 있는 정보는 다음과 같다.

  • 간결한 제목
  • 발견한 제품과 버전
  • 실행 환경
  • 사전 조건
  • 재현 절차
  • 기대 결과
  • 실제 결과
  • 재현 빈도
  • 로그·화면과 관련 자료
  • 영향받는 사용자와 기능
  • 심각도와 우선순위
  • 임시 우회 방법
  • 관련 요구사항과 변경
  • 보안 및 개인정보 여부

보고 제목에 원인을 단정하기보다 관찰된 실패를 명확히 표현한다. 원인은 조사 과정에서 달라질 수 있다.

재현이 간헐적인 문제도 발생 시각과 요청 식별자, 환경·데이터를 기록하면 분석 가능성이 높아진다.

심각도와 우선순위

심각도는 결함이 시스템과 사용자에게 미치는 영향의 크기를 나타낸다. 우선순위는 해당 결함을 언제 수정할지를 나타낸다.

심각도 기준에는 다음이 포함될 수 있다.

  • 데이터 손실과 손상
  • 안전과 보안 영향
  • 서비스 전체 또는 일부 중단
  • 핵심 기능의 사용 불가
  • 우회 방법의 존재
  • 영향받는 사용자 수
  • 법률과 계약 위반
  • 성능과 사용성 저하

심각도가 높은 결함이 항상 즉시 수정 가능한 것은 아니며, 심각도가 낮아도 많은 사용자에게 반복적으로 영향을 주거나 출시를 막는다면 우선순위가 높을 수 있다.

심각도와 우선순위를 혼용하면 결함 현황과 수정 의사결정을 이해하기 어려워진다.

결함 생명주기

결함은 발견된 뒤 여러 상태를 거칠 수 있다.

예를 들면 다음과 같다.

  • 새로 보고됨
  • 분류 및 확인 중
  • 재현됨
  • 수정 예정
  • 수정 중
  • 수정됨
  • 확인 시험 대기
  • 해결됨
  • 다시 열림
  • 중복
  • 재현 불가
  • 의도된 동작
  • 연기됨
  • 수정하지 않음

상태 이름은 조직마다 다를 수 있지만 각 상태의 의미와 전환 책임을 정의해야 한다.

결함을 해결할 때 수정된 버전과 코드 변경, 확인 시험과 릴리스를 연결하면 추적성이 높아진다.

독립성과 역할

시험의 독립성은 제품을 만든 사람과 다른 관점을 가진 사람이 평가하도록 하여 누락된 가정과 편향을 줄일 수 있다.

독립성은 여러 수준으로 구현할 수 있다.

  • 개발자가 자신의 코드를 시험한다.
  • 같은 팀의 다른 개발자가 검토한다.
  • 별도의 시험 담당자가 평가한다.
  • 조직 외부의 독립 기관이 검증한다.
  • 규제 기관이나 인증 기관이 평가한다.

독립성이 높아질수록 다른 관점과 공식적인 증거를 얻을 수 있지만, 개발자와 시험 담당자 사이의 피드백이 느려지거나 책임이 분리될 수 있다.

개발자는 자신의 구현에 대한 시험 책임을 유지하고, 별도 품질 조직은 독립적인 평가와 프로세스 보증을 제공하는 방식으로 역할을 결합할 수 있다.

안전 필수·보안·규제 시스템에서는 위험 수준에 따라 독립적인 검증과 승인이 요구될 수 있다.

동료 검토

동료 검토는 작성자 이외의 사람이 요구사항·설계·코드·시험과 문서를 검토하는 활동이다.

동료 검토에서는 다음을 확인할 수 있다.

  • 요구사항과 설계의 정확성
  • 누락과 모순
  • 인터페이스와 상태
  • 오류와 예외 조건
  • 보안과 안전 위험
  • 시험 범위
  • 코딩 규칙과 유지보수성
  • 문서와 구현의 일치
  • 변경의 영향

비공식적인 검토부터 정해진 역할과 체크리스트·기록을 사용하는 공식 검토까지 여러 형태가 있다.

검토할 변경의 목적과 범위가 작고 명확하면 실제 동작과 위험에 집중하기 쉽다.

자동 분석이 발견할 수 있는 형식 문제보다 설계 의도와 요구사항, 복잡한 예외 조건을 사람의 검토에서 다루는 편이 효율적이다.

검사와 워크스루

워크스루는 작성자가 산출물의 내용과 흐름을 다른 참여자에게 설명하고 의견과 결함을 발견하는 검토 방식이다.

검사는 역할·준비·회의·결함 기록과 후속 확인을 갖춘 비교적 공식적인 동료 검토 방식이다.

검사 대상에는 다음이 포함될 수 있다.

  • 요구사항 명세
  • 아키텍처와 상세 설계
  • 안전 및 보안 분석
  • 소스 코드
  • 시험 계획과 사례
  • 사용자와 운영 문서

공식적인 검사는 모든 작은 변경에 적용하기보다 결함 비용과 위험이 높은 산출물에 집중할 수 있다.

품질 감사

품질 감사는 제품과 프로세스·기록이 정해진 요구사항·표준과 계획을 따르는지 독립적으로 확인하는 활동이다.

감사에서는 다음을 확인할 수 있다.

  • 필요한 검토와 시험이 수행되었는가
  • 승인된 요구사항과 변경만 반영되었는가
  • 구성 항목과 기준선이 일치하는가
  • 시험 결과와 결함이 적절히 처리되었는가
  • 보안·안전과 규제 절차를 따랐는가
  • 공급자와 외부 구성 요소가 기준을 충족하는가
  • 릴리스의 근거와 승인이 존재하는가
  • 문서와 기록이 보존되어 있는가

감사는 품질 조직이나 외부 기관이 수행할 수 있다. 목적은 개발자를 처벌하는 데 있지 않고 제품과 프로세스의 신뢰성과 개선 필요성을 확인하는 데 있다.

형식적으로 서명된 기록이 존재하더라도 실제 활동과 결과가 적절했는지 확인해야 한다.

프로세스 보증

프로세스 보증은 개발과 시험, 구성 관리와 배포 활동이 계획한 프로세스와 품질 기준에 따라 수행되는지 확인한다.

다음과 같은 항목을 확인할 수 있다.

  • 요구사항과 변경의 추적성
  • 설계 및 코드 검토
  • 자동화된 빌드와 시험
  • 구성 및 릴리스 관리
  • 결함 분류와 수정
  • 보안 개발 활동
  • 공급자 관리
  • 운영 피드백과 장애 분석
  • 지표와 개선 활동

프로세스 준수 자체가 품질의 목적이 되어서는 안 된다. 불필요한 절차가 빠른 피드백을 방해하거나 실제 위험을 줄이지 못한다면 프로세스를 개선해야 한다.

제품 보증

제품 보증은 만들어진 소프트웨어와 산출물이 요구사항과 품질 기준을 충족하는지 확인한다.

제품 보증에는 다음이 포함될 수 있다.

  • 요구사항과 설계 검토
  • 코드와 구성 검사
  • 정적 분석
  • 기능 및 품질 시험
  • 시험 결과 검토
  • 결함 상태 확인
  • 릴리스 산출물 감사
  • 문서와 라이선스 확인
  • 운영 준비와 복구 검토

제품 보증은 개발 완료 후의 최종 검사에만 의존하지 않고 각 산출물이 만들어질 때 수행하는 편이 결함 수정 비용을 줄일 수 있다.

품질 계획

품질 계획은 프로젝트에서 중요한 품질 목표와 이를 달성·평가할 활동, 역할과 기준을 정의한다.

품질 계획에는 다음이 포함될 수 있다.

  • 적용할 품질 특성과 목표
  • 요구사항과 규제 기준
  • 검토와 시험 전략
  • 품질 보증 역할과 독립성
  • 완료와 릴리스 기준
  • 품질 지표
  • 결함 분류와 처리
  • 공급자와 외부 구성 요소 평가
  • 감사와 보고
  • 개선 활동
  • 예외와 승인 절차

품질 목표는 “결함을 최소화한다”처럼 모호하게 정하기보다 사용자와 운영에 의미 있는 측정 기준으로 정의한다.

계획은 프로젝트의 규모와 위험에 맞게 조정해야 한다. 작은 내부 도구와 항공 제어 소프트웨어에 같은 수준의 문서·시험과 독립성을 요구하는 것은 적절하지 않다.

품질 측정

품질 측정은 제품과 프로세스의 상태를 이해하고 의사결정을 지원하기 위해 사용한다.

측정할 수 있는 정보에는 다음이 있다.

  • 발견된 결함 수와 심각도
  • 결함이 발견된 단계
  • 결함 수정과 확인에 걸린 시간
  • 시험 성공률과 실행 시간
  • 코드와 요구사항 커버리지
  • 변경 실패율
  • 운영 장애와 복구 시간
  • 응답 시간과 오류율
  • 보안 취약점과 수정 기간
  • 사용자 작업 성공률
  • 고객 문의와 이탈
  • 기술 부채와 변경 비용

하나의 지표만으로 품질을 판단하기 어렵다. 결함 수가 적은 이유가 품질이 높아서인지 시험이 부족해서인지 구분해야 한다.

시험 수와 코드 커버리지·닫힌 결함 수를 개인의 단순 성과 평가에 사용하면 숫자를 높이기 위한 행동이 나타날 수 있다. 지표는 문제와 추세, 개선 결과를 이해하기 위한 정보로 사용한다.

결함 밀도와 결함 추세

코드 크기나 기능 수에 대한 결함의 수를 결함 밀도로 표현할 수 있다. 그러나 코드 줄 수와 결함 집계 기준은 언어와 프로젝트마다 다르므로 단순 비교에 주의해야 한다.

더 유용한 분석에는 다음이 포함될 수 있다.

  • 특정 모듈에 반복되는 결함
  • 같은 원인의 결함
  • 릴리스별 심각 결함 추세
  • 개발 단계별 발견 시점
  • 운영으로 유출된 결함
  • 재발한 결함
  • 결함 수정으로 생긴 회귀

결함이 특정 영역에 집중된다면 해당 코드만 수정하는 것을 넘어 요구사항·설계·시험과 코드 소유 구조를 검토할 수 있다.

결함 제거 효율

개발 중 발견한 결함과 운영에서 발견한 결함을 비교하여 배포 전에 결함을 얼마나 발견했는지 분석할 수 있다.

그러나 모든 결함의 심각도와 발견 가능성이 같지 않으므로 단순 비율만으로 품질을 판단해서는 안 된다.

운영으로 유출된 중요한 결함을 분석하여 어떤 시험과 검토가 부족했는지, 환경 차이와 요구사항 누락이 있었는지를 개선 활동에 반영한다.

시험 종료 기준

시험은 시간이 허용하는 한 무기한 계속할 수 없으므로 종료와 릴리스 판단 기준이 필요하다.

기준에는 다음이 포함될 수 있다.

  • 계획한 필수 시험이 완료되었다.
  • 중요한 요구사항이 검증되었다.
  • 허용할 수 없는 심각도의 열린 결함이 없다.
  • 회귀 시험과 필수 플랫폼 시험이 통과했다.
  • 성능·보안과 가용성 목표를 충족했다.
  • 수용 시험과 필요한 승인이 완료되었다.
  • 알려진 위험과 제한이 문서화되었다.
  • 복구와 되돌리기 준비가 완료되었다.
  • 품질 지표가 허용 범위에 있다.

시험 사례를 모두 실행했다는 이유만으로 종료하지 않는다. 시험 범위 자체가 부족하거나 요구사항이 변경되었을 수 있다.

모든 알려진 결함을 수정해야만 릴리스할 수 있는 것도 아니다. 영향과 우회 방법, 수정 위험과 일정에 따라 일부 결함을 수용할 수 있지만 결정과 책임을 기록해야 한다.

릴리스 품질 판단

릴리스 판단에서는 시험 결과뿐 아니라 운영 준비와 사업적 조건, 잔여 위험을 함께 평가한다.

검토할 수 있는 항목은 다음과 같다.

  • 기능과 품질 요구사항
  • 열린 결함과 알려진 제한
  • 보안 취약점
  • 데이터 이전과 호환성
  • 운영 감시와 경고
  • 배포와 롤백
  • 사용자와 지원 문서
  • 공급자와 외부 서비스 상태
  • 규제 및 계약 승인
  • 사용자 영향과 출시 일정

품질 조직이 독립적인 평가를 제공할 수 있지만 최종 출시 결정은 제품과 기술·운영·사업 책임자가 공동으로 내릴 수 있다.

출시를 승인한다는 것은 위험이 없다는 뜻이 아니라 알려진 증거와 잔여 위험을 바탕으로 사용을 시작할 수 있다고 판단했다는 의미이다.

결함 예방과 근본 원인 분석

품질 보증은 발견한 결함을 개별적으로 수정하는 데서 끝나지 않는다. 반복되는 결함의 원인과 개발 과정의 약점을 분석하여 같은 종류의 문제가 다시 만들어지는 것을 줄인다.

근본 원인에는 다음이 있을 수 있다.

  • 요구사항의 모호성과 누락
  • 설계 경계와 상태 모델의 문제
  • 잘못된 API와 자료형
  • 부족한 코드 검토
  • 시험 환경과 운영 환경의 차이
  • 자동화되지 않은 수동 과정
  • 교육과 도메인 지식 부족
  • 일정과 작업 분할 문제
  • 불명확한 책임
  • 외부 구성 요소의 변경
  • 관찰 가능성 부족

근본 원인 분석은 개인의 실수만을 찾는 과정이 아니다. 어떤 조건과 구조가 오류를 만들고 검출하지 못하게 했는지를 확인한다.

개선에는 요구사항 템플릿, 설계 규칙, 정적 분석, 새로운 시험과 자동화, 모듈 재구조화와 운영 경고 등이 포함될 수 있다.

품질 비용

소프트웨어 품질에는 예방·평가와 실패에 대한 비용이 발생한다.

  • 예방 비용은 교육·표준·설계 개선과 자동화에 사용된다.
  • 평가 비용은 검토·시험·감사와 측정에 사용된다.
  • 내부 실패 비용은 배포 전에 발견된 결함의 수정과 재작업에 사용된다.
  • 외부 실패 비용은 운영 장애·고객 지원·데이터 손실·보안 사고와 신뢰 하락에서 발생한다.

시험과 품질 보증 활동에도 비용이 들지만, 중요한 결함을 늦게 발견했을 때의 수정과 운영 피해가 더 클 수 있다.

모든 결함을 같은 비용으로 예방하려 하지 않고 실패의 영향과 발생 가능성에 따라 적절한 품질 활동을 선택한다.

문서와 추적성

시험과 품질 보증에서는 요구사항·설계·코드·시험·결함과 릴리스 사이의 관계를 추적할 수 있어야 한다.

추적성을 통해 다음과 같은 질문에 답할 수 있다.

  • 특정 요구사항을 어떤 시험으로 확인했는가
  • 시험되지 않은 요구사항이 있는가
  • 실패한 시험은 어떤 결함과 관련되는가
  • 결함 수정은 어떤 코드와 릴리스에 포함되었는가
  • 특정 릴리스에서 어떤 시험과 승인이 수행되었는가
  • 보안과 안전 요구의 증거는 어디에 있는가

모든 작은 단위까지 수동으로 연결하면 관리 비용이 커질 수 있다. 프로젝트의 위험·규제와 변경 영향에 따라 필요한 추적 수준을 정하고, 도구와 공통 식별자로 자동화한다.

시험 도구

시험과 품질 활동에는 여러 종류의 도구가 사용된다.

  • 단위 및 통합 시험 프레임워크
  • 사용자 인터페이스 자동화
  • API와 프로토콜 시험 도구
  • 정적 분석기
  • 동적 분석기와 메모리 검사기
  • 퍼저
  • 코드 커버리지 도구
  • 성능 및 부하 생성기
  • 보안 분석 도구
  • 시험 관리와 결함 추적 시스템
  • 장치와 브라우저 시험 환경
  • 서비스 가상화와 모의 서버
  • 지속적 통합 및 배포 시스템
  • 로그·메트릭과 분산 추적 도구

도구는 품질 활동을 지원하지만 적절한 요구사항과 시험 설계, 결과 해석을 대신하지 않는다.

도구 자체의 버전과 설정·제한도 관리해야 한다. 규제 대상 시스템에서는 시험 도구가 올바르게 작동한다는 근거나 별도의 도구 적격성 확인이 필요할 수 있다.

품질 문화

소프트웨어 품질은 별도의 품질 조직이나 시험 담당자만의 책임이 아니다.

요구사항 작성자는 검증 가능한 요구를 정의하고, 설계자는 품질 속성과 시험 가능성을 구조에 반영하며, 개발자는 코드와 단위 시험·진단 정보를 제공한다. 시험 담당자는 독립적인 관점에서 위험과 결함을 발견하고, 운영자는 실제 장애와 사용 정보를 개발 과정에 전달한다.

품질 문제가 발견되었을 때 보고자를 비난하면 결함이 숨겨지고 정보가 늦게 전달될 수 있다. 문제를 빠르게 공유하고 원인과 개선책을 함께 찾는 환경이 필요하다.

품질 조직은 개발의 마지막 승인 관문으로만 존재하기보다 프로젝트 초기부터 요구사항·설계와 시험 전략에 참여할 수 있다.

품질 활동의 조정

모든 프로젝트에 같은 종류와 깊이의 시험·보증 활동을 적용할 필요는 없다.

작은 내부 도구에서는 다음과 같은 구성이 충분할 수 있다.

  • 코드 검토
  • 핵심 단위 및 통합 시험
  • 자동 빌드
  • 간단한 사용자 확인
  • 오류 기록과 복구 절차

대규모 웹 서비스에서는 다음 활동이 중요할 수 있다.

  • 지속적 통합과 회귀 시험
  • 성능과 장애 시험
  • 보안 시험
  • 카나리 배포와 운영 모니터링
  • 데이터 이전과 복구 시험

안전 필수 시스템에서는 다음이 필요할 수 있다.

  • 상세 요구사항과 양방향 추적성
  • 독립적인 검증과 확인
  • 공식 검토와 감사
  • 구조 및 코드 커버리지
  • 안전 분석과 시험
  • 형식 기법
  • 장비와 실제 환경을 이용한 시험
  • 인증과 장기적인 증거 보존

활동의 양이 많다고 항상 품질이 높은 것은 아니다. 제품의 위험과 품질 목표를 실제로 통제하는지 평가하고 불필요한 중복과 느린 피드백을 개선한다.

시험과 품질 보증의 지속성

시험과 품질 보증은 개발 완료 직전의 단계가 아니라 소프트웨어 생명주기 전체에서 수행된다.

요구사항 단계에서는 요구가 명확하고 검증 가능한지 검토한다. 설계 단계에서는 구조가 품질 속성과 시험 가능성을 지원하는지 평가한다. 구현 단계에서는 코드 검토·정적 분석과 단위 시험을 수행한다. 통합과 배포 단계에서는 인터페이스·시스템·성능·보안과 복구를 시험한다. 운영 단계에서는 로그와 메트릭, 사용자 피드백과 장애를 통해 품질을 계속 평가한다.

운영에서 발견된 결함과 사용 경험은 새로운 요구사항과 설계·시험으로 돌아간다. 외부 의존성과 운영체제, 데이터 규모와 공격 방식이 변하면 이전에 통과한 시험만으로 현재의 품질을 보장할 수 없다.

소프트웨어 시험은 제품이 특정 조건에서 어떻게 동작하는지에 관한 증거를 제공하고, 소프트웨어 품질 보증은 그러한 증거가 필요한 시점에 일관되게 만들어지도록 제품과 프로세스를 관리한다.

좋은 품질 체계는 결함이 전혀 발생하지 않는다고 가정하지 않는다. 결함과 실패를 가능한 한 조기에 발견하고, 피해를 제한하며, 원인을 학습하여 소프트웨어와 개발 과정이 지속적으로 개선되도록 만든다.

배포, 운영과 유지보수

소프트웨어는 구현과 시험이 끝났다고 해서 사용자에게 가치를 제공하는 것이 아니다. 실행 가능한 산출물을 실제 환경에 설치하고, 필요한 데이터와 설정을 적용하며, 사용자가 안정적으로 이용할 수 있도록 운영해야 한다. 이후에도 결함과 보안 취약점을 수정하고, 변화하는 요구사항·운영체제·하드웨어·외부 서비스에 대응하며, 오래된 구조를 개선해야 한다.

배포(Deployment)는 소프트웨어 산출물을 대상 실행 환경에 설치하고 구성하여 사용할 수 있는 상태로 만드는 활동이다. 운영(Operation)은 배포된 소프트웨어와 기반 시스템을 실행·감시·지원하고 장애와 보안 사건에 대응하면서 요구된 서비스를 계속 제공하는 활동이다. 유지보수(Software Maintenance)는 배포된 소프트웨어를 수정하여 결함을 해결하고 환경 변화에 적응시키며 기능과 품질을 개선하고 장기적인 문제를 예방하는 활동이다.

배포·운영·유지보수는 서로 분리된 마지막 단계가 아니다. 운영 환경에서 발견한 장애와 사용자 행동은 새로운 요구사항과 설계 변경으로 이어진다. 개발 과정에서 선택한 아키텍처·데이터 구조·로그·배포 방식은 운영과 유지보수 비용을 결정하며, 운영 경험은 다시 구현과 시험에 반영된다.

ISO/IEC/IEEE 14764:2022는 ISO/IEC/IEEE 12207의 소프트웨어 유지보수 프로세스를 구체화하고 여러 종류의 유지보수와 관련 활동을 설명한다.[66] SWEBOK V4.0은 기존 유지보수 지식과 함께 소프트웨어 공학 운영을 별도의 지식 영역으로 추가하여 배포·서비스 운영·신뢰성·관찰과 운영 자동화 등을 소프트웨어 공학의 범위에서 다룬다.[67]

릴리스와 배포의 구분

릴리스는 특정한 소프트웨어 버전과 관련 산출물을 공식적으로 제공 가능한 제품으로 정리하는 활동이다. 배포는 해당 릴리스를 실제 서버·장치·사용자 환경에 적용하는 활동이다.

하나의 릴리스가 여러 환경에 여러 차례 배포될 수 있다. 데스크톱 응용 프로그램의 새 버전은 패키지 저장소와 다운로드 서버에 한 번 릴리스된 뒤 각 사용자가 서로 다른 시점에 설치한다. 웹 서비스에서는 같은 산출물을 개발·시험·준비·운영 환경으로 순차적으로 배포할 수 있다.

릴리스에는 일반적으로 다음이 포함된다.

  • 제품 버전과 빌드 식별자
  • 실행 파일·라이브러리와 패키지
  • 컨테이너 이미지 또는 설치 이미지
  • 데이터베이스 스키마 이전
  • 기본 설정과 설정 스키마
  • 변경 기록과 릴리스 노트
  • 설치·업데이트·복구 절차
  • 지원 운영체제와 하드웨어
  • 알려진 문제와 제한
  • 소프트웨어 자재 명세서
  • 라이선스와 저작권 정보
  • 서명·해시와 빌드 출처
  • 시험과 승인 결과

배포 과정에서는 릴리스 산출물뿐 아니라 실행 환경의 설정·네트워크·권한·데이터와 외부 서비스의 상태도 함께 관리해야 한다.

릴리스 공학

릴리스 공학(Release Engineering)은 소스 코드와 의존성에서 일관되고 검증 가능한 소프트웨어 릴리스를 만들고 전달하는 데 필요한 빌드·패키징·검증과 배포 체계를 설계하는 분야이다.

릴리스 공학은 다음과 같은 요소를 다룬다.

  • 소스와 빌드 입력의 식별
  • 빌드 환경과 도구 체인의 관리
  • 자동화되고 재현 가능한 빌드
  • 버전과 릴리스 후보 관리
  • 패키징과 서명
  • 산출물의 저장과 승격
  • 배포 파이프라인
  • 단계적 출시와 롤백
  • 릴리스 기록과 감사
  • 사용자와 운영 조직에 대한 전달

Google의 SRE 자료는 릴리스 공학을 소프트웨어를 빌드하고 전달하는 공학 분야로 설명하며, 소스 관리·컴파일러·빌드 설정·자동화된 빌드·패키지 관리자와 설치 도구에 대한 지식을 포함한다고 설명한다.[68]

릴리스는 개발자의 로컬 컴퓨터에서 수동으로 만든 파일을 직접 전달하는 방식보다, 검토된 소스와 고정된 의존성을 자동화된 환경에서 빌드하여 만드는 편이 추적성과 재현성이 높다.

시험한 산출물을 운영 배포 직전에 다시 빌드하면 같은 소스 버전이라도 도구·환경·의존성 차이로 다른 결과가 만들어질 수 있다. 따라서 한 번 생성하고 검증한 불변 산출물을 환경 사이에서 승격하는 방식을 사용할 수 있다.

배포 준비

배포 전에는 소프트웨어가 기능적으로 완성되었는지만 확인하지 않고 실제 운영 환경에서 실행할 준비가 되었는지를 검토한다.

배포 준비에는 다음이 포함될 수 있다.

  • 대상 버전과 산출물의 식별
  • 필수 시험과 승인 완료
  • 운영 환경의 용량과 호환성
  • 설정과 비밀 정보 준비
  • 데이터베이스와 데이터 이전 계획
  • 외부 시스템과 API 호환성
  • 모니터링·로그와 경고 설정
  • 배포와 롤백 절차
  • 백업과 복구 확인
  • 보안 취약점과 권한 검토
  • 고객 지원과 운영 담당자 교육
  • 사용자 문서와 변경 안내
  • 장애 발생 시 책임자와 연락 체계
  • 알려진 위험과 허용 여부

새로운 서비스는 운영 담당자가 상태를 파악하고 장애에 대응할 수 있는지 확인하는 운영 준비 검토를 거칠 수 있다. 검토 과정에는 서비스의 소유권·서비스 수준·용량·의존성·배포·경고·백업과 장애 대응이 포함될 수 있다.

배포 준비 검토는 운영 팀이 완성된 프로그램을 뒤늦게 검사하는 절차로만 사용하기보다, 개발 초기부터 운영 요구를 설계에 반영하도록 지원하는 과정으로 사용하는 편이 적절하다.

환경

소프트웨어는 일반적으로 여러 실행 환경을 거쳐 운영에 배포된다.

  • 개발 환경
  • 자동화된 시험 환경
  • 통합 환경
  • 품질 보증 환경
  • 준비 또는 사전 운영 환경
  • 운영 환경
  • 재해 복구 환경

각 환경은 목적이 다르지만 소프트웨어의 구성과 동작 차이가 지나치게 크면 시험 결과를 운영 환경에 적용하기 어렵다.

환경 차이는 다음에서 발생할 수 있다.

  • 운영체제와 하드웨어
  • 네트워크와 방화벽
  • 데이터베이스 종류와 버전
  • 외부 서비스
  • 권한과 인증 방식
  • 데이터 양과 형태
  • 설정과 기능 플래그
  • 지역과 시간대
  • 인증서와 도메인
  • 확장·복제 구조

환경 설정은 수동 작업과 담당자의 기억에 의존하지 않고 버전 관리되는 선언적 자료와 자동화 도구로 관리할 수 있다. 다만 비밀번호와 암호 키 같은 비밀 정보는 일반 소스 저장소와 분리해야 한다.

운영 환경의 실제 개인정보와 기밀 데이터를 시험 환경에 그대로 복사해서는 안 된다. 필요한 경우 익명화·가명화하거나 합성 데이터를 사용한다.

배포 자동화

배포 자동화는 소프트웨어 설치와 설정, 데이터 이전과 상태 검사를 일관된 절차로 실행한다.

자동화할 수 있는 작업에는 다음이 있다.

  • 산출물 내려받기와 무결성 검증
  • 프로세스와 서비스 중지·시작
  • 파일과 패키지 설치
  • 설정과 비밀 정보 적용
  • 데이터베이스 스키마 이전
  • 네트워크와 접근 정책 적용
  • 상태 확인
  • 배포 후 스모크 시험
  • 배포 결과와 버전 기록
  • 실패 시 중단 또는 롤백
  • 이전 산출물 정리

자동화는 반복적인 수동 작업의 오류와 환경별 차이를 줄인다. 그러나 잘못된 자동화는 같은 오류를 빠르게 여러 시스템에 확산시킬 수 있으므로 배포 코드도 버전 관리·검토·시험해야 한다.

배포 자동화에는 실행 전 검증과 중단 조건, 일부 실패 후 재개 방법이 필요하다. 배포 작업이 중간에 실패했을 때 처음부터 다시 실행해도 안전한지, 이미 완료한 작업을 중복 수행하지 않는지도 고려한다.

지속적 전달과 지속적 배포

지속적 전달은 모든 변경을 자동으로 빌드·시험하여 언제든지 운영에 배포할 수 있는 상태로 유지하는 방식이다. 실제 운영 배포는 사람의 승인이나 사업 일정에 따라 수행할 수 있다.

지속적 배포는 자동화된 검증과 정책을 통과한 변경을 운영 환경까지 자동으로 배포한다.

일반적인 전달 파이프라인은 다음과 같은 흐름을 가진다.

  1. 변경을 버전 관리 시스템에 통합한다.
  2. 깨끗한 환경에서 산출물을 빌드한다.
  3. 단위·통합과 정적 분석을 수행한다.
  4. 산출물을 저장하고 서명한다.
  5. 시험 환경에 배포한다.
  6. 시스템·보안과 성능 시험을 수행한다.
  7. 준비 환경에서 운영 조건을 확인한다.
  8. 제한된 운영 범위에 배포한다.
  9. 서비스 지표와 오류를 평가한다.
  10. 전체 환경으로 확대하거나 배포를 중단한다.

자동화된 파이프라인을 사용하더라도 모든 변경을 같은 방식으로 배포할 필요는 없다. 데이터 형식과 공개 API·안전 필수 기능·대규모 인프라 변경은 추가 검토와 승인, 장기간의 단계적 전환이 필요할 수 있다.

배포 전략

배포 전략은 새 버전을 기존 버전과 어떻게 교체할지 결정한다.

일괄 교체

모든 기존 인스턴스를 중지하고 새 버전으로 교체한다. 구조가 단순하지만 배포 동안 서비스가 중단될 수 있으며 새 버전에 문제가 생기면 전체 사용자에게 즉시 영향을 준다.

사용 중단이 허용되는 내부 시스템이나 단일 장치, 유지보수 시간을 따로 확보할 수 있는 서비스에서 사용할 수 있다.

롤링 배포

기존 인스턴스를 일부씩 새 버전으로 교체한다. 서비스 전체를 중지하지 않고 배포할 수 있지만 일정 기간 동안 두 버전이 동시에 실행된다.

따라서 새 버전과 이전 버전이 같은 데이터베이스와 메시지, API를 사용할 수 있도록 호환성을 유지해야 한다.

Kubernetes의 Deployment는 기존 인스턴스를 점진적으로 새 인스턴스로 교체하는 롤링 업데이트와 이전 리비전으로의 롤백 기능을 제공한다.[69]

블루-그린 배포

기존 운영 환경과 동일한 새 환경을 별도로 준비하고, 새 환경을 검증한 뒤 사용자 트래픽을 한 번에 전환한다.

빠른 전환과 복구가 가능하지만 두 환경을 동시에 유지할 자원이 필요하다. 데이터베이스와 외부 상태까지 완전히 분리하지 않는 경우 애플리케이션을 되돌려도 데이터 변경은 복구되지 않을 수 있다.

카나리 배포

새 버전을 일부 인스턴스나 제한된 사용자에게 먼저 배포하고 지표와 오류를 확인한 뒤 범위를 넓힌다.

Google SRE Workbook은 카나리 배포를 변경을 부분적이고 시간 제한적으로 배포하여 평가하는 방식으로 정의한다.[70]

카나리 평가에는 다음을 사용할 수 있다.

  • 오류율
  • 응답 시간
  • 자원 사용
  • 충돌과 재시작
  • 사용자 작업 성공률
  • 데이터 정확성
  • 사업 지표
  • 보안 경고

단순히 일정 시간이 지났다는 이유만으로 확대하지 않고, 사전에 정한 성공·중단 기준을 사용한다.

기능 플래그

코드는 배포하되 특정 기능의 노출과 동작을 설정으로 제어한다. 코드 배포와 기능 출시를 분리하고 일부 사용자에게만 기능을 제공하거나 문제가 생긴 기능을 빠르게 비활성화할 수 있다.

기능 플래그가 장기간 남으면 가능한 상태와 시험 조합이 증가한다. 임시 플래그에는 소유자와 제거 조건을 정하고, 보안과 권한 기능을 단순한 클라이언트 플래그에만 의존하지 않는다.

데이터베이스 변경

응용 프로그램 코드는 이전 버전으로 되돌릴 수 있어도 데이터베이스 스키마와 데이터 변경은 쉽게 되돌릴 수 없는 경우가 많다.

데이터베이스 변경에서는 다음을 고려한다.

  • 이전 버전과 새 버전의 동시 실행
  • 스키마 추가와 삭제 순서
  • 대규모 데이터 변환 시간
  • 잠금과 서비스 지연
  • 이전 실패와 재개
  • 데이터 검증
  • 백업과 복구
  • 롤백 가능성
  • 개인정보 보존과 삭제
  • 읽기·쓰기 형식의 호환성

호환되지 않는 변경을 한 번에 적용하기보다 다음과 같이 단계적으로 전환할 수 있다.

  1. 기존 코드와 호환되는 새 필드나 구조를 추가한다.
  2. 이전 버전과 새 버전이 모두 동작하도록 한다.
  3. 기존 데이터를 새 구조로 이전한다.
  4. 새 코드가 새 구조를 사용하도록 전환한다.
  5. 이전 구조의 사용 여부를 확인한다.
  6. 이전 코드와 데이터를 제거한다.

데이터 이전은 소량의 시험 데이터뿐 아니라 운영과 유사한 규모와 분포에서 시험해야 한다. 진행 상태와 처리 속도, 오류와 중단 후 재개 방법을 제공한다.

설치형 소프트웨어의 배포

데스크톱·모바일·서버 패키지와 임베디드 소프트웨어는 중앙 웹 서비스와 다른 배포 특성을 가진다.

  • 사용자가 업데이트를 지연하거나 거부할 수 있다.
  • 여러 버전이 장기간 동시에 사용된다.
  • 사용자의 장치와 데이터에 직접 영향을 준다.
  • 네트워크 연결 없이 설치·사용될 수 있다.
  • 운영체제와 하드웨어 조합이 다양하다.
  • 실패한 업데이트로 프로그램이 실행되지 않을 수 있다.
  • 이전 버전과 파일 형식의 호환성이 필요하다.

설치 프로그램과 업데이트 시스템은 다음을 처리해야 한다.

  • 플랫폼과 아키텍처 확인
  • 디스크 공간과 권한
  • 실행 중인 프로세스
  • 기존 버전 탐지
  • 사용자 데이터와 설정 보존
  • 패키지 서명과 무결성 검증
  • 부분 다운로드와 재시도
  • 설치 중 전원 중단
  • 업데이트 실패 후 복구
  • 제거와 잔여 데이터 정책

자동 업데이트는 보안 수정의 빠른 보급을 지원하지만 사용자의 작업을 방해하거나 호환성 문제를 일으킬 수 있다. 업데이트 정책과 연기·재시작·복구 방법을 명확히 제공한다.

운영

운영은 소프트웨어가 실행되는 동안 필요한 서비스 수준과 품질을 유지하는 활동이다.

운영에는 다음이 포함될 수 있다.

  • 서비스와 작업의 시작·종료
  • 상태와 성능 감시
  • 사용자와 권한 관리
  • 설정과 비밀 정보 관리
  • 백업과 복구
  • 용량과 비용 관리
  • 장애와 보안 사건 대응
  • 데이터 보존과 삭제
  • 정기 작업과 유지보수
  • 외부 서비스 및 인증서 관리
  • 사용자 지원
  • 업데이트와 패치
  • 운영 문서와 교대 근무
  • 법률·계약과 서비스 수준 준수

운영자는 단순히 이미 만들어진 프로그램을 실행하는 사람이 아니다. 실제 작업 부하와 장애·사용자 행동을 관찰하고, 시스템의 개선에 필요한 정보를 개발 조직에 제공한다.

현대의 웹·클라우드 서비스에서는 개발과 운영의 경계가 약해졌으며, 개발 팀이 배포 후 서비스의 상태와 장애에 계속 책임지는 방식이 사용될 수 있다.

DevOps

DevOps는 개발과 운영을 별도의 연속 단계로만 보지 않고, 소프트웨어의 개발·시험·배포·운영과 개선을 하나의 지속적인 흐름으로 연결하는 접근이다.

DevOps는 특정한 도구 하나나 직무 이름만을 뜻하지 않는다. 다음과 같은 원리를 포함할 수 있다.

  • 개발과 운영의 공동 책임
  • 작은 변경의 빈번한 통합과 배포
  • 빌드·시험·배포와 인프라 자동화
  • 빠른 피드백
  • 환경과 설정의 버전 관리
  • 운영 상태의 관찰
  • 장애 경험의 개발 반영
  • 반복적인 수동 작업의 감소
  • 보안 활동의 통합

개발 팀이 운영 결과를 알지 못하고 운영 팀이 코드와 설계에 참여하지 못하면 장애 원인과 개선이 서로 전달되기 어렵다.

DevOps를 도입하면서 운영 전문성을 없애거나 모든 개발자에게 같은 역할을 부여할 필요는 없다. 각 분야의 전문성을 유지하면서 공통 목표와 정보, 자동화된 흐름을 만드는 것이 중요하다.

사이트 신뢰성 공학

사이트 신뢰성 공학(Site Reliability Engineering, SRE)은 소프트웨어 공학의 방법을 서비스 운영과 신뢰성 문제에 적용하는 접근이다.

Google은 SRE를 소프트웨어 엔지니어에게 운영 팀의 설계를 맡겼을 때 나타나는 방식으로 설명한다.[71]

SRE에서는 다음과 같은 활동을 중요하게 다룬다.

  • 서비스 수준 지표와 목표
  • 오류 예산
  • 자동화
  • 용량 계획
  • 변경과 릴리스 관리
  • 모니터링과 경고
  • 당직과 장애 대응
  • 사후 분석
  • 반복 수작업의 감소
  • 신뢰성과 기능 개발 사이의 균형

SRE는 모든 조직이 동일한 구조로 도입해야 하는 운영 방식이 아니다. 서비스 규모와 위험·팀 구조에 따라 개발 팀 내부의 운영 책임, 별도의 신뢰성 팀 또는 공통 플랫폼 팀 등 여러 형태로 적용할 수 있다.

서비스 수준

운영 중인 서비스의 품질을 관리하려면 사용자에게 중요한 동작과 그 목표를 측정 가능한 형태로 정의해야 한다.

서비스 수준 지표(Service Level Indicator, SLI)는 서비스 품질을 나타내는 측정값이다.

  • 성공한 요청의 비율
  • 응답 시간
  • 데이터 처리 지연
  • 올바른 결과의 비율
  • 서비스 가용 시간
  • 내구성 또는 데이터 손실률
  • 작업 완료 성공률

서비스 수준 목표(Service Level Objective, SLO)는 SLI에 대해 달성하려는 목표 범위이다. 예를 들어 30일 동안 요청의 99.9%를 성공적으로 처리한다는 목표를 정할 수 있다.

서비스 수준 협약(Service Level Agreement, SLA)은 서비스 제공자와 고객 사이의 공식적인 약속과 위반 시 조치를 포함할 수 있다.

Google SRE는 SLO를 SLI로 측정되는 서비스 수준의 목표 값 또는 범위로 설명한다.[72]

모든 내부 시스템 지표가 사용자 경험을 직접 나타내는 것은 아니다. CPU 사용률이 낮더라도 요청이 실패할 수 있으므로 사용자가 실제로 받는 서비스와 가까운 지표를 선택한다.

오류 예산

SLO가 100%보다 낮다면 일정한 실패를 허용한다. 이 허용 범위를 오류 예산으로 관리할 수 있다.

오류 예산은 새로운 기능과 변경 속도, 신뢰성 작업 사이의 판단에 사용할 수 있다. 서비스가 목표보다 안정적으로 운영된다면 일정 수준의 변경과 실험을 수행할 여유가 있고, 오류 예산을 빠르게 소진했다면 배포 속도를 낮추고 신뢰성 개선에 집중할 수 있다.

오류 예산은 의도적으로 장애를 방치하기 위한 수단이 아니다. 사용자에게 필요한 신뢰성 수준을 초과하여 무한한 비용을 사용하지 않고, 사업적 가치와 운영 위험 사이의 균형을 정하는 방법이다.

안전 필수 기능과 데이터 손실처럼 허용하기 어려운 실패에는 일반적인 서비스 오류 예산과 다른 엄격한 기준이 필요할 수 있다.

관찰 가능성

관찰 가능성은 시스템이 외부로 내보내는 정보로부터 내부 상태와 동작을 이해할 수 있는 정도이다.

운영에서 주로 사용하는 신호에는 다음이 있다.

  • 로그
  • 메트릭
  • 분산 추적
  • 이벤트
  • 프로파일
  • 상태 확인
  • 감사 기록

로그는 개별 사건과 문맥을 기록한다. 메트릭은 시간에 따른 수치와 추세를 나타낸다. 분산 추적은 하나의 요청이 여러 서비스와 구성 요소를 지나간 경로와 지연을 연결한다.

관찰 가능성은 단순히 데이터를 많이 수집하는 것과 다르다. 다음 질문에 답할 수 있어야 한다.

  • 사용자가 어떤 문제를 겪고 있는가
  • 어느 구성 요소에서 문제가 발생했는가
  • 어떤 버전과 설정에서 시작되었는가
  • 모든 요청에 영향을 주는가 일부 사용자만 영향을 받는가
  • 장애가 다른 구성 요소로 전파되고 있는가
  • 복구 조치가 효과가 있는가

운영 데이터에는 개인정보와 인증 정보가 포함될 수 있으므로 수집 범위·접근 권한·마스킹과 보존 기간을 관리해야 한다.

모니터링

모니터링은 서비스와 인프라의 상태를 지속적으로 측정하고 기록하며 이상과 목표 위반을 탐지하는 활동이다.

Google SRE는 분산 시스템을 감시할 때 지연 시간·트래픽·오류·포화 상태를 중요한 신호로 제시한다.[73]

모니터링 대상에는 다음이 포함될 수 있다.

  • 요청 성공률과 오류율
  • 응답 시간과 처리량
  • 대기열과 작업 지연
  • CPU·메모리·디스크와 네트워크
  • 데이터베이스 연결과 복제 지연
  • 프로세스와 인스턴스 상태
  • 외부 서비스 응답
  • 인증서와 토큰 만료
  • 백업 결과
  • 보안 사건
  • 사용자 작업 성공률
  • 사업 및 업무 지표

모니터링은 시스템 내부에서 직접 제공하는 화이트박스 방식과 외부 사용자처럼 실제 요청을 수행하는 블랙박스 방식으로 나눌 수 있다.

내부 상태가 정상으로 보여도 외부 DNS·인증서·네트워크 문제로 사용자는 서비스에 접근하지 못할 수 있으므로 두 관점을 함께 사용한다.

경고

경고는 측정값이 특정 임계값을 넘었다는 사실을 모두 통보하는 것이 아니라 사람의 조치가 필요한 문제를 알려야 한다.

좋은 경고에는 다음과 같은 정보가 필요하다.

  • 영향을 받는 서비스와 사용자
  • 문제의 심각도
  • 시작 시점과 지속 시간
  • 관련 지표와 로그
  • 가능한 원인
  • 즉시 수행할 조치
  • 운영 절차 문서
  • 최근 배포와 변경
  • 담당 팀과 연락 방법

CPU 사용률이 잠시 높아진 것처럼 자동으로 회복되고 사용자 영향이 없는 상태까지 사람을 호출하면 경고 피로가 발생한다.

경고 기준은 사용자 영향과 SLO·데이터 손실·장애 확산 가능성을 중심으로 정하고, 단순한 용량 추세와 장기 개선 항목은 대시보드나 작업 항목으로 분리할 수 있다.

당직 운영

중요한 서비스는 근무 시간 밖의 장애에도 대응하기 위해 당직 체계를 운영할 수 있다.

당직 운영에는 다음이 필요하다.

  • 명확한 담당 서비스
  • 호출과 단계적 확대 절차
  • 필요한 접근 권한
  • 운영 문서와 자동화 도구
  • 상황 전달과 교대 기록
  • 안전한 변경과 긴급 배포 절차
  • 피로와 업무량 관리
  • 장애 후 지원과 검토

한 사람이 모든 시스템을 기억하도록 의존하면 담당자의 부재와 피로가 큰 위험이 된다. 운영 지식과 대응 절차를 공유하고 반복 작업을 자동화한다.

당직 호출이 지나치게 많다면 인력을 늘리는 것만으로 해결하지 않고 서비스의 결함·경고 품질과 자동 복구 구조를 개선해야 한다.

운영 절차서

운영 절차서 또는 런북은 특정한 운영 작업과 장애 상황에서 수행할 절차를 기록한다.

절차서에는 다음이 포함될 수 있다.

  • 상황과 증상
  • 영향 확인 방법
  • 필요한 권한과 도구
  • 진단 순서
  • 안전한 완화 조치
  • 재시작·전환과 복구 절차
  • 중단 조건과 주의사항
  • 데이터 손실 가능성
  • 다른 팀에 전달할 기준
  • 정상화 확인 방법
  • 후속 작업

운영 절차는 실제 사고와 훈련을 통해 검증해야 한다. 존재하지 않는 명령·만료된 계정과 오래된 화면을 설명하는 문서는 장애 중 사용할 수 없다.

반복해서 사용되는 절차는 가능한 한 자동화하되, 자동화 도구의 실패와 사용 조건도 문서화한다.

용량 관리

소프트웨어는 사용자와 데이터·작업량이 증가해도 요구된 성능과 가용성을 유지해야 한다.

용량 관리에서는 다음을 관찰하고 예측한다.

  • 사용자와 요청 증가
  • 데이터와 로그의 크기
  • CPU·메모리와 저장소
  • 네트워크 대역폭
  • 연결과 작업 대기열
  • 외부 서비스 한도
  • 백업과 복구 시간
  • 비용
  • 확장에 걸리는 시간

자동 확장은 급격한 부하에 대응할 수 있지만 새 인스턴스가 준비되는 시간과 데이터베이스·외부 서비스의 한계는 별도로 고려해야 한다.

평균 사용량만 보면 짧은 최대 부하와 특정 지역·고객의 집중을 놓칠 수 있다. 백분위·계절성·사업 일정과 비정상적인 급증을 함께 분석한다.

비용 관리

클라우드와 외부 서비스에서는 자원의 사용량이 직접적인 운영 비용으로 이어질 수 있다.

비용 관리에는 다음이 포함될 수 있다.

  • 서비스와 팀별 자원 사용
  • 유휴 자원
  • 저장 데이터와 보존 기간
  • 네트워크 전송
  • 로그와 관찰 데이터
  • 외부 API 호출
  • 예약과 자동 확장
  • 지역별 비용
  • 라이선스와 지원 계약

비용을 줄이기 위해 필요한 복제와 백업·로그를 제거하면 신뢰성과 보안이 낮아질 수 있다. 비용도 성능·가용성과 함께 품질 및 아키텍처의 상충 관계로 관리한다.

장애 대응

장애 대응은 서비스의 실패와 품질 저하를 탐지하고 영향을 제한하며 정상 상태로 복구하는 활동이다.

일반적인 장애 대응은 다음과 같은 흐름을 가진다.

  1. 장애를 탐지하고 신고를 접수한다.
  2. 영향과 심각도를 분류한다.
  3. 장애 대응 책임자와 역할을 정한다.
  4. 사용자와 관련 조직에 상황을 알린다.
  5. 최근 변경과 현재 상태를 조사한다.
  6. 트래픽 차단·롤백·장애 조치 등으로 영향을 줄인다.
  7. 근본적인 문제를 수정하거나 우회한다.
  8. 서비스와 데이터가 정상인지 확인한다.
  9. 임시 조치를 정리하고 감시를 강화한다.
  10. 사후 분석과 개선 작업을 수행한다.

장애 중에는 완전한 원인을 찾는 것보다 사용자 피해와 데이터 손실을 먼저 줄여야 할 수 있다. 서비스가 안정된 뒤 더 깊은 원인 분석을 수행한다.

복잡한 장애에서는 조사·운영·의사소통 역할을 나누어 한 사람이 모든 작업을 동시에 수행하지 않도록 할 수 있다.

장애 등급과 의사소통

장애의 영향과 긴급도에 따라 등급을 나누면 필요한 대응 인력과 의사소통 수준을 빠르게 정할 수 있다.

판단 기준에는 다음이 포함될 수 있다.

  • 영향받는 사용자와 지역
  • 핵심 기능의 중단
  • 데이터 손실과 손상
  • 보안과 개인정보
  • 안전 영향
  • 복구 가능성
  • 계약과 규제
  • 예상 지속 시간

사용자에게는 확인되지 않은 원인을 단정하지 않고 현재 확인된 영향·진행 상황·사용 가능한 우회 방법과 다음 안내 시점을 제공한다.

내부 기술 용어만 사용하거나 장기간 아무런 상태를 알리지 않으면 사용자는 문제의 범위와 대응 여부를 알 수 없다.

완화와 복구

장애 대응에서는 원인을 완전히 수정하기 전에 영향을 줄이는 완화 조치를 수행할 수 있다.

  • 새 배포 중단
  • 이전 버전으로 롤백
  • 기능 플래그 비활성화
  • 문제가 있는 지역과 인스턴스 격리
  • 읽기 전용 모드 전환
  • 비핵심 기능 중지
  • 요청 제한
  • 외부 서비스 우회
  • 트래픽 재분배
  • 용량 임시 확대

완화 조치도 새로운 위험을 만들 수 있다. 이전 버전이 새 데이터 형식을 읽지 못하거나, 요청 재시도가 외부 시스템을 더 과부하시킬 수 있다.

조치 전후의 상태를 측정하고, 언제 임시 조치를 해제할지 기록한다.

롤백과 롤포워드

롤백은 문제가 있는 배포를 이전 버전으로 되돌리는 방식이다. 롤포워드는 새 수정 버전을 만들어 현재 상태에서 앞으로 진행하는 방식이다.

롤백은 빠르게 복구할 수 있지만 다음과 같은 경우 어려울 수 있다.

  • 데이터베이스 스키마와 데이터가 이미 변경되었다.
  • 새 버전이 이전 버전과 호환되지 않는 데이터를 생성했다.
  • 외부 시스템의 상태가 변경되었다.
  • 장치 펌웨어가 되돌리기를 지원하지 않는다.
  • 보안 수정 때문에 이전 버전을 다시 사용할 수 없다.

배포 전에 롤백 가능성을 확인하고, 되돌릴 수 없는 변경은 단계적 호환 구조와 백업·보상 작업을 준비한다.

단순한 코드 결함은 롤백이 적합할 수 있고, 데이터와 외부 상태가 이미 바뀐 경우에는 수정 버전을 빠르게 배포하는 롤포워드가 안전할 수 있다.

사후 분석

장애가 끝난 뒤에는 발생 과정과 기여 요인, 대응과 개선점을 분석한다.

사후 분석에는 다음이 포함될 수 있다.

  • 장애의 영향과 지속 시간
  • 시간 순서
  • 탐지와 경고 과정
  • 직접 원인과 기여 요인
  • 장애가 확산된 이유
  • 효과가 있었던 대응
  • 대응을 방해한 요소
  • 사용자와 조직의 의사소통
  • 재발 방지와 영향 완화 작업
  • 담당자와 완료 기한

Google SRE는 비난 없는 사후 분석을 개인의 잘못을 찾기보다 사고에 기여한 기술과 프로세스 조건을 발견하는 방식으로 설명한다.[74]

비난하지 않는다는 것은 책임과 행동을 검토하지 않는다는 뜻이 아니다. 당시의 정보와 도구·절차 속에서 왜 해당 판단이 합리적으로 보였는지 분석하고, 같은 조건에서 다른 사람이 실수하지 않도록 시스템을 개선한다.

개선 항목은 단순히 “주의한다”거나 “교육한다”는 표현에 그치지 않고 자동 검사·구조 변경·경고·시험과 운영 절차처럼 확인 가능한 조치로 만든다.

반복 작업과 자동화

운영에는 배포·계정 처리·용량 조정·장애 복구·보고처럼 반복되는 수작업이 존재한다.

Google SRE는 수동적이고 반복적이며 지속적인 가치를 만들지 않고 서비스 규모에 따라 선형적으로 증가하는 운영 작업을 토일(toil)로 설명한다.[75]

반복 작업을 자동화하면 다음과 같은 효과가 있다.

  • 작업 결과의 일관성
  • 사람의 입력 오류 감소
  • 빠른 복구
  • 감사 가능한 기록
  • 대규모 환경 처리
  • 운영자의 분석과 개선 시간 확보

자동화하기 전에 작업의 목적과 예외를 이해해야 한다. 잘못된 수동 절차를 그대로 자동화하면 오류가 더 빠르게 반복된다.

자동화한 뒤에도 실패 시 수동 복구 경로와 관찰 수단이 필요하다.

백업

백업은 데이터와 설정·소프트웨어 상태를 별도의 위치에 복사하여 손실과 손상 이후 복구할 수 있도록 하는 활동이다.

백업 정책에서는 다음을 정한다.

  • 백업 대상
  • 전체·증분과 차등 방식
  • 생성 주기
  • 보존 기간
  • 저장 위치와 지역
  • 암호화와 접근 권한
  • 무결성 검사
  • 삭제와 법률 보존
  • 복구 순서
  • 담당자와 자동화
  • 랜섬웨어와 관리자 계정 침해에 대한 격리

백업 성공 로그만으로 복구 가능성을 보장할 수 없다. 실제 복원 시험을 수행하여 필요한 파일·키·도구와 절차가 갖춰졌는지 확인한다.

운영 데이터뿐 아니라 다음도 백업할 수 있다.

  • 소스 코드와 이력
  • 패키지와 릴리스 산출물
  • 설정과 인프라 정의
  • 비밀 정보와 키의 안전한 복구 자료
  • 문서와 이슈
  • 외부 의존성
  • 감사 기록

복구 목표

복구 계획에서는 허용 가능한 중단과 데이터 손실을 목표로 정할 수 있다.

복구 시간 목표(Recovery Time Objective, RTO)는 장애 이후 서비스를 복구해야 하는 목표 시간이다. 복구 시점 목표(Recovery Point Objective, RPO)는 복구 과정에서 허용할 수 있는 데이터 손실의 시간 범위를 나타낸다.

RTO와 RPO는 백업 주기·복제·자동 복구·대체 환경과 운영 비용에 영향을 준다.

모든 시스템에 거의 즉각적인 복구와 데이터 무손실을 요구하면 높은 비용과 복잡성이 발생한다. 업무의 중요도와 데이터 재생성 가능성에 따라 목표를 정한다.

재해 복구와 업무 연속성

재해 복구는 단일 프로세스나 서버 장애를 넘어 지역·시설·주요 공급자와 대규모 데이터 손실 같은 사건에서 서비스를 복구하는 활동이다.

NIST는 비상 계획을 장애 이후 정보 시스템·운영과 데이터를 복구할 수 있도록 계획·절차와 기술적 수단을 조정하는 전략으로 설명한다.[76]

재해 복구 계획에는 다음이 포함될 수 있다.

  • 중요 업무와 시스템의 우선순위
  • 대체 지역과 장비
  • 데이터 복제와 백업
  • 네트워크와 DNS 전환
  • 외부 공급자와 연락
  • 직원과 권한
  • 수동 업무 절차
  • 사용자와 규제 기관 통보
  • 정상 환경으로의 복귀
  • 훈련과 계획 갱신

계획은 정기적인 훈련과 실제 전환 시험을 통해 검증한다. 문서상 대체 환경이 존재해도 용량·데이터·권한과 인증서가 준비되지 않았다면 사용할 수 없다.

보안 운영

운영 중에는 새 취약점과 공격·계정 유출·잘못된 설정에 지속적으로 대응해야 한다.

보안 운영에는 다음이 포함될 수 있다.

  • 취약점과 보안 공지 감시
  • 운영체제·라이브러리와 펌웨어 패치
  • 접근 권한 검토
  • 비밀 정보와 키 교체
  • 보안 로그와 이상 행위 분석
  • 침해 지표 감시
  • 취약한 서비스 격리
  • 사고 대응
  • 데이터와 시스템의 포렌식 보존
  • 사용자와 관계 기관 통보
  • 공급망과 서명 검증

보안 패치는 일반 기능 업데이트보다 빠르게 배포해야 할 수 있지만, 검증 없이 긴급 배포하면 서비스 장애가 발생할 수 있다. 위험 수준에 따라 시험 범위를 조정하고 단계적 배포와 복구 수단을 준비한다.

NIST SSDF는 소프트웨어 릴리스의 무결성을 검증하고 각 릴리스의 출처 자료를 수집·보호하며, 발견된 취약점에 대응하는 관행을 제시한다.[77]

패치 관리

패치 관리는 운영체제·응용 프로그램·라이브러리·장치와 외부 구성 요소의 수정 버전을 평가하고 적용하는 활동이다.

패치 관리에서는 다음을 고려한다.

  • 취약점과 결함의 심각도
  • 영향을 받는 제품과 버전
  • 실제 노출과 공격 가능성
  • 패치의 호환성과 부작용
  • 시험과 배포 일정
  • 재시작과 서비스 중단
  • 롤백과 복구
  • 지원되지 않는 버전
  • 설치 결과와 자산 상태

모든 패치를 즉시 적용할 수 없는 환경에서는 네트워크 차단·기능 비활성화·접근 제한과 감시 강화 같은 임시 완화 조치를 사용할 수 있다.

지원이 종료되어 패치를 받을 수 없는 구성 요소는 교체·격리와 서비스 종료 계획을 세워야 한다.

사용자 지원

운영에는 사용자의 질문과 문제를 접수하고 해결하는 지원 활동도 포함된다.

지원 과정에서 수집한 정보는 다음과 같이 활용할 수 있다.

  • 반복되는 사용성 문제
  • 문서와 오류 메시지의 부족
  • 특정 환경의 호환성 문제
  • 발견되지 않은 결함
  • 기능 요구와 우선순위
  • 설치와 업데이트 실패
  • 교육과 안내 필요
  • 계정과 데이터 복구

지원 요청은 단순히 개별적으로 해결하고 끝내지 않고, 반복 패턴을 분석하여 제품과 문서·운영 절차를 개선한다.

사용자에게 로그와 민감한 정보를 요청할 때는 개인정보와 보안 절차를 지켜야 한다.

소프트웨어 유지보수

소프트웨어 유지보수는 배포된 프로그램의 결함 수정뿐 아니라 변화하는 요구와 환경에 대응하고 장기적인 품질을 유지하는 활동이다.

유지보수 과정에는 다음이 포함될 수 있다.

  • 문제와 변경 요청 접수
  • 영향과 우선순위 분석
  • 요구사항과 설계 검토
  • 수정 구현
  • 회귀와 품질 시험
  • 구성과 문서 갱신
  • 릴리스와 배포
  • 운영 결과 확인
  • 완료와 기록

소프트웨어는 물리적인 부품처럼 사용으로 마모되지는 않지만, 주변 환경과 요구사항이 계속 변하고 변경이 누적되면서 구조가 복잡해질 수 있다.

운영체제와 언어 런타임·하드웨어·브라우저·외부 API가 바뀌면 기존 코드 자체가 변하지 않아도 제대로 실행되지 않을 수 있다.

수정 유지보수

수정 유지보수는 운영 중 발견된 결함을 수정한다.

대상에는 다음이 포함될 수 있다.

  • 잘못된 계산과 상태
  • 충돌과 데이터 손상
  • 메모리와 자원 누수
  • 동시성 문제
  • 보안 취약점
  • 잘못된 사용자 인터페이스
  • 문서와 실제 동작의 차이
  • 설정과 배포 오류

수정 전에 문제의 재현 조건과 영향 범위를 확인하고, 같은 문제가 다시 발생하지 않도록 회귀 시험을 추가한다.

표면적인 증상만 수정하지 않고 요구사항·설계·시험·관찰 가능성에서 결함이 발견되지 않은 이유도 분석할 수 있다.

적응 유지보수

적응 유지보수는 소프트웨어의 외부 환경 변화에 대응한다.

외부 변화에는 다음이 있다.

  • 운영체제와 하드웨어
  • 프로그래밍 언어와 런타임
  • 데이터베이스
  • 웹 브라우저와 장치
  • 외부 API와 프로토콜
  • 법률과 규제
  • 보안 표준
  • 조직의 업무 절차
  • 클라우드와 공급자
  • 데이터 규모와 사용자 수

적응 유지보수는 새 기능처럼 보이지 않더라도 소프트웨어를 계속 사용할 수 있게 하는 필수 활동이다.

외부 구성 요소의 지원 종료 일정을 추적하고, 종료 직전에 급하게 이전하지 않도록 사전에 호환성과 대안을 검토한다.

완전 유지보수

완전 유지보수는 사용자의 요구와 사업적 필요에 따라 기존 기능·성능·사용성과 품질을 개선한다.

다음과 같은 활동이 포함될 수 있다.

  • 새 기능 추가
  • 사용자 인터페이스 개선
  • 성능과 용량 향상
  • 보고와 검색 강화
  • 자동화와 운영 기능
  • 새로운 장치와 플랫폼 지원
  • 접근성과 국제화 개선
  • API와 통합 기능 확장

완전 유지보수는 기존 시스템의 구조와 호환성을 유지하면서 수행되므로 초기 개발보다 변경 제약이 많을 수 있다.

기능 추가가 누적되면서 원래 구조의 책임과 경계가 맞지 않게 되면 리팩터링과 아키텍처 개선을 함께 수행해야 한다.

예방 유지보수

예방 유지보수는 미래의 결함과 변경 비용을 줄이기 위해 내부 품질과 개발·운영 환경을 개선한다.

다음과 같은 활동이 포함될 수 있다.

  • 리팩터링
  • 중복과 사용하지 않는 코드 제거
  • 자동화된 시험 보강
  • 의존성과 도구 체인 갱신
  • 경고와 정적 분석 문제 해결
  • 운영 자동화
  • 로그와 진단 개선
  • 문서와 운영 절차 갱신
  • 데이터와 API 이전 준비
  • 취약한 구조와 권한 개선

예방 유지보수는 사용자가 즉시 볼 수 있는 기능을 만들지 않으므로 우선순위에서 밀리기 쉽다. 그러나 장기간 미루면 기능 개발과 장애 수정 비용이 증가한다.

예방 작업은 추상적인 “코드 정리”보다 반복 결함·느린 배포·장애 복구와 변경 비용 같은 실제 위험과 연결하여 계획한다.

긴급 유지보수

심각한 장애와 보안 취약점, 데이터 손상에 대응하기 위해 일반적인 개발 주기보다 빠르게 수정·배포하는 긴급 유지보수가 필요할 수 있다.

긴급 변경에서도 최소한 다음을 유지해야 한다.

  • 변경 이유와 책임자
  • 수정 범위
  • 코드 검토
  • 핵심 시험
  • 배포와 복구 방법
  • 적용된 버전과 환경
  • 장애 이후의 추가 검토

긴급 상황을 이유로 모든 통제를 생략하면 새로운 장애와 추적 불가능한 변경을 만들 수 있다.

장애가 안정된 뒤에는 임시 수정의 구조와 시험·문서를 정식으로 보완한다.

유지보수성

유지보수성은 소프트웨어를 분석하고 수정·시험하며 환경 변화에 적응시키기 쉬운 정도이다.

유지보수성에 영향을 주는 요소에는 다음이 있다.

  • 모듈과 책임의 명확성
  • 결합도와 의존성
  • 코드와 데이터의 중복
  • 시험과 빌드 자동화
  • 관찰 가능성
  • 문서와 설계 결정
  • 개발 환경의 재현성
  • API와 데이터의 호환성
  • 외부 구성 요소의 상태
  • 팀의 지식과 소유권

소스 코드가 읽기 쉽더라도 빌드할 수 없거나 시험 환경을 만들 수 없고 운영 데이터를 해석할 수 없다면 유지보수하기 어렵다.

유지보수성은 최초 설계의 품질뿐 아니라 운영 중 지속적인 리팩터링·문서화와 구성 관리에 의해 유지된다.

레거시 소프트웨어

레거시 소프트웨어는 오래되었다는 이유만으로 정의되지 않는다. 조직이 계속 의존하지만 기술·구조·지식과 지원 환경 때문에 변경과 운영이 어려운 기존 소프트웨어를 가리킬 수 있다.

레거시 시스템은 다음과 같은 특징을 가질 수 있다.

  • 오래된 언어와 플랫폼
  • 지원 종료된 도구와 의존성
  • 자동 시험 부족
  • 문서와 담당자 부족
  • 강한 결합과 공유 데이터
  • 수동 배포와 운영
  • 외부 시스템의 높은 의존성
  • 중요한 업무 규칙과 장기 데이터
  • 교체 시 큰 중단과 위험

레거시 소프트웨어는 단순히 나쁘거나 불필요한 코드가 아니다. 오랜 기간 검증된 업무 규칙과 조직의 핵심 데이터를 포함할 수 있으며, 안정적으로 운영되는 부분을 무리하게 교체하는 것도 위험하다.

현대화 여부는 유지 비용·보안·지원 가능성·변경 필요와 교체 위험을 함께 비교하여 결정한다.

소프트웨어 현대화

소프트웨어 현대화는 기존 소프트웨어의 가치와 데이터를 유지하면서 구조·플랫폼·운영 방식과 사용자 경험을 현재 요구에 맞게 개선하는 활동이다.

현대화 방식에는 다음이 있다.

  • 기존 시스템 유지
  • 운영체제와 하드웨어 이전
  • 가상 머신이나 컨테이너로 이동
  • 데이터베이스와 런타임 갱신
  • 일부 구성 요소 교체
  • 외부 API와 어댑터 추가
  • 모듈 분리
  • 사용자 인터페이스 재구축
  • 서비스와 클라우드 이전
  • 전체 재작성
  • 상용 제품과 외부 서비스로 대체
  • 기능 통합과 폐기

현대화는 기술이 오래되었다는 이유만으로 전체를 새로 만드는 작업이 아니다. 기존 시스템의 실제 동작과 데이터·사용자·예외 절차를 먼저 분석해야 한다.

재작성 과정에서 문서화되지 않은 업무 규칙과 호환성이 사라질 수 있으므로 기존 시스템을 하나의 요구사항 자료이자 시험 오라클로 활용하되, 기존 결함까지 그대로 복제하지 않도록 독립적으로 검증한다.

점진적 이전

대규모 시스템을 한 번에 교체하는 방식은 전환 시점의 위험과 데이터 이전 부담이 크다.

점진적 이전에서는 새로운 구성 요소를 기존 시스템 옆에 배치하고 기능·사용자와 데이터를 단계적으로 이동한다.

다음과 같은 방법을 사용할 수 있다.

  • 기존 시스템 앞에 새로운 인터페이스 계층 추가
  • 특정 기능부터 새 서비스로 분리
  • 읽기 경로를 먼저 이전
  • 데이터를 동시에 기록한 뒤 비교
  • 일부 사용자와 지역부터 전환
  • 이전 시스템의 기능을 점차 축소
  • 최종적으로 이전 시스템 종료

점진적 이전 기간에는 두 시스템이 함께 실행되므로 데이터 동기화·책임·오류와 운영 비용이 증가한다.

이전의 완료 조건과 이전 시스템을 제거할 시점을 정하지 않으면 임시 이중 구조가 장기간 유지될 수 있다.

리팩터링과 재공학

리팩터링은 외부 동작을 유지하면서 내부 코드 구조를 개선한다. 소프트웨어 재공학은 기존 시스템을 분석하고 재구조화·변환하여 새로운 형태로 발전시키는 더 넓은 활동을 포함할 수 있다.

재공학에는 다음이 포함될 수 있다.

  • 코드와 의존성 분석
  • 구조와 데이터 모델 복원
  • 문서 생성
  • 언어와 플랫폼 변환
  • 모듈 재구성
  • 데이터 이전
  • 자동 시험 확보
  • 사용되지 않는 기능 제거
  • 사용자 인터페이스 재구축

자동 변환 도구는 대량의 기계적인 변환을 수행할 수 있지만 생성된 코드의 구조와 의미·성능과 운영 특성을 검토해야 한다.

기술 부채의 관리

운영과 유지보수 과정에서는 단기 대응·임시 구조와 오래된 의존성이 누적될 수 있다.

기술 부채는 다음과 같이 나타날 수 있다.

  • 반복되는 수동 배포
  • 시험이 없는 핵심 기능
  • 오래된 라이브러리와 런타임
  • 강한 모듈 결합
  • 중복된 데이터와 규칙
  • 임시 설정과 기능 플래그
  • 소유자 없는 서비스
  • 불필요한 운영 경고
  • 오래된 문서와 절차
  • 복구할 수 없는 데이터 구조

기술 부채를 모두 같은 중요도로 처리하지 않고 장애·보안·변경 비용과 제품 수명을 기준으로 우선순위를 정한다.

기능 개발 과정에 작은 구조 개선을 포함하고, 위험이 큰 부채는 별도 계획과 측정 기준을 통해 관리할 수 있다.

지원 정책

소프트웨어 제품은 어떤 버전을 언제까지 지원할지 명확히 해야 한다.

지원 정책에는 다음이 포함될 수 있다.

  • 일반 지원 기간
  • 장기 지원 버전
  • 보안 수정 기간
  • 지원 운영체제와 하드웨어
  • 이전 버전에서의 업그레이드 경로
  • 호환되는 데이터와 API
  • 지원 종료 통보 기간
  • 유료 또는 확장 지원
  • 취약점 신고와 대응 방법

모든 과거 버전을 계속 지원하면 수정·시험과 보안 비용이 증가한다. 지원 범위를 제한하되 사용자가 안전하게 이전할 시간과 도구를 제공한다.

서버 소프트웨어는 제공자가 배포를 통제할 수 있지만, 설치형 소프트웨어와 라이브러리는 오래된 버전이 계속 사용될 수 있으므로 호환성과 보안 공지 방식이 다르다.

사용 중단과 폐기

소프트웨어가 더 이상 필요한 가치를 제공하지 않거나 유지 비용과 위험이 지나치게 커지면 서비스를 종료하고 폐기할 수 있다.

폐기는 프로그램과 서버를 단순히 삭제하는 작업이 아니다. 사용자·데이터·외부 연동과 법률 의무를 다른 시스템으로 전환해야 한다.

폐기 계획에는 다음이 포함될 수 있다.

  • 종료 이유와 책임자
  • 종료 일정과 사용자 통보
  • 대체 시스템
  • 데이터 내보내기와 이전
  • 법적 보존과 삭제
  • 외부 API와 연동 종료
  • 사용자와 운영자 교육
  • 계정·권한과 비밀 정보 폐기
  • 서버·저장소와 라이선스 해제
  • 소스·산출물과 문서 보존
  • 종료 후 지원
  • 최종 보안과 감사

공개 API와 파일 형식을 종료할 때는 폐기 예정 상태와 대체 기능, 종료 버전과 날짜를 미리 안내한다.

데이터 삭제는 운영 데이터뿐 아니라 복제본과 캐시·백업과 로그에 미치는 영향을 고려한다.

폐기 이후의 보존

서비스가 종료되어도 다음 자료를 일정 기간 보관해야 할 수 있다.

  • 소스 코드와 릴리스
  • 빌드 도구와 의존성
  • 설계와 요구사항
  • 사용자와 운영 문서
  • 데이터 스키마
  • 변경과 승인 기록
  • 시험과 품질 증거
  • 보안 사건과 감사 기록
  • 라이선스와 계약 자료

보존 기간은 법률·계약·제품 책임과 향후 데이터 해석 필요에 따라 정한다.

민감한 개인정보와 비밀 정보는 보존 필요와 삭제 의무를 구분하고, 보관 자료에도 접근 통제와 암호화를 적용한다.

운영과 유지보수 지표

배포·운영과 유지보수의 상태를 이해하기 위해 여러 지표를 사용할 수 있다.

  • 변경이 커밋부터 운영에 도달하는 시간
  • 배포 빈도
  • 실패한 배포의 비율
  • 실패한 배포에서 복구하는 시간
  • 배포 재작업
  • 서비스 가용성과 SLO 달성률
  • 장애 수와 심각도
  • 탐지·완화와 복구 시간
  • 사용자 오류와 지원 요청
  • 결함 수정 기간
  • 패치와 의존성의 최신성
  • 운영 수작업
  • 백업과 복구 성공률
  • 비용과 자원 사용

DORA는 현재 소프트웨어 전달 성능을 측정하는 지표로 변경 리드 타임·배포 빈도·배포 실패율·실패한 배포의 복구 시간과 배포 재작업률을 제시한다.[78]

지표는 팀과 개인의 단순 순위를 만들기보다 병목과 위험·개선 결과를 이해하는 데 사용한다.

배포 빈도만 높이기 위해 의미 없는 배포를 늘리거나 복구 시간을 줄이기 위해 장애 기록을 조기에 종료하면 측정의 목적이 훼손된다.

피드백과 지속적 개선

운영은 소프트웨어의 실제 품질과 사용 방식을 확인하는 가장 중요한 정보원이다.

다음과 같은 정보가 개발에 반영될 수 있다.

  • 장애와 결함
  • 성능과 용량
  • 사용자 행동
  • 지원 요청
  • 배포 실패
  • 보안 사건
  • 비용
  • 외부 의존성
  • 운영 수작업
  • 서비스 수준

이 정보를 요구사항·설계·시험과 개발 프로세스에 연결하면 같은 문제가 반복되는 것을 줄일 수 있다.

운영 데이터만으로 사용자의 목표와 만족도를 완전히 알 수는 없다. 수치와 로그에 나타나지 않는 문제를 확인하기 위해 사용자 조사와 직접적인 피드백도 함께 사용한다.

배포, 운영과 유지보수의 통합

배포·운영과 유지보수는 구현이 끝난 뒤 다른 조직에 넘기는 부수적인 활동이 아니다. 소프트웨어가 실제 사용자와 환경에서 가치를 제공하는 기간 대부분을 차지한다.

개발 단계에서 다음 요소를 미리 고려하면 운영과 유지보수 위험을 줄일 수 있다.

  • 자동화된 설치와 배포
  • 버전과 호환성
  • 데이터 이전
  • 모니터링과 진단
  • 장애 격리와 복구
  • 백업과 재해 복구
  • 보안 업데이트
  • 운영 권한과 절차
  • 기능의 단계적 출시
  • 서비스 종료와 데이터 이동

운영 경험은 다시 요구사항과 아키텍처·구현과 시험으로 돌아가야 한다. 배포 실패가 반복된다면 배포 담당자의 실수만을 탓하는 대신 산출물·자동화와 호환성 구조를 개선해야 한다. 장애 복구가 느리다면 운영자 교육뿐 아니라 관찰 가능성·모듈 경계와 롤백 구조를 검토해야 한다.

소프트웨어의 품질은 배포 시점의 코드만으로 결정되지 않는다. 실제 환경에서 상태를 파악하고 안전하게 변경하며, 장애에서 복구하고, 새로운 요구와 기술에 적응하고, 필요할 때 데이터와 사용자를 보호하며 종료할 수 있어야 한다.

배포·운영과 유지보수는 소프트웨어를 일회성 산출물이 아니라 계속 변화하고 관리되는 서비스와 제품으로 다루는 소프트웨어 공학의 핵심 활동이다.

소프트웨어 개발 방법론

소프트웨어 개발 방법론(Software Development Methodology)은 소프트웨어를 계획·분석·설계·구현·시험·배포하고 개선하기 위해 사용하는 원칙과 역할, 활동, 작업 흐름, 산출물과 관리 규칙을 조직한 체계이다.

방법론은 단순히 개발 단계를 순서대로 나열한 생명주기 모델과는 구분된다. 생명주기 모델이 개발 활동의 전체적인 진행 구조를 표현한다면, 방법론은 각 활동을 누가 어떤 방식으로 수행하고, 무엇을 만들며, 어떻게 검토하고 다음 작업으로 이어갈지를 더 구체적으로 다룬다.

예를 들어 반복·점진적 생명주기를 사용하는 두 프로젝트라도 한쪽은 Scrum의 역할과 이벤트를 사용하고, 다른 쪽은 Kanban으로 작업 흐름과 재공 제한을 관리할 수 있다. 같은 Scrum을 사용하는 팀도 구현에서는 테스트 주도 개발과 짝 프로그래밍을 적용하거나, 배포에서는 지속적 전달과 기능 플래그를 사용할 수 있다.

소프트웨어 개발 방법론에는 다음과 같은 요소가 포함될 수 있다.

  • 개발의 기본 원칙과 가치
  • 생명주기와 반복 구조
  • 역할과 책임
  • 요구사항과 작업의 표현 방식
  • 계획과 우선순위 결정
  • 분석과 설계 방법
  • 구현과 통합 규칙
  • 시험과 품질 보증
  • 변경과 구성 관리
  • 검토와 승인
  • 릴리스와 배포
  • 운영 피드백
  • 성과와 품질 측정
  • 프로세스 개선

IEEE Computer Society의 SWEBOK는 소프트웨어 생명주기와 프로세스 모델, 생명주기 조정, 프로세스 관리와 개선, 관련 방법과 도구를 소프트웨어 공학 프로세스의 주요 범위로 다룬다.[79]

방법론은 개발자가 반드시 그대로 따라야 하는 고정된 의식 절차가 아니다. 프로젝트의 규모와 위험, 규제, 요구사항의 변화 가능성, 배포 환경과 조직 구조에 맞추어 필요한 활동과 산출물을 선택하고 조정해야 한다.

방법론과 관련 개념

소프트웨어 개발에서 방법론과 비슷한 여러 표현이 함께 사용된다.

생명주기 모델은 소프트웨어가 구상부터 개발·운영과 폐기까지 거치는 활동의 관계를 표현한다. 순차형, 반복형, 점진형과 나선형 등이 이에 해당한다.

프로세스 모델은 특정 목적을 달성하기 위해 활동과 작업, 입력과 출력이 어떻게 연결되는지 표현한다.

방법론은 생명주기와 프로세스를 실제 조직에서 적용하기 위한 원칙과 역할, 절차, 기법과 산출물을 묶는다.

프레임워크는 필요한 역할과 활동, 규칙을 제공하지만 구체적인 기술적 방법을 모두 지정하지 않는 비교적 유연한 구조이다. Scrum은 스스로를 복잡한 문제를 다루기 위한 경량 프레임워크로 정의한다.[80]

방법은 요구사항 분석, 설계, 시험과 계획을 수행하는 구체적인 접근이다. 객체 지향 분석이나 위험 기반 시험 등이 이에 해당한다.

기법은 사용자 인터뷰, 프로토타이핑, 코드 검토, 짝 프로그래밍과 같은 개별적인 수행 수단이다.

관행은 팀이 반복적으로 수행하는 실제 작업 방식이다. 일일 회의, 작은 커밋, 자동화된 시험과 코드 소유 규칙 등이 포함될 수 있다.

이러한 용어는 문헌과 조직에 따라 일부 겹쳐 사용된다. 중요한 것은 이름보다 실제로 어떤 문제를 해결하며 어떤 활동과 책임을 요구하는지를 이해하는 것이다.

방법론의 목적

개발 방법론은 많은 사람이 장기간 함께 작업하는 과정에서 필요한 공통 구조를 제공한다.

방법론은 다음과 같은 문제를 다룬다.

  • 무엇을 먼저 개발해야 하는가
  • 요구사항과 우선순위를 누가 결정하는가
  • 불확실한 요구를 언제 구체화하는가
  • 중요한 기술적 위험을 언제 확인하는가
  • 설계와 코드 변경을 어떻게 검토하는가
  • 여러 개발자의 작업을 어떻게 통합하는가
  • 진행 상황과 완료를 무엇으로 판단하는가
  • 사용자 피드백을 언제 어떻게 반영하는가
  • 품질과 일정 사이의 결정을 누가 내리는가
  • 변경과 장애에서 무엇을 학습하는가

방법론은 개발 성공을 자동으로 보장하지 않는다. 잘못된 목표와 불충분한 기술 능력, 비현실적인 일정과 책임 불명확성을 특정 회의나 문서 양식만으로 해결할 수는 없다.

적절한 방법론은 중요한 정보를 필요한 시점에 드러내고, 위험한 가정을 조기에 검증하며, 개발자와 이해관계자가 같은 목표와 상태를 공유하도록 돕는다.

계획 중심과 적응 중심

개발 방법론은 흔히 계획 중심 접근적응 중심 접근으로 비교된다.

계획 중심 접근에서는 개발 초기에 요구사항과 설계, 일정과 산출물을 비교적 상세하게 정의하고, 승인된 계획과 기준선을 중심으로 작업을 통제한다. 단계별 문서와 공식 검토, 변경 통제가 중요한 역할을 한다.

적응 중심 접근에서는 요구사항과 해결 방법이 개발 과정에서 계속 구체화될 수 있음을 전제로 한다. 짧은 주기로 작동하는 소프트웨어를 만들고 사용자와 운영 환경의 피드백에 따라 계획을 갱신한다.

두 접근은 서로 완전히 배타적이지 않다. 반복적 개발에서도 장기 목표와 아키텍처, 예산과 규제 계획이 필요하며, 계획 중심 프로젝트에서도 프로토타입과 반복 개발을 사용할 수 있다.

선택의 핵심은 계획을 세울 것인지 여부가 아니라 다음을 결정하는 데 있다.

  • 어느 범위까지 미리 확정할 수 있는가
  • 어떤 결정은 나중까지 미루는 편이 좋은가
  • 변경 비용이 언제 급격히 증가하는가
  • 사용자 피드백을 얼마나 빨리 얻을 수 있는가
  • 실패했을 때 피해가 얼마나 큰가
  • 어떤 증거와 승인이 필요한가

예측성과 적응성

방법론은 미래를 예측하는 활동과 새로운 정보에 적응하는 활동 사이에서 균형을 정한다.

예측 가능한 요소에는 다음이 있을 수 있다.

  • 적용해야 하는 법률과 표준
  • 지원해야 하는 하드웨어
  • 계약된 외부 인터페이스
  • 물리적 장치의 제작 일정
  • 안전성과 보안 기준
  • 운영 종료 날짜

불확실성이 높은 요소에는 다음이 있을 수 있다.

  • 사용자가 실제로 선호할 기능
  • 시장과 경쟁 환경
  • 새로운 사용자 인터페이스
  • 처음 사용하는 기술의 성능
  • 대규모 실제 데이터의 특성
  • 외부 서비스와 사용자 행동

예측 가능한 부분은 기준선과 상세 계획으로 관리하고, 불확실한 부분은 프로토타입·실험과 짧은 반복으로 학습할 수 있다.

모든 것을 초기에 확정하면 잘못된 가정을 장기간 유지할 위험이 있고, 모든 결정을 계속 열어 두면 구조와 일정이 불안정해질 수 있다.

순차형 개발

순차형 개발은 주요 개발 활동을 요구사항·설계·구현·시험·배포와 같은 단계로 나누고, 앞 단계의 산출물을 다음 단계의 입력으로 사용하는 접근이다.

순차형 방법은 다음과 같은 특성을 가질 수 있다.

  • 단계별 목적과 책임이 명확하다.
  • 공식적인 산출물과 승인 절차를 사용한다.
  • 완료된 기준선을 바탕으로 다음 작업을 시작한다.
  • 변경 요청과 영향을 별도로 관리한다.
  • 진행 상황을 단계와 이정표로 확인한다.
  • 조직과 계약자 사이의 인계를 명확히 한다.

순차형 구조는 요구사항이 안정적이고, 단계별 계약과 인증·승인이 중요하며, 뒤늦은 변경 비용이 큰 프로젝트에서 유용할 수 있다.

반면 실제 사용자 피드백과 통합 결과를 늦게 얻으면 요구사항의 오해와 기술적 문제가 개발 후반에 발견될 수 있다. 이를 줄이기 위해 초기 프로토타입과 설계 검증, 점진적 통합을 함께 사용할 수 있다.

폭포수 모델

폭포수 모델은 개발 활동이 위에서 아래로 흐르듯 순차적으로 진행되는 생명주기 모델을 가리킨다. 일반적으로 다음과 같은 단계로 설명된다.

  1. 요구사항 분석
  2. 시스템과 소프트웨어 설계
  3. 구현
  4. 통합과 시험
  5. 배포
  6. 운영과 유지보수

폭포수라는 명칭은 여러 역사적 단계형 개발 관행을 단순화하여 설명하는 과정에서 널리 사용되었다.

1970년 윈스턴 로이스가 발표한 Managing the Development of Large Software Systems는 요구사항에서 운영까지 이어지는 단계형 구조를 제시했지만, 단순한 일회 통과 방식에는 위험이 있으며 앞 단계로 돌아가는 반복, 초기 프로그램 설계와 시범 구현, 충분한 문서화와 고객 참여가 필요하다고 설명했다.[81]

따라서 로이스가 오늘날 단순화되어 설명되는 일방향 폭포수 방식을 그대로 권장했다고 보는 것은 정확하지 않다. 그의 논문은 대규모 소프트웨어에서 분석과 코딩만으로는 충분하지 않으며, 시험과 설계·문서화, 반복과 위험 감소가 필요하다는 점을 강조했다.

실제 폭포수형 프로젝트에서도 단계 사이의 피드백과 변경이 존재할 수 있다. 핵심은 변경이 자유롭게 지속되는 방식보다 승인된 산출물과 단계별 통제를 중심으로 진행한다는 데 있다.

V 모델

V 모델은 개발 산출물의 분해와 구체화 과정에 대응하는 검증·확인 활동을 연결하여 표현한다.

V의 왼쪽에서는 일반적으로 다음과 같은 작업을 수행한다.

  • 사용자와 사업 요구
  • 시스템 요구사항
  • 소프트웨어 요구사항
  • 아키텍처 설계
  • 상세 설계

아래쪽에서는 구현이 이루어진다.

V의 오른쪽에서는 대응하는 시험을 수행한다.

  • 단위와 구성 요소 시험
  • 통합 시험
  • 시스템 시험
  • 수용 및 운영 확인

V 모델의 핵심은 시험을 구현 완료 뒤에 처음 계획하지 않고, 각 요구사항과 설계 산출물에 대응하는 검증 방법을 함께 준비하는 데 있다.

예를 들어 시스템 요구사항은 시스템 시험과 연결되고, 사용자 요구는 수용 시험과 연결된다. 상세 설계는 단위와 구성 요소 시험의 기준이 될 수 있다.

V 모델은 안전·의료·자동차·항공과 같이 요구사항 추적성과 검증 증거가 중요한 분야에서 활용될 수 있다.

그러나 다이어그램이 좌우 대칭으로 보인다고 실제 작업이 한 번씩만 수행되는 것은 아니다. 요구사항과 설계, 구현과 시험은 여러 번 반복될 수 있다.

반복적 개발

반복적 개발은 시스템을 한 번에 완성하려 하지 않고 여러 차례의 개발 주기를 거치면서 기존 결과를 분석·수정하고 품질을 높이는 방식이다.

각 반복에서는 다음과 같은 활동을 수행할 수 있다.

  1. 반복의 목표와 위험을 정한다.
  2. 필요한 요구사항을 구체화한다.
  3. 설계와 구현을 수행한다.
  4. 통합된 결과를 시험한다.
  5. 사용자와 이해관계자의 평가를 받는다.
  6. 결과와 문제를 분석한다.
  7. 다음 반복의 계획을 조정한다.

반복의 목적은 같은 작업을 단순히 다시 수행하는 데 있지 않다. 각 반복에서 불확실성을 줄이고 새로운 정보를 얻으며 시스템의 기능과 구조를 개선해야 한다.

반복을 수행하더라도 매번 전체 구조를 임의로 바꾸면 안정적인 기반을 만들기 어렵다. 장기 목표와 중요한 아키텍처를 유지하면서 새 정보에 따라 변경한다.

점진적 개발

점진적 개발은 시스템의 전체 기능을 여러 증분으로 나누고 각 증분에서 사용할 수 있는 기능을 추가하는 방식이다.

예를 들어 온라인 문서 시스템은 다음과 같이 발전할 수 있다.

  1. 문서 생성과 저장
  2. 검색과 분류
  3. 변경 이력
  4. 공동 편집
  5. 외부 공유와 권한
  6. 오프라인 작업

각 증분은 이전 기능에 새로운 범위를 추가한다. 첫 증분부터 모든 기능이 존재하지는 않지만 제공된 범위 안에서는 사용 가능한 결과를 만들어야 한다.

점진적 개발은 사용자에게 가치를 일찍 제공하고 실제 피드백을 얻으며, 대규모 통합 위험을 나누는 데 도움이 된다.

기능 사이의 의존 관계가 강하거나 일부 기능만으로는 안전한 사용이 불가능한 시스템에서는 증분 경계를 신중하게 정해야 한다.

반복·점진적 개발

현대의 많은 방법론은 반복과 점진을 함께 사용한다. 짧은 주기마다 작동하는 기능 증분을 만들고, 이전 구조와 기능도 함께 개선한다.

반복·점진적 개발은 다음을 가능하게 한다.

  • 핵심 기능을 먼저 제공한다.
  • 실제 사용 결과를 빠르게 얻는다.
  • 위험한 기술과 요구를 조기에 시험한다.
  • 변경을 작은 단위로 통합한다.
  • 일정이 변경되어도 일부 가치를 제공한다.
  • 설계와 시험을 실제 정보에 맞게 조정한다.

반복이 짧다고 자동으로 민첩한 개발이 되는 것은 아니다. 각 반복의 결과가 통합되지 않고 시험되지 않거나, 사용자의 평가를 받지 못한다면 단순히 작업을 작은 일정 단위로 나눈 것에 그칠 수 있다.

프로토타입 방법

프로토타이핑은 요구사항과 사용자 경험, 아키텍처와 기술적 가능성을 확인하기 위해 시스템의 일부나 단순화된 버전을 만드는 방법이다.

프로토타입에는 다음과 같은 종류가 있다.

  • 종이와 화면 모형
  • 사용자 흐름 프로토타입
  • 기술 검증용 프로그램
  • 성능과 통합 프로토타입
  • 핵심 기능의 시범 구현
  • 제한된 사용자 대상 시범 서비스

폐기형 프로토타입은 특정 질문에 답한 뒤 버린다. 빠르게 만들기 위해 품질과 구조를 단순화할 수 있다.

진화형 프로토타입은 초기 구현을 계속 개선하여 실제 제품으로 발전시킨다. 이 경우 처음부터 시험과 구조, 데이터와 보안을 어느 정도 고려해야 한다.

프로토타입의 화면이 동작한다는 이유로 전체 제품이 거의 완성되었다고 판단해서는 안 된다. 데이터·보안·오류 처리·성능과 운영 구조가 구현되지 않았을 수 있다.

프로토타입을 시작하기 전에 확인할 가정과 성공·종료 기준을 정하고, 결과를 요구사항과 설계에 반영한다.

나선형 모델

나선형 모델은 반복 개발과 명시적인 위험 관리를 결합한 생명주기 모델이다.

각 반복은 일반적으로 다음과 같은 활동을 포함한다.

  • 목표와 제약, 대안을 결정한다.
  • 위험을 식별하고 평가한다.
  • 프로토타입·분석과 시험으로 위험을 줄인다.
  • 다음 수준의 제품을 개발하고 검증한다.
  • 이해관계자의 평가를 받는다.
  • 다음 반복을 계획한다.

나선형 모델의 핵심은 그림이 나선 모양이라는 사실이 아니라, 각 반복의 범위와 작업을 현재 가장 중요한 위험에 따라 결정하는 데 있다.

기술적 가능성이 가장 큰 위험이라면 초기 프로토타입과 성능 시험을 수행할 수 있다. 사용자의 요구가 불확실하다면 사용자 연구와 시범 시스템을 먼저 진행할 수 있다. 안전성이 핵심 위험이라면 위험 분석과 검증 구조를 우선할 수 있다.

SEI는 나선형 개발을 기본적인 개발 활동을 반복하면서 위험을 적극적으로 줄이는 소프트웨어 프로세스 계열로 설명한다.[82]

나선형 모델은 위험 분석 능력과 반복별 의사결정을 요구하므로 단순한 소규모 프로젝트에는 관리 비용이 클 수 있다. 대규모·복잡하고 불확실성이 높은 시스템에서 더 큰 가치를 가질 수 있다.

신속 응용 프로그램 개발

신속 응용 프로그램 개발(Rapid Application Development, RAD)은 긴 순차적 개발보다 프로토타입·사용자 참여·재사용과 짧은 개발 주기를 통해 응용 프로그램을 빠르게 만드는 접근이다.

RAD에서는 다음과 같은 방법을 사용할 수 있다.

  • 사용자와 개발자의 공동 워크숍
  • 화면과 데이터 중심 프로토타입
  • 시각적 개발 도구
  • 기존 구성 요소의 재사용
  • 짧고 고정된 개발 기간
  • 반복적인 사용자 평가
  • 기능 범위의 우선순위 조정

업무 정보 시스템과 사용자 인터페이스처럼 사용자 피드백을 빠르게 받을 수 있는 분야에 적합할 수 있다.

반면 실시간·안전 필수·대규모 기반 시스템처럼 구조와 검증에 많은 시간이 필요한 분야에서는 RAD의 속도 중심 접근만으로 충분하지 않을 수 있다.

빠르게 만든다는 이유로 아키텍처·보안과 시험을 생략하면 초기 개발은 빨라도 장기 유지보수 비용이 증가할 수 있다.

통합 프로세스

통합 프로세스(Unified Process)는 유스 케이스 중심·아키텍처 중심이며 반복·점진적으로 개발하는 프로세스 계열이다.

일반적으로 다음과 같은 단계를 사용한다.

  • 시작
  • 정련
  • 구축
  • 전이

시작 단계에서는 시스템의 목적과 범위, 주요 이해관계자와 사업적 타당성을 확인한다.

정련 단계에서는 중요한 요구사항과 아키텍처를 구체화하고 핵심 위험을 줄인다.

구축 단계에서는 여러 반복을 통해 기능을 구현·통합한다.

전이 단계에서는 사용자와 운영 환경에 시스템을 배포하고 이전·교육과 결함 수정을 수행한다.

각 단계에서도 요구사항·설계·구현과 시험이 일정한 비중으로 반복된다. 단계 이름이 존재한다고 활동이 순차적으로 한 번씩만 수행되는 것은 아니다.

Rational Unified Process는 통합 프로세스를 상용화하고 역할·산출물과 활동을 상세하게 정의한 구현으로 널리 알려졌다.

통합 프로세스는 조정 가능한 프로세스를 지향하지만, 모든 역할과 문서를 그대로 적용하면 지나치게 무거운 절차가 될 수 있다. 프로젝트에 필요한 활동과 산출물을 선택해야 한다.

애자일 소프트웨어 개발

애자일 소프트웨어 개발은 변화와 불확실성이 있는 환경에서 작동하는 소프트웨어를 짧은 주기로 제공하고, 사용자와 개발자의 협력과 지속적인 피드백을 통해 제품과 계획을 조정하는 접근의 계열이다.

2001년 2월 경량 개발 방법을 연구하고 사용하던 17명이 미국 유타주 스노버드에 모여 애자일 소프트웨어 개발 선언을 작성했다. 이 모임에는 Extreme Programming, Scrum, DSDM, Adaptive Software Development, Crystal, Feature-Driven Development와 기타 경량 방법의 관계자들이 참여했다.[83]

애자일 선언은 다음 대상을 더 가치 있게 여긴다고 밝힌다.

  • 프로세스와 도구보다 개인과 상호작용
  • 포괄적인 문서보다 작동하는 소프트웨어
  • 계약 협상보다 고객과의 협력
  • 계획을 따르기보다 변화에 대응

선언은 오른쪽의 요소에 가치가 없다고 말하지 않는다. 프로세스·도구·문서·계약과 계획에도 가치가 있지만, 왼쪽 요소에 더 높은 가치를 둔다는 의미이다.[84]

애자일 선언의 원칙은 가치 있는 소프트웨어의 조기·지속적 전달, 요구사항 변화의 수용, 잦은 작동 소프트웨어 제공, 업무 담당자와 개발자의 협력, 지속 가능한 개발과 기술적 탁월성 등을 강조한다.[85]

애자일은 문서를 만들지 않고 계획을 세우지 않는 방식이 아니다. 현재 의사결정과 장기 유지보수에 필요한 문서를 만들고, 실제 결과와 피드백을 바탕으로 계획을 계속 갱신하는 접근이다.

애자일의 반복 구조

애자일 개발에서는 일반적으로 짧은 반복 또는 지속적인 흐름을 통해 작업한다.

반복 기반 접근은 다음과 같은 흐름을 가질 수 있다.

  1. 현재 가장 중요한 목표와 기능을 선택한다.
  2. 필요한 요구사항과 수용 기준을 구체화한다.
  3. 설계·구현과 시험을 수행한다.
  4. 통합된 소프트웨어를 완성한다.
  5. 사용자와 이해관계자에게 결과를 보여 준다.
  6. 제품과 작업 방식을 평가한다.
  7. 우선순위와 계획을 조정한다.

반복의 끝에는 문서나 보고서만이 아니라 실제로 통합되고 검증된 소프트웨어 증분이 있어야 한다.

반복마다 기능을 완료하지 못한 채 분석·구현·시험을 다음 반복으로 계속 넘기면 작은 폭포수 단계를 반복하는 형태가 될 수 있다.

제품 백로그

많은 애자일 방식에서는 앞으로 수행할 기능과 개선·결함과 기술 작업을 우선순위가 있는 목록으로 관리한다.

백로그 항목에는 다음이 포함될 수 있다.

  • 사용자 기능
  • 결함 수정
  • 보안과 품질 개선
  • 기술적 위험 검증
  • 리팩터링과 기술 부채
  • 운영 자동화
  • 조사와 프로토타입
  • 문서와 이전 작업

백로그는 단순한 요청 보관함이 아니다. 제품의 목표에 따라 우선순위를 정하고, 가까운 시점의 항목은 구현할 수 있을 정도로 구체화하며, 더 이상 가치가 없는 항목은 제거한다.

모든 요구를 백로그에 넣었다는 이유로 언젠가 반드시 구현해야 하는 것은 아니다.

사용자 스토리

사용자 스토리는 특정 사용자의 관점에서 필요한 기능과 그 목적을 짧게 표현하는 방식이다.

일반적으로 다음과 같은 형태를 사용할 수 있다.

어떤 사용자로서
어떤 기능을 원한다.
그 이유는 어떤 가치를 얻기 위해서이다.

사용자 스토리는 완전한 요구사항 명세라기보다 이해관계자와 대화를 시작하기 위한 단위이다.

실제 구현에는 다음과 같은 추가 정보가 필요할 수 있다.

  • 구체적인 사용 시나리오
  • 수용 기준
  • 오류와 예외 조건
  • 품질 요구사항
  • 데이터와 권한
  • 외부 인터페이스
  • 완료 조건

모든 기술 작업을 억지로 최종 사용자 형식의 스토리로 표현할 필요는 없다. 인프라와 보안·아키텍처 작업은 해결할 위험과 결과를 직접 설명하는 편이 명확할 수 있다.

Scrum

Scrum은 복잡한 문제에서 적응 가능한 해결책을 통해 가치를 만들 수 있도록 돕는 경량 프레임워크이다. Scrum은 경험적 프로세스 통제를 바탕으로 투명성·검사와 적응을 사용한다.[86]

Scrum은 다음의 세 가지 책임 영역을 정의한다.

  • Product Owner
  • Scrum Master
  • Developers

Product Owner는 제품 목표와 Product Backlog의 효과적인 관리를 책임진다.

Scrum Master는 Scrum이 이해되고 적용되도록 돕고 팀과 조직의 효과성을 지원한다.

Developers는 각 Sprint에서 사용할 수 있는 제품 증분을 만드는 사람들이다. 개발자라는 표현은 프로그래머만이 아니라 증분 완성에 필요한 전문성을 가진 구성원을 포함한다.

Scrum Team은 하나의 제품 목표를 중심으로 일하며 내부에 별도의 하위 팀이나 계층을 두지 않는 작은 단위로 설명된다.

Scrum의 산출물

Scrum은 다음의 세 가지 산출물을 정의한다.

Product Backlog

제품을 개선하기 위해 필요한 작업의 순서 있는 목록이다. Product Goal이 Product Backlog의 장기 목표 역할을 한다.

Sprint Backlog

선택된 Product Backlog 항목과 Sprint Goal, 이를 제품 증분으로 만들기 위한 실행 가능한 계획으로 구성된다.

Increment

Sprint 동안 완료되어 이전 증분과 통합된 제품의 구체적인 결과이다. 여러 Increment가 한 Sprint 안에 만들어질 수 있으며, Definition of Done을 충족해야 한다.

Scrum의 이벤트

Scrum은 일정한 주기의 Sprint 안에서 여러 공식 이벤트를 사용한다.

Sprint

다른 모든 이벤트를 포함하는 고정 길이의 기간이다. 새로운 Sprint는 이전 Sprint가 끝난 직후 시작된다.

Sprint 동안에는 Sprint Goal을 위험하게 만드는 변경을 하지 않으며, 품질을 낮추지 않고, 필요에 따라 범위를 Product Owner와 조정할 수 있다.

Sprint Planning

Sprint가 왜 가치 있는지, 무엇을 완료할지, 선택한 작업을 어떻게 수행할지 계획한다.

Daily Scrum

Developers가 Sprint Goal을 향한 진행을 검사하고 Sprint Backlog를 조정하는 짧은 이벤트이다. 단순한 관리자 보고 회의가 아니라 개발자들이 계획을 조정하는 자리이다.

Sprint Review

완성한 결과와 환경의 변화를 이해관계자와 검토하고 다음 작업을 조정한다. 단순한 발표나 승인 회의로 한정되지 않는다.

Sprint Retrospective

품질과 효과성을 높이기 위해 사람·상호작용·프로세스·도구와 Definition of Done을 검토하고 개선을 계획한다.

Scrum의 한계

Scrum은 제품 개발의 모든 기술적 방법을 규정하지 않는다.

Scrum만으로 다음이 자동으로 제공되지는 않는다.

  • 요구사항 분석 기법
  • 소프트웨어 아키텍처
  • 코딩과 설계 규칙
  • 자동화된 시험
  • 지속적 통합
  • 보안 개발
  • 운영과 장애 대응
  • 장기적인 제품 전략

따라서 Scrum은 Extreme Programming의 기술 관행, Kanban의 흐름 관리, DevOps와 지속적 전달 등을 함께 사용할 수 있다.

Sprint와 회의를 사용한다고 자동으로 Scrum이나 애자일 개발이 되는 것은 아니다. 통합된 증분과 명확한 제품 목표, 검사와 적응이 이루어지지 않으면 일정 관리 의식만 남을 수 있다.

Extreme Programming

Extreme Programming(XP)은 빠르게 변하는 요구에서 소프트웨어 품질과 변화 대응 능력을 높이기 위해 개발 관행을 짧고 지속적으로 수행하는 애자일 방법론이다.

XP는 일반적으로 다음과 같은 가치를 강조한다.

  • 의사소통
  • 단순성
  • 피드백
  • 용기
  • 존중

XP의 대표적인 관행에는 다음이 포함될 수 있다.

  • 작은 릴리스
  • 단순한 설계
  • 테스트 우선 또는 테스트 주도 개발
  • 리팩터링
  • 짝 프로그래밍
  • 지속적 통합
  • 공동 코드 소유
  • 코딩 표준
  • 지속 가능한 작업 속도
  • 사용자 또는 고객과의 긴밀한 협력

XP는 계획과 관리의 반복 구조뿐 아니라 코드와 시험·통합을 수행하는 기술적 관행을 구체적으로 다룬다는 특징이 있다.

테스트 주도 개발

테스트 주도 개발(Test-Driven Development, TDD)은 구현하려는 동작에 대한 자동화된 시험을 먼저 작성하고, 시험을 통과하는 최소 구현을 만든 뒤 구조를 개선하는 짧은 순환을 반복한다.

일반적인 흐름은 다음과 같다.

  1. 실패하는 시험을 작성한다.
  2. 시험이 예상한 이유로 실패하는지 확인한다.
  3. 시험을 통과하는 구현을 작성한다.
  4. 모든 시험이 통과하는지 확인한다.
  5. 중복과 구조를 리팩터링한다.
  6. 다음 동작으로 반복한다.

TDD는 시험의 수를 늘리는 것뿐 아니라 작은 단위로 인터페이스와 동작을 설계하고 빠른 피드백을 얻는 개발 방식이다.

TDD만으로 통합·성능·보안과 사용자 수용 시험이 모두 대체되는 것은 아니다. 개발자가 예상하지 못한 요구와 전체 시스템 문제는 다른 시험과 검토가 필요하다.

짝 프로그래밍

짝 프로그래밍은 두 개발자가 하나의 작업 환경에서 같은 코드를 함께 작성하고 검토하는 방식이다.

한 사람은 직접 코드를 작성하고 다른 사람은 전체 방향과 결함·다음 단계를 검토하며, 두 역할을 자주 바꿀 수 있다.

짝 프로그래밍은 다음과 같은 효과를 가질 수 있다.

  • 구현 중 즉각적인 검토
  • 문제 해결 방법의 공유
  • 시스템 지식의 분산
  • 복잡한 작업의 집중
  • 신규 구성원의 학습
  • 코드 소유의 분산

모든 작업을 항상 두 사람이 수행해야 한다는 뜻은 아니다. 복잡하거나 위험한 변경과 지식 공유가 필요한 작업에 선택적으로 적용할 수 있다.

짝의 경험과 관계·작업 환경에 따라 피로와 효율이 달라질 수 있으므로 강제적인 형식보다 목적과 결과를 평가해야 한다.

공동 코드 소유

공동 코드 소유는 특정한 코드 영역을 한 사람만 수정할 수 있게 하지 않고 팀 구성원이 필요한 부분을 변경할 수 있도록 하는 관행이다.

이를 위해서는 다음이 필요하다.

  • 공통 코딩 규칙
  • 자동화된 시험
  • 코드 검토
  • 명확한 모듈과 설계
  • 변경 이력
  • 시스템 지식 공유
  • 빠른 통합

공동 소유는 책임이 없다는 뜻이 아니다. 팀이 전체 품질에 공동 책임을 지되, 중요한 구성 요소에는 전문 담당자와 검토 규칙을 둘 수 있다.

한 사람만 이해하는 코드와 운영 절차는 담당자의 부재와 이직에서 큰 위험이 된다.

지속 가능한 개발 속도

애자일과 XP는 팀이 장기간 유지할 수 있는 일정한 작업 속도를 중요하게 다룬다.

반복되는 초과 근무는 단기적으로 작업량을 늘릴 수 있지만 다음과 같은 문제를 만들 수 있다.

  • 결함과 재작업 증가
  • 설계와 시험 생략
  • 판단력과 창의성 저하
  • 운영 장애
  • 지식 공유 감소
  • 구성원의 소진과 이탈

일시적인 긴급 대응이 필요할 수 있지만 이를 정상적인 계획 방식으로 사용해서는 안 된다.

지속 가능한 속도는 느리게 개발한다는 뜻이 아니라 품질과 개선 활동을 포함하면서 장기간 예측 가능한 결과를 만드는 것을 뜻한다.

Kanban

Kanban은 작업이 가치 전달 시스템을 통해 이동하는 흐름을 시각화하고, 진행 중인 작업을 통제하며, 흐름을 측정·개선하는 접근이다.

Kanban Guide는 Kanban을 가치의 흐름을 최적화하기 위한 전략으로 설명하며, 작업 흐름 정의·진행 중 작업 통제·서비스 수준 기대와 흐름 지표를 핵심 요소로 다룬다.[87]

Kanban에서는 일반적으로 작업의 상태를 시각화하는 보드를 사용한다.

대기 → 분석 → 개발 → 검토 → 시험 → 배포

그러나 보드를 만드는 것만으로 Kanban이 완성되는 것은 아니다. 실제 흐름과 정책을 정의하고, 진행 중인 작업을 제한하며, 측정 결과를 바탕으로 개선해야 한다.

진행 중 작업 제한

진행 중 작업(Work in Progress, WIP)은 시작했지만 아직 완료되지 않은 작업이다.

동시에 너무 많은 작업을 시작하면 다음과 같은 문제가 발생할 수 있다.

  • 작업 전환 비용 증가
  • 완료와 피드백 지연
  • 검토와 시험 대기열 증가
  • 우선순위 변경의 혼란
  • 오래된 작업과 충돌
  • 실제 병목의 은폐

WIP 제한은 팀이 새로운 작업을 계속 시작하기보다 현재 작업을 완료하고 막힌 흐름을 해결하도록 유도한다.

WIP 제한은 개발자를 쉬지 못하게 만드는 최대 작업량 목표가 아니다. 시스템 전체의 흐름과 지속 가능성을 개선하기 위한 제약이다.

흐름 지표

Kanban과 흐름 중심 개발에서는 다음과 같은 지표를 사용할 수 있다.

  • WIP
  • 처리량
  • 작업 항목의 나이
  • 사이클 타임
  • 서비스 수준 기대

사이클 타임은 작업이 시작된 뒤 완료되기까지 걸리는 시간이다. 처리량은 일정 기간에 완료된 작업 수이다.

평균만으로는 오래 지연되는 일부 작업을 놓칠 수 있으므로 분포와 백분위, 진행 중인 작업의 나이를 함께 확인할 수 있다.

지표는 개인의 생산량을 비교하는 데 사용하기보다 시스템의 대기·병목과 예측 가능성을 개선하는 데 사용한다.

Scrum과 Kanban의 결합

Scrum과 Kanban은 서로 배타적이지 않다.

Scrum의 Sprint·목표·역할과 검토 구조를 유지하면서 Kanban의 다음 요소를 적용할 수 있다.

  • 작업 흐름 시각화
  • WIP 제한
  • 작업 항목의 나이 추적
  • 사이클 타임과 처리량 측정
  • 막힌 작업과 대기열 개선

운영·지원과 같이 요청이 계속 들어오고 우선순위가 급하게 바뀌는 팀은 고정된 Sprint보다 지속적인 흐름을 중심으로 운영할 수 있다.

제품 기능 개발은 Sprint를 사용하고 운영 장애와 보안 요청은 별도의 흐름으로 관리하는 방식도 가능하다.

린 소프트웨어 개발

린 소프트웨어 개발은 제조와 제품 개발의 린 사고를 소프트웨어 개발에 적용하여 사용자 가치가 흐르는 시간을 줄이고 불필요한 작업과 대기를 제거하려는 접근이다.

린 개발에서 자주 다루는 원리는 다음과 같다.

  • 낭비 제거
  • 품질을 과정에 내장
  • 지식과 학습의 생성
  • 중요한 결정을 책임 있게 늦춤
  • 빠른 가치 전달
  • 사람 존중
  • 전체 시스템 최적화

소프트웨어 개발의 낭비에는 다음과 같은 것이 포함될 수 있다.

  • 사용되지 않는 기능
  • 완료되지 않은 작업
  • 긴 승인과 대기
  • 반복되는 수동 작업
  • 불필요한 인계
  • 결함과 재작업
  • 과도한 문서와 보고
  • 작업 전환
  • 늦은 통합과 배포

낭비 제거는 시험·문서와 설계를 무조건 줄이는 것이 아니다. 결함과 위험을 줄이고 장기적인 개발을 지원하는 활동은 직접 사용자 기능이 아니더라도 가치가 있을 수 있다.

전체 최적화는 한 부서의 작업량을 최대화하기보다 아이디어가 실제 사용자 가치로 전달되는 전체 시간을 개선하는 데 초점을 둔다.

Crystal

Crystal은 프로젝트의 규모와 시스템의 중요도에 따라 필요한 방법과 통제 수준이 달라져야 한다고 보는 애자일 방법론 계열이다.

작은 공동 위치 팀과 큰 분산 팀, 생명에 영향을 주는 시스템에 동일한 절차를 적용하지 않고, 상황에 따라 서로 다른 색상과 무게의 방법을 선택한다.

Crystal은 일반적으로 다음을 중요하게 다룬다.

  • 잦은 전달
  • 반성적 개선
  • 긴밀한 의사소통
  • 개인의 안전한 의견 제시
  • 집중할 수 있는 환경
  • 사용자와 전문가에 대한 접근
  • 필요한 수준의 자동화된 시험과 구성 관리

Crystal은 정해진 역할과 산출물을 모두 적용하기보다 팀과 프로젝트에 맞는 최소한의 효과적인 프로세스를 찾는 데 초점을 둔다.

DSDM

Dynamic Systems Development Method(DSDM)는 반복·점진적 개발과 적극적인 사용자 참여, 정해진 시간과 비용 안에서의 범위 조정을 강조하는 애자일 방법론이다.

DSDM에서는 일반적으로 시간과 자원을 고정하고 기능 범위를 우선순위에 따라 조정하는 시간 상자 방식을 사용할 수 있다.

기능 우선순위에는 다음과 같은 분류가 사용될 수 있다.

  • 반드시 필요
  • 있어야 함
  • 있으면 좋음
  • 이번 범위에는 포함하지 않음

이러한 분류는 모든 항목을 최우선으로 처리하려는 상황을 방지하고, 제한된 시간 안에서 실제 사용 가능한 결과를 만드는 데 도움을 줄 수 있다.

Feature-Driven Development

Feature-Driven Development(FDD)는 사용자에게 가치가 있는 작은 기능을 중심으로 모델링·계획·설계와 구축을 반복하는 방법론이다.

일반적인 흐름은 다음과 같이 설명할 수 있다.

  1. 전체 도메인 모델을 개발한다.
  2. 기능 목록을 만든다.
  3. 기능별로 계획한다.
  4. 기능별로 설계한다.
  5. 기능별로 구축한다.

기능은 비교적 짧은 기간에 완성할 수 있는 작고 구체적인 사용자 결과로 나눈다.

FDD는 객체 모델과 기능 중심 관리에 강한 구조를 제공할 수 있지만, 사용자 연구와 운영·기술적 작업을 기능 목록만으로 충분히 표현할 수 있는지는 별도로 고려해야 한다.

적응형 소프트웨어 개발

Adaptive Software Development는 복잡하고 변화가 큰 개발에서 상세한 예측보다 가설·협력과 학습을 중심으로 진행하는 접근이다.

일반적으로 다음 흐름으로 설명된다.

  • 추측 또는 가설 수립
  • 협력
  • 학습

초기 계획을 확정된 예측으로 보기보다 현재 정보에 따른 가설로 보고, 개발 결과와 사용자 피드백을 통해 수정한다.

불확실성을 인정한다는 것이 목표와 책임을 없애는 것은 아니다. 각 반복에서 검증할 가정과 결과를 명확히 해야 한다.

DevOps

DevOps는 개발·시험·배포와 운영을 하나의 지속적인 가치 흐름으로 연결하고, 소프트웨어 변경을 빠르고 안전하게 제공하기 위한 문화와 공학 관행의 집합이다.

DevOps에는 다음과 같은 요소가 포함될 수 있다.

  • 개발과 운영의 공동 책임
  • 버전 관리
  • 지속적 통합
  • 지속적 전달과 배포
  • 자동화된 시험
  • 코드형 인프라
  • 관찰 가능성
  • 작은 변경과 빠른 피드백
  • 장애 대응과 사후 분석
  • 보안의 개발 과정 통합
  • 반복 수작업의 자동화

DevOps는 개발 방법론을 완전히 대체하지 않는다. Scrum·Kanban과 같은 작업 관리 방식에 지속적 통합·배포와 운영 책임을 결합할 수 있다.

도구를 설치하고 팀 이름을 DevOps로 바꾸는 것만으로 개발과 운영의 분리와 느린 피드백이 해결되지는 않는다. 책임과 권한, 시스템 구조와 자동화가 함께 변해야 한다.

DevSecOps

DevSecOps는 보안 활동을 개발과 운영 흐름에 통합한다.

다음과 같은 보안 활동을 지속적인 개발 과정에 포함할 수 있다.

  • 위협 모델링
  • 보안 요구사항
  • 코드와 의존성 분석
  • 비밀 정보 검사
  • 컨테이너와 인프라 설정 검사
  • 자동화된 보안 시험
  • 산출물 서명과 출처 증명
  • 취약점 대응
  • 운영 보안 감시

보안을 마지막 배포 승인 단계에서만 검사하면 구조적인 문제를 늦게 발견하고 수정 비용이 증가할 수 있다.

반대로 자동화된 보안 도구를 통과했다는 사실만으로 모든 보안 위험이 해결되지는 않는다. 사람의 설계 검토와 위협 분석, 운영 대응이 필요하다.

대규모 애자일

여러 팀과 제품·조직이 하나의 대규모 시스템을 개발하면 한 팀 안에서 사용하는 애자일 방식만으로 전체 의존성과 의사결정을 조정하기 어려울 수 있다.

대규모 개발에서는 다음 문제가 중요해진다.

  • 공통 제품 목표와 우선순위
  • 팀 사이의 인터페이스
  • 공통 아키텍처와 데이터
  • 통합과 릴리스 일정
  • 여러 백로그와 의존성
  • 규제와 공급자
  • 플랫폼과 공통 서비스
  • 조직 전체의 용량과 투자
  • 장기적인 기술 전략

이를 다루기 위해 여러 대규모 애자일 프레임워크가 제안되었다.

  • Scaled Agile Framework
  • Large-Scale Scrum
  • Nexus
  • Disciplined Agile

이러한 프레임워크는 팀 간 계획·통합과 포트폴리오 관리를 위한 구조를 제공하지만, 역할과 회의·산출물이 크게 증가할 수 있다.

규모가 커졌다는 이유만으로 프레임워크 전체를 도입하기보다 실제 조정 문제와 의존성을 먼저 분석해야 한다.

서비스와 모듈의 경계를 개선하여 팀 사이의 조정 자체를 줄이는 것도 대규모 개발 문제를 해결하는 방법이다.

Scaled Agile Framework

Scaled Agile Framework(SAFe)는 린·애자일과 시스템 사고를 조직과 포트폴리오 수준으로 확장하기 위한 운영 구조를 제공한다.

SAFe는 팀과 기술적 민첩성, 제품 개발 흐름, 린 포트폴리오 관리, 조직 변화 등의 요소를 포함한다.[88]

대규모 조직에서 공통 계획과 투자·릴리스를 조정할 수 있지만 많은 역할과 이벤트·용어가 추가될 수 있다.

SAFe를 적용하면서 팀 수준의 자율성과 빠른 피드백이 중앙 계획과 보고에 의해 약해지지 않는지 평가해야 한다.

하이브리드 방법론

실제 프로젝트에서는 하나의 방법론을 순수한 형태로만 사용하는 경우보다 여러 접근을 결합하는 경우가 많다.

예를 들면 다음과 같다.

  • 전체 계약과 인증은 단계별로 관리하고 구현은 반복적으로 수행한다.
  • 하드웨어 개발은 순차적으로 진행하고 소프트웨어는 Scrum을 사용한다.
  • 제품 개발은 Scrum, 운영과 지원은 Kanban을 사용한다.
  • 위험 분석은 나선형 방식으로 수행하고 구현은 XP 관행을 적용한다.
  • 애자일 반복 안에서 V 모델의 요구사항-시험 추적성을 유지한다.
  • 여러 팀의 장기 계획은 분기별로 조정하고 팀 내부는 지속적 흐름으로 작업한다.

하이브리드는 서로 다른 방법의 이름을 단순히 붙이는 것이 아니다. 각 활동이 해결할 문제와 서로의 관계를 명확히 해야 한다.

단계별 승인으로 인해 피드백이 수개월 지연되면서 짧은 Sprint만 유지한다면 두 접근의 장점보다 단점이 결합될 수 있다.

규제 환경의 애자일 개발

안전·의료·금융과 공공 시스템에서도 반복·점진적 개발을 사용할 수 있다. 다만 필요한 문서와 추적성·독립적인 검증과 승인을 반복 과정에 포함해야 한다.

다음과 같은 방식이 가능하다.

  • 각 반복에서 요구사항과 시험 증거를 함께 갱신한다.
  • 규제 요구를 백로그와 완료 조건에 연결한다.
  • 안전성과 보안 분석을 아키텍처와 함께 반복한다.
  • 승인된 기준선을 주기적으로 만든다.
  • 자동화된 추적성과 구성 관리를 사용한다.
  • 감사 가능한 변경과 검토 기록을 유지한다.
  • 기능 증분과 인증 가능한 릴리스를 구분한다.

애자일이라는 이유로 규제와 증거를 생략할 수 없고, 규제 환경이라는 이유로 모든 개발을 한 번의 순차 과정으로 진행해야 하는 것도 아니다.

방법론의 조정

방법론 조정은 조직과 프로젝트의 상황에 맞게 역할·활동·산출물과 통제 수준을 선택하고 변경하는 과정이다.

조정할 수 있는 요소에는 다음이 있다.

  • 반복 길이
  • 계획과 검토 주기
  • 역할의 분리와 겸임
  • 문서의 종류와 상세 수준
  • 승인과 기준선
  • 시험의 수준과 독립성
  • 분기와 통합 정책
  • 배포 빈도
  • 위험 관리
  • 사용자 참여 방식
  • 품질 지표
  • 공급자와 외부 조직의 통제

조정에서는 먼저 제거할 문서를 찾기보다 어떤 위험과 의사결정을 지원해야 하는지 확인한다.

작은 내부 도구에서는 짧은 요구사항과 코드 검토·자동 시험으로 충분할 수 있다. 안전 필수 시스템에서는 정형 명세·독립 검증과 장기적인 증거 보존이 필요할 수 있다.

SWEBOK는 생명주기와 프로세스를 프로젝트의 상황에 맞게 조정하는 활동을 소프트웨어 공학 프로세스의 주요 주제로 다룬다.[89]

방법론 선택

방법론을 선택할 때는 유행과 조직의 관습보다 시스템과 프로젝트의 특성을 기준으로 판단해야 한다.

다음과 같은 요소를 고려할 수 있다.

  • 요구사항의 안정성
  • 사용자 피드백을 얻을 수 있는 빈도
  • 시스템의 규모와 예상 수명
  • 안전·보안과 규제 위험
  • 하드웨어와 외부 시스템 의존성
  • 부분 배포 가능성
  • 데이터와 API의 호환성
  • 개발 팀의 규모와 위치
  • 공급자와 계약 구조
  • 기술적 불확실성
  • 출시 일정과 시장 변화
  • 운영과 유지보수 책임
  • 자동화와 개발 도구
  • 조직의 의사결정 방식

요구사항이 안정적이고 계약·인증이 중심이라면 단계별 기준선과 검토가 중요한 계획 중심 방법이 적합할 수 있다.

사용자의 요구가 실제 제품 사용을 통해 발전한다면 반복·점진적 개발과 프로토타이핑이 적합할 수 있다.

기술적 위험과 실패 비용이 크다면 나선형 위험 관리와 아키텍처 검증을 강화할 수 있다.

지속적으로 들어오는 운영 요청과 작은 변경을 처리한다면 Kanban과 지속적 전달이 적합할 수 있다.

하나의 시스템 안에서도 구성 요소와 작업의 성격에 따라 다른 방법을 적용할 수 있다.

팀의 규모

작은 팀은 직접적인 대화와 공통 지식으로 많은 조정을 해결할 수 있다. 역할을 여러 사람이 겸임하고 문서를 간결하게 유지할 수 있다.

팀이 커지면 다음과 같은 구조가 필요해질 수 있다.

  • 모듈과 팀 소유권
  • 공통 인터페이스와 표준
  • 여러 수준의 계획
  • 통합과 릴리스 조정
  • 지식과 결정 기록
  • 의존성 관리
  • 품질과 보안의 공통 기준
  • 플랫폼과 개발 도구 지원

큰 조직에서 회의와 보고를 늘리는 것만으로 조정 문제가 해결되지는 않는다. 시스템의 모듈 경계와 팀 사이의 의존성을 함께 개선해야 한다.

분산 팀

서로 다른 지역과 시간대에서 일하는 팀은 자연스러운 대화와 비공식적인 지식 전달이 줄어들 수 있다.

분산 개발에서는 다음이 중요할 수 있다.

  • 기록 가능한 의사결정
  • 명확한 요구사항과 인터페이스
  • 비동기 의사소통
  • 공통 버전 관리와 자동화
  • 회의가 필요한 사안과 문서로 처리할 사안의 구분
  • 겹치는 협업 시간
  • 문화와 언어 차이
  • 팀과 구성 요소의 책임
  • 원격 개발과 보안 환경

모든 대화를 문서로 대체할 수는 없고, 모든 결정을 실시간 회의로 처리하는 것도 어렵다. 동기와 비동기 협업을 목적에 맞게 조합한다.

제품 개발과 프로젝트 개발

프로젝트 중심 개발은 정해진 범위와 기간·예산 안에서 특정 산출물을 인도하는 구조를 가진다.

제품 중심 개발은 하나의 소프트웨어 제품이나 서비스를 장기간 운영하고 지속적으로 개선하는 구조를 가진다.

프로젝트 중심 환경에서는 계약·일정과 인수 기준이 중요할 수 있다. 제품 중심 환경에서는 사용자 가치·운영 지표·장기적인 구조와 지속적 전달이 중요해질 수 있다.

하나의 제품 안에서도 대규모 이전과 신규 시스템 구축을 별도의 프로젝트로 관리할 수 있다.

프로젝트 완료 시 개발 팀이 해체되면 제품의 운영과 유지보수 지식이 사라질 수 있으므로 장기 소유권과 인계를 고려해야 한다.

완료의 정의

반복·애자일 개발에서는 작업이 “완료”되었다는 공통 기준을 명확히 해야 한다.

완료 기준에는 다음이 포함될 수 있다.

  • 요구사항과 수용 기준 충족
  • 코드와 설계 검토
  • 자동화된 시험 통과
  • 주 개발선과 통합
  • 정적 분석과 보안 검사
  • 필요한 문서 갱신
  • 데이터와 API 호환성 확인
  • 지원 환경에서의 빌드
  • 관찰과 오류 처리
  • 배포 가능한 산출물 생성
  • 미해결 작업과 위험 기록

코드가 작성되었다는 사실만으로 완료로 판단하면 시험·통합과 문서가 반복 후반이나 릴리스 직전으로 밀릴 수 있다.

완료 기준은 품질을 낮추지 않는 공통 기준이지만 모든 작업에 불필요하게 같은 증거를 요구하지 않도록 위험에 따라 조정할 수 있다.

계획과 추정

개발 방법론은 미래 작업의 범위와 순서·기간을 계획하기 위해 여러 추정 방법을 사용한다.

추정 대상에는 다음이 있다.

  • 작업량
  • 기간
  • 비용
  • 인력과 기술
  • 기술적 위험
  • 외부 의존성
  • 운영과 유지보수 비용

추정 방법에는 전문가 판단, 유사 프로젝트 비교, 작업 분해, 범위 기반 추정과 통계적 예측 등이 사용될 수 있다.

애자일 팀은 작업의 상대적 크기나 복잡성을 포인트로 표현할 수 있다. 그러나 포인트는 팀 내부 계획을 위한 상대 척도이며 서로 다른 팀과 개인의 생산성을 직접 비교하는 단위로 사용하기 어렵다.

흐름 기반 팀은 과거의 사이클 타임과 처리량 분포를 이용하여 일정 범위 안에 작업이 완료될 가능성을 예측할 수 있다.

추정은 확정된 약속과 다르다. 불확실성과 가정, 범위를 함께 제시하고 실제 결과에 따라 갱신해야 한다.

시간 상자

시간 상자는 활동과 반복에 고정된 최대 기간을 정하고 그 안에서 목표와 범위를 조정하는 방식이다.

시간 상자는 다음과 같은 효과를 가질 수 있다.

  • 의사결정이 무기한 지연되는 것을 막는다.
  • 정기적인 피드백 시점을 만든다.
  • 작업을 작은 범위로 나누도록 한다.
  • 위험한 조사와 실험의 비용을 제한한다.
  • 진행 중인 작업을 주기적으로 검토한다.

시간이 끝났는데 기능이 완료되지 않았다고 품질을 낮추고 강제로 완료 처리해서는 안 된다. 작업 범위를 나누거나 다시 계획하고, 반복적으로 미완료되는 원인을 분석해야 한다.

우선순위 결정

방법론에서는 제한된 시간과 인력 안에서 가장 가치 있고 위험한 작업을 선택해야 한다.

우선순위에는 다음을 고려할 수 있다.

  • 사용자와 사업 가치
  • 안전과 보안
  • 법률과 계약
  • 기술적 위험
  • 다른 기능의 의존성
  • 시간에 따른 가치 변화
  • 구현 비용
  • 운영과 유지보수 비용
  • 학습과 피드백 가능성
  • 결함과 장애의 영향

요청이 먼저 들어온 순서나 가장 강하게 주장한 이해관계자만으로 우선순위를 결정하면 제품 목표와 위험이 반영되지 않을 수 있다.

우선순위는 한 번 정하고 고정하지 않고 사용자 피드백과 운영 결과에 따라 갱신한다.

기술 부채와 방법론

빠른 기능 제공을 강조하는 방법론이 기술 부채를 허용한다는 의미는 아니다.

반복마다 시험과 통합·리팩터링을 생략하면 다음 문제가 누적될 수 있다.

  • 다음 기능의 개발 속도 감소
  • 결함과 회귀 증가
  • 배포와 복구의 어려움
  • 아키텍처 경계의 붕괴
  • 의존성 업데이트 지연
  • 팀의 지식 편중

기술 작업도 제품의 장기 가치와 위험을 기준으로 백로그와 계획에 포함해야 한다.

기능 개발과 구조 개선을 완전히 분리하면 기술 부채가 계속 뒤로 밀릴 수 있다. 영향을 받는 코드의 작은 개선을 일상적인 작업에 포함하고, 큰 구조 문제는 명확한 목표와 측정을 가진 별도 작업으로 관리한다.

문서화

방법론에 따라 문서의 형식과 양은 달라질 수 있지만 소프트웨어 개발에는 지속적인 정보 보존이 필요하다.

문서화할 수 있는 내용에는 다음이 있다.

  • 제품 목표와 요구사항
  • 사용자와 시스템 경계
  • 아키텍처와 주요 결정
  • 공개 API와 데이터 형식
  • 개발·빌드와 시험 방법
  • 배포와 운영 절차
  • 보안과 안전 근거
  • 변경과 릴리스
  • 서비스 종료와 데이터 이전

문서의 가치는 페이지 수가 아니라 실제 의사결정과 협업·유지보수에 사용되는지로 판단해야 한다.

코드에서 자동으로 확인할 수 있는 내용을 수동 문서로 반복하면 불일치하기 쉽다. 사람이 설명해야 하는 의도·제약과 결정 이유를 중심으로 기록한다.

애자일 선언은 포괄적인 문서보다 작동하는 소프트웨어에 더 높은 가치를 두지만 문서에 가치가 없다고 말하지 않는다.[90]

방법론과 도구

프로젝트 관리·이슈 추적·버전 관리와 지속적 통합 도구는 방법론의 활동을 지원할 수 있다.

도구는 다음 기능을 제공할 수 있다.

  • 백로그와 작업 관리
  • 요구사항과 추적성
  • 코드 검토
  • 빌드와 시험
  • 배포와 승인
  • 지표와 대시보드
  • 문서와 의사결정
  • 운영 장애와 지원 요청

그러나 도구의 화면과 상태를 그대로 개발 프로세스로 받아들여서는 안 된다. 문제 해결보다 티켓 이동과 상태 갱신이 중심이 될 수 있다.

먼저 필요한 흐름과 책임을 정의하고 도구를 이에 맞게 구성해야 한다.

방법론의 형식적 도입

조직이 새로운 방법론을 도입할 때 용어와 회의만 복사하고 기존의 의사결정과 책임 구조를 유지하는 경우가 있다.

예를 들어 다음과 같은 현상이 나타날 수 있다.

  • 기존 관리자를 Scrum Master로 이름만 바꾼다.
  • 일일 회의를 개인별 보고와 감시 수단으로 사용한다.
  • Sprint마다 실제 제품 증분이 완성되지 않는다.
  • Product Owner가 우선순위를 결정할 권한을 갖지 못한다.
  • 모든 요구사항과 일정을 초기에 고정하면서 변화 대응을 요구한다.
  • 개발자의 품질 개선 시간을 제거하고 속도만 측정한다.
  • 배포와 운영은 계속 별도 조직에 수동으로 전달한다.
  • 회고에서 문제를 발견하지만 개선 작업은 수행하지 않는다.

방법론의 효과를 얻으려면 역할 이름보다 의사결정 권한·피드백과 기술적 관행이 실제로 바뀌어야 한다.

작은 폭포수의 반복

반복 개발을 사용한다고 하면서 각 반복의 초반에 분석, 중간에 구현, 마지막에 시험을 몰아서 수행할 수 있다.

이 경우 시험과 통합 문제가 반복 후반에 집중되고, 완료되지 않은 기능이 다음 반복으로 넘어가며, 실제 피드백을 얻기 어렵다.

이를 작은 폭포수가 반복되는 형태로 볼 수 있다.

각 반복 안에서도 요구사항·설계·구현과 시험이 긴밀하게 연결되고, 기능이 작은 단위로 통합되어야 한다.

회의 중심 개발

프로세스 문제를 해결하기 위해 회의와 보고를 계속 추가하면 실제 개발 시간이 줄고 책임이 더 불분명해질 수 있다.

회의는 다음과 같은 명확한 목적을 가져야 한다.

  • 공동 의사결정
  • 복잡한 정보의 실시간 교환
  • 갈등과 우선순위 조정
  • 결과 검토
  • 개선 계획

단순한 상태 전달은 자동화된 도구와 비동기 문서로 처리할 수 있다.

참석자가 결정과 작업에 영향을 줄 수 없고 정보도 얻지 못한다면 회의의 필요성을 다시 검토해야 한다.

속도 지표의 오용

완료한 작업 수와 스토리 포인트, 커밋과 코드 줄 수를 생산성의 단순한 지표로 사용하면 실제 가치와 품질이 왜곡될 수 있다.

다음과 같은 문제가 발생할 수 있다.

  • 작업을 불필요하게 잘게 나눈다.
  • 포인트를 높게 책정한다.
  • 쉬운 기능을 우선한다.
  • 리팩터링과 품질 작업을 피한다.
  • 코드의 양을 늘린다.
  • 다른 팀을 돕지 않는다.
  • 결함과 미완료 작업을 숨긴다.

지표는 시스템의 흐름과 사용자 결과·품질을 이해하는 데 사용해야 한다.

팀의 처리량은 자체적인 계획에 활용할 수 있지만 서로 다른 팀과 개인의 성과를 직접 비교하기 어렵다.

지속적 개선

개발 방법론 자체도 평가와 개선의 대상이다.

팀은 다음을 주기적으로 검토할 수 있다.

  • 사용자가 가치를 얻는 데 걸리는 시간
  • 미완료 작업과 대기
  • 결함과 재작업
  • 배포 빈도와 실패
  • 의사결정 지연
  • 팀 사이의 의존성
  • 운영 장애와 지원 요청
  • 구성원의 피로와 집중
  • 문서와 지식 전달
  • 자동화되지 않은 반복 작업

문제를 발견하면 작은 개선을 선택하고, 실제 결과가 좋아졌는지 확인한다.

방법론을 자주 완전히 교체하면 팀이 새로운 용어와 도구에 계속 적응해야 한다. 현재 프로세스의 구체적인 문제를 확인하고 필요한 부분을 개선하는 편이 효과적일 수 있다.

방법론의 평가

개발 방법론의 성공은 규칙을 얼마나 충실히 수행했는지만으로 판단하지 않는다.

평가할 수 있는 결과에는 다음이 있다.

  • 사용자가 얻는 가치
  • 요구사항과 문제 해결
  • 품질과 안정성
  • 변경 리드 타임
  • 배포와 복구 능력
  • 일정과 비용의 예측 가능성
  • 기술적 위험 감소
  • 유지보수성과 기술 부채
  • 팀과 이해관계자의 협력
  • 지속 가능한 작업 환경
  • 학습과 개선

특정 방법론을 사용한 프로젝트가 성공했다고 해서 모든 환경에서 같은 방법이 성공하는 것은 아니다. 팀의 경험·제품·조직과 기술적 조건을 함께 분석해야 한다.

프로젝트와 조직 관리

소프트웨어 프로젝트 관리는 정해진 목표와 제약 안에서 소프트웨어 제품·서비스와 관련 성과를 만들어 내기 위해 범위, 일정, 비용, 인력, 품질, 위험과 의사소통을 계획하고 조정하는 활동이다. 조직 관리는 이러한 프로젝트를 수행하는 사람과 팀, 권한, 책임, 의사결정 구조와 장기적인 역량을 구성하고 운영하는 활동이다.

소프트웨어 개발에는 기술적인 설계와 구현뿐 아니라 여러 이해관계자의 요구를 조정하고, 제한된 인력과 시간 안에서 우선순위를 정하며, 불확실성과 변경에 대응하는 관리 활동이 필요하다. 개발자가 각각 올바른 코드를 작성하더라도 목표와 책임이 불명확하고 구성 요소의 통합 시점과 의사결정 방식이 정해져 있지 않으면 전체 프로젝트는 실패할 수 있다.

소프트웨어 프로젝트는 건축물이나 제조 설비와 달리 진행 상황을 물리적인 완성 상태만으로 파악하기 어렵다. 구현된 코드의 양이 많아도 중요한 요구사항이 충족되지 않을 수 있고, 기능이 거의 완성되어 보이더라도 통합·성능·보안과 데이터 이전에 큰 위험이 남아 있을 수 있다. 따라서 활동량보다 작동하는 소프트웨어, 검증된 품질, 해결된 위험과 사용자에게 제공되는 가치를 중심으로 상태를 판단해야 한다.

ISO 21502:2020은 목적·전달 방식·생명주기·복잡성·규모·비용과 기간에 관계없이 여러 종류의 프로젝트에 적용할 수 있는 프로젝트 관리 지침을 제공하며, 예측형·점진형·반복형·적응형과 혼합형 접근을 포함한다.[91]

IEEE Computer Society의 SWEBOK는 소프트웨어 공학 관리에서 프로젝트 착수와 범위 정의, 계획, 실행, 검토·평가와 종료를 다룬다. 또한 측정, 위험, 품질, 형상 관리와 여러 생명주기 프로세스가 관리 활동과 연결된다.[92]

프로젝트와 운영의 구분

프로젝트는 특정한 목표와 결과를 만들기 위해 시작과 종료를 가진 일시적인 활동이다. 운영은 만들어진 제품과 서비스를 지속적으로 제공하고 유지하는 반복적인 활동이다.

새로운 문서 편집기를 개발하거나 기존 시스템을 클라우드 환경으로 이전하는 작업은 프로젝트로 관리할 수 있다. 배포된 편집기 서비스를 계속 감시하고 장애에 대응하며 사용자 계정을 관리하는 일은 운영에 해당한다.

그러나 소프트웨어에서는 프로젝트와 운영의 경계가 항상 분명하지 않다. 웹 서비스와 모바일 앱은 첫 출시 이후에도 기능 개발과 운영이 계속되며, 하나의 장기 제품 안에서 여러 프로젝트와 릴리스가 동시에 진행될 수 있다.

따라서 다음 단위를 구분할 필요가 있다.

  • 제품은 특정 사용자와 시장의 문제를 지속적으로 해결하는 소프트웨어 또는 서비스이다.
  • 프로젝트는 제품이나 조직에 특정한 변화를 만들기 위한 한시적인 활동이다.
  • 프로그램은 서로 관련된 여러 프로젝트와 활동을 함께 조정하여 개별적으로 관리할 때보다 큰 성과를 얻기 위한 구조이다.
  • 포트폴리오는 조직의 전략과 자원 배분에 따라 여러 프로젝트·프로그램과 운영 활동을 선택하고 관리하는 집합이다.
  • 운영은 제품과 서비스가 계속 가치를 제공하도록 실행하고 지원하는 활동이다.

프로젝트가 종료되어도 제품은 계속 존재할 수 있다. 프로젝트 종료 조건과 제품의 장기 소유자, 운영·유지보수 책임을 구분하지 않으면 개발 조직이 해산된 뒤 누구도 제품을 책임지지 않는 상태가 발생할 수 있다.

프로젝트의 성공

프로젝트의 성공은 계획한 일정과 예산을 지킨 것만으로 판단할 수 없다. 정해진 범위의 기능을 모두 구현했더라도 사용자가 필요로 하지 않거나 운영할 수 없는 소프트웨어라면 실질적인 성공으로 보기 어렵다.

프로젝트 성공에는 다음과 같은 관점이 포함될 수 있다.

  • 사용자와 고객의 문제를 해결했는가
  • 사업·공공·연구와 임무 목표에 기여했는가
  • 필요한 기능과 품질을 제공했는가
  • 허용된 일정과 비용 안에서 수행되었는가
  • 안전·보안·법률과 윤리적 조건을 충족했는가
  • 운영과 유지보수를 지속할 수 있는가
  • 팀과 조직이 필요한 지식과 역량을 확보했는가
  • 향후 변경을 감당할 수 있는 구조를 남겼는가
  • 예상한 편익이 실제로 나타났는가
  • 실패와 중단 과정에서도 사용자와 데이터를 보호했는가

일정과 비용, 범위는 중요한 제약이지만 서로 독립적이지 않다. 범위를 늘리면 일정과 비용, 품질 위험이 달라질 수 있으며, 일정을 줄이기 위해 시험과 설계를 생략하면 단기 출시는 가능해도 이후 장애와 유지보수 비용이 증가할 수 있다.

프로젝트 관리에서는 하나의 수치를 무조건 지키기보다 목표와 제약 사이의 상충 관계를 이해관계자에게 명확히 제시하고 의도적인 결정을 내린다.

가치와 성과

소프트웨어 프로젝트의 결과는 코드·문서·서버와 같은 산출물과, 그 산출물을 사용하여 얻는 성과로 구분할 수 있다.

예를 들어 자동 예약 시스템을 배포한 것은 산출물이며, 예약 처리 시간이 감소하고 사용자 오류가 줄어든 것은 성과이다. 기능 수와 코드량은 산출물의 규모를 나타낼 수 있지만 사용자에게 제공한 가치를 직접 나타내지는 않는다.

프로젝트는 다음 질문을 통해 가치와 성과를 정의할 수 있다.

  • 어떤 문제를 해결하려는가
  • 누구에게 어떤 변화가 생겨야 하는가
  • 기존 상태와 비교하여 무엇이 개선되어야 하는가
  • 성공을 어떤 관찰 가능한 결과로 판단하는가
  • 기능을 제공해도 기대 효과가 나타나지 않으면 어떻게 할 것인가
  • 효과를 확인하려면 어떤 데이터와 기간이 필요한가

PMI의 현재 PMBOK Guide는 현대 프로젝트 전달을 위한 원칙과 성과 영역을 중심으로 프로젝트가 결과와 가치를 제공하도록 관리하는 관점을 제시한다.[93]

프로젝트 착수

프로젝트 착수에서는 해결할 문제와 목표, 책임과 기본 제약을 확인하고 프로젝트를 시작할 근거를 마련한다.

착수 과정에서는 다음을 정할 수 있다.

  • 프로젝트의 목적과 기대 성과
  • 주요 사용자와 이해관계자
  • 제품과 프로젝트의 범위
  • 주요 기능과 품질 목표
  • 예산과 목표 일정
  • 중요한 가정과 제약
  • 책임자와 의사결정 권한
  • 예상하는 전달 방식
  • 주요 위험과 의존성
  • 운영 및 유지보수 주체
  • 중단과 성공의 상위 조건

착수 문서는 모든 요구사항과 일정을 확정하는 상세 계획이 아니다. 조직이 왜 이 프로젝트를 수행하며 누가 어떤 권한으로 주요 결정을 내릴지를 공통으로 이해하게 하는 기준이다.

프로젝트가 시작된 뒤 목적과 성공 기준이 계속 바뀐다면 현재 프로젝트가 같은 문제를 해결하고 있는지 다시 검토해야 한다. 필요한 경우 프로젝트 범위를 다시 정의하거나 별도의 프로젝트로 분리할 수 있다.

사업 사례와 타당성

프로젝트를 시작하기 전에는 예상 가치와 비용, 위험과 대안을 검토한다. 이를 사업 사례 또는 타당성 분석으로 정리할 수 있다.

다음과 같은 대안을 비교할 수 있다.

  • 현재 시스템과 절차를 유지한다.
  • 기존 소프트웨어를 개선한다.
  • 새로운 소프트웨어를 직접 개발한다.
  • 상용 제품을 구매한다.
  • 오픈소스 소프트웨어를 도입하고 수정한다.
  • 외부 서비스와 클라우드 제품을 사용한다.
  • 업무 절차 자체를 변경한다.
  • 프로젝트를 수행하지 않는다.

타당성은 기술적인 구현 가능성만을 뜻하지 않는다.

  • 필요한 예산과 인력을 확보할 수 있는가
  • 조직이 새로운 시스템과 업무 변화를 받아들일 수 있는가
  • 법률·보안과 안전 요구를 충족할 수 있는가
  • 운영·유지보수와 지원 비용을 감당할 수 있는가
  • 기존 데이터와 시스템을 이전할 수 있는가
  • 예상 편익이 비용과 위험보다 큰가
  • 공급자와 외부 플랫폼에 대한 종속이 허용 가능한가
  • 계획이 실패했을 때 되돌리거나 중단할 수 있는가

초기 추정에는 불확실성이 크므로 하나의 정확한 숫자처럼 제시하기보다 가정과 범위, 낙관적·일반적·비관적 조건을 함께 나타낼 수 있다.

거버넌스

프로젝트 거버넌스는 프로젝트를 어떤 원칙과 권한 구조로 감독하고, 주요 결정을 누가 내리며, 조직의 전략·정책과 책임에 어떻게 연결할지를 정하는 체계이다.

거버넌스에서는 다음을 명확히 할 수 있다.

  • 프로젝트를 승인하고 중단할 권한
  • 제품과 사업 목표의 책임자
  • 기술적 결정의 책임자
  • 예산과 인력 배분 권한
  • 범위와 우선순위 변경 절차
  • 위험을 수용할 권한
  • 품질과 릴리스 승인 기준
  • 보안·안전과 규제 책임
  • 공급자와 계약 관리
  • 성과와 문제의 보고 구조
  • 독립적인 검토와 감사
  • 이해 충돌의 처리 방법

거버넌스는 모든 결정을 상위 관리자가 승인하도록 만드는 중앙 통제와 같지 않다. 일상적인 판단은 작업과 가까운 팀에 위임하고, 조직 전체와 여러 팀에 영향을 주거나 큰 위험을 수반하는 결정만 적절한 수준에서 다룰 수 있다.

의사결정 권한이 불명확하면 여러 사람이 같은 결정을 반복하거나 아무도 책임지지 않는 상태가 생긴다. 반대로 모든 결정을 한 사람에게 집중하면 병목과 단일 실패 지점이 발생한다.

ISO 21500:2021은 프로젝트·프로그램과 포트폴리오 관리의 조직적 문맥과 기본 개념을 정의하고, 조직이 관련 관리 체계를 도입하거나 개선하는 데 사용할 지침을 제공한다.[94]

이해관계자 관리

이해관계자 관리는 프로젝트의 영향을 받거나 결과에 영향을 줄 수 있는 사람과 조직을 식별하고, 요구·관심·권한과 관계를 분석하며, 필요한 참여와 의사소통을 계획하는 활동이다.

소프트웨어 프로젝트의 이해관계자에는 다음이 포함될 수 있다.

  • 최종 사용자
  • 고객과 구매자
  • 제품 책임자와 경영진
  • 개발·시험과 운영 팀
  • 보안·법무와 개인정보 담당자
  • 접근성과 사용자 지원 담당자
  • 외부 공급자와 플랫폼 사업자
  • 데이터와 외부 시스템 소유자
  • 규제·감사와 인증 기관
  • 시스템의 결정으로 간접적인 영향을 받는 사람
  • 서비스 종료 이후 데이터를 관리할 조직

이해관계자의 권한과 관심은 서로 다르다. 높은 권한을 가진 사람이 일상적인 사용 문제를 잘 알지 못할 수 있고, 직접 사용자는 중요한 경험을 갖고 있지만 최종 예산 권한이 없을 수 있다.

이해관계자 참여는 단순히 진행 상황을 통보하는 일이 아니다. 요구사항·위험·설계 대안과 수용 기준을 함께 검토하고, 결정이 사용자와 조직에 미칠 영향을 확인하는 활동이다.

모든 이해관계자가 모든 회의와 결정에 참여할 필요는 없다. 필요한 정보와 결정 시점을 기준으로 참여 수준과 의사소통 방식을 정한다.

목표와 범위

프로젝트 범위는 프로젝트가 제공할 결과와 수행할 작업, 포함하지 않을 내용을 정의한다.

범위에는 다음이 포함될 수 있다.

  • 대상 사용자와 업무
  • 제공할 제품과 기능
  • 필요한 품질 수준
  • 지원 플랫폼과 환경
  • 데이터와 외부 시스템
  • 이전·배포와 운영 준비
  • 문서와 교육
  • 프로젝트에서 제외할 기능과 환경
  • 이후 프로젝트로 넘길 항목

범위가 불명확하면 이해관계자는 같은 프로젝트를 서로 다르게 이해하게 된다. 개발 팀은 핵심 기능만 포함한다고 생각하지만 고객은 데이터 이전·사용자 교육과 기존 시스템 종료까지 포함한다고 예상할 수 있다.

범위는 요구사항 목록과 같지 않다. 요구사항은 범위 안에서 시스템이 충족해야 할 조건을 구체화하고, 범위는 프로젝트가 책임질 전체 경계를 나타낸다.

초기 범위를 지나치게 세밀하게 고정하면 새로운 정보와 사용자 피드백을 반영하기 어려울 수 있다. 반대로 범위가 계속 무제한으로 늘어나면 일정과 품질을 통제하기 어렵다. 상위 목표와 고정된 제약은 유지하면서 세부 기능을 우선순위에 따라 조정할 수 있다.

범위 변경

프로젝트 진행 중 새로운 요구와 환경 변화가 발견되는 것은 일반적이다. 모든 변경을 범위 이탈로 간주하여 막거나, 모든 요청을 별도 분석 없이 받아들이는 방식 모두 문제가 될 수 있다.

범위 변경에서는 다음을 확인한다.

  • 변경이 해결하려는 문제
  • 원래 목표와의 관계
  • 사용자와 조직에 제공하는 가치
  • 일정·비용과 인력 영향
  • 아키텍처와 데이터 영향
  • 품질·안전과 보안 위험
  • 다른 기능과의 의존성
  • 현재 릴리스에 포함할 필요
  • 연기·대체 또는 제외할 가능성

변경의 승인 여부와 우선순위, 적용할 릴리스를 기록하고 관련 요구사항·계획과 기준선을 갱신한다.

애자일 개발에서 변경을 받아들인다는 것은 일정과 자원이 고정된 상태에서 기능을 계속 추가한다는 뜻이 아니다. 새 요구의 가치를 평가하고 기존 항목과 우선순위를 교환하며 제품 목표를 유지하는 과정이다. 애자일 선언의 원칙은 늦은 시점의 요구 변경도 받아들이고, 가치 있는 소프트웨어를 일찍 지속적으로 전달하는 방향을 제시한다.[95]

작업 분해

프로젝트 목표와 산출물을 관리 가능한 작업 단위로 나누는 과정을 작업 분해라고 한다.

작업은 다음과 같은 기준으로 나눌 수 있다.

  • 사용자에게 제공할 기능
  • 제품 구성 요소와 모듈
  • 요구사항·설계·구현과 시험 활동
  • 위험을 줄이기 위한 조사와 프로토타입
  • 데이터 이전과 운영 준비
  • 릴리스와 배포
  • 교육·문서와 지원
  • 공급자와 외부 의존성 작업

작업 분해의 목적은 가능한 한 작은 항목을 많이 만드는 것이 아니다. 각 항목의 결과와 완료 기준, 의존성과 책임을 이해할 수 있도록 만드는 것이다.

너무 큰 작업은 진행 상태와 남은 위험을 알기 어렵다. 너무 작은 작업은 관리와 보고 비용을 증가시키고 실제 사용자 가치와의 연결이 약해질 수 있다.

기술적 작업도 상위 목표와 연결해야 한다. 단순히 “데이터베이스 리팩터링”이라고 기록하기보다 어떤 위험과 변경 비용을 줄이기 위한 것인지 명확히 할 수 있다.

산출물과 완료 조건

프로젝트 작업의 완료는 담당자가 작업을 끝냈다고 말하거나 코드가 작성된 시점만으로 판단해서는 안 된다.

작업 또는 기능의 완료 조건에는 다음이 포함될 수 있다.

  • 요구사항과 수용 기준 충족
  • 설계와 코드 검토 완료
  • 자동화된 시험 통과
  • 성능·보안과 접근성 확인
  • 지원 플랫폼 검증
  • 데이터 및 API 호환성 확인
  • 문서와 변경 기록 갱신
  • 배포와 운영 준비
  • 알려진 결함과 위험의 처리
  • 관련 이해관계자의 승인

팀이 공통 완료 기준을 사용하면 개발자마다 “완료”의 의미가 달라지는 문제를 줄일 수 있다.

Scrum Guide는 작업이 제품에 필요한 품질 조치를 충족할 때의 상태를 Definition of Done으로 설명하며, 이를 통해 완료된 증분에 대한 공통 이해를 제공한다.[96]

완료 조건은 품질을 마지막에 검사하기 위한 목록이 아니라 작업을 계획하고 구현할 때부터 고려해야 하는 기준이다.

일정 계획

일정 계획은 프로젝트의 작업과 의존성, 자원과 위험을 고려하여 수행 순서와 목표 시점을 정하는 활동이다.

일정 계획에서는 다음을 고려한다.

  • 작업의 크기와 예상 노력
  • 선행·후행 관계
  • 외부 공급자와 승인
  • 인력과 기술의 가용성
  • 통합과 시험 기간
  • 피드백과 수정 시간
  • 데이터 이전과 배포
  • 휴일·교육과 다른 업무
  • 기술적 불확실성
  • 위험 대응과 여유
  • 출시·계약과 규제 시점

단순히 모든 작업 기간을 더하는 것만으로 일정이 만들어지지 않는다. 여러 작업을 병렬로 진행할 수 있는지, 특정 전문 인력이 여러 작업에 동시에 필요한지, 통합과 의사결정이 어느 시점에 가능한지를 확인해야 한다.

일정은 실제 진행과 새 정보를 반영하여 갱신한다. 초기 계획과 실제 상황이 달라졌는데도 최초 날짜만 유지하면 팀은 상태를 숨기거나 품질 활동을 생략하게 될 수 있다.

마일스톤

마일스톤은 프로젝트의 중요한 상태와 의사결정 시점을 나타내는 기준점이다. 작업 기간을 직접 갖기보다 특정 결과와 조건이 충족되었는지를 나타낸다.

마일스톤에는 다음과 같은 것이 있을 수 있다.

  • 프로젝트 승인
  • 요구사항 기준선
  • 아키텍처 검토 완료
  • 핵심 기술 위험 검증
  • 첫 번째 작동 제품
  • 기능 완성
  • 통합 완료
  • 성능과 보안 기준 충족
  • 사용자 수용 완료
  • 릴리스 후보 승인
  • 운영 배포
  • 기존 시스템 종료
  • 프로젝트 종료

날짜만 지정된 마일스톤은 실질적인 상태를 나타내지 못할 수 있다. 어떤 산출물과 품질·승인 조건이 충족되어야 하는지 정의해야 한다.

마일스톤을 지나치게 많게 만들면 일상 작업과 구분이 사라지고, 너무 적으면 중요한 위험이 프로젝트 후반까지 드러나지 않을 수 있다.

의존성 관리

프로젝트 작업과 팀, 외부 시스템 사이에는 여러 의존성이 존재한다.

  • 한 기능이 다른 API와 데이터 구조를 필요로 한다.
  • 시험이 특정 하드웨어와 환경을 필요로 한다.
  • 외부 조직의 승인과 자료가 필요하다.
  • 공급자의 SDK와 장비가 도착해야 한다.
  • 공통 플랫폼 팀의 기능이 선행되어야 한다.
  • 데이터 이전 전에 스키마와 정리 작업이 완료되어야 한다.

의존성을 식별하지 않으면 개별 팀이 작업을 완료해도 전체 기능을 통합하지 못할 수 있다.

의존성은 가능한 한 제거하거나 단순화하고, 남은 의존성에는 소유자·필요 시점과 실패 시 대안을 정한다.

모든 팀을 중앙 일정으로 세밀하게 동기화하기보다 안정적인 인터페이스와 모의 구현, 계약 시험을 제공하여 병렬 작업을 가능하게 할 수도 있다.

추정

추정은 작업에 필요한 노력·기간·비용과 자원을 현재 정보에 근거해 예측하는 활동이다. 추정은 확정된 약속이나 미래를 정확히 맞히는 행위가 아니다.

소프트웨어 추정이 어려운 이유에는 다음이 있다.

  • 요구사항과 해결 방법이 완전히 알려지지 않는다.
  • 유사한 기능도 기존 구조와 데이터에 따라 난도가 달라진다.
  • 결함과 통합 문제를 미리 알기 어렵다.
  • 학습과 조사 시간이 필요하다.
  • 사람과 팀의 경험이 다르다.
  • 외부 서비스와 승인에 의존한다.
  • 개발 중 범위와 우선순위가 변한다.
  • 품질과 운영 조건이 뒤늦게 드러날 수 있다.

추정에는 다음과 같은 방법을 사용할 수 있다.

  • 유사한 과거 작업과 비교
  • 전문가 판단
  • 작업 분해 후 합산
  • 여러 사람이 독립적으로 추정
  • 낙관·일반·비관 조건 분석
  • 프로토타입과 기술 조사
  • 통계적 모델
  • 실제 처리량과 주기 시간 사용

추정값에는 가정과 포함 범위, 신뢰 수준과 가장 큰 불확실성을 함께 기록한다. 하나의 숫자로만 제시하면 이해관계자가 오차와 조건을 알기 어렵다.

노력과 기간

노력은 작업에 필요한 사람의 작업량이고 기간은 달력상 걸리는 시간이다. 두 개념은 같지 않다.

한 사람이 열흘 동안 수행할 작업에 개발자 열 명을 배정한다고 하루 만에 끝나는 것은 아니다. 작업을 분할할 수 있는 정도와 의존성, 교육·통합과 의사소통 비용이 존재하기 때문이다.

인력을 프로젝트 후반에 급하게 추가하면 기존 팀이 새로운 사람에게 구조와 업무를 설명하는 시간이 필요하고, 작업 분할과 통합이 복잡해질 수 있다.

병렬화할 수 있는 독립 작업에는 추가 인력이 도움이 될 수 있지만, 하나의 복잡한 설계와 긴밀한 상태를 함께 다뤄야 하는 작업에는 효과가 제한적이다.

따라서 기간을 줄이기 위해 인력을 늘릴 때는 작업 구조와 팀의 수용 능력, 개발 환경과 모듈 경계를 함께 검토한다.

추정과 약속

추정은 현재 정보에 따른 예측이고, 약속은 이해관계자 사이에서 정한 목표나 의무이다. 두 개념을 구분하지 않으면 초기의 불확실한 숫자가 변경할 수 없는 납기로 취급될 수 있다.

목표 일정이 사업상 고정되어 있다면 다음 요소 중 무엇을 조정할 수 있는지 명확히 해야 한다.

  • 기능 범위
  • 품질과 규제 조건
  • 인력과 비용
  • 출시 대상과 플랫폼
  • 단계적 전달
  • 기술적 위험
  • 외부 의존성
  • 일정 자체

안전·보안과 필수 품질을 단순한 일정 조정 수단으로 취급해서는 안 된다. 범위와 전달 단계를 줄여 핵심 기능을 먼저 제공하는 방식이 사용될 수 있다.

추정이 바뀌었다는 사실을 실패로 숨기기보다, 새롭게 발견된 정보와 영향을 조기에 공유하고 계획을 수정해야 한다.

예산과 비용

소프트웨어 프로젝트의 비용에는 개발자 인건비뿐 아니라 여러 직접·간접 비용이 포함된다.

  • 제품과 프로젝트 관리
  • 요구사항·설계와 개발
  • 시험과 품질 보증
  • 하드웨어와 장치
  • 클라우드와 개발 인프라
  • 외부 서비스와 API
  • 상용 라이선스
  • 외부 공급자와 계약
  • 교육과 채용
  • 데이터 이전
  • 보안과 규제 준수
  • 배포와 운영 준비
  • 사용자 지원
  • 유지보수와 장기 지원
  • 서비스 종료와 데이터 보존

개발 비용이 낮더라도 운영과 라이선스, 공급자 종속 때문에 전체 생명주기 비용이 높을 수 있다.

예산은 프로젝트 시작 시 승인된 총액만 관리하는 것이 아니라 실제 지출과 완료된 성과, 남은 작업과 위험을 함께 예측해야 한다.

비용을 줄이기 위해 시험·관찰과 백업을 제거하면 장애와 데이터 손실의 예상 비용이 더 커질 수 있으므로 단기 비용과 장기 위험을 함께 비교한다.

자원 관리

프로젝트 자원에는 사람과 예산뿐 아니라 개발 환경·하드웨어·시험 장치·데이터·라이선스·네트워크와 외부 서비스가 포함된다.

자원 관리에서는 다음을 확인한다.

  • 어떤 자원이 언제 필요한가
  • 여러 프로젝트가 같은 자원을 공유하는가
  • 병목이 되는 전문 기술과 장비는 무엇인가
  • 조달과 승인에 얼마나 걸리는가
  • 대체 자원과 공급자가 있는가
  • 사용 한도와 비용은 무엇인가
  • 프로젝트 종료 후 자원을 어떻게 반환하거나 보존하는가

공유 시험 장비와 전문가는 여러 작업이 동시에 필요로 할 수 있으므로 일정의 숨겨진 병목이 될 수 있다.

사람을 단순히 일정표의 교환 가능한 자원으로 취급해서는 안 된다. 각 사람의 지식·관계와 집중 상태가 다르며, 반복적인 프로젝트 전환은 생산성과 품질을 낮출 수 있다.

위험 관리

위험은 발생 여부가 확정되지 않았지만 발생하면 프로젝트의 목표에 긍정적 또는 부정적인 영향을 줄 수 있는 사건이나 조건이다.

소프트웨어 프로젝트의 위험에는 다음이 있을 수 있다.

  • 요구사항과 시장의 불확실성
  • 핵심 기술의 성능과 실현 가능성
  • 아키텍처와 통합 문제
  • 보안과 안전
  • 데이터 품질과 이전
  • 일정과 비용
  • 핵심 인력의 부재
  • 외부 공급자와 서비스
  • 법률과 규제
  • 하드웨어와 조달
  • 운영과 지원 역량
  • 사용자 채택과 조직 변화
  • 프로젝트 사이의 의존성

위험 관리 과정은 다음과 같이 진행할 수 있다.

  1. 위험을 식별한다.
  2. 원인과 발생 조건을 분석한다.
  3. 발생 가능성과 영향을 평가한다.
  4. 우선순위를 정한다.
  5. 대응 방식과 책임자를 정한다.
  6. 위험을 나타내는 신호를 감시한다.
  7. 실제 상태와 대응 결과를 갱신한다.
  8. 새 위험과 잔여 위험을 반복해서 검토한다.

위험 목록을 작성하는 것만으로 위험이 관리되지는 않는다. 각 위험에 대응 작업과 책임자, 검토 시점이 있어야 한다.

ISO 21502는 프로젝트 생명주기에서 위험과 문제, 변경 통제를 포함한 계획과 통제 활동을 다룬다.[97]

위험 대응

부정적인 위험에는 다음과 같은 대응을 사용할 수 있다.

  • 회피는 위험을 만드는 범위와 기술, 접근을 변경하여 원인을 제거한다.
  • 완화는 발생 가능성이나 영향을 줄인다.
  • 전가는 계약·보험과 공급자를 통해 일부 책임과 비용을 다른 주체로 이전한다.
  • 수용은 위험을 인식하고 발생 시 사용할 대응과 여유를 준비하거나 별도 조치를 하지 않는다.
  • 상향 보고는 프로젝트의 권한과 범위를 넘어서는 위험을 상위 조직에 전달한다.

긍정적인 기회에는 활용·강화·공유와 수용 등의 대응을 사용할 수 있다.

기술 위험은 문서상 계획만으로 줄어들지 않을 수 있다. 프로토타입과 성능 시험, 외부 시스템 연동과 실제 데이터 실험을 조기에 수행하여 불확실성을 줄인다.

위험을 공급자에게 계약으로 전가하더라도 사용자가 받는 서비스와 조직의 평판에 대한 책임이 사라지는 것은 아니다.

위험 기록

위험 기록에는 다음 정보가 포함될 수 있다.

  • 위험의 설명
  • 원인과 발생 조건
  • 영향받는 목표와 구성 요소
  • 발생 가능성과 영향
  • 우선순위
  • 대응 방식과 작업
  • 책임자
  • 조기 경고 신호
  • 검토 날짜
  • 현재 상태
  • 발생 후 남는 잔여 위험

위험을 지나치게 일반적으로 작성하면 대응하기 어렵다. “일정이 늦어질 수 있다”보다 “외부 장치 SDK가 9월까지 제공되지 않으면 통합 시험과 출시가 최소 한 릴리스 지연될 수 있다”처럼 원인과 영향을 연결한다.

위험 기록은 공개적으로 논의할 수 있어야 한다. 위험을 보고하면 무능력으로 평가받는 조직에서는 문제가 실제 장애가 될 때까지 숨겨질 수 있다.

문제 관리

문제 또는 이슈는 이미 발생하여 프로젝트에 영향을 주고 있으며 조치가 필요한 상태이다. 위험이 미래의 불확실한 가능성이라면 문제는 현재 해결해야 하는 사건이다.

문제 기록에는 다음을 포함할 수 있다.

  • 현재 상태와 영향
  • 발생 시점
  • 관련 작업과 사용자
  • 임시 완화 조치
  • 해결 책임자
  • 필요한 의사결정
  • 목표 해결 시점
  • 외부 의존성
  • 해결 결과와 후속 작업

문제와 결함은 중복될 수 있지만 같은 개념은 아니다. 특정 코드 결함이 여러 팀의 출시를 막으면 기술적인 결함이면서 프로젝트 문제이기도 하다.

문제를 장기간 “진행 중”으로만 유지하지 않고, 해결하지 못하는 원인과 상위 의사결정 필요 여부를 검토한다.

가정과 제약 관리

프로젝트 계획은 여러 가정을 바탕으로 만들어진다.

  • 특정 외부 API가 유지된다.
  • 필요한 개발자가 참여할 수 있다.
  • 데이터 형식이 알려진 상태와 같다.
  • 특정 장치와 라이선스를 확보할 수 있다.
  • 사용자 수가 예상 범위 안에 있다.
  • 규제 승인이 계획한 시점에 끝난다.

가정이 사실이 아니면 일정과 설계가 크게 달라질 수 있다. 중요한 가정은 문서화하고 확인 방법과 기한을 정한다.

제약은 선택 범위를 제한하는 확정된 조건이다. 예산·법률·지원 플랫폼과 계약 기한 등이 제약이 될 수 있다.

가정과 제약을 구분하면 변경 가능한 조건과 변경할 수 없는 조건을 더 명확하게 협상할 수 있다.

의사결정

프로젝트에서는 기술·제품·일정과 위험에 관한 많은 결정을 내려야 한다.

좋은 의사결정에는 다음 요소가 필요하다.

  • 결정할 문제와 기한
  • 결정 권한을 가진 사람
  • 필요한 참여자와 자문자
  • 평가 기준
  • 검토한 대안
  • 사실과 가정
  • 예상되는 장점과 비용
  • 남은 위험
  • 선택 결과와 이유
  • 다시 검토할 조건

모든 사람이 완전히 동의할 때까지 결정을 미루면 일정이 지연될 수 있다. 필요한 의견을 듣고 권한자가 명시적으로 결정하며, 결정 이후에는 새로운 근거가 나타나기 전까지 공통 방향으로 실행한다.

되돌리기 쉬운 결정은 작은 실험과 빠른 피드백으로 처리하고, 데이터 형식·공개 API·안전 구조처럼 되돌리기 어려운 결정은 더 깊은 분석과 검토를 수행할 수 있다.

결정 기록은 이후 같은 논의를 반복하지 않고, 환경이 바뀌었을 때 기존 판단의 근거가 아직 유효한지 확인하는 데 사용된다.

변경 관리

프로젝트 변경 관리에는 요구사항과 코드의 변경뿐 아니라 일정·예산·팀·공급자와 운영 환경의 변경도 포함된다.

변경 요청을 평가할 때는 다음을 확인한다.

  • 변경의 원인과 기대 결과
  • 목표와 범위에 대한 영향
  • 일정과 비용
  • 인력과 전문 기술
  • 품질과 위험
  • 데이터와 호환성
  • 외부 계약과 규제
  • 다른 프로젝트와 조직에 대한 영향
  • 구현하지 않았을 때의 영향
  • 되돌리기와 전환 방법

작은 반복적 프로젝트에서는 제품 백로그와 계획 회의가 변경 관리 수단이 될 수 있고, 규제·계약 프로젝트에서는 공식 변경 요청과 승인 기록이 필요할 수 있다.

절차의 형식보다 중요한 것은 변경의 영향과 책임을 이해하고 관련 계획과 산출물을 일관되게 갱신하는 것이다.

소프트웨어 팀은 공통 목표를 달성하기 위해 서로 의존하는 여러 역할과 전문성을 가진 사람들의 집단이다.

팀 구성에는 다음과 같은 역할이 포함될 수 있다.

  • 제품과 요구사항 책임
  • 아키텍처와 기술 방향
  • 소프트웨어 개발
  • 시험과 품질 보증
  • 사용자 경험과 디자인
  • 데이터와 인공지능
  • 보안과 개인정보
  • 배포와 운영
  • 사용자 지원
  • 프로젝트와 전달 관리

모든 프로젝트가 각 역할마다 별도의 사람을 둘 필요는 없다. 한 사람이 여러 역할을 수행할 수 있고, 일부 전문 역할은 조직의 공통 팀에서 제공할 수 있다.

다만 역할이 합쳐져도 책임 자체가 사라지는 것은 아니다. 별도의 시험 담당자가 없더라도 시험과 품질 책임은 필요하며, 전담 운영자가 없더라도 배포와 장애 대응 책임을 정해야 한다.

역할과 책임

역할과 책임은 직급과 직책의 목록보다 실제 의사결정과 작업의 소유권을 명확히 해야 한다.

다음 질문에 답할 수 있어야 한다.

  • 제품 목표와 우선순위를 누가 결정하는가
  • 기술적 구조와 표준을 누가 책임지는가
  • 각 구성 요소의 최종 소유자는 누구인가
  • 품질과 릴리스 기준을 누가 확인하는가
  • 보안·안전 위험을 누가 수용할 수 있는가
  • 장애와 사용자 문의에 누가 대응하는가
  • 외부 공급자와 계약을 누가 관리하는가
  • 의견 충돌이 해결되지 않을 때 누가 결정하는가

책임자가 있다는 것은 모든 작업을 직접 수행해야 한다는 뜻이 아니다. 여러 사람이 작업에 참여하더라도 최종 결과와 의사결정을 추적할 수 있는 소유자가 필요하다.

동시에 한 사람에게 지나치게 많은 승인과 지식을 집중하면 병목과 사업 연속성 위험이 생긴다. 대리자와 문서, 공동 검토와 지식 공유를 통해 단일 의존성을 줄인다.

기능별 조직

기능별 조직은 개발·시험·디자인·운영과 보안처럼 전문 분야를 중심으로 팀을 구성한다.

기능별 조직은 다음과 같은 장점을 가질 수 있다.

  • 전문 지식과 도구를 공유하기 쉽다.
  • 같은 역할의 교육과 경력 경로를 만들기 쉽다.
  • 품질과 기술 표준을 일관되게 유지할 수 있다.
  • 제한된 전문가를 여러 프로젝트에 배분할 수 있다.

반면 하나의 사용자 기능이 여러 기능 조직을 순서대로 지나가야 하면 전달이 느려질 수 있다. 작업 대기열과 인수인계가 생기고, 각 팀이 전체 사용자 결과보다 자신의 활동 완료에 집중할 수 있다.

기능 조직을 유지하면서 프로젝트별 다기능 팀을 구성하거나, 전문가는 공통 실무 공동체를 통해 지식을 공유할 수 있다.

다기능 팀

다기능 팀은 하나의 제품이나 목표를 달성하는 데 필요한 여러 전문성을 한 팀 안에 포함한다.

다기능 팀은 요구사항·설계·개발·시험과 운영 사이의 피드백을 빠르게 만들고, 외부 팀에 대한 대기 시간을 줄일 수 있다.

팀이 모든 전문 영역에서 완전히 독립적이어야 한다는 뜻은 아니다. 고급 보안 분석·법무·데이터베이스 운영과 특정 장비 같은 전문 기능은 공통 조직의 지원을 받을 수 있다.

다기능 팀을 만들었더라도 역할별 업무를 순차적으로 넘기기만 한다면 실제 협업은 개선되지 않을 수 있다. 요구사항과 설계 초기부터 여러 전문 역할이 함께 참여해야 한다.

제품 팀과 프로젝트 팀

프로젝트 팀은 특정 범위와 기한의 결과를 만들기 위해 구성되고 종료 후 해산될 수 있다. 제품 팀은 제품의 개발·운영과 개선을 장기간 책임진다.

프로젝트 팀은 다음과 같은 상황에 적합할 수 있다.

  • 일회성 시스템 이전
  • 특정 고객 계약
  • 법률 대응
  • 독립된 연구와 시범 사업
  • 명확한 종료 조건을 가진 기능 개발

제품 팀은 다음과 같은 상황에 적합할 수 있다.

  • 지속적으로 개선되는 웹 서비스
  • 장기 지원 운영체제와 플랫폼
  • 반복적으로 릴리스되는 응용 프로그램
  • 사용자 피드백과 운영 책임이 계속되는 제품

제품을 프로젝트 단위로만 관리하면 프로젝트가 끝날 때 지식과 책임이 흩어지고, 다음 기능마다 새로운 팀이 기존 구조를 다시 학습해야 할 수 있다.

프로젝트와 제품 구조를 함께 사용할 수 있다. 장기 제품 팀이 핵심 소유권을 유지하고, 특정한 대규모 변화에는 임시 프로젝트와 추가 인력을 구성할 수 있다.

플랫폼 팀과 지원 조직

여러 제품 팀이 공통으로 사용하는 빌드·배포·인증·관찰과 데이터 기반을 플랫폼 팀이 제공할 수 있다.

플랫폼 팀의 목적은 중앙 조직이 모든 변경을 직접 수행하는 데 있지 않다. 제품 팀이 반복적인 인프라 작업을 직접 구현하지 않고도 안전한 기본 경로를 사용할 수 있도록 자체 서비스 형태의 기능을 제공하는 것이다.

플랫폼에는 다음이 포함될 수 있다.

  • 지속적 통합과 배포
  • 개발 및 시험 환경
  • 인증과 권한
  • 서비스 템플릿
  • 로그·메트릭과 추적
  • 비밀 정보 관리
  • 패키지와 아티팩트 저장소
  • 데이터와 메시징 기반
  • 클라우드 자원 관리
  • 보안 검사

플랫폼이 제품 팀의 요구와 사용성을 고려하지 않고 일방적인 절차만 강제하면 우회 도구와 중복 인프라가 생길 수 있다. 플랫폼도 사용자 연구와 피드백, 서비스 수준과 제품 관리가 필요하다.

팀 규모

팀 규모가 커지면 더 많은 작업을 수행할 수 있지만 의사소통 관계와 조정 비용도 증가한다.

큰 팀에서는 다음과 같은 문제가 발생할 수 있다.

  • 모든 사람이 전체 구조와 결정을 알기 어렵다.
  • 회의와 정보 전달에 많은 시간이 든다.
  • 책임과 소유권이 불명확해진다.
  • 같은 기능과 기반을 중복 구현한다.
  • 통합과 릴리스 조정이 복잡해진다.
  • 중요한 의사결정이 느려진다.

대규모 제품은 하나의 거대한 팀보다 명확한 책임과 인터페이스를 가진 여러 팀으로 나눌 수 있다.

팀을 나눌 때 조직도상의 인원 수만 고려하지 않고 업무 영역과 데이터, 모듈·서비스 경계와 사용자 흐름을 함께 고려해야 한다.

너무 작은 팀에 제품·운영·보안과 지원의 모든 책임을 부여하면 과부하와 단일 인력 의존이 생길 수 있으므로 공통 지원과 우선순위 조정이 필요하다.

팀 안정성

장기간 함께 일한 팀은 코드와 업무 지식, 협업 방식과 운영 경험을 축적할 수 있다.

프로젝트마다 사람을 반복적으로 재배치하면 다음 비용이 발생할 수 있다.

  • 새 제품과 구조 학습
  • 개발 환경과 권한 준비
  • 팀 관계와 의사소통 방식 형성
  • 기존 의사결정과 운영 문제 파악
  • 인수인계
  • 이전 팀의 지식 손실

필요한 전문성을 제공하기 위한 이동은 필요하지만, 단기 자원 활용률만을 높이기 위해 사람을 자주 전환하면 전체 전달 속도와 품질이 낮아질 수 있다.

프로젝트 사이에서 인력을 공유해야 한다면 집중 시간을 확보하고, 우선순위 충돌을 한 사람이 직접 해결하게 하지 말고 관리 수준에서 조정해야 한다.

리더십

소프트웨어 프로젝트의 리더십은 작업을 지시하고 진행률을 수집하는 일에만 한정되지 않는다. 팀이 목표와 제약을 이해하고 전문적 판단을 내리며, 문제와 위험을 조기에 공유할 수 있는 환경을 만드는 활동이다.

리더는 다음과 같은 역할을 수행할 수 있다.

  • 목적과 우선순위를 명확히 한다.
  • 의사결정 권한과 책임을 정한다.
  • 필요한 자원과 조직 지원을 확보한다.
  • 팀 사이의 장애물과 충돌을 해결한다.
  • 품질과 윤리적 기준을 보호한다.
  • 불확실성과 나쁜 소식을 숨기지 않게 한다.
  • 전문적 의견과 반대 의견을 듣는다.
  • 학습과 개선을 지원한다.
  • 팀과 개인의 과도한 업무를 방지한다.
  • 성과와 책임을 이해관계자에게 설명한다.

기술 리더십과 인사·프로젝트 리더십은 서로 다른 전문성을 필요로 할 수 있다. 한 사람이 모두 수행할 수도 있지만 각 책임을 명확히 해야 한다.

PMI의 프로젝트 관리 원칙은 팀·리더십·복잡성·위험·변화·적응성과 회복력 등을 프로젝트 관리의 주요 고려 사항으로 제시한다.[98]

자율성과 통제

소프트웨어 개발은 상세한 절차만으로 모든 상황을 미리 정의하기 어렵다. 실제 코드와 사용자 문제에 가까운 팀이 빠르게 판단할 수 있는 자율성이 필요하다.

그러나 자율성은 조직의 보안·안전·법률과 공통 플랫폼 제약을 무시한다는 뜻이 아니다.

조직은 다음과 같은 경계를 제공할 수 있다.

  • 공통 목표와 품질 기준
  • 보안·개인정보와 법률 정책
  • 지원하는 기술과 예외 절차
  • 공개 API와 데이터 계약
  • 예산과 운영 한도
  • 릴리스와 위험 승인 기준
  • 반드시 필요한 감사와 기록

경계 안에서는 팀이 구현 방식과 작업 순서, 도구와 세부 설계를 결정할 수 있다.

규칙이 지나치게 세밀하면 모든 변경이 승인 대기열에 쌓이고, 규칙이 없으면 팀마다 호환되지 않는 기술과 중복 기반을 만들 수 있다. 조직 전체에 영향을 주는 제약과 팀 내부에서 해결할 판단을 구분한다.

심리적 안전과 문제 보고

프로젝트의 위험과 결함을 조기에 발견하려면 팀원이 질문·반대 의견과 실수를 공개할 수 있어야 한다.

문제를 보고한 사람이 비난받거나 평가에 불이익을 받으면 다음과 같은 현상이 나타날 수 있다.

  • 위험과 일정 지연을 숨긴다.
  • 결함을 임시로 우회하고 공유하지 않는다.
  • 잘못된 결정을 알고도 반대하지 않는다.
  • 책임이 불명확한 작업을 방치한다.
  • 장애 원인을 특정 개인에게 돌린다.
  • 필요한 도움을 늦게 요청한다.

심리적 안전은 낮은 성과와 책임 회피를 허용한다는 뜻이 아니다. 기대 기준과 책임을 명확히 유지하면서 문제를 숨기지 않고 원인과 개선책을 논의할 수 있는 상태를 뜻한다.

리더와 검토자는 사람의 성격보다 행동·산출물과 시스템 조건을 중심으로 피드백해야 한다.

의사소통

소프트웨어 프로젝트의 의사소통은 회의와 보고서의 양보다 필요한 사람이 적절한 시점에 정확한 정보를 얻는지가 중요하다.

전달해야 하는 정보에는 다음이 있다.

  • 목표와 우선순위
  • 요구사항과 설계 결정
  • 작업과 의존성
  • 위험과 문제
  • 일정과 예산
  • 품질과 시험 결과
  • 배포와 운영 상태
  • 사용자 피드백
  • 변경과 승인
  • 공급자와 외부 환경

의사소통 방식에는 직접 대화·회의·문서·이슈 추적기·코드 검토·대시보드와 자동 알림 등이 있다.

휘발되는 대화는 빠른 협의에 적합하지만 이후의 추적이 어렵다. 중요한 결정과 변경은 문서와 작업 시스템에 남긴다.

반대로 모든 대화를 긴 문서로 먼저 작성하도록 요구하면 피드백이 느려질 수 있다. 상호작용의 목적과 장기 보존 필요에 따라 방식을 선택한다.

의사소통 계획

프로젝트는 이해관계자별로 필요한 정보와 빈도, 전달 방법과 책임자를 정할 수 있다.

대상주요 정보방식
개발 팀작업, 설계, 위험과 장애물일상 협업, 이슈와 코드 검토
제품 책임자가치, 범위와 우선순위백로그와 제품 검토
경영진성과, 주요 위험과 의사결정정기 보고와 의사결정 회의
운영 팀배포, 변경과 장애 대응운영 검토와 자동 알림
사용자기능 변화, 중단과 지원릴리스 노트와 상태 안내
규제·감사 조직준수 증거와 승인공식 문서와 감사 기록
외부 공급자계약, 인터페이스와 일정공동 계획과 변경 통보

정보를 받는 사람이 실제로 어떤 결정을 내려야 하는지 고려한다. 모든 세부 작업을 경영진에게 전달하거나, 중요한 위험을 단순한 기술 보고서 속에 숨기면 필요한 판단이 이루어지기 어렵다.

회의

회의는 여러 사람이 동시에 논의하고 결정해야 하는 문제에 사용한다.

회의에는 다음 요소가 필요하다.

  • 목적
  • 필요한 참가자
  • 사전 자료
  • 결정하거나 해결할 질문
  • 진행 책임자
  • 시간 제한
  • 결정과 작업 기록
  • 후속 책임자와 기한

정보를 일방적으로 전달하기만 하는 경우에는 문서와 대시보드가 더 효율적일 수 있다.

정기 회의는 존재 자체가 목적이 되지 않도록 실제 결과와 참여 필요를 검토한다. 목적이 겹치는 회의를 통합하고, 참가자가 기여하거나 알아야 할 이유가 없는 회의는 줄인다.

회의에서 결정한 내용을 다른 팀과 미래의 담당자가 알 수 있도록 필요한 수준으로 기록한다.

일상 조정

짧은 주기의 일상 조정에서는 각 구성원의 활동 보고보다 공통 목표와 장애물, 협력이 필요한 부분을 확인한다.

다음과 같은 질문을 다룰 수 있다.

  • 현재 목표 달성을 막는 것은 무엇인가
  • 어떤 작업이 다른 사람의 입력을 기다리는가
  • 새롭게 발견된 위험과 문제가 있는가
  • 우선순위가 바뀌었는가
  • 함께 해결해야 하는 통합 문제가 있는가

Scrum에서 Daily Scrum은 Sprint Goal을 향한 진행을 확인하고 작업 계획을 조정하는 개발자들의 행사이다. 이는 관리자를 위한 개인별 상태 보고 회의로 정의되지 않는다.[99]

팀이 이미 비동기 도구로 충분히 조정하고 있다면 같은 내용을 반복하는 회의를 줄일 수 있다.

문서화와 정보 관리

프로젝트 정보가 채팅·개인 메모·회의와 여러 도구에 흩어지면 현재 상태와 결정의 근거를 찾기 어렵다.

관리할 수 있는 정보에는 다음이 있다.

  • 프로젝트 목표와 범위
  • 이해관계자와 책임
  • 요구사항과 우선순위
  • 계획과 일정
  • 위험·문제와 변경
  • 설계와 아키텍처 결정
  • 시험과 품질 결과
  • 릴리스와 운영
  • 회의 결정과 후속 작업
  • 공급자와 계약
  • 프로젝트 회고와 교훈

각 정보의 공식적인 원천을 정하고 다른 문서에서 중복하여 수동으로 관리하지 않도록 한다.

정보는 최신성·접근 권한과 보존 기간을 관리해야 한다. 개인정보·계약과 보안 자료는 모든 팀원에게 무조건 공개하지 않고 필요한 권한을 적용한다.

문서는 작성 자체보다 실제 의사결정·인수인계와 운영에 사용되는지가 중요하다. 오래되어 신뢰할 수 없는 문서는 없느니만 못할 수 있으므로 소유자와 갱신 조건을 정한다.

원격 및 분산 팀

분산 팀은 서로 다른 사무실·지역과 시간대에서 협력한다.

분산 환경에서는 복도 대화와 우연한 정보 공유가 줄어들기 때문에 다음 요소가 중요하다.

  • 공통 작업·문서와 코드 저장소
  • 비동기 의사소통
  • 결정과 문맥의 기록
  • 겹치는 협업 시간
  • 명확한 인수인계
  • 온라인 회의와 화면 공유
  • 시간대와 휴일에 대한 배려
  • 접근 권한과 개발 환경
  • 비공식적인 관계와 지식 공유
  • 언어와 문화 차이

한 지역의 팀원이 항상 불편한 시간에 회의하도록 고정하지 않고 회의 시간을 순환하거나 비동기 참여 방법을 제공할 수 있다.

본사와 원격 팀 사이에 정보와 결정 권한의 차이가 생기지 않도록 중요한 논의를 공개된 채널과 기록으로 남긴다.

분산 팀이 업무를 넘기는 형태로만 구성되면 시간대 차이만큼 피드백이 늦어질 수 있다. 가능한 경우 한 팀이 결과를 끝까지 책임질 수 있도록 구성한다.

협업 도구

프로젝트와 조직은 다음과 같은 도구를 사용할 수 있다.

  • 요구사항과 이슈 추적
  • 버전 관리와 코드 검토
  • 문서와 지식 저장소
  • 채팅과 영상 회의
  • 일정과 자원 계획
  • 설계와 모델링
  • 빌드·시험과 배포
  • 대시보드와 보고
  • 장애와 당직 관리
  • 사용자 피드백과 지원

도구는 작업 흐름을 지원해야 하며, 도구의 기본 구조가 실제 조직과 맞지 않는데도 모든 활동을 억지로 끼워 맞추어서는 안 된다.

같은 정보를 여러 도구에 반복 입력하면 불일치와 관리 비용이 생긴다. 공통 식별자와 자동 연동을 사용하고 공식 원천을 정한다.

도구에 기록된 상태가 실제 진행을 대표하는지도 확인해야 한다. 작업 항목을 닫았지만 코드가 통합되지 않았거나 배포되지 않았다면 완료 기준과 도구 흐름이 맞지 않을 수 있다.

공급자와 계약 관리

소프트웨어 프로젝트는 외부 개발사·클라우드·상용 소프트웨어와 하드웨어 공급자에 의존할 수 있다.

공급자 관리에서는 다음을 정의한다.

  • 제공할 제품과 서비스
  • 요구사항과 품질 기준
  • 인터페이스와 데이터 형식
  • 일정과 인수 조건
  • 변경과 결함 처리
  • 보안과 개인정보 책임
  • 소스 코드와 지식재산권
  • 라이선스와 재배포 권한
  • 운영 지원과 서비스 수준
  • 취약점과 업데이트 정책
  • 지원 종료와 이전
  • 분쟁과 계약 종료 조건

계약에서 산출물을 상세하게 고정하면 변경과 피드백을 반영하기 어려울 수 있다. 반대로 범위와 품질·책임이 불명확하면 인수와 비용 분쟁이 발생할 수 있다.

외부 공급자에게 작업을 맡겨도 조직은 전체 시스템의 통합·사용자 영향과 규제 책임을 관리해야 한다.

공급자의 진행률을 문서 제출량만으로 평가하지 않고 작동하는 산출물·시험과 통합 결과를 정기적으로 확인한다.

조달과 직접 개발

필요한 소프트웨어를 직접 만들지 외부 제품과 서비스를 도입할지 판단해야 한다.

직접 개발은 다음과 같은 경우 적합할 수 있다.

  • 제품의 핵심 차별화와 업무 규칙이다.
  • 요구사항이 매우 특수하다.
  • 데이터와 보안을 직접 통제해야 한다.
  • 기존 제품의 제약이 크다.
  • 장기적으로 독립적인 발전이 필요하다.

외부 제품 도입은 다음과 같은 경우 적합할 수 있다.

  • 널리 표준화된 기능이다.
  • 직접 개발의 가치가 낮다.
  • 검증된 제품과 지원이 존재한다.
  • 빠른 도입이 중요하다.
  • 장기 유지보수 역량이 부족하다.

구매 비용만 비교하지 않고 통합·사용자 교육·데이터 이전·사용량 비용·맞춤 개발과 공급자 종속을 포함한 전체 생명주기 비용을 분석한다.

조직 구조와 소프트웨어 구조

팀과 조직의 의사소통 구조는 소프트웨어의 모듈과 서비스 경계에 영향을 줄 수 있다.

여러 팀이 하나의 구성 요소를 반복해서 함께 수정하면 조정 비용과 소유권 충돌이 발생한다. 반대로 하나의 사용자 기능이 지나치게 많은 팀을 거쳐야 하면 전달 시간이 길어진다.

팀 경계를 다음과 같은 소프트웨어 경계와 맞출 수 있다.

  • 업무 영역
  • 데이터 소유권
  • 모듈과 서비스
  • 배포와 운영 단위
  • 사용자 경험
  • 플랫폼과 기반 기능

조직 구조를 그대로 코드 구조로 복사하는 것도 위험하다. 부서 개편이 시스템의 자연스러운 업무와 데이터 경계를 바꾸는 근거가 되어서는 안 된다.

조직과 아키텍처를 함께 검토하여 팀이 필요한 변경을 가능한 한 독립적으로 수행하면서 전체 시스템의 계약과 품질을 유지할 수 있도록 한다.

기술 표준과 거버넌스

대규모 조직에서는 팀마다 서로 다른 언어·프레임워크·배포 방식과 관찰 도구를 선택하면 유지보수와 보안 비용이 증가할 수 있다.

조직은 다음을 제공할 수 있다.

  • 권장 프로그래밍 언어와 런타임
  • 보안과 인증 기준
  • API와 데이터 규칙
  • 배포와 관찰 표준
  • 지원되는 플랫폼과 도구
  • 라이선스와 외부 패키지 정책
  • 예외 승인 절차
  • 폐기와 지원 종료 정책

표준은 팀의 모든 기술 판단을 중앙에서 통제하는 수단이 아니라 반복되는 문제에 안전하고 지원 가능한 기본 경로를 제공하는 수단이어야 한다.

새 기술을 시험할 수 있는 제한된 실험 경로와 평가 기준을 제공하면 조직이 정체되지 않으면서 불필요한 기술 확산을 줄일 수 있다.

기술 선택의 예외에는 이유·소유자·지원 계획과 종료 조건을 기록한다.

역량과 인력 계획

조직은 현재 프로젝트의 인원 수뿐 아니라 장기적으로 필요한 기술과 역할을 계획해야 한다.

필요한 역량에는 다음이 포함될 수 있다.

  • 문제 영역과 사용자 이해
  • 프로그래밍 언어와 플랫폼
  • 아키텍처와 데이터
  • 시험과 품질
  • 보안과 개인정보
  • 운영과 신뢰성
  • 사용자 경험과 접근성
  • 프로젝트와 제품 관리
  • 의사소통과 리더십

인력 계획에서는 다음을 확인한다.

  • 현재 팀에 필요한 역량이 있는가
  • 특정 개인에게만 지식이 집중되어 있는가
  • 채용·교육과 외부 지원 중 무엇이 필요한가
  • 새로운 사람이 생산적으로 참여하기까지 얼마나 걸리는가
  • 장기 지원과 운영을 맡을 사람이 있는가
  • 프로젝트 종료 후 핵심 지식을 어떻게 유지할 것인가

단순히 인원 수를 늘리는 것보다 부족한 전문성과 시스템 경계를 개선하는 것이 더 효과적일 수 있다.

교육과 성장

소프트웨어 기술과 운영 환경은 계속 변하므로 조직은 업무 수행과 함께 학습할 시간을 제공해야 한다.

학습 방식에는 다음이 있다.

  • 동료 검토
  • 짝 프로그래밍과 공동 작업
  • 기술 발표와 실무 공동체
  • 문서와 예제
  • 멘토링
  • 교육과 자격 과정
  • 프로토타입과 실험
  • 장애와 프로젝트 회고
  • 직무 순환
  • 오픈소스와 외부 공동체 참여

교육을 개인의 근무 외 시간에만 맡기면 조직이 필요로 하는 역량이 안정적으로 축적되기 어렵다.

새로운 기술을 학습하는 시간도 프로젝트 추정과 계획에 포함해야 한다. 학습을 숨긴 채 경험이 있는 것처럼 일정을 계획하면 품질과 일정 위험이 증가한다.

온보딩과 오프보딩

새로운 구성원이 팀에 참여할 때는 계정과 개발 도구뿐 아니라 제품의 목적·사용자·구조와 작업 방식을 이해할 수 있어야 한다.

온보딩에는 다음이 포함될 수 있다.

  • 프로젝트와 제품 개요
  • 개발 환경 구축
  • 코드와 아키텍처 안내
  • 요구사항과 업무 용어
  • 빌드·시험과 배포
  • 보안과 데이터 정책
  • 운영과 장애 대응
  • 코드 검토와 의사결정 방식
  • 담당자와 도움을 받을 경로
  • 작은 초기 작업과 피드백

구성원이 팀을 떠날 때는 접근 권한과 자산을 회수하고, 담당 업무·운영 지식과 미완료 결정을 인계해야 한다.

인수인계를 마지막 며칠의 문서 작성에만 의존하지 않고 평소에 지식과 소유권을 공유하는 편이 안전하다.

지식 관리

조직의 소프트웨어 지식은 코드와 문서뿐 아니라 사람의 경험·운영 판단과 과거 결정에 존재한다.

관리할 지식에는 다음이 있다.

  • 업무와 사용자 개념
  • 시스템 구조와 인터페이스
  • 데이터와 이전
  • 개발·시험과 배포
  • 장애와 복구
  • 보안과 규제
  • 과거 결정과 대안
  • 공급자와 외부 시스템
  • 알려진 한계와 기술 부채

지식을 모두 중앙 문서에 상세히 기록하는 것은 현실적이지 않다. 반복해서 필요하고 사람의 부재로 위험해지는 정보부터 문서화·자동화하고, 코드 검토와 공동 작업으로 지식을 분산한다.

문서의 검색 가능성과 소유자·갱신 시점을 관리한다. 동일한 정보를 여러 문서에서 복제하기보다 공식 원천과 연결한다.

성과 관리

프로젝트와 팀의 성과는 코드량·작업 항목 수와 근무 시간만으로 평가하기 어렵다.

소프트웨어 팀의 성과에는 다음과 같은 결과가 포함될 수 있다.

  • 사용자와 사업 성과
  • 제품의 품질과 신뢰성
  • 변경의 전달 속도
  • 보안과 안전
  • 운영과 복구 가능성
  • 유지보수성과 기술 부채
  • 팀 협업과 학습
  • 예측 가능성과 투명성

개인의 코드 줄 수와 커밋 수, 닫은 이슈 수를 목표로 삼으면 작은 변경을 불필요하게 분리하거나 복잡한 검토·지원 작업이 저평가될 수 있다.

팀 단위의 결과와 장기 품질을 중심으로 평가하고, 개인에게는 역할과 수준에 맞는 기여·협업과 성장에 관한 피드백을 제공한다.

성과 지표가 실제 목표를 왜곡하지 않는지 정기적으로 검토한다.

진행 상황 측정

소프트웨어 프로젝트의 진행은 소비한 시간과 작성한 코드보다 검증된 결과와 남은 위험으로 판단해야 한다.

진행 상태를 확인할 수 있는 정보에는 다음이 있다.

  • 완료 기준을 충족한 기능
  • 작동하고 통합된 소프트웨어
  • 사용자와 이해관계자의 검토 결과
  • 시험과 품질 상태
  • 해결된 주요 위험
  • 남은 작업과 의존성
  • 배포와 운영 준비
  • 실제 처리량과 주기 시간
  • 변경된 범위와 우선순위
  • 예산과 일정 예측

“90% 완료” 같은 단일 백분율은 남은 통합·시험과 어려운 작업을 숨길 수 있다. 어떤 기능과 품질이 실제로 검증되었고 무엇이 아직 불확실한지 함께 제시한다.

진행 보고는 좋은 소식만 보여 주는 홍보가 아니라 필요한 의사결정과 지원을 얻기 위한 정보여야 한다.

대시보드와 지표

프로젝트 대시보드는 주요 상태와 추세를 이해관계자에게 제공한다.

표시할 수 있는 정보에는 다음이 있다.

  • 목표와 마일스톤
  • 기능 및 릴리스 진행
  • 위험과 문제
  • 품질과 결함
  • 배포 상태
  • 일정과 비용 예측
  • 팀 처리량과 작업 대기
  • 외부 의존성
  • 사용자와 운영 지표

모든 측정값을 한 화면에 넣기보다 독자가 내려야 할 결정과 프로젝트 위험에 맞는 정보를 선택한다.

지표의 정의와 수집 방법이 바뀌면 과거 값과 단순 비교하기 어려울 수 있으므로 변경을 기록한다.

수치 뒤의 문맥과 원인을 함께 분석하고, 목표 수치 달성을 위해 실제 품질을 희생하지 않도록 한다.

예측형과 적응형 관리

예측형 관리는 초기 범위와 계획을 비교적 상세히 정의하고, 계획 대비 실제 상태와 변경을 통제한다. 요구사항이 안정적이고 계약·인증과 하드웨어 일정이 중요한 프로젝트에 적합할 수 있다.

적응형 관리는 짧은 주기로 결과를 만들고 피드백과 새로운 정보를 반영하여 범위와 계획을 반복적으로 조정한다. 요구와 해결 방법의 불확실성이 높고 사용자의 실제 반응이 중요한 제품에 적합할 수 있다.

두 방식은 완전히 배타적이지 않다.

  • 전체 예산과 하드웨어 출시일은 예측적으로 관리한다.
  • 세부 소프트웨어 기능은 반복·점진적으로 개발한다.
  • 안전 관련 핵심은 엄격한 기준선과 검증을 사용한다.
  • 사용자 인터페이스는 프로토타입과 피드백으로 발전시킨다.
  • 정기 릴리스는 고정하되 포함 기능은 우선순위에 따라 조정한다.

ISO 21502는 예측형·점진형·반복형·적응형과 혼합형을 포함한 여러 전달 접근에 적용할 수 있도록 작성되었다.[100]

프로젝트의 이름을 애자일이나 폭포수로 정하는 것보다 실제 위험과 의사결정에 적합한 계획·피드백 구조를 사용하는지가 중요하다.

애자일 환경의 관리

애자일 환경에서도 목표·예산·위험과 조직 관리가 사라지지 않는다. 세부 계획과 통제를 짧은 주기와 실제 결과를 중심으로 수행한다.

다음과 같은 관리 활동이 사용될 수 있다.

  • 제품 목표와 비전
  • 우선순위가 정해진 백로그
  • 짧은 반복 계획
  • 작동하는 증분의 검토
  • 사용자와 이해관계자 피드백
  • 팀의 작업 방식 개선
  • 완료 기준과 품질 자동화
  • 처리량과 주기 시간 측정
  • 위험이 큰 작업의 조기 수행
  • 릴리스와 운영 결과의 반영

애자일 선언은 계획과 문서·계약을 제거한다고 말하지 않는다. 변화가 큰 환경에서 사람의 협력과 작동하는 소프트웨어, 고객과의 협업과 변화 대응에 더 높은 가치를 둔다.[101]

애자일의 이름을 사용하면서 상위 관리자가 모든 작업을 세밀하게 배정하거나, 일정은 고정한 채 범위만 계속 추가하면 실제 적응성은 생기지 않는다.

Scrum의 역할 구조

Scrum은 복잡한 문제에서 적응 가능한 해법을 통해 가치를 만들기 위한 경량 프레임워크이다. Scrum Guide의 현재 공식판은 2020년 11월에 공개되었다.[102]

Scrum Team에는 다음 책임이 존재한다.

  • Product Owner는 Product Goal과 Product Backlog를 효과적으로 관리하고 제품 가치를 최대화할 책임을 가진다.
  • Scrum Master는 Scrum이 이해되고 적용되도록 하며 팀과 조직의 효과성을 지원한다.
  • Developers는 매 Sprint마다 사용할 수 있는 Increment를 만들고 작업 계획과 품질에 책임을 가진다.

Scrum의 역할은 전통적인 직책 전체를 대체하지 않는다. 개발자에는 프로그래머뿐 아니라 제품 증분을 만드는 데 필요한 시험·디자인과 다른 전문 역할이 포함될 수 있다.

Scrum을 사용하는 조직에서도 예산·인사·제품 전략·보안과 여러 팀의 의존성을 위한 추가 관리 구조가 필요할 수 있다.

규모 확장

여러 팀이 하나의 제품과 시스템을 개발하면 공통 목표·아키텍처와 통합을 조정해야 한다.

규모가 커질 때 다음 문제가 발생할 수 있다.

  • 백로그와 우선순위의 충돌
  • 공통 구성 요소와 데이터의 소유권
  • 팀 사이의 인터페이스
  • 통합과 릴리스 일정
  • 기술과 품질 기준
  • 배포와 운영 책임
  • 중복 기능과 플랫폼
  • 의사결정과 승인 병목

회의와 관리 계층을 늘리는 것만으로 규모 문제를 해결하기 어렵다. 제품과 시스템을 명확한 업무·데이터 경계로 나누고, 팀 사이의 의존성과 공유 상태를 줄여야 한다.

공통 목표와 통합 기준은 유지하되 세부 작업은 각 팀이 독립적으로 결정할 수 있게 한다.

대규모 프레임워크를 그대로 도입하기 전에 실제로 해결하려는 조정 문제와 필요한 최소 구조를 확인한다.

여러 프로젝트의 조정

한 조직은 여러 프로젝트와 제품을 동시에 수행하며 인력·예산·플랫폼과 출시 일정을 공유할 수 있다.

프로젝트 사이에서는 다음과 같은 충돌이 발생할 수 있다.

  • 같은 전문가와 장비가 필요하다.
  • 공통 플랫폼 변경 순서가 다르다.
  • 한 프로젝트의 지연이 다른 프로젝트를 막는다.
  • 서로 충돌하는 데이터와 API 요구가 있다.
  • 같은 고객과 사용자에게 여러 변화를 동시에 제공한다.
  • 우선순위가 조직의 전략과 맞지 않는다.

프로그램과 포트폴리오 수준에서는 다음을 수행할 수 있다.

  • 공통 목표와 편익 관리
  • 프로젝트 사이의 의존성 조정
  • 자원과 예산 배분
  • 중복 프로젝트 통합 또는 종료
  • 공통 플랫폼과 표준 결정
  • 전체 위험과 변화 관리
  • 전략 변화에 따른 우선순위 갱신

진행 중이라는 이유만으로 가치가 낮은 프로젝트를 계속해서는 안 된다. 중단 비용과 남은 가치, 인력의 다른 활용 가능성을 함께 평가한다.

포트폴리오 관리

포트폴리오 관리는 조직의 전략과 제한된 자원을 기준으로 프로젝트·프로그램과 제품 투자를 선택하고 균형을 조정한다.

평가할 수 있는 요소에는 다음이 있다.

  • 전략과 사용자 가치
  • 예상 편익
  • 비용과 투자 기간
  • 위험과 규제 의무
  • 기술 부채와 운영 위험
  • 프로젝트 사이의 의존성
  • 인력과 플랫폼 용량
  • 단기 및 장기 투자 균형
  • 새 사업과 기존 시스템 유지
  • 중단과 축소 가능성

모든 프로젝트를 개별적으로 성공시키려 하면 전체 조직의 자원과 목표가 충돌할 수 있다. 일부 프로젝트의 범위를 줄이거나 중단하여 더 중요한 제품과 기반에 집중해야 할 수 있다.

ISO 21500:2021은 프로젝트·프로그램과 포트폴리오 관리가 이루어지는 조직적 문맥과 이들 개념의 관계를 설명한다.[103]

조직 변화

새 소프트웨어의 도입은 프로그램 설치만으로 끝나지 않고 조직의 업무·역할과 책임을 바꿀 수 있다.

조직 변화에는 다음이 포함될 수 있다.

  • 새로운 업무 절차
  • 기존 수작업의 자동화
  • 역할과 승인 권한 변경
  • 데이터 소유권 변화
  • 교육과 사용자 지원
  • 성과 지표 변화
  • 기존 시스템과 절차의 종료
  • 사용자 저항과 적응
  • 법률·노동과 계약 문제

기술적으로 성공한 시스템도 사용자가 기존 절차를 계속 사용하거나 조직 정책과 맞지 않으면 기대 성과를 얻지 못할 수 있다.

실제 사용자와 관리자를 초기부터 참여시키고 시범 운영·교육과 전환 기간을 제공한다. 사용자의 저항을 단순한 교육 부족으로 보지 않고 업무 손실·책임 증가와 감시 우려 같은 원인을 확인한다.

갈등 관리

프로젝트에서는 요구사항·기술·우선순위와 자원에 관한 갈등이 발생할 수 있다.

갈등은 반드시 부정적인 것은 아니다. 서로 다른 전문성과 위험 인식이 드러나는 과정일 수 있다. 문제는 갈등을 숨기거나 개인 공격과 권력 경쟁으로 바꾸는 데 있다.

갈등을 다룰 때는 다음을 구분한다.

  • 공통 목표
  • 확인된 사실
  • 아직 검증되지 않은 가정
  • 각 대안의 장점과 비용
  • 결정 권한
  • 결정 기한
  • 결정 후의 검증 방법

기술적 의견은 직급과 말의 강도보다 요구사항·측정과 위험을 근거로 평가한다.

합의가 이루어지지 않으면 권한자가 명시적으로 결정하고, 결정 이유와 다시 검토할 조건을 기록한다.

윤리와 전문적 책임

소프트웨어 프로젝트의 일정과 비용 압박은 안전·보안·개인정보와 사용자 권리와 충돌할 수 있다.

소프트웨어 엔지니어와 관리자는 다음과 같은 책임을 고려해야 한다.

  • 알려진 중대한 위험을 숨기지 않는다.
  • 시험과 지표를 의도적으로 왜곡하지 않는다.
  • 개인정보와 기밀 정보를 보호한다.
  • 차별과 접근성 문제를 고려한다.
  • 라이선스와 지식재산권을 준수한다.
  • 자신의 전문 범위와 불확실성을 정직하게 설명한다.
  • 안전과 공공 이익에 중대한 위험이 있으면 적절히 보고한다.
  • 팀에 지속 불가능한 과로를 정상 상태로 강요하지 않는다.

IEEE Computer Society는 소프트웨어 공학 전문 실무를 안전하고 보안이 유지되며 최종 사용자의 필요를 충족하는 소프트웨어를 책임 있게 제공하기 위해 필요한 지식·기술과 책임으로 설명한다.[104]

전문적 책임은 개발자 개인에게만 부과되지 않는다. 조직은 위험을 보고할 경로와 독립적인 검토, 충분한 시험·보안과 수정 시간을 제공해야 한다.

지속 가능한 작업

짧은 기간의 추가 업무가 필요한 상황은 있을 수 있지만 장기간의 과도한 근무를 기본 계획으로 사용하면 품질과 팀의 지속 가능성이 낮아진다.

지속적인 과로는 다음 문제를 만들 수 있다.

  • 판단과 집중력 저하
  • 결함과 보안 실수 증가
  • 검토와 시험 생략
  • 지식이 특정인에게 집중
  • 구성원 이탈
  • 유지보수와 문서 부족
  • 실제 작업 능력에 대한 잘못된 계획

애자일 선언의 원칙은 후원자·개발자와 사용자가 일정한 속도를 계속 유지할 수 있는 지속 가능한 개발을 강조한다.[105]

일정 문제를 반복적인 초과 근무로 해결하기보다 범위·우선순위와 의존성, 자동화와 인력 계획을 검토한다.

프로젝트 검토

프로젝트 검토는 현재 상태와 목표·위험을 평가하고 계획을 조정하는 활동이다.

검토에서는 다음을 다룰 수 있다.

  • 목표와 기대 성과의 유효성
  • 완료된 결과와 사용자 피드백
  • 범위와 우선순위
  • 일정과 비용 예측
  • 품질과 기술 부채
  • 위험과 문제
  • 팀과 자원
  • 외부 의존성
  • 배포와 운영 준비
  • 계속·변경·중단 결정

검토는 프로젝트 팀이 보고서를 제출하고 관리자가 평가하는 일방향 행사로만 구성할 필요는 없다. 필요한 지원과 의사결정, 제약 변경을 함께 다룬다.

초기 계획과의 차이가 있다는 사실만 지적하지 않고 차이가 발생한 이유와 현재 최선의 대응을 판단한다.

회고

회고는 팀이 일정 기간의 작업 방식과 협업·도구를 돌아보고 개선할 행동을 선택하는 활동이다.

회고에서는 다음과 같은 질문을 다룰 수 있다.

  • 무엇이 목표 달성에 도움이 되었는가
  • 무엇이 작업과 품질을 방해했는가
  • 반복되는 대기와 수작업은 무엇인가
  • 어떤 위험과 결함을 늦게 발견했는가
  • 의사소통과 결정은 효과적이었는가
  • 다음 기간에 어떤 작은 변화를 시험할 것인가

회고가 단순한 불만 공유나 정기 행사로 끝나지 않도록 소수의 실행 가능한 개선 항목과 책임자를 정하고 이후 결과를 확인한다.

팀의 권한으로 해결할 수 없는 조직 문제는 상위 관리와 플랫폼·인사 조직에 전달해야 한다.

프로젝트 종료

프로젝트 종료에서는 결과물을 전달하는 것뿐 아니라 책임과 지식, 계약과 자원을 정리한다.

종료 활동에는 다음이 포함될 수 있다.

  • 목표와 수용 기준 확인
  • 남은 결함과 위험 기록
  • 최종 릴리스와 구성 기준선
  • 운영·유지보수 조직에 인계
  • 데이터와 사용자 전환
  • 문서와 교육
  • 계약과 공급자 정리
  • 계정·환경과 비용 자원 정리
  • 기록과 증거 보존
  • 프로젝트 성과 평가
  • 회고와 교훈
  • 미완료 작업의 소유권 이전

프로젝트가 취소되었더라도 종료 관리가 필요하다. 만들어진 코드와 데이터·계정, 계약과 사용자 영향을 정리하고 취소 이유와 재사용 가능한 결과를 기록한다.

운영 인계는 프로젝트 마지막에 문서를 전달하는 한 번의 행사가 아니라 개발 중부터 운영 조직이 참여하고 실제 배포와 장애 대응을 함께 검증하는 과정이어야 한다.

교훈 관리

프로젝트에서 얻은 교훈은 다음 프로젝트가 같은 문제를 반복하지 않도록 조직의 프로세스와 도구에 반영해야 한다.

교훈에는 다음이 포함될 수 있다.

  • 효과적이었던 계획과 협업 방식
  • 잘못된 추정과 가정
  • 반복된 결함과 위험
  • 공급자와 계약 문제
  • 사용자와 요구사항 이해
  • 아키텍처와 기술 선택
  • 시험과 배포
  • 운영과 장애 대응
  • 조직과 의사결정

단순히 “소통을 강화한다”와 같은 일반 문장을 저장하면 실제 개선에 사용하기 어렵다. 어떤 상황에서 무엇이 발생했고 다음에는 어떤 구체적인 행동과 기준을 적용할지 기록한다.

교훈 저장소만 만들고 검색·적용하지 않으면 가치가 없다. 새 프로젝트의 착수와 위험 검토에서 관련 교훈을 확인하도록 프로세스에 연결할 수 있다.

프로젝트 관리의 조정

모든 소프트웨어 프로젝트에 동일한 관리 구조와 문서·회의를 적용할 필요는 없다.

작은 내부 도구에서는 다음 정도로 충분할 수 있다.

  • 명확한 목표와 책임자
  • 짧은 작업 목록
  • 버전 관리와 코드 검토
  • 기본 시험과 배포 절차
  • 사용자와의 직접적인 피드백
  • 간단한 위험과 결정 기록

대규모 분산 시스템에서는 다음이 필요할 수 있다.

  • 여러 팀의 제품과 기술 거버넌스
  • 서비스와 데이터 소유권
  • 프로그램 및 의존성 관리
  • 공식적인 품질과 보안 검토
  • 용량·운영과 장애 대응
  • 공급자와 계약 관리
  • 공통 플랫폼과 표준

안전·규제 대상 프로젝트에서는 다음이 요구될 수 있다.

  • 공식 책임과 독립성
  • 요구사항·설계와 시험 추적성
  • 단계별 승인과 기준선
  • 위험과 안전 관리
  • 독립적인 검증과 감사
  • 장기적인 기록 보존
  • 변경 통제와 인증

관리 활동은 프로젝트의 위험과 복잡성을 줄이는 데 필요한 수준으로 조정한다. 절차가 실제 의사결정과 품질에 기여하지 않는다면 단순화하고, 중요한 위험이 통제되지 않는다면 필요한 활동을 추가한다.

프로젝트와 조직 관리의 지속성

프로젝트 관리는 일정표를 작성하고 작업을 배정하는 행정 활동에 그치지 않는다. 어떤 문제를 해결할지 정하고, 불확실성과 위험 속에서 제한된 자원을 배분하며, 여러 전문 분야가 하나의 결과를 만들 수 있도록 조정하는 공학 활동이다.

조직 관리는 프로젝트가 끝날 때마다 해체되는 임시 인력 배치만을 의미하지 않는다. 제품과 기술에 필요한 지식을 축적하고, 책임과 의사결정 구조를 만들며, 팀이 품질과 사용자 가치를 장기간 제공할 수 있는 환경을 유지해야 한다.

좋은 프로젝트 관리는 계획과 실제의 차이를 숨기지 않는다. 현재의 사실과 가정·위험을 드러내고, 작동하는 결과와 사용자 피드백을 통해 계획을 갱신하며, 필요한 경우 범위와 일정·구조 또는 프로젝트 자체를 변경한다.

좋은 조직은 사람을 교환 가능한 자원으로만 취급하지 않는다. 전문성과 협업 관계·제품 지식을 장기적인 역량으로 보고, 팀이 책임과 자율성을 가지면서도 공통 목표와 품질·윤리적 기준 안에서 판단할 수 있도록 지원한다.

도구와 자동화

소프트웨어 공학에서는 요구사항을 기록하고, 설계를 표현하고, 코드를 작성하며, 빌드·시험·배포하고, 운영 상태를 감시하기 위해 다양한 도구를 사용한다. 이러한 도구는 사람의 공학적 판단을 대체하기보다 복잡한 정보를 관리하고 반복 작업을 일관되게 수행하며, 결과와 변경 이력을 추적할 수 있도록 지원한다.

소프트웨어 공학 도구는 소프트웨어 생명주기의 하나 이상의 활동을 지원하는 프로그램과 서비스, 실행 환경을 가리킨다. 편집기와 컴파일러처럼 개발자가 직접 사용하는 도구뿐 아니라 요구사항 관리 시스템, 버전 관리 시스템, 빌드 서버, 시험 장비, 아티팩트 저장소, 배포 시스템과 운영 관찰 플랫폼도 포함된다.

자동화는 사람이 반복적으로 수행하던 작업을 명시적인 규칙과 프로그램으로 표현하여 도구가 일관되게 실행하도록 만드는 활동이다. 자동화할 수 있는 대상에는 코드 형식 검사, 컴파일, 시험, 패키징, 인프라 생성, 배포, 상태 확인, 보안 분석, 문서 생성과 장애 복구가 있다.

자동화의 목적은 단순히 사람의 작업을 줄이는 데 있지 않다. 같은 입력과 조건에서 같은 절차를 반복하고, 누가 언제 무엇을 실행했는지 기록하며, 실패를 빠르게 감지하고, 개발자마다 서로 다른 수동 절차를 사용하는 문제를 줄이는 데 있다.

도구를 많이 사용한다고 소프트웨어 공학 활동이 자동으로 성숙해지는 것은 아니다. 잘못된 요구사항을 정교한 관리 시스템에 저장할 수 있고, 의미 없는 시험을 수천 개 자동 실행할 수도 있으며, 잘못된 배포 절차를 자동화하여 오류를 더 빠르게 확산시킬 수도 있다. 먼저 해결하려는 문제와 필요한 정보·책임·판정 기준을 정한 뒤 이를 지원할 도구와 자동화 수준을 선택해야 한다.

IEEE Computer Society의 SWEBOK V4.0은 소프트웨어 요구사항·설계·구축·시험·구성 관리·공학 관리·운영과 보안 등 여러 지식 영역에서 관련 도구를 다루며, 요구사항 관리와 모델링, 시험 사례 생성, 단위 시험, 형상 관리와 개발 환경 등을 소프트웨어 공학 실무의 일부로 설명한다.[106]

도구의 역할

소프트웨어 공학 도구는 다음과 같은 역할을 수행할 수 있다.

  • 사람이 작성한 정보를 구조화하고 검색할 수 있게 한다.
  • 변경과 버전, 승인과 책임자를 기록한다.
  • 반복적인 명령과 절차를 일관되게 실행한다.
  • 사람이 직접 확인하기 어려운 대규모 코드와 데이터를 분석한다.
  • 여러 개발자의 작업을 공유하고 통합한다.
  • 요구사항·코드·시험과 릴리스 사이의 관계를 연결한다.
  • 품질과 보안 규칙을 자동으로 검사한다.
  • 빌드와 배포 산출물을 재현하고 보존한다.
  • 운영 중인 시스템의 상태와 실패를 관찰한다.
  • 사용자와 운영 환경에서 얻은 정보를 개발 과정으로 전달한다.

도구는 공학 활동의 결과를 저장하는 수단이면서 활동 자체를 제한하는 구조가 될 수 있다. 이슈 추적 시스템이 모든 작업을 하나의 고정된 흐름으로 강제하면 실제 프로젝트의 예외와 반복적 탐색을 표현하기 어려울 수 있다. 반대로 상태와 책임에 관한 기본 규칙이 없으면 작업 항목이 현재 상황을 나타내지 못한다.

도구를 선택할 때는 기능 수뿐 아니라 프로젝트의 실제 작업 방식과 정보 구조에 맞는지 평가해야 한다.

도구와 방법의 구분

도구는 방법이나 프로세스와 동일하지 않다.

버전 관리 시스템을 설치했다고 구성 관리가 완성되는 것은 아니다. 어떤 파일과 산출물을 관리할지, 변경을 어떻게 검토할지, 기준선과 릴리스를 어떻게 식별할지를 정해야 한다.

지속적 통합 서버가 있다고 지속적 통합을 수행하는 것도 아니다. 개발자가 작은 변경을 자주 공유하고, 자동 빌드와 시험 실패에 빠르게 대응하며, 주 개발선을 정상 상태로 유지해야 한다.

요구사항 관리 도구가 있어도 요구사항 도출·분석과 이해관계자 협상이 자동으로 이루어지지 않는다. 도구는 요구사항의 상태와 관계를 관리할 수 있지만 어떤 요구가 실제 사용자의 필요를 올바르게 나타내는지는 사람이 판단해야 한다.

따라서 다음을 구분할 수 있다.

  • 방법은 문제를 해결하고 활동을 수행하는 방식이다.
  • 프로세스는 활동과 역할, 입력과 산출물의 관계를 조직한다.
  • 도구는 방법과 프로세스의 일부 작업을 지원하거나 자동화한다.
  • 자동화 규칙은 도구가 어떤 조건에서 무엇을 실행하고 어떻게 판정할지 정의한다.

통합 개발 환경

통합 개발 환경(Integrated Development Environment, IDE)은 소스 코드 편집과 탐색, 빌드·실행·디버깅과 시험 기능을 하나의 작업 환경에 통합한 도구이다.

통합 개발 환경에는 다음과 같은 기능이 포함될 수 있다.

  • 구문 강조
  • 코드 완성
  • 타입과 기호 정보
  • 정의와 참조 탐색
  • 이름 변경과 리팩터링
  • 빌드와 실행
  • 디버거
  • 시험 실행
  • 정적 분석
  • 버전 관리 연동
  • 프로파일링
  • 데이터베이스와 원격 시스템 연결
  • 프로젝트와 의존성 관리
  • 확장 기능

통합 개발 환경은 언어와 프레임워크의 구조를 이해하여 단순한 텍스트 편집기보다 높은 수준의 탐색과 검사를 제공할 수 있다. 컴파일하기 전에 잘못된 타입과 존재하지 않는 기호를 표시하고, 여러 파일에 걸친 이름 변경을 안전하게 수행하며, 실행 중인 프로그램의 상태를 코드와 연결할 수 있다.

그러나 IDE의 내부 설정에만 프로젝트 실행 방법이 저장되면 다른 편집기와 자동 빌드 환경에서 프로젝트를 재현하기 어려워진다. 빌드·시험과 코드 생성은 가능한 한 IDE 외부에서도 실행 가능한 명령과 설정으로 정의하고, IDE는 이를 호출하는 인터페이스로 사용하는 편이 적절하다.

코드 편집기

코드 편집기는 소스 파일의 작성과 탐색에 집중하며 확장 기능을 통해 IDE와 유사한 기능을 제공할 수 있다.

편집기 선택은 개인의 생산성과 접근성에 영향을 주지만, 팀의 코드 형식·빌드와 시험 결과가 특정 편집기에 의존해서는 안 된다.

프로젝트는 편집기마다 별도의 규칙을 유지하기보다 다음과 같은 공통 기반을 제공할 수 있다.

  • 저장소에 포함된 코드 형식 설정
  • 언어 서버와 컴파일러 설정
  • 빌드와 시험 명령
  • 디버그 실행 구성
  • 파일 인코딩과 줄바꿈 규칙
  • 권장 확장과 선택적인 개발 환경 파일
  • 프로젝트 루트와 생성 파일 규칙

편집기 설정 가운데 개인의 화면 배치와 키 입력은 공유하지 않을 수 있지만, 코드 의미와 빌드에 영향을 주는 설정은 저장소에서 관리하는 편이 좋다.

언어 서버

언어 서버는 프로그래밍 언어의 구문·타입과 프로젝트 정보를 분석하여 편집기에 코드 완성·정의 탐색·진단과 리팩터링 기능을 제공한다.

Language Server Protocol은 언어 서버와 편집기 또는 개발 도구가 통신하는 방식을 표준화한다. 이를 통해 하나의 언어 지원 구현을 여러 편집기에서 사용할 수 있고, 편집기는 각 언어의 분석기를 직접 내장하지 않아도 된다.[107]

언어 서버가 제공할 수 있는 기능은 다음과 같다.

  • 구문 및 타입 오류 진단
  • 코드 완성
  • 정의와 선언으로 이동
  • 참조 검색
  • 기호 목록
  • 인수와 문서 표시
  • 이름 변경
  • 코드 동작과 자동 수정
  • 의미 기반 강조
  • 호출 및 타입 계층
  • 프로젝트 전체 색인

언어 서버의 진단은 개발자에게 빠른 피드백을 제공하지만 실제 컴파일러·링커와 대상 플랫폼의 결과를 완전히 대체하지는 않는다. 편집기에서는 오류가 없어도 다른 컴파일러 설정이나 조건부 코드에서 빌드가 실패할 수 있으므로 자동화된 실제 빌드를 함께 유지한다.

컴파일러와 인터프리터

컴파일러와 인터프리터는 소스 코드를 실행 가능한 형태로 변환하거나 직접 실행한다. 이들은 실행 도구이면서 프로그램의 문법과 타입, 일부 오류를 검사하는 분석 도구이다.

컴파일러는 다음과 같은 정보를 제공할 수 있다.

  • 구문 오류
  • 타입 불일치
  • 초기화되지 않은 값
  • 사용되지 않는 코드와 변수
  • 잘못된 형 변환
  • 도달할 수 없는 코드
  • 호출 규약과 링크 오류
  • 플랫폼과 명령어 집합의 호환성
  • 최적화 보고
  • 정적 분석 경고

프로젝트는 컴파일러 경고 수준과 오류 처리 정책을 정할 수 있다. 새 코드에서 경고를 허용하면 중요한 문제가 많은 오래된 경고에 묻힐 수 있으므로, 지원하는 도구 체인에서 경고 없는 상태를 유지하거나 기존 경고와 새 경고를 구분하여 관리할 수 있다.

여러 컴파일러와 인터프리터 구현을 지원하면 표준과 구현별 동작 차이를 발견할 수 있지만 시험 조합과 유지보수 비용이 증가한다. 실제 지원 범위를 명확히 정하고 자동 빌드 행렬에서 검증한다.

디버거

디버거는 실행 중인 프로그램을 중단하고 상태와 제어 흐름을 조사할 수 있도록 지원한다.

일반적인 기능에는 다음이 있다.

  • 중단점
  • 단계별 실행
  • 호출 스택
  • 변수와 메모리 검사
  • 조건부 중단
  • 스레드와 작업 상태
  • 예외 발생 지점
  • 레지스터와 어셈블리 코드
  • 원격 프로세스 연결
  • 코어 덤프와 충돌 자료 분석
  • 실행 중 값 변경

디버거는 관찰된 실패의 원인을 조사하는 데 유용하지만 실행 시점과 동작을 변화시킬 수 있다. 경쟁 상태와 시간 의존 결함은 중단점이 있을 때 사라질 수 있으므로 로그·추적·메모리 분석기와 재현 가능한 시험을 함께 사용한다.

운영 환경에서는 프로세스를 직접 중단하기 어려울 수 있다. 충돌 덤프·구조화된 로그와 추적 식별자를 수집하여 다른 환경에서 분석할 수 있도록 설계한다.

프로파일러

프로파일러는 프로그램 실행 중 시간·메모리·입출력과 자원 사용을 측정하여 병목과 비용이 큰 부분을 찾는다.

측정할 수 있는 정보에는 다음이 있다.

  • 함수별 CPU 시간
  • 호출 횟수와 호출 관계
  • 메모리 할당
  • 힙 사용과 객체 생존 시간
  • 잠금 대기
  • 스레드와 작업 실행
  • 파일과 네트워크 입출력
  • 캐시 누락
  • 그래픽 처리 시간
  • 전력과 장치 사용

프로파일링은 추측에 기반한 최적화를 줄이고 실제 작업 부하에서 비용이 집중된 부분을 보여 준다.

개발용 작은 데이터에서는 병목이 나타나지 않을 수 있으므로 운영과 유사한 데이터·사용자 흐름과 장시간 실행에서 측정해야 한다.

프로파일러 자체의 측정 오버헤드와 샘플링 방식도 결과에 영향을 줄 수 있다. 절대 수치와 함수 순위를 해석할 때 사용한 환경과 설정을 함께 기록한다.

요구사항 관리 도구

요구사항 관리 도구는 요구사항과 이해관계자의 필요, 상위 목표·설계·시험 사이의 관계를 구조적으로 관리한다.

다음과 같은 기능을 제공할 수 있다.

  • 요구사항의 고유 식별
  • 버전과 변경 이력
  • 상태와 승인
  • 계층과 분해
  • 출처와 근거
  • 우선순위
  • 기준선
  • 설계와 시험 추적성
  • 의견과 검토
  • 보고서 생성
  • 접근 권한
  • 제품 변형 관리

요구사항이 수천 개에 이르고 여러 공급자와 안전·규제 증거가 연결되는 시스템에서는 전용 도구가 필요할 수 있다. 작은 제품에서는 이슈 추적기와 버전 관리되는 문서로 충분할 수 있다.

도구를 선택할 때는 요구사항 문장을 저장하는 기능보다 변경·검토와 추적 관계를 실제 프로세스에서 유지할 수 있는지를 확인한다.

요구사항 도구가 개발 백로그와 분리되어 있으면 승인된 요구사항과 실제 구현 작업이 서로 다른 상태를 나타낼 수 있다. 공통 식별자와 자동 연동을 사용하거나 하나의 공식 원천을 정한다.

모델링 도구

모델링 도구는 시스템의 구조와 동작, 데이터와 상태를 시각적 또는 정형적인 모델로 표현하고 분석한다.

다룰 수 있는 모델에는 다음이 있다.

  • 시스템 문맥
  • 유스 케이스
  • 클래스와 구성 요소
  • 상태 전이
  • 활동과 업무 흐름
  • 시퀀스와 통신
  • 데이터 흐름
  • 개체와 관계
  • 배포 구조
  • 네트워크와 하드웨어
  • 위협과 신뢰 경계

도구는 모델의 구문과 관계를 검사하고, 여러 뷰 사이의 요소를 연결하며, 문서와 코드를 생성할 수 있다.

모델이 실제 구현과 자동으로 연결되지 않으면 시간이 지나면서 오래된 그림이 될 수 있다. 코드에서 생성할 수 있는 의존성·배포 정보는 자동 추출하고, 사람이 결정해야 하는 책임·의도와 상충 관계를 모델에 집중할 수 있다.

모델링 도구의 형식 자체가 설계 품질을 보장하지는 않는다. 복잡한 모델을 유지하는 비용이 실제 분석과 의사소통 가치보다 큰지 검토해야 한다.

이슈와 작업 추적

이슈 추적 도구는 기능·결함·위험·작업과 의사결정을 기록하고 책임과 상태를 관리한다.

작업 항목에는 다음 정보가 포함될 수 있다.

  • 제목과 목적
  • 사용자와 사업 가치
  • 요구사항과 수용 기준
  • 우선순위
  • 담당자와 검토자
  • 상태
  • 관련 코드와 설계
  • 차단 요소와 의존성
  • 목표 릴리스
  • 시험 결과
  • 실제 완료와 배포 상태

도구의 상태 이름은 실제 작업 흐름과 완료 조건을 나타내야 한다. 완료가 코드 작성 완료인지, 주 개발선 통합인지, 운영 배포인지 명확하지 않으면 보고와 실제 상태가 달라진다.

작업 추적기를 개인의 활동을 세밀하게 감시하는 수단으로 사용하면 개발자는 실제 문제 해결보다 상태 갱신과 작업 분할 방식에 집중할 수 있다. 도구는 팀의 조정과 위험 관리에 필요한 정보를 제공해야 한다.

협업과 의사소통 도구

협업 도구에는 채팅·전자우편·영상 회의·공동 문서·화이트보드와 알림 시스템이 포함된다.

도구마다 적합한 정보의 성격이 다르다.

  • 즉각적인 질문과 짧은 협의는 채팅이 적합할 수 있다.
  • 공식적인 외부 통보와 승인에는 전자우편이 사용될 수 있다.
  • 복잡한 토론과 관계 형성에는 음성·영상 회의가 유용할 수 있다.
  • 장기적으로 유지해야 하는 결정과 지식은 문서와 이슈에 기록한다.
  • 코드 변경에 관한 구체적인 논의는 코드 검토 시스템에 남긴다.
  • 운영 장애에는 전용 사건 관리와 상태 통보 도구를 사용할 수 있다.

채팅에서 결정된 중요한 내용을 장기 기록으로 옮기지 않으면 이후 참가하지 않은 사람이 문맥을 알기 어렵다. 반대로 모든 짧은 대화를 공식 문서로 만들면 의사소통 속도가 낮아진다.

각 정보의 공식 원천과 보존 기간, 접근 권한을 정하고 여러 도구의 중복을 줄인다.

버전 관리 도구

버전 관리 시스템은 소스 코드와 문서·설정의 변경 이력을 기록하고 여러 개발자의 작업을 통합한다.

주요 기능에는 다음이 있다.

  • 변경 이력
  • 커밋과 작성자
  • 분기와 병합
  • 태그
  • 차이 비교
  • 과거 버전 복원
  • 변경 원인 추적
  • 접근 권한
  • 서명과 검증
  • 원격 저장소
  • 코드 검토 연동

버전 관리는 소스 코드뿐 아니라 다음 자료에도 적용할 수 있다.

  • 요구사항과 설계 문서
  • 빌드 스크립트
  • 자동 시험
  • 데이터베이스 이전
  • 인프라 정의
  • 배포 설정
  • 운영 절차
  • 대시보드와 경고 규칙
  • 문서 생성 설정

빌드 결과와 대형 데이터·비밀 정보는 일반 소스 저장소에 직접 저장하지 않고 별도의 아티팩트·데이터와 비밀 관리 도구를 사용할 수 있다.

모든 운영 변경이 버전 관리되는 정의를 통해 이루어지면 현재 환경과 저장소의 차이를 줄이고 변경의 검토·복구와 감사를 지원할 수 있다.

코드 검토 도구

코드 검토 도구는 변경 전후의 차이와 관련 이슈·시험 결과를 보여 주고 다른 개발자의 의견과 승인을 기록한다.

지원할 수 있는 기능에는 다음이 있다.

  • 줄 단위 의견
  • 제안된 수정
  • 검토자 지정
  • 구성 요소 소유자 승인
  • 자동 검사 결과
  • 변경 이력
  • 토론 해결 상태
  • 병합 조건
  • 서명과 작성자 검증
  • 요구사항과 릴리스 연결

코드 검토 도구는 변경의 구조와 목적이 명확할 때 가장 효과적이다. 서로 무관한 기능·대규모 형식 변경과 생성 파일이 한 검토에 포함되면 실제 동작의 차이를 파악하기 어렵다.

자동화된 형식·빌드와 정적 분석은 사람의 검토 전에 수행하여 검토자가 요구사항·설계·오류와 보안 판단에 집중하도록 할 수 있다.

자동 승인은 위험하다. 도구가 모든 검사를 통과했다고 하더라도 업무 규칙의 오해와 잘못된 설계, 사용자 영향까지 판정할 수는 없다.

빌드 도구

빌드 도구는 소스 코드와 자원·의존성에서 실행 파일·라이브러리·패키지와 다른 산출물을 생성한다.

다음 작업을 자동화할 수 있다.

  • 코드 생성
  • 컴파일
  • 링크
  • 자원 변환
  • 의존성 해결
  • 시험 실행
  • 정적 분석
  • 문서 생성
  • 패키징
  • 서명
  • 컨테이너 이미지 생성
  • SBOM과 빌드 메타데이터 생성

빌드 정의는 입력과 출력, 의존 관계를 명시해야 한다. 어떤 파일이 변경되었을 때 어떤 산출물을 다시 만들어야 하는지 알 수 있어야 한다.

증분 빌드는 변경된 부분만 처리하여 시간을 줄이지만, 깨끗한 전체 빌드와 결과가 달라지지 않는지 확인해야 한다.

빌드 명령이 개발자의 개인 환경과 숨겨진 파일에 의존하면 자동화 서버와 다른 개발자가 같은 결과를 만들기 어렵다. 도구 체인·의존성·환경과 명령을 프로젝트에서 관리한다.

패키지 관리자

패키지 관리자는 외부 라이브러리와 도구의 검색·설치·버전 선택과 의존성 해결을 자동화한다.

다음 기능을 제공할 수 있다.

  • 패키지 이름과 버전 관리
  • 전이 의존성 해결
  • 중앙 또는 내부 저장소
  • 무결성 해시
  • 서명 검증
  • 잠금 파일
  • 플랫폼별 패키지 선택
  • 개발 및 운영 의존성 구분
  • 업데이트 탐지
  • 라이선스와 보안 정보

자동 의존성 해결은 편리하지만 동일한 소스에서 설치 시점마다 다른 버전이 선택될 수 있다. 잠금 파일과 고정 버전을 통해 실제 사용한 의존성 집합을 기록할 수 있다.

버전을 고정한 뒤 갱신하지 않으면 보안 수정과 호환성 개선을 받지 못한다. 자동 업데이트 제안과 시험을 사용하되 변경 기록과 검토 없이 즉시 운영에 적용하지 않는다.

패키지 이름이 같다는 이유만으로 출처가 같은 것은 아니다. 공식 저장소·내부 미러와 무결성 정보를 관리하고 잘못된 이름이나 공급망 공격을 탐지해야 한다.

아티팩트 저장소

아티팩트 저장소는 빌드된 라이브러리·실행 파일·패키지·컨테이너 이미지와 관련 메타데이터를 보관한다.

산출물에는 다음 정보를 연결할 수 있다.

  • 제품과 버전
  • 소스 커밋
  • 빌드 번호
  • 대상 플랫폼
  • 빌드 구성
  • 사용한 도구와 의존성
  • 암호학적 해시
  • 서명
  • 시험과 승인 상태
  • SBOM
  • 출처 증명
  • 보존 기간

운영에 배포한 산출물은 나중에 같은 이름으로 덮어쓰지 않고 불변으로 보관하는 편이 추적성과 복구에 유리하다.

환경마다 다시 빌드하지 않고 검증된 동일 산출물을 개발·시험·준비와 운영 환경으로 승격하면 실제 배포 파일이 시험한 파일과 같다는 신뢰를 높일 수 있다.

아티팩트 저장소도 접근 통제·백업과 무결성 검사가 필요하다. 저장소가 침해되면 정상적인 배포 절차를 통해 악성 산출물이 제공될 수 있다.

재현 가능한 빌드 도구

재현 가능한 빌드는 같은 소스 코드·빌드 환경과 지침을 사용했을 때 다른 주체가 비트 단위로 같은 지정 산출물을 다시 만들 수 있는 빌드이다.[108]

재현성을 확인하는 도구는 여러 환경에서 산출물을 다시 만들고 차이를 비교할 수 있다.

비결정적인 요소에는 다음이 있다.

  • 빌드 시각
  • 임의 값과 생성 식별자
  • 파일 처리 순서
  • 사용자와 절대 경로
  • 지역과 문자 인코딩
  • 병렬 실행 순서
  • 변경 가능한 네트워크 자료
  • 도구와 의존성 버전
  • 자동 생성된 서명 키

비트 단위 재현성이 모든 프로젝트에 즉시 필요한 것은 아니지만, 빌드 입력과 환경을 명확히 기록하고 깨끗한 환경에서 반복 가능한 빌드를 수행하는 것은 일반적인 구성 관리에도 도움이 된다.

재현 가능한 빌드는 소스와 바이너리의 관계를 독립적으로 확인할 수 있게 하지만 소스 코드 자체에 결함이나 악성 동작이 없음을 보장하지는 않는다.

정적 분석 도구

정적 분석기는 프로그램을 실행하지 않고 소스 코드·중간 표현이나 바이너리를 분석한다.

탐지할 수 있는 문제에는 다음이 있다.

  • 타입과 자료 흐름 오류
  • 널 참조
  • 자원 누수
  • 버퍼와 배열 경계
  • 정수 오버플로
  • 정의되지 않은 동작
  • 사용되지 않는 코드
  • 순환 의존성
  • 코딩 규칙 위반
  • 취약한 API 사용
  • 입력 검증 누락
  • 비밀 정보의 포함
  • 라이선스와 외부 구성 요소 문제

정적 분석 결과에는 실제 문제가 아닌 오탐과 도구가 발견하지 못하는 미탐이 존재할 수 있다.

조직은 모든 경고를 무조건 동일하게 처리하기보다 심각도·확신과 프로젝트 문맥을 기준으로 분류할 수 있다. 억제한 경고에는 이유와 적용 범위를 기록하고, 광범위한 전역 제외로 실제 결함이 숨겨지지 않도록 한다.

NIST SSDF는 사람이 읽을 수 있는 코드를 검토·분석하고 실행 가능한 코드를 시험하여 이전에 발견되지 않은 취약점을 찾는 활동을 소프트웨어 개발 생명주기에 통합하도록 권고한다.[109]

코드 형식화와 린트

코드 형식화 도구는 들여쓰기·줄바꿈·공백과 표현 방식을 공통 규칙에 맞게 자동 변경한다.

린터는 코드의 문법적으로 허용되지만 오류 가능성이 높거나 프로젝트 규칙에 맞지 않는 표현을 찾는다.

자동 형식화의 장점은 다음과 같다.

  • 사람마다 다른 형식 논쟁을 줄인다.
  • 코드 검토에서 의미 있는 변경을 보기 쉽게 한다.
  • 저장소 전체의 표현을 일관되게 유지한다.
  • 생성 코드와 수동 코드의 차이를 예측 가능하게 한다.

형식화 도구의 버전이 다르면 같은 코드가 반복해서 바뀔 수 있으므로 프로젝트에서 버전과 설정을 관리한다.

린트 규칙을 지나치게 많이 추가하면 개발자가 의미를 이해하지 않고 경고를 억제하게 될 수 있다. 실제 결함과 유지보수 문제를 줄이는 규칙을 중심으로 사용하고 효과가 낮은 규칙은 제거한다.

동적 분석 도구

동적 분석기는 실행 중인 프로그램에 계측을 추가하거나 상태를 관찰하여 결함을 찾는다.

다음과 같은 기능이 있다.

  • 잘못된 메모리 접근
  • 해제 후 사용
  • 메모리와 자원 누수
  • 정의되지 않은 동작
  • 스레드 경쟁
  • 교착 상태
  • 코드 커버리지
  • 실행 경로 추적
  • 시스템 호출 분석
  • 네트워크 동작
  • 자원 사용
  • 성능 프로파일링

동적 분석기는 일반 실행보다 느리고 메모리를 많이 사용할 수 있으며 프로그램의 타이밍을 바꾼다.

하나의 분석기가 모든 종류의 문제를 찾지 못하므로 메모리·동시성·성능과 보안 목적에 따라 여러 도구를 사용한다.

분석 빌드를 자동 파이프라인에서 정기적으로 실행하고 발견된 결함을 일반 시험으로 재현할 수 있게 만들면 재발을 방지하기 쉽다.

시험 자동화 도구

시험 자동화 도구는 시험 환경 준비·입력 제공·결과 확인과 보고를 반복 가능하게 수행한다.

대상에는 다음이 있다.

  • 함수와 클래스
  • 구성 요소
  • API
  • 데이터베이스
  • 메시지와 이벤트
  • 사용자 인터페이스
  • 브라우저와 모바일 장치
  • 네트워크 프로토콜
  • 설치와 업데이트
  • 성능과 부하
  • 보안
  • 장애와 복구

시험 도구는 실행 결과와 기대값을 자동 판정할 수 있어야 한다. 프로그램을 실행하기만 하고 결과를 검증하지 않으면 자동화된 시험이 아니다.

DORA는 모든 종류의 시험을 소프트웨어 전달 생명주기 전반에서 지속적으로 수행하고, 빠르고 신뢰할 수 있는 자동 시험 묶음을 지속적 전달 파이프라인에 포함할 것을 권장한다.[110]

자동 시험이 느리거나 불안정하면 개발자는 실행을 피하고 실패를 무시할 수 있다. 시험의 속도·격리와 오류 메시지도 제품 코드처럼 관리해야 한다.

시험 환경 관리

시험 환경 도구는 필요한 서버·데이터베이스·외부 서비스와 데이터를 자동으로 준비하고 정리한다.

사용할 수 있는 방식에는 다음이 있다.

  • 로컬 프로세스
  • 가상 머신
  • 컨테이너
  • 임시 클라우드 환경
  • 서비스 가상화
  • 모의 서버
  • 장치 팜
  • 브라우저 실행 환경
  • 네트워크 지연과 장애 주입
  • 데이터 생성과 초기화

시험마다 독립된 임시 환경을 만들면 공유 상태로 인한 불안정성을 줄일 수 있지만 생성 시간과 비용이 증가한다.

공용 환경을 사용할 때는 시험 데이터와 계정을 격리하고 실행 전후 상태를 복원한다.

운영 환경의 복잡성을 지나치게 단순화하면 실제 배포와 권한·네트워크 문제를 발견하지 못할 수 있으므로 시험 수준에 따라 실제에 가까운 환경을 사용한다.

코드 커버리지 도구

코드 커버리지 도구는 시험 중 실행된 문장·분기·함수와 조건을 측정한다.

커버리지는 다음 용도로 사용할 수 있다.

  • 한 번도 실행되지 않은 새 코드 발견
  • 오류와 예외 경로 확인
  • 플랫폼별 코드의 시험 범위 확인
  • 변경 전후의 시험 누락 비교
  • 안전·규제 기준의 증거 생성

높은 커버리지는 시험이 코드를 실행했다는 뜻이지 결과를 올바르게 판정했다는 뜻은 아니다.

커버리지 목표를 개인 성과로 사용하면 의미 없는 시험과 단순 실행이 증가할 수 있다. 위험이 높은 영역과 복잡한 조건에서 누락된 검증을 찾는 보조 지표로 사용한다.

퍼징 도구

퍼저는 많은 비정상적·변형된 입력을 자동 생성하여 충돌·메모리 오류·무한 반복과 잘못된 상태를 찾는다.

퍼징 도구는 다음을 지원할 수 있다.

  • 유효 입력의 변형
  • 형식과 문법을 이해한 입력 생성
  • 코드 커버리지 기반 탐색
  • 여러 프로세스와 컴퓨터의 병렬 실행
  • 충돌 입력 저장
  • 입력 최소화
  • 중복 결함 분류
  • 회귀 시험 생성

파일·네트워크·컴파일러와 직렬화 경계처럼 입력 공간이 크고 신뢰할 수 없는 데이터를 처리하는 구성 요소에 효과적이다.

퍼징이 충돌을 찾지 못했다고 논리적 결과와 보안이 모두 올바른 것은 아니다. 불변 조건과 결과를 판정하는 별도 오라클을 제공할 수 있다.

성능 및 부하 시험 도구

성능 시험 도구는 요청·사용자·데이터와 장치 부하를 생성하고 응답 시간·처리량과 자원 사용을 측정한다.

도구는 다음을 제공할 수 있다.

  • 동시 사용자와 요청 생성
  • 실제 작업 흐름 재생
  • 부하의 단계적 증가
  • 분산 부하 발생기
  • 응답 결과 검증
  • 지연 시간 백분위
  • 오류율과 처리량
  • 서버 자원과의 상관 분석
  • 결과 비교와 회귀 감지

부하 생성기 자체가 네트워크와 CPU 병목이 되면 대상 시스템의 한계를 잘못 측정할 수 있다. 발생기와 대상 시스템을 분리하고 생성 가능한 최대 부하를 확인한다.

성능 시험 결과는 실행 환경·데이터·캐시 상태·설정과 도구 버전을 함께 기록해야 비교할 수 있다.

보안 도구

소프트웨어 보안 도구는 개발·빌드·배포와 운영 전반에서 취약점과 공급망 위험을 분석한다.

다음과 같은 종류가 있다.

  • 정적 애플리케이션 보안 분석
  • 동적 애플리케이션 보안 시험
  • 대화형 실행 분석
  • 소프트웨어 구성 분석
  • 의존성 취약점 검사
  • 비밀 정보 탐지
  • 컨테이너와 운영체제 이미지 검사
  • 인프라와 설정 정책 검사
  • SBOM 생성
  • 서명과 출처 검증
  • 퍼징
  • 침투 시험 도구
  • 운영 보안 정보 및 사건 관리

도구가 보고한 취약점 수만으로 실제 위험을 판단하기 어렵다. 코드가 해당 기능을 사용하는지, 외부에 노출되는지, 완화 수단이 있는지 분석해야 한다.

자동 보안 검사는 빠른 피드백을 제공하지만 아키텍처의 신뢰 경계와 업무 권한·오용 가능성을 이해하지 못할 수 있으므로 위협 모델링과 사람의 검토를 함께 수행한다.

소프트웨어 자재 명세서 도구

SBOM 생성 도구는 패키지와 실행 파일·컨테이너 이미지에서 포함된 구성 요소와 버전, 관계와 라이선스 정보를 수집한다.

SBOM은 다음 활동에 사용할 수 있다.

  • 새 취약점의 영향 분석
  • 외부 구성 요소와 공급자 추적
  • 라이선스 준수
  • 지원 종료 관리
  • 고객과 규제 기관에 구성 정보 제공
  • 빌드와 릴리스의 비교
  • 공급망 사건 조사

SPDX는 소프트웨어 패키지와 관련 구성 요소·메타데이터 정보를 전달하기 위한 국제 표준 형식이며 ISO/IEC 5962:2021로 표준화되어 있다.[111][112]

SBOM은 개발 저장소에 선언된 의존성만이 아니라 실제 빌드 산출물에 포함된 구성 요소를 반영해야 한다.

도구마다 간접 의존성·정적 링크와 수정된 내부 패키지를 다르게 식별할 수 있으므로 생성 결과를 릴리스 과정에서 검증한다.

지속적 통합 도구

지속적 통합 도구는 저장소의 변경을 감지하여 빌드·분석과 시험을 자동 실행하고 결과를 개발자에게 전달한다.

일반적인 흐름은 다음과 같다.

  1. 개발자가 변경을 저장소에 제출한다.
  2. 격리된 실행 환경을 준비한다.
  3. 소스와 고정된 의존성을 가져온다.
  4. 코드 형식과 정적 분석을 실행한다.
  5. 소프트웨어를 빌드한다.
  6. 단위·구성 요소와 통합 시험을 실행한다.
  7. 보안과 라이선스 검사를 실행한다.
  8. 결과와 로그·보고서를 보관한다.
  9. 성공한 산출물을 아티팩트 저장소에 게시한다.
  10. 변경의 통합 가능 여부를 표시한다.

DORA는 지속적 통합을 작은 작업 단위와 빠른 피드백을 통해 통합 비용을 낮추고 품질과 생산성을 높이는 역량으로 설명한다.[113]

지속적 통합 도구가 존재하더라도 변경이 며칠 또는 몇 주 동안 별도 분기에 남고 통합 실패를 방치한다면 빠른 통합 효과를 얻기 어렵다.

파이프라인의 속도와 안정성은 개발 흐름에 직접 영향을 준다. 중복 작업을 병렬화하고 안전한 캐시를 사용하되, 캐시가 오래된 산출물을 제공하지 않도록 입력과 키를 정확히 관리한다.

파이프라인

파이프라인은 소프트웨어 변경을 빌드·시험·패키징·배포하는 여러 자동화 단계를 순서와 조건에 따라 연결한 실행 흐름이다.

파이프라인은 다음을 표현할 수 있다.

  • 실행 계기
  • 입력 소스와 버전
  • 단계와 의존성
  • 병렬 실행
  • 성공과 실패 조건
  • 승인
  • 산출물 전달
  • 환경별 배포
  • 재시도와 시간 제한
  • 비밀 정보 접근
  • 로그와 결과 보존

파이프라인 정의도 소프트웨어이므로 버전 관리와 검토·시험의 대상이다.

복잡한 스크립트를 파이프라인 설정 안에 직접 길게 작성하면 로컬 재현과 재사용이 어려울 수 있다. 핵심 작업은 일반 명령과 스크립트로 구현하고 파이프라인은 실행 순서와 환경을 조정하도록 구성할 수 있다.

파이프라인이 공급망 공격의 대상이 될 수 있으므로 수정 권한·실행기 격리와 비밀 정보 접근을 제한해야 한다.

지속적 전달 도구

지속적 전달 도구는 검증된 산출물을 언제든지 운영 환경에 배포할 수 있는 상태로 유지하도록 지원한다.

DORA는 지속적 전달을 모든 종류의 변경을 빠르고 안전하며 지속 가능한 방식으로 필요할 때 릴리스할 수 있는 역량으로 정의한다.[114]

지속적 전달 도구는 다음과 같은 기능을 제공할 수 있다.

  • 환경별 산출물 승격
  • 배포 승인
  • 설정과 비밀 정보 적용
  • 데이터베이스 이전
  • 상태 검사
  • 스모크 시험
  • 점진적 배포
  • 배포 중단
  • 롤백
  • 감사 기록
  • 운영 지표를 이용한 판정

지속적 전달은 모든 변경을 즉시 사용자에게 공개해야 한다는 뜻이 아니다. 기능 플래그와 릴리스 정책을 통해 코드 배포와 기능 출시를 분리할 수 있다.

배포 자동화 도구

배포 자동화는 패키지와 설정을 대상 환경에 적용하고 서비스 상태를 검증한다.

DORA는 배포 자동화를 테스트와 운영 환경에 소프트웨어를 반복 가능하게 배포하고, 배포 위험을 줄이며 변경 직후 품질에 대한 빠른 피드백을 얻기 위한 기반으로 설명한다.[115]

배포 자동화에는 다음이 필요하다.

  • 대상 환경과 버전 식별
  • 산출물 무결성 확인
  • 접근 권한
  • 설치와 설정
  • 순서와 의존성
  • 데이터 이전
  • 상태 검사
  • 성공과 실패 판정
  • 중단과 재개
  • 롤백 또는 롤포워드
  • 배포 결과 기록

배포 명령이 여러 번 실행되어도 같은 결과를 만들거나 이미 완료된 작업을 안전하게 인식하도록 설계하면 중간 실패에서 복구하기 쉽다.

자동화된 배포가 수동 승인보다 항상 안전한 것은 아니다. 자동화의 품질과 시험·권한 구조가 중요하며, 위험이 큰 변경에는 독립적인 승인과 제한된 배포를 추가할 수 있다.

인프라 코드화

Infrastructure as Code는 서버·네트워크·저장소와 클라우드 자원 등의 인프라를 수동 화면 조작 대신 기계가 읽을 수 있는 정의로 관리하는 방식이다.

인프라 정의는 코드와 마찬가지로 다음 활동의 대상이 될 수 있다.

  • 버전 관리
  • 코드 검토
  • 정적 검사
  • 시험
  • 변경 계획 확인
  • 자동 적용
  • 재사용
  • 모듈화
  • 감사
  • 롤백과 복구

HashiCorp의 공식 문서는 인프라를 사람이 읽을 수 있는 구성 파일로 정의하고 이를 버전 관리·재사용과 공유할 수 있는 Infrastructure as Code 방식을 설명한다.[116]

인프라 코드화의 장점은 모든 환경을 완전히 동일하게 만드는 데만 있지 않다. 어떤 자원이 왜 존재하고 어떤 변경으로 만들어졌는지 추적하며, 새로운 환경과 재해 복구 환경을 반복적으로 생성할 수 있게 한다.

운영자가 화면에서 직접 변경하면 저장소의 정의와 실제 환경 사이에 차이가 생긴다. 도구를 통해 이러한 드리프트를 탐지하고 승인된 정의로 되돌리거나 실제 변경을 코드에 반영한다.

구성 관리 자동화

구성 관리 도구는 운영체제와 프로그램의 패키지·파일·서비스·사용자와 설정을 원하는 상태로 유지한다.

다음과 같은 작업을 수행할 수 있다.

  • 패키지 설치와 제거
  • 설정 파일 배치
  • 사용자와 권한
  • 서비스 시작과 종료
  • 인증서와 키 배포
  • 방화벽과 네트워크
  • 정기 작업
  • 보안 정책
  • 상태 검사
  • 변경 결과 보고

구성 정의는 여러 번 실행해도 같은 목표 상태에 도달하도록 설계할 수 있다.

수동으로 수정한 설정이 다음 자동 실행에서 사라질 수 있으므로 운영자는 자동화가 관리하는 범위와 긴급 변경 절차를 알아야 한다.

비밀 정보는 일반 구성 파일과 분리하고 자동화 도구에는 필요한 시점과 대상에만 제공한다.

컨테이너와 가상화 도구

컨테이너와 가상 머신은 개발·시험과 배포 환경을 격리하고 반복적으로 생성하는 데 사용된다.

컨테이너는 응용 프로그램과 필요한 사용자 공간 의존성을 이미지로 묶어 여러 환경에 전달할 수 있다. 가상 머신은 별도의 운영체제 커널과 더 강한 환경 격리를 제공할 수 있다.

이러한 도구는 다음 용도로 사용될 수 있다.

  • 개발 환경
  • 자동 빌드 실행기
  • 통합 시험
  • 서비스와 데이터베이스의 임시 실행
  • 서로 다른 운영체제 시험
  • 배포 패키징
  • 보안 격리
  • 오래된 도구 체인 보존

컨테이너 이미지가 동일해도 호스트 커널·CPU와 장치, 네트워크와 볼륨 설정에 따라 동작이 달라질 수 있다. 이미지 하나만으로 전체 환경의 동일성이 보장되지는 않는다.

기반 이미지와 포함 패키지도 의존성이므로 버전·취약점과 지원 종료를 관리한다.

개발 환경 자동화

개발 환경 자동화는 새 개발자가 저장소를 받은 뒤 필요한 도구와 의존성·서비스를 일관되게 준비할 수 있도록 한다.

자동화할 수 있는 항목에는 다음이 있다.

  • 컴파일러와 런타임
  • 패키지 관리자
  • 프로젝트 의존성
  • 데이터베이스와 외부 서비스 대체 환경
  • 환경 변수
  • 코드 생성
  • 빌드와 시험
  • 편집기 및 디버거 연동
  • 샘플 데이터
  • 인증과 로컬 인증서

개발 환경이 자동화되어도 사용자가 각 구성 요소의 목적과 문제 해결 방법을 전혀 알지 못하면 도구가 실패했을 때 대응하기 어렵다. 자동화와 함께 구조·명령과 일반적인 오류를 문서화한다.

개발 환경 정의는 운영 환경의 비밀과 실제 개인정보를 포함하지 않아야 한다.

문서 자동화

문서 자동화 도구는 소스 코드와 스키마·주석과 메타데이터에서 API 문서·참조표와 변경 기록을 생성한다.

생성할 수 있는 문서에는 다음이 있다.

  • API 참조
  • 명령행 도움말
  • 데이터와 설정 스키마
  • 버전과 변경 기록
  • 코드 커버리지
  • 의존성 목록
  • SBOM
  • 배포와 환경 정보
  • 아키텍처 의존성 그래프
  • 라이선스 고지

자동 생성은 코드와 문서의 불일치를 줄일 수 있지만 시스템의 목적과 개념·올바른 사용 방식, 설계 결정까지 자동으로 설명하지는 못한다.

생성된 문서는 사람이 작성한 안내·예제와 함께 사용하고, 공개 전에 잘못된 내부 정보와 비밀이 포함되지 않았는지 확인한다.

문서 생성 도구와 설정도 버전 관리하고 지속적 통합에서 깨진 링크와 예제 코드를 검사할 수 있다.

코드 생성 도구

코드 생성기는 스키마·인터페이스 정의와 모델에서 반복적인 코드를 만든다.

다음과 같은 용도로 사용된다.

  • 프로토콜 직렬화
  • API 클라이언트와 서버 뼈대
  • 데이터베이스 접근 코드
  • 파서와 어휘 분석기
  • 사용자 인터페이스 바인딩
  • 상태 기계
  • 플랫폼별 인터페이스
  • 타입과 상수
  • 시험 데이터와 모의 구현

코드 생성에는 기준이 되는 원본 정의와 생성 도구·버전과 명령이 필요하다.

생성된 파일을 사람이 직접 수정하면 다음 생성에서 변경이 사라질 수 있다. 생성 파일을 읽기 전용으로 취급하고 확장 지점과 사용자 코드를 분리한다.

생성 결과를 저장소에 포함할지 빌드 중 생성할지는 재현성·도구 가용성과 코드 검토 필요를 기준으로 결정한다.

데이터베이스 도구

데이터베이스 도구는 스키마 설계·질의·이전·백업과 성능 분석을 지원한다.

기능에는 다음이 있다.

  • 스키마 모델링
  • 질의 편집과 실행
  • 실행 계획 분석
  • 데이터 비교
  • 스키마 차이
  • 이전 파일 생성
  • 백업과 복구
  • 권한 관리
  • 데이터 익명화
  • 연결과 성능 감시
  • 복제 상태
  • 데이터 품질 검사

운영 데이터베이스에 대화형 도구로 직접 변경하면 변경 이력과 재현성이 사라질 수 있다. 스키마와 반복 가능한 데이터 변경은 버전 관리되는 이전 파일로 수행한다.

긴급 운영 변경이 필요하다면 명령·승인과 결과를 기록하고 이후 공식 자동화에 반영한다.

그래픽 관리 도구가 편리하더라도 실제 실행된 질의와 변경을 확인할 수 있어야 한다.

API 개발 도구

API 도구는 인터페이스를 정의하고 호출·검증하며 문서와 클라이언트를 생성한다.

지원할 수 있는 기능에는 다음이 있다.

  • 요청과 응답 스키마
  • 인증
  • 예제 호출
  • 모의 서버
  • 계약 시험
  • 클라이언트 생성
  • 호환성 비교
  • 성능 시험
  • 버전과 폐기 표시
  • 문서 게시

API 명세를 기계가 읽을 수 있는 형식으로 관리하면 서버·클라이언트와 문서를 같은 계약에서 생성하고 검증할 수 있다.

그러나 명세에 기록된 형식과 실제 업무 의미가 다를 수 있으므로 사용자 시나리오와 오류·권한 조건을 별도로 검토해야 한다.

API 키와 토큰을 개발 도구의 공유 파일과 이력에 저장하지 않고 비밀 관리 기능을 사용한다.

사용자 인터페이스 도구

사용자 인터페이스 개발에는 화면 설계·프로토타이핑·디자인 시스템과 자동 시험 도구가 사용된다.

다음 활동을 지원할 수 있다.

  • 화면과 흐름 모형
  • 상호작용 프로토타입
  • 재사용 가능한 구성 요소
  • 디자인 토큰
  • 다양한 화면 크기
  • 접근성 속성
  • 화면 비교
  • 사용자 행동 기록
  • 자동 사용자 인터페이스 시험
  • 번역과 국제화 관리

디자인 도구의 화면이 실제 구현과 별도로 발전하면 사용자에게 제공되는 인터페이스와 설계가 달라질 수 있다.

재사용 가능한 디자인 시스템과 구현 구성 요소·문서를 연결하고 변경을 공동으로 관리할 수 있다.

화면 이미지 비교 자동화는 의도하지 않은 시각적 변화를 찾을 수 있지만 모든 차이가 결함은 아니며 사용성과 접근성을 직접 판단하지 못한다.

운영 관찰 도구

운영 관찰 도구는 실행 중인 소프트웨어가 생성하는 로그·메트릭·추적과 프로파일을 수집·처리하고 검색·시각화한다.

OpenTelemetry는 추적·메트릭과 로그 같은 텔레메트리를 계측·생성·수집하고 내보내기 위한 공급자 중립적인 공개 관찰 프레임워크이다.[117]

관찰 도구는 다음 기능을 제공할 수 있다.

  • 로그 검색과 집계
  • 지표 저장과 질의
  • 대시보드
  • 임계값과 이상 탐지
  • 분산 추적
  • 요청과 사용자 흐름 연결
  • 오류와 배포 버전 연계
  • 프로파일
  • 서비스 의존성
  • 경고와 사건 관리
  • 장기 추세 분석

관찰 도구를 설치하는 것만으로 필요한 정보를 얻을 수 있는 것은 아니다. 프로그램이 중요한 상태와 오류·요청 식별자를 구조화된 형태로 내보내도록 계측해야 한다.

OpenTelemetry는 관찰 가능성을 위해 응용 프로그램이 추적·메트릭과 로그를 생성하고 이를 관찰 백엔드로 전달하도록 계측하는 구조를 설명한다.[118]

로그 관리

로그 관리 도구는 여러 프로그램과 장치의 로그를 중앙에서 수집·검색하고 보존한다.

구조화된 로그에는 다음 정보가 포함될 수 있다.

  • 시각
  • 심각도
  • 서비스와 구성 요소
  • 버전
  • 요청과 작업 식별자
  • 사용자 또는 계정의 안전한 식별 정보
  • 사건 종류
  • 오류 코드
  • 관련 자원
  • 실행 환경

자유 형식 문자열만 사용하면 같은 사건을 일관되게 집계하기 어렵다. 구조화된 필드와 공통 명명 규칙을 사용할 수 있다.

로그에 비밀번호·토큰과 개인정보가 기록되지 않도록 자동 검사와 마스킹을 적용한다.

모든 세부 정보를 무기한 저장하면 비용과 개인정보 위험이 증가하므로 로그 종류별 보존 기간과 접근 권한을 정한다.

메트릭과 대시보드

메트릭 도구는 시간에 따른 수치와 분포를 수집한다.

측정할 수 있는 정보에는 다음이 있다.

  • 요청 수와 오류율
  • 응답 시간
  • 작업 대기
  • CPU와 메모리
  • 저장 공간
  • 데이터베이스 연결
  • 캐시 적중률
  • 메시지 처리
  • 사용자 작업 성공률
  • 배포와 변경
  • 서비스 수준 지표

대시보드는 여러 지표를 시각화하여 시스템의 상태와 추세를 보여 준다.

대시보드가 지나치게 많거나 모든 팀이 서로 다른 지표 이름을 사용하면 장애 중 필요한 정보를 찾기 어렵다. 서비스별 핵심 지표와 표준 템플릿을 제공할 수 있다.

대시보드는 질문에 답하기 위한 수단이다. 그래프를 많이 배치하는 것보다 사용자 영향·병목과 최근 변경을 확인할 수 있는 구조가 중요하다.

경고 자동화

경고 도구는 서비스 수준과 오류·자원 상태가 정해진 조건을 벗어날 때 담당자에게 통보하거나 자동 대응을 실행한다.

경고 조건에는 다음이 있다.

  • 사용자 요청 실패 증가
  • 응답 시간 목표 위반
  • 데이터 손실 가능성
  • 서비스 인스턴스 감소
  • 대기열 적체
  • 저장 공간 부족
  • 인증서 만료
  • 백업 실패
  • 보안 사건
  • 오류 예산 소진

경고는 사람의 조치가 필요한 상황을 중심으로 만들어야 한다. 자동으로 회복되고 사용자 영향이 없는 짧은 변화까지 당직자를 호출하면 경고 피로가 발생한다.

경고에는 영향을 받는 서비스·대시보드와 운영 절차, 최근 변경과 담당 팀을 연결한다.

반복되는 경고는 임계값만 높여 숨기기보다 시스템 결함·용량과 경고 설계를 분석한다.

사건 관리 도구

사건 관리 도구는 운영 장애의 신고·등급과 역할, 의사소통과 시간 순서를 관리한다.

기능에는 다음이 포함될 수 있다.

  • 자동 사건 생성
  • 담당자 호출
  • 심각도 분류
  • 대응 역할 지정
  • 공동 작업 채널
  • 상태 페이지 연동
  • 시간 순서 기록
  • 관련 로그와 대시보드
  • 사용자 통보
  • 사후 분석과 개선 작업

장애 중 여러 도구에 같은 내용을 반복 입력하면 대응이 느려질 수 있으므로 경고·채팅·상태 페이지와 이슈 추적을 연결할 수 있다.

자동 생성된 기록은 완전하지 않을 수 있다. 중요한 판단과 완화 조치·사용자 영향을 사람이 보완한다.

사건 종료 후 기록을 근본 원인 분석과 운영 절차·시험 개선에 연결한다.

자동 복구

자동 복구는 알려진 실패 조건을 감지하고 사람의 개입 없이 서비스를 정상 상태로 되돌리거나 영향을 줄인다.

예를 들면 다음과 같다.

  • 실패한 프로세스 재시작
  • 비정상 인스턴스 교체
  • 트래픽 우회
  • 복제본 승격
  • 용량 자동 확장
  • 손상된 작업 재처리
  • 회로 차단
  • 요청 제한
  • 이전 구성으로 전환
  • 비핵심 기능 비활성화

자동 복구가 근본 원인을 숨겨서는 안 된다. 반복 재시작으로 서비스가 겉으로 유지되더라도 데이터 손상과 자원 누수가 계속될 수 있다.

자동 조치에는 실행 조건·최대 반복 횟수와 중단 조건, 결과 기록과 사람에게 상향 보고할 기준이 필요하다.

복구 자동화 자체를 시험 환경과 제한된 운영 범위에서 검증한다.

정책 코드화

Policy as Code는 보안·품질·운영과 규제 규칙을 기계가 판정할 수 있는 형식으로 표현하고 자동화된 흐름에서 검사하는 방식이다.

정책에는 다음과 같은 조건이 포함될 수 있다.

  • 승인되지 않은 라이선스 금지
  • 심각한 취약점이 있는 의존성 차단
  • 공개 저장소의 비밀 정보 차단
  • 필수 코드 검토
  • 보호된 분기
  • 인프라의 공개 네트워크 제한
  • 암호화와 백업 요구
  • 배포 가능한 지역
  • 컨테이너 권한
  • 필수 태그와 소유자
  • 서비스 수준과 배포 조건

정책을 코드로 표현하면 여러 프로젝트에 일관되게 적용하고 변경 이력과 예외를 추적할 수 있다.

정책 도구의 판정이 조직 규칙의 유일한 설명이 되어서는 안 된다. 개발자가 규칙의 목적과 수정 방법·예외 절차를 이해할 수 있는 문서를 제공한다.

모든 규칙을 배포 차단으로 만들면 사소한 문제 때문에 긴급 수정이 지연될 수 있다. 위험에 따라 경고·차단과 사후 검토 수준을 구분한다.

보안 자동화

보안 자동화는 개발자의 코드 작성 시점부터 빌드·배포와 운영까지 여러 검사와 보호를 연결한다.

자동화할 수 있는 활동에는 다음이 있다.

  • 커밋 전 비밀 정보 검사
  • 코드와 의존성 분석
  • 빌드 환경 격리
  • 산출물 서명
  • SBOM 생성
  • 출처 증명
  • 이미지와 인프라 검사
  • 배포 정책 확인
  • 운영 취약점 감시
  • 패치와 업데이트 제안
  • 보안 사건 대응

NIST SSDF는 소프트웨어와 개발 환경을 무단 접근과 변조에서 보호하고, 소프트웨어 릴리스의 무결성과 출처를 확인하며, 취약점을 지속적으로 식별·대응하는 관행을 제시한다.[119]

자동 보안 도구가 많은 경고를 생성하면 실제 중요한 위험을 찾기 어렵다. 위험·노출과 실행 가능성을 기준으로 분류하고 반복되는 오탐을 관리한다.

보안 검사를 마지막 릴리스 단계에만 두면 수정 비용과 일정 충돌이 커질 수 있으므로 개발 환경과 지속적 통합에서 빠른 검사를 제공한다.

빌드 출처와 증명

빌드 출처 도구는 특정 산출물이 어떤 소스·빌드 시스템과 의존성, 명령과 환경에서 만들어졌는지를 기계가 검증할 수 있는 형태로 기록한다.

출처 정보에는 다음이 포함될 수 있다.

  • 소스 저장소와 커밋
  • 빌드 시스템의 신원
  • 빌드 정의
  • 입력 아티팩트
  • 도구와 실행 환경
  • 생성된 산출물과 해시
  • 실행 시각
  • 서명과 인증 정보

출처 증명은 공격자가 별도의 환경에서 만든 파일을 정상 빌드 결과로 바꾸는 위험을 줄이는 데 사용될 수 있다.

출처가 존재한다는 사실만으로 빌드 시스템이 안전하다는 뜻은 아니다. 빌드 실행기·자격 증명과 서명 키, 저장소 권한을 함께 보호해야 한다.

도구 체인

도구 체인은 소프트웨어 생명주기의 여러 도구가 입력과 결과를 전달하며 연결된 전체 체계이다.

예를 들어 다음과 같은 흐름이 만들어질 수 있다.

  1. 요구사항과 작업 항목을 등록한다.
  2. 관련 분기와 코드 변경을 만든다.
  3. 코드 검토와 자동 분석을 수행한다.
  4. 지속적 통합이 빌드와 시험을 실행한다.
  5. 산출물을 저장하고 SBOM과 출처를 생성한다.
  6. 배포 시스템이 환경에 산출물을 적용한다.
  7. 관찰 도구가 새 버전의 상태를 측정한다.
  8. 장애와 사용자 피드백을 새 작업 항목으로 연결한다.

도구 사이에 공통 식별자를 사용하면 하나의 요구사항이 어떤 코드와 시험·릴리스로 구현되었는지 추적할 수 있다.

도구 연동이 지나치게 복잡하면 한 도구의 변경과 장애가 전체 개발을 막을 수 있다. 중요한 정보를 공개 형식으로 내보내고 교체 가능한 경계를 유지한다.

도구 통합

도구는 API·웹훅·메시지와 파일 형식으로 서로 통신할 수 있다.

통합을 통해 다음을 자동화할 수 있다.

  • 이슈와 커밋 연결
  • 코드 검토 상태의 작업 반영
  • 시험 실패의 결함 생성
  • 릴리스 노트 생성
  • 배포 결과의 버전 기록
  • 장애와 최근 배포 연결
  • SBOM과 취약점 정보 연결
  • 사용자 피드백의 백로그 등록

같은 상태를 여러 도구가 각각 소유하면 동기화 오류가 발생할 수 있다. 각 정보의 공식 원천을 정하고 다른 도구는 참조하거나 복사본임을 명확히 한다.

도구 계정과 자동화 토큰에는 최소 권한을 적용한다. 하나의 통합 자격 증명이 모든 저장소·배포와 운영 환경을 수정할 수 있다면 침해 영향이 커진다.

표준과 교환 형식

공개 표준과 교환 형식은 서로 다른 도구 사이에서 정보를 이동하고 특정 공급자에 대한 종속을 줄인다.

사용할 수 있는 형식에는 다음이 있다.

  • 소스 코드와 일반 텍스트
  • 패치와 변경 형식
  • 요구사항과 시험 결과 교환 형식
  • API 명세
  • 로그와 텔레메트리 프로토콜
  • SBOM
  • 취약점 정보
  • 컨테이너 이미지
  • 패키지 메타데이터
  • 아키텍처와 모델 형식

모든 정보가 완전히 같은 의미로 교환되는 것은 아니다. 도구별 확장과 상태·권한 구조가 손실될 수 있으므로 이전 가능성을 실제로 시험한다.

핵심 코드와 문서·빌드 정의를 사람이 읽을 수 있고 공개된 형식으로 보관하면 장기 보존과 도구 교체에 유리하다.

자동화의 대상 선정

모든 수동 작업을 즉시 자동화할 필요는 없다.

다음과 같은 작업은 자동화 가치가 높을 수 있다.

  • 자주 반복된다.
  • 절차와 성공 조건이 명확하다.
  • 사람이 수행할 때 실수가 자주 발생한다.
  • 여러 프로젝트와 환경에서 동일하게 수행한다.
  • 실행 결과와 기록이 중요하다.
  • 빠른 피드백이 품질에 영향을 준다.
  • 야간과 대규모 환경에서 수행해야 한다.
  • 보안과 감사상 일관성이 필요하다.

다음과 같은 작업은 사람의 판단이 더 중요할 수 있다.

  • 새로운 요구사항과 사용자 문제 탐색
  • 아키텍처 대안의 상충 관계
  • 모호한 사용성 평가
  • 윤리와 사회적 영향
  • 복잡한 장애의 초기 조사
  • 이해관계자 협상
  • 새로운 기술과 위험의 평가

처음 한두 번만 수행하는 불확실한 절차는 수동으로 학습한 뒤 안정된 부분을 자동화할 수 있다.

자동화 비용에는 구현뿐 아니라 시험·운영과 도구 변경에 따른 유지보수도 포함된다.

자동화 수준

자동화는 여러 수준으로 적용할 수 있다.

  • 사람이 명령을 직접 실행하지만 절차가 스크립트로 정리되어 있다.
  • 저장소 변경이나 일정에 따라 자동 실행된다.
  • 결과를 자동 수집하지만 최종 판정은 사람이 한다.
  • 명확한 규칙에 따라 성공·실패를 자동 판정한다.
  • 조건을 충족하면 다음 환경과 단계로 자동 진행한다.
  • 운영 상태에 따라 자동 롤백과 복구를 수행한다.

높은 자동화 수준이 항상 더 적합한 것은 아니다. 잘못된 판정의 영향과 되돌리기 가능성을 고려해야 한다.

개발 빌드와 단위 시험은 완전히 자동화할 수 있지만 안전 필수 시스템의 운영 배포에는 독립적인 검토와 공식 승인이 필요할 수 있다.

자동화된 결정에는 사용한 입력·규칙과 결과를 사람이 검토할 수 있는 기록을 남긴다.

자동화와 승인

수동 승인은 안전을 보장하는 절대적인 수단이 아니다. 승인자가 변경 내용을 충분히 검토하지 못하고 형식적으로 버튼만 누르면 실제 통제 효과가 낮다.

반대로 모든 승인을 제거하면 중요한 사업·보안과 데이터 변경이 자동으로 넓게 배포될 수 있다.

승인은 다음과 같은 경우에 집중할 수 있다.

  • 되돌리기 어려운 데이터 변경
  • 공개 API와 호환성 변경
  • 안전·보안 경계 변경
  • 대규모 사용자에게 영향을 주는 배포
  • 규제와 계약상 요구
  • 자동 검사가 충분히 다루지 못하는 위험
  • 오류 예산과 서비스 수준을 크게 위협하는 변경

승인자는 검토해야 할 정보와 책임을 알아야 한다. 자동 도구가 위험·시험 결과와 변경 범위를 요약하여 제공할 수 있다.

자동화 실패

자동화도 소프트웨어이므로 결함과 장애가 발생한다.

자동화 실패에는 다음이 있다.

  • 잘못된 조건으로 정상 변경 차단
  • 검사 누락과 잘못된 성공 판정
  • 오래된 캐시와 산출물 사용
  • 환경 일부만 변경된 상태
  • 비밀 정보 노출
  • 무한 재시도
  • 잘못된 대상에 배포
  • 여러 작업의 경쟁
  • 외부 API와 도구 버전 변경
  • 기록과 실제 상태의 불일치

자동화에는 시간 제한·재시도와 중단, 부분 실패의 복구와 사람이 개입할 수 있는 경로가 필요하다.

실패가 발생했을 때 단순히 수동으로 우회하고 끝내지 않고 자동화 자체의 결함을 수정하고 시험을 추가한다.

핵심 자동화에는 소유자와 서비스 수준·장애 대응과 백업을 정할 수 있다.

파이프라인 보안

자동화 파이프라인은 소스 코드와 비밀 정보·서명 키, 운영 배포 권한에 접근할 수 있으므로 중요한 보안 경계이다.

다음과 같은 보호가 필요하다.

  • 최소 권한
  • 다중 인증
  • 짧은 수명의 자격 증명
  • 실행기 격리
  • 신뢰할 수 없는 변경과 비밀의 분리
  • 보호된 분기
  • 검토된 파이프라인 정의
  • 외부 작업과 플러그인 버전 고정
  • 네트워크 접근 제한
  • 산출물 서명
  • 감사 로그
  • 실행 환경의 폐기와 초기화

외부 기여자의 코드가 실행되는 파이프라인에 운영 비밀을 제공하면 악성 변경이 자격 증명을 탈취할 수 있다.

캐시와 빌드 산출물도 신뢰 경계를 넘어 공유될 수 있으므로 출처와 키를 분리하고 무결성을 확인한다.

도구 권한 관리

도구마다 사용자와 서비스 계정에 필요한 권한을 최소화한다.

권한 범위에는 다음이 있다.

  • 저장소 읽기와 쓰기
  • 코드 검토와 병합
  • 파이프라인 변경
  • 비밀 정보 접근
  • 아티팩트 게시와 삭제
  • 시험 환경 배포
  • 운영 배포
  • 데이터베이스 변경
  • 로그와 개인정보 열람
  • 사용자와 권한 관리

관리자 계정을 일상 작업에 사용하면 실수와 침해의 영향이 커진다.

사람의 역할 변경과 퇴사, 서비스 폐기 시 권한을 회수하고 정기적으로 실제 사용 여부를 검토한다.

공유 계정은 책임과 감사가 어려우므로 개인·서비스별 신원을 사용한다.

비밀 관리 도구

비밀 관리 도구는 비밀번호·API 토큰·암호 키와 인증서를 일반 설정과 분리하여 저장·제공하고 교체한다.

기능에는 다음이 있을 수 있다.

  • 암호화 저장
  • 접근 정책
  • 감사 기록
  • 짧은 수명의 동적 자격 증명
  • 자동 교체
  • 버전과 폐기
  • 특정 작업과 환경에 대한 일시 제공
  • 하드웨어 보안 모듈 연동
  • 유출 탐지

비밀은 소스 저장소·빌드 로그와 컨테이너 이미지에 포함하지 않아야 한다.

개발·시험과 운영 환경은 서로 다른 자격 증명을 사용하고, 운영 비밀을 개발자 컴퓨터에 복사하지 않는다.

비밀 관리 시스템이 중단되었을 때 서비스가 어떻게 시작·복구되는지도 계획한다.

캐시

빌드·시험과 패키지 내려받기의 결과를 캐시에 저장하면 반복 실행 시간을 줄일 수 있다.

캐시 대상에는 다음이 있다.

  • 컴파일 결과
  • 패키지
  • 컨테이너 계층
  • 코드 분석 색인
  • 시험 데이터
  • 생성 코드
  • 도구 체인

캐시 키는 결과에 영향을 주는 모든 입력을 반영해야 한다. 소스만 사용하고 컴파일러 버전과 빌드 설정을 무시하면 잘못된 산출물이 재사용될 수 있다.

보안 경계가 다른 프로젝트가 같은 캐시를 공유하면 악성 파일과 비밀이 전달될 수 있다.

캐시가 없어도 전체 작업이 정확하게 수행되어야 하며, 주기적으로 깨끗한 환경에서 빌드해 숨겨진 의존성을 확인한다.

병렬화

자동화 작업을 병렬로 실행하면 피드백 시간을 줄일 수 있다.

병렬화할 수 있는 대상에는 다음이 있다.

  • 플랫폼별 빌드
  • 독립적인 시험 묶음
  • 정적 분석
  • 패키지와 이미지 검사
  • 여러 환경의 호환성 시험
  • 데이터 분할 기반의 부하 생성

병렬 실행은 공유 상태와 자원 충돌을 만들 수 있다. 시험이 같은 데이터베이스와 파일·포트를 사용하면 실행 순서에 따라 실패할 수 있다.

작업을 독립적으로 만들고 임시 환경과 고유한 자원을 할당한다.

병렬 작업의 로그와 결과를 하나의 파이프라인 실행에 연결하여 실패 원인을 찾을 수 있게 한다.

자동화의 관찰 가능성

자동화 도구도 실행 상태와 성능을 관찰할 수 있어야 한다.

측정할 수 있는 정보에는 다음이 있다.

  • 실행 성공률
  • 대기와 실행 시간
  • 실패 단계와 원인
  • 재시도 횟수
  • 실행기와 자원 사용
  • 캐시 적중률
  • 배포 빈도
  • 시험 불안정성
  • 외부 서비스 지연
  • 수동 승인 대기
  • 비용

파이프라인이 느리다면 단순히 더 빠른 서버를 추가하기 전에 대기·중복 작업과 불안정한 시험을 분석한다.

자동화 장애가 개발과 배포를 얼마나 막는지 서비스 수준을 정하고 중요도에 따라 운영할 수 있다.

도구 평가

도구를 도입하기 전에 다음을 평가할 수 있다.

  • 해결하려는 문제
  • 현재 작업 방식과의 적합성
  • 지원 언어와 플랫폼
  • 기능과 확장성
  • API와 데이터 내보내기
  • 성능과 대규모 프로젝트 지원
  • 안정성과 지원 기간
  • 보안과 접근 통제
  • 라이선스와 비용
  • 공급자 종속
  • 설치와 운영 복잡성
  • 사용자 경험과 접근성
  • 팀의 학습 비용
  • 기존 도구와의 통합
  • 도구 종료 시 이전 가능성

기능 목록과 짧은 시연만으로 실제 사용성을 판단하기 어렵다. 대표 프로젝트와 실제 데이터·사용자를 이용한 제한된 시범 도입을 수행할 수 있다.

도구 도입으로 줄어드는 비용뿐 아니라 유지보수·업데이트·권한과 통합 운영에 필요한 비용을 포함한다.

도구 표준화

조직 전체에서 공통 도구를 사용하면 교육·보안과 지원, 통합 비용을 줄일 수 있다.

표준화할 수 있는 영역에는 다음이 있다.

  • 버전 관리
  • 코드 검토
  • 지속적 통합
  • 아티팩트 저장소
  • 비밀 관리
  • 관찰과 경고
  • 보안 분석
  • 프로젝트와 문서 관리
  • 개발 환경

그러나 모든 팀과 제품에 하나의 도구와 작업 흐름을 강제하면 특수한 플랫폼과 안전·규제 요구를 충족하지 못할 수 있다.

지원되는 기본 도구와 예외 기준을 제공하고, 새 도구를 도입할 때 보안·운영과 이전 계획을 검토한다.

표준 도구는 중앙 조직의 편의보다 실제 사용자 팀의 생산성과 품질을 지원해야 한다.

도구 종속

도구에 많은 정보와 자동화가 저장되면 다른 도구로 이전하기 어려워질 수 있다.

종속은 다음에서 발생한다.

  • 독점 파일과 데이터 형식
  • 도구 안에만 존재하는 스크립트
  • 공급자 전용 API
  • 복잡한 권한과 워크플로
  • 내보낼 수 없는 이력과 의견
  • 특정 클라우드와 실행 환경
  • 외부 플러그인과 마켓플레이스
  • 라이선스와 가격 구조

핵심 코드·문서와 빌드 정의를 공개 형식과 일반 저장소에서 관리하고, 도구 전용 설정의 범위를 제한할 수 있다.

도구 교체 가능성을 위해 모든 기능을 직접 추상화할 필요는 없다. 교체 비용과 제품 수명·공급자 위험을 기준으로 중요한 정보의 내보내기와 백업을 확보한다.

도구의 생명주기

도구도 도입·운영·업데이트와 폐기의 생명주기를 가진다.

관리해야 하는 내용에는 다음이 있다.

  • 소유자
  • 지원 버전
  • 업데이트와 보안 패치
  • 플러그인과 의존성
  • 백업과 복구
  • 접근 권한
  • 사용자 교육
  • 성능과 용량
  • 비용
  • 지원 종료
  • 데이터 이전
  • 대체 도구

오래된 도구 체인을 유지해야 하는 제품은 가상 머신과 컨테이너·내부 패키지 보관소를 이용해 환경을 보존할 수 있다.

지원 종료된 도구를 인터넷과 운영 환경에 계속 연결하면 보안 위험이 증가하므로 격리와 교체 계획이 필요하다.

자동화 코드의 품질

빌드·시험·배포와 운영 스크립트도 제품 코드와 같은 품질 관리가 필요하다.

다음 원칙을 적용할 수 있다.

  • 버전 관리
  • 코드 검토
  • 모듈화
  • 명확한 입력과 출력
  • 오류 처리
  • 시간 제한과 취소
  • 멱등성
  • 로그와 진단
  • 자동 시험
  • 보안과 비밀 관리
  • 문서
  • 호환성과 폐기 정책

일회성으로 작성한 작은 스크립트가 시간이 지나며 핵심 배포 시스템이 될 수 있다. 중요도가 커지면 책임자와 시험·운영 기준을 높여야 한다.

자동화 스크립트가 특정 개인의 컴퓨터와 경로·계정에 의존하지 않도록 한다.

자동화 시험

자동화 자체를 검증하기 위해 다음과 같은 시험을 수행할 수 있다.

  • 빌드가 깨끗한 환경에서 성공하는가
  • 입력 변경에 따라 필요한 단계가 실행되는가
  • 실패한 시험이 실제로 파이프라인을 실패시키는가
  • 잘못된 산출물이 게시되지 않는가
  • 배포 중단과 롤백이 동작하는가
  • 비밀 정보가 로그에 노출되지 않는가
  • 권한이 없는 변경이 운영에 배포되지 않는가
  • 캐시 없이도 올바르게 실행되는가
  • 같은 정의가 여러 환경에서 일관된 결과를 만드는가
  • 부분 실패 뒤 다시 실행할 수 있는가

파이프라인 설정을 변경한 뒤 실제 운영 배포에서 처음 시험하지 않고 제한된 샌드박스와 시험 저장소에서 검증할 수 있다.

자동화 도구의 업그레이드도 기존 작업과 플러그인의 호환성을 시험한다.

자동화와 추적성

자동화된 흐름은 요구사항부터 운영까지의 증거를 연결할 수 있다.

예를 들어 다음 관계를 기록할 수 있다.

  • 작업 항목과 코드 변경
  • 코드 변경과 검토
  • 검토된 커밋과 빌드
  • 빌드와 시험 결과
  • 빌드와 SBOM
  • 산출물과 서명
  • 배포와 환경
  • 운영 지표와 장애
  • 장애와 수정 작업

공통 식별자를 산출물·로그와 릴리스에 포함하면 운영 중인 프로세스가 어떤 소스와 시험 결과에서 만들어졌는지 확인할 수 있다.

추적성 정보를 사람이 여러 도구에 반복 입력하기보다 파이프라인과 도구 통합으로 자동 생성한다.

자동 생성된 관계가 실제 의미와 일치하는지 정기적으로 감사해야 한다.

인공지능 보조 개발 도구

인공지능 기반 도구는 소스 코드·문서와 자연어 입력을 바탕으로 코드 완성·설명·변환·시험과 분석 결과를 제안할 수 있다.

사용할 수 있는 영역에는 다음이 있다.

  • 코드 완성과 초안
  • 자연어에서 코드 생성
  • 코드 설명
  • 오류 원인 후보
  • 리팩터링 제안
  • 시험 사례 생성
  • 문서와 주석 생성
  • 검색과 코드베이스 질의
  • 취약점과 결함 후보
  • 반복적인 이전 작업
  • 이슈와 장애 정보 요약

NIST의 DevSecOps 관련 지침은 인공지능이 코딩·보안 분석과 취약점 탐지·수정 등 생명주기 활동의 자동화에 사용되고 있음을 설명한다.[120]

인공지능 도구의 출력은 정답이나 승인된 변경이 아니라 검토가 필요한 제안으로 취급해야 한다.

생성된 코드는 다음과 같은 문제를 포함할 수 있다.

  • 존재하지 않는 API
  • 잘못된 업무 규칙
  • 경계 조건 누락
  • 보안 취약점
  • 비효율적인 알고리즘
  • 프로젝트 구조와 다른 방식
  • 불필요하거나 허용되지 않는 의존성
  • 라이선스와 출처 문제
  • 오래된 기술 정보
  • 시험이 구현과 같은 잘못된 가정을 공유하는 문제

기존 코드와 동일하게 검토·빌드·시험과 보안 검사를 거쳐야 하며, 중요한 설계와 안전 판단을 도구에 위임해서는 안 된다.

인공지능 도구와 데이터 보호

인공지능 도구에 입력하는 코드와 문서에는 영업 비밀·개인정보와 보안 취약점이 포함될 수 있다.

도입 시 다음을 확인해야 한다.

  • 입력 데이터가 외부 서버로 전송되는가
  • 입력과 출력이 학습에 사용되는가
  • 저장 기간과 지역
  • 공급자와 하위 처리자
  • 접근 통제와 감사
  • 비밀 정보 자동 제거
  • 사용 가능한 저장소와 데이터 등급
  • 생성 코드의 출처와 라이선스 정책
  • 계정 종료와 데이터 삭제
  • 장애와 서비스 종료 시 이전 가능성

공개가 허용되지 않은 코드와 고객 데이터를 개인 계정의 도구에 입력하지 않도록 조직 정책과 기술적 제한을 제공한다.

도구가 저장소 전체에 접근할 경우 읽기 권한과 외부 명령 실행·네트워크 사용 범위를 최소화한다.

자율 에이전트와 자동 변경

일부 도구는 코드 제안뿐 아니라 파일 수정·명령 실행·시험과 변경 제출을 연속적으로 수행할 수 있다.

자율성이 높아질수록 다음 통제가 중요해진다.

  • 격리된 실행 환경
  • 최소 권한
  • 허용된 명령과 네트워크
  • 변경 범위 제한
  • 비밀 정보 차단
  • 실행 기록
  • 비용과 시간 한도
  • 사람의 검토
  • 자동 빌드와 시험
  • 운영 배포와의 분리
  • 실패 시 작업 중단
  • 생성한 산출물과 출처 표시

에이전트가 시험을 통과시키기 위해 시험을 삭제하거나 기준을 약화하지 못하도록 보호 규칙을 둘 수 있다.

사람이 읽지 않은 변경을 자동으로 운영에 배포하는 것은 잘못된 요구사항과 보안 문제의 영향을 크게 만들 수 있다.

자율 도구의 효과는 생성한 코드량이 아니라 실제로 승인·유지된 변경과 결함률, 검토 시간과 사용자 성과로 평가해야 한다.

자동화와 사람의 판단

자동화는 명확한 규칙과 반복 가능한 작업에 강하지만 모호한 목표와 사회적·윤리적 영향, 새로운 위험의 판단에는 한계가 있다.

사람은 다음 역할을 유지한다.

  • 해결할 문제와 가치 결정
  • 이해관계자 협상
  • 요구사항의 의미 판단
  • 아키텍처 상충 관계
  • 위험 수용
  • 사용성과 접근성 평가
  • 안전과 윤리적 책임
  • 복잡한 장애의 조사
  • 자동화 규칙의 설계
  • 결과와 예외의 검토

자동화 결과를 그대로 받아들이기보다 어떤 입력과 규칙으로 판정했는지 확인할 수 있어야 한다.

도구의 판단을 사람이 항상 다시 수행한다면 자동화 가치가 낮을 수 있다. 반대로 사람이 이해할 수 없는 자동 판정에만 의존하면 실패를 발견하고 책임지기 어렵다. 위험과 되돌리기 가능성에 따라 적절한 분담을 정한다.

측정과 자동화 개선

도구와 자동화의 효과를 평가하기 위해 다음 정보를 측정할 수 있다.

  • 빌드와 시험 피드백 시간
  • 파이프라인 성공률
  • 불안정한 시험 비율
  • 배포 빈도와 실패율
  • 수동 작업과 승인 대기
  • 환경 생성 시간
  • 자동화 장애
  • 보안 문제의 발견 시점
  • 개발자의 도구 대기 시간
  • 신규 개발자의 환경 준비 시간
  • 운영 복구 시간
  • 도구의 비용과 사용률

자동화 단계가 많아졌다는 사실을 성과로 삼지 않는다. 실제로 피드백이 빨라지고 오류와 수동 작업이 줄었는지 확인한다.

느린 파이프라인의 일부 검사를 제거하기 전에 어떤 결함을 발견하는지와 실행 빈도를 조정할 수 있는지 분석한다.

사용하지 않는 도구와 중복된 검사를 제거하여 도구 체인의 복잡성을 줄인다.

개발자 경험

개발자 경험은 개발자가 프로젝트를 이해하고 환경을 준비하며, 코드 변경을 빌드·시험하고 배포하기까지 겪는 전체 작업 경험을 가리킨다.

개발자 경험에 영향을 주는 요소에는 다음이 있다.

  • 문서와 검색
  • 환경 구축 시간
  • 빌드와 시험 속도
  • 오류 메시지
  • 도구의 일관성
  • 권한과 승인 대기
  • 코드베이스의 구조
  • 로컬과 자동화 환경의 차이
  • 배포와 운영 정보 접근
  • 지원과 책임자

좋은 개발자 경험은 모든 안전 검사와 절차를 제거한다는 뜻이 아니다. 안전하고 권장되는 경로를 가장 쉽게 사용할 수 있게 만드는 것이다.

개발자가 규칙을 우회해야만 작업을 끝낼 수 있다면 도구와 프로세스의 설계를 검토해야 한다.

플랫폼 팀은 공통 자동화와 자체 서비스 인터페이스를 제공하여 제품 팀이 반복 인프라 작업보다 사용자 기능에 집중하도록 지원할 수 있다.

도구와 접근성

개발 도구도 장애와 다양한 사용 조건을 가진 개발자가 사용할 수 있어야 한다.

고려할 수 있는 요소에는 다음이 있다.

  • 키보드 조작
  • 화면 읽기 프로그램
  • 색상에만 의존하지 않는 상태 표시
  • 글꼴과 확대
  • 고대비와 어두운 화면
  • 소리와 시각적 알림의 대체
  • 원격 환경의 지연
  • 명확한 오류 메시지
  • 명령행과 그래픽 인터페이스의 대안
  • 자동 생성 보고서의 접근성

도구 표준화 과정에서 특정 인터페이스만 강제하면 일부 구성원이 효율적으로 작업하기 어려울 수 있다.

공통 빌드·시험과 저장소 규칙은 유지하면서 개인이 사용할 수 있는 편집기와 접근성 도구를 허용할 수 있다.

소규모 프로젝트의 도구

작은 프로젝트에서는 복잡한 도구 체인 자체가 개발보다 더 큰 부담이 될 수 있다.

다음과 같은 최소 구성이 가능하다.

  • 버전 관리
  • 문서화된 빌드 명령
  • 코드 형식과 기본 정적 분석
  • 자동 단위 시험
  • 간단한 지속적 통합
  • 패키지와 릴리스 저장
  • 기본 오류 로그와 백업

도구를 선택할 때 한 명 또는 소수의 개발자가 운영할 수 있는지 확인한다.

대규모 조직의 복잡한 승인·배포 체계를 그대로 복사하기보다 실제 사용자와 데이터 위험에 필요한 수준을 사용한다.

프로젝트가 성장하면 병목과 반복 작업을 기준으로 자동화를 점진적으로 추가한다.

대규모 조직의 도구

대규모 조직에서는 수많은 저장소·서비스와 팀을 일관되게 지원하기 위한 공통 플랫폼과 정책이 필요할 수 있다.

다음과 같은 기능이 사용된다.

  • 조직 전체의 신원과 권한
  • 저장소와 프로젝트 생성 자동화
  • 공통 파이프라인 템플릿
  • 내부 패키지와 아티팩트 저장소
  • 비밀 관리
  • 보안과 라이선스 정책
  • 관찰과 사건 관리
  • 서비스 목록과 소유권
  • 비용과 용량 관리
  • 데이터와 모델 거버넌스
  • 규제 증거와 감사
  • 표준 개발 환경

중앙 플랫폼이 모든 팀의 배포를 직접 처리하면 병목이 될 수 있다. 안전한 기본 경로를 자체 서비스로 제공하고 팀이 필요한 범위에서 독립적으로 운영하도록 할 수 있다.

공통 템플릿을 변경할 때 수많은 프로젝트에 미치는 영향을 시험하고 단계적으로 전환해야 한다.

안전 및 규제 시스템의 도구

안전·의료·항공과 다른 규제 시스템에서는 도구가 생성하는 결과가 인증과 안전 판단의 근거가 될 수 있다.

다음과 같은 추가 관리가 필요할 수 있다.

  • 도구의 버전과 설정 고정
  • 검증된 사용 범위
  • 도구 결과의 독립적인 확인
  • 요구사항부터 시험까지 추적성
  • 접근과 변경 통제
  • 공식 기준선
  • 감사 가능한 실행 기록
  • 장기 보존
  • 공급자와 지원 상태
  • 도구 결함의 영향 분석

코드 생성기와 컴파일러·시험 도구가 잘못된 결과를 만들면 제품 결함을 만들거나 검출하지 못할 수 있다.

위험 수준에 따라 도구 적격성 평가와 독립적인 검증을 수행하고, 도구 업그레이드는 일반 소프트웨어 변경처럼 영향과 회귀를 평가한다.

도구와 자동화의 한계

도구는 다음과 같은 한계를 가진다.

  • 요구사항과 업무 의미를 완전히 이해하지 못한다.
  • 분석 결과에 오탐과 미탐이 존재한다.
  • 설정과 사용 방법에 따라 결과가 달라진다.
  • 복잡한 도구 체인은 자체 결함과 보안 위험을 만든다.
  • 공급자의 가격·정책과 서비스 종료에 의존할 수 있다.
  • 자동화가 실제 작업과 달라지면 잘못된 상태를 신뢰하게 된다.
  • 사람의 지식이 줄어들어 도구 장애에 대응하기 어려워질 수 있다.
  • 쉬운 측정값과 자동 판정만 중요하게 다뤄질 수 있다.
  • 도구가 지원하지 않는 제품과 사용자가 소외될 수 있다.

자동화할 수 없는 문제를 단순히 수동 작업의 부족으로 보지 않는다. 문제 정의와 조직 구조·아키텍처를 바꾸면 작업 자체를 제거할 수 있는지 검토한다.

도구가 제안한 결과와 측정값은 의사결정의 자료이며 목적 자체가 아니다.

자동화의 지속적 관리

자동화는 한 번 완성하고 끝나는 산출물이 아니다. 소프트웨어와 운영체제·외부 서비스와 보안 위협이 변하면 자동화도 함께 갱신해야 한다.

지속적으로 관리할 내용에는 다음이 있다.

  • 도구와 플러그인 업데이트
  • 오래된 API와 기능의 폐기
  • 파이프라인 속도와 안정성
  • 시험 불안정성
  • 권한과 비밀 정보
  • 캐시와 실행 환경
  • 보안 경고와 오탐
  • 사용하지 않는 자동화
  • 비용과 용량
  • 사용자 피드백
  • 문서와 책임자

도구 장애와 배포 실패·보안 사건을 분석하여 자동화의 구조와 검사를 개선한다.

특정 개인만 이해하는 스크립트와 계정에 의존하지 않도록 코드 검토·문서와 공동 소유를 유지한다.

도구와 자동화의 통합적 의미

소프트웨어 공학에서 도구와 자동화는 별도의 마지막 지원 활동이 아니다. 요구사항·설계·구현·시험·배포와 운영의 정보를 연결하고 각 단계의 피드백을 빠르게 만드는 기반이다.

요구사항 도구는 사용자 필요와 작업을 연결하고, 버전 관리와 코드 검토는 구현 변경을 기록한다. 빌드와 시험 자동화는 변경의 품질을 빠르게 평가하고, 아티팩트와 배포 도구는 검증된 산출물을 실제 환경에 제공한다. 관찰 도구는 운영 결과와 장애를 다시 개발 과정으로 돌려보낸다.

좋은 도구 체인은 다음과 같은 특성을 가진다.

  • 사람이 이해할 수 있는 명확한 작업 흐름을 따른다.
  • 반복 작업을 일관되게 수행한다.
  • 실패를 빠르고 구체적으로 보여 준다.
  • 요구사항부터 운영까지 변경을 추적할 수 있다.
  • 같은 입력과 환경에서 결과를 재현할 수 있다.
  • 최소 권한과 공급망 보호를 적용한다.
  • 수동 개입과 예외를 기록한다.
  • 특정 도구가 실패해도 중요한 자료와 제품을 복구할 수 있다.
  • 프로젝트 규모와 위험에 맞는 복잡성을 가진다.
  • 실제 사용자와 개발자의 작업을 개선한다.

자동화의 목표는 개발 과정에서 사람을 제거하는 것이 아니다. 사람을 반복적이고 오류가 발생하기 쉬운 작업에서 해방하고, 중요한 요구사항·설계와 위험 판단에 집중하게 하는 것이다.

도구와 자동화는 공학적 원칙을 대신하지 않는다. 명확한 요구사항과 책임·품질 기준이 있을 때 이를 빠르고 일관되게 실행하며, 소프트웨어가 변경되고 운영되는 전체 생명주기의 상태와 근거를 보존하는 수단이다.

보안, 안전과 전문 윤리

소프트웨어는 정보와 자원을 처리하는 기술적 시스템인 동시에 사람과 조직의 행동·권리와 안전에 영향을 주는 사회적 시스템이다. 소프트웨어의 결함이나 잘못된 설계는 데이터 유출과 서비스 중단을 일으킬 수 있고, 교통·의료·산업과 기반 시설에서는 사람의 부상과 환경 피해로 이어질 수 있다. 사용자를 조종하거나 차별하는 기능, 필요 이상의 감시와 개인정보 수집, 위험을 숨긴 채 제품을 출시하는 결정도 소프트웨어 공학의 문제에 포함된다.

소프트웨어 보안(Software Security)은 소프트웨어와 데이터·서비스가 공격과 오용, 무단 접근과 변경에 견디며 필요한 기능을 신뢰할 수 있게 제공하도록 설계·구현·운영하는 활동이다. 보안은 기밀성·무결성·가용성뿐 아니라 인증·권한·책임 추적·복원력과 공급망을 포함한다.

소프트웨어 안전(Software Safety)은 소프트웨어의 동작과 실패가 사람·재산과 환경에 허용할 수 없는 피해를 일으키지 않도록 위험을 식별·통제하고 필요한 증거를 만드는 활동이다. 안전은 프로그램이 정상적으로 동작하는 상황뿐 아니라 센서 오류·통신 단절·하드웨어 고장·사용자 실수와 예상하지 못한 상태를 함께 다룬다.

전문 윤리(Professional Ethics)는 소프트웨어를 설계·개발·배포하고 운영하는 사람이 공공의 이익과 사용자의 권리, 정직성·공정성과 전문적 책임을 지키기 위해 따라야 하는 원칙이다. 법률과 계약에서 명시하지 않은 상황에서도 무엇이 책임 있는 행동인지 판단하는 기준을 제공한다.

보안·안전과 윤리는 별개의 부가 기능이 아니다. 안전한 시스템이 공격으로 조작되면 안전 기능을 신뢰할 수 없고, 보안 기능이 강하더라도 사용자의 권리를 침해하거나 차별을 확대한다면 책임 있는 시스템으로 보기 어렵다. 일정과 비용, 기능과 성능을 결정할 때부터 함께 고려해야 한다.

NIST SP 800-218의 Secure Software Development Framework는 소프트웨어 취약성의 수와 영향을 줄이기 위한 상위 수준의 보안 개발 관행을 여러 소프트웨어 생명주기 모델에 통합할 수 있도록 제시한다.[121]

IEC 61508은 전기·전자·프로그램 가능 전자 안전 관련 시스템의 기능 안전을 생명주기 전체에서 다루며, 위험에 따라 안전 기능에 필요한 성능과 안전 무결성 수준을 결정하는 접근을 사용한다.[122]

ACM과 IEEE Computer Society가 공동으로 만든 Software Engineering Code of Ethics and Professional Practice는 소프트웨어 엔지니어가 공공·고객과 고용주·제품·판단·관리·전문직·동료와 자신에 대해 가져야 할 책임을 여덟 원칙으로 정리한다.[123]

보안과 안전의 구분

한국어에서는 security와 safety가 모두 안전 또는 보안과 관련된 말로 번역될 수 있지만 소프트웨어 공학에서는 중심적으로 다루는 위험이 다르다.

보안은 주로 의도적인 공격과 무단 행위, 오용과 악의적인 조작에 대응한다.

  • 공격자가 계정을 탈취한다.
  • 권한이 없는 사용자가 데이터를 읽거나 변경한다.
  • 악성 입력으로 프로그램의 제어권을 얻는다.
  • 공급망을 침해하여 악성 코드를 배포한다.
  • 서비스를 과부하시켜 사용할 수 없게 만든다.
  • 내부자가 권한을 남용한다.
  • 로그와 감사 기록을 삭제한다.
  • 사용자를 속여 비밀 정보를 입력하게 한다.

안전은 의도 여부와 관계없이 시스템의 동작이 사람·재산과 환경에 일으킬 수 있는 피해를 다룬다.

  • 센서 오류로 장치가 위험한 동작을 수행한다.
  • 제어 프로그램의 계산 오류로 기계가 허용 범위를 벗어난다.
  • 경고가 늦게 표시되어 운영자가 대응하지 못한다.
  • 통신 단절 뒤 장치가 안전하지 않은 상태를 유지한다.
  • 잘못된 상태 전이로 비상 정지가 작동하지 않는다.
  • 사용자 인터페이스가 혼동을 일으켜 잘못된 명령을 선택한다.
  • 소프트웨어 재시작 중 안전 기능이 비활성화된다.

보안 사고가 안전 사고를 일으킬 수 있다. 공격자가 자동차·의료 장비나 산업 제어 시스템의 명령을 변경하면 원래 올바르게 구현된 안전 기능도 무력화될 수 있다. 반대로 안전을 위해 만들어진 원격 관리와 비상 제어 기능이 강한 권한을 가지면 공격자에게 중요한 표적이 될 수 있다.

따라서 보안과 안전을 서로 독립적인 검토로 끝내지 않고 공통 자산·위험·신뢰 경계와 실패 시나리오를 함께 분석한다.

신뢰성과 보안·안전

신뢰성은 시스템이 정해진 조건과 기간 동안 요구된 기능을 올바르게 수행하는 정도이다. 신뢰성이 높은 시스템이라도 공격에 취약할 수 있고, 정상적인 기능을 안정적으로 수행하면서도 그 기능 자체가 위험하거나 비윤리적일 수 있다.

예를 들어 사용자의 위치를 항상 정확하게 수집하고 전송하는 프로그램은 기능적으로 신뢰성이 높을 수 있다. 그러나 사용자의 동의와 필요 범위를 벗어나 정보를 수집한다면 개인정보와 윤리 문제가 발생한다.

안전 관련 시스템에서는 신뢰성이 중요한 기반이지만 모든 실패가 같은 안전 영향을 갖지는 않는다. 화면의 색상이 잘못 표시되는 결함과 비상 정지 명령이 전달되지 않는 결함은 위험이 다르다.

보안에서도 단순한 결함 수보다 공격자가 결함을 실제로 이용할 가능성과 보호 자산, 공격 범위와 복구 가능성을 평가해야 한다.

자산과 보호 목표

보안 활동은 보호해야 하는 자산을 식별하는 것에서 시작한다.

자산에는 다음이 포함될 수 있다.

  • 개인정보와 인증 정보
  • 금융·의료와 업무 데이터
  • 소스 코드와 설계
  • 암호 키와 비밀 정보
  • 시스템 설정
  • 컴퓨팅 자원
  • 서비스 가용성
  • 사용자 계정과 권한
  • 감사 기록
  • 제품과 조직의 신뢰
  • 안전 기능과 제어 권한
  • 소프트웨어 공급망
  • 지식재산권

각 자산에 필요한 보호 목표가 다를 수 있다.

  • 기밀성은 권한이 없는 주체가 정보를 보지 못하게 한다.
  • 무결성은 정보와 소프트웨어가 허가 없이 변경되거나 손상되지 않게 한다.
  • 가용성은 권한이 있는 사용자가 필요할 때 서비스와 정보에 접근할 수 있게 한다.
  • 진정성은 사용자·서비스와 데이터가 주장하는 주체와 출처가 맞는지 확인한다.
  • 책임 추적성은 누가 어떤 행동을 했는지 확인할 수 있게 한다.
  • 부인 방지는 수행한 행위나 전달한 정보를 이후에 부정하기 어렵게 한다.
  • 복원력은 공격과 장애가 발생해도 중요한 기능을 유지하거나 복구하게 한다.

모든 정보에 같은 수준의 기밀성과 보존을 적용하면 비용과 사용성이 악화될 수 있다. 데이터와 기능의 민감도·위험과 법적 의무를 기준으로 분류하고 필요한 통제를 적용한다.

위협

위협은 자산에 피해를 일으킬 가능성이 있는 행위자·사건이나 조건이다.

위협 행위자에는 다음이 포함될 수 있다.

  • 외부 공격자
  • 범죄 조직
  • 경쟁자
  • 국가 지원 조직
  • 악의적인 내부자
  • 권한을 실수로 잘못 사용하는 직원
  • 침해된 외부 공급자
  • 자동화된 악성 프로그램
  • 일반 사용자로 위장한 공격자

위협은 사람의 악의적 행동에만 한정되지 않는다. 잘못된 설정·하드웨어 고장·자연재해와 외부 서비스 중단도 가용성과 무결성에 위험을 만들 수 있다.

공격자의 목표와 능력·접근 경로를 구체적으로 분석해야 한다. 모든 공격자가 무제한의 시간과 자원을 가진다고 가정하면 현실적인 우선순위를 정하기 어렵고, 반대로 일반적인 공격만 고려하면 중요한 고급 위협을 놓칠 수 있다.

취약점

취약점은 공격자나 우발적 사건이 시스템의 보호 목표를 위반하는 데 이용할 수 있는 약점이다.

취약점은 소스 코드의 메모리 오류에만 존재하지 않는다.

  • 잘못된 인증과 권한 설계
  • 예측 가능한 비밀번호 재설정
  • 입력 검증 누락
  • 지나치게 넓은 서비스 권한
  • 암호 키의 잘못된 보관
  • 기본 보안 설정의 부재
  • 안전하지 않은 업데이트
  • 오래된 외부 라이브러리
  • 공개된 관리 인터페이스
  • 로그와 경고 부족
  • 복구할 수 없는 백업
  • 혼란스러운 사용자 인터페이스
  • 불명확한 운영 책임
  • 공급자 계정의 침해
  • 검토되지 않은 빌드 파이프라인

취약점이 존재한다고 항상 같은 위험이 발생하는 것은 아니다. 공격자가 접근할 수 있는지, 중요한 자산과 연결되는지, 다른 통제가 공격을 제한하는지 함께 평가한다.

위험

보안과 안전에서 위험은 바람직하지 않은 사건이 발생할 가능성과 그 결과의 심각성을 결합하여 판단한다.

위험 분석에서는 다음을 확인한다.

  • 어떤 자산과 사람이 영향을 받는가
  • 어떤 사건과 실패가 발생할 수 있는가
  • 원인과 공격 경로는 무엇인가
  • 발생 가능성은 어느 정도인가
  • 피해의 범위와 심각도는 어느 정도인가
  • 기존 통제가 위험을 얼마나 줄이는가
  • 사건을 탐지하고 복구할 수 있는가
  • 남은 위험을 누가 수용할 수 있는가

위험을 하나의 점수로만 표현하면 불확실성과 서로 다른 종류의 피해가 가려질 수 있다. 개인정보 침해·재정 손실과 사람의 부상을 동일한 숫자로 단순 비교하기 어려울 수 있으므로 설명과 근거를 함께 유지한다.

위험 평가는 새로운 정보와 운영 환경·공격 방식에 따라 갱신한다. 과거에 낮은 위험으로 평가한 기능도 사용자 수와 데이터 가치가 증가하면 위험이 달라질 수 있다.

위협 모델링

위협 모델링은 시스템의 자산·구성 요소와 데이터 흐름, 신뢰 경계를 분석하여 가능한 위협과 공격 경로, 필요한 통제를 발견하는 활동이다.

위협 모델링에서는 다음과 같은 질문을 다룬다.

  • 무엇을 보호해야 하는가
  • 누가 시스템과 데이터에 접근하는가
  • 신뢰 경계는 어디에 있는가
  • 데이터는 어디에서 생성·저장되고 이동하는가
  • 공격자는 어떤 입력과 인터페이스를 사용할 수 있는가
  • 구성 요소가 침해되면 어디까지 접근할 수 있는가
  • 어떤 가정이 깨지면 보안이 무너지는가
  • 공격을 예방·탐지하고 복구할 방법이 있는가
  • 남은 위험은 허용 가능한가

위협 모델은 한 번 작성하고 보관하는 그림이 아니다. 새로운 API·데이터 흐름·외부 서비스와 권한이 추가되면 갱신해야 한다.

시스템 전체를 한 번에 완벽하게 모델링하기보다 중요한 사용자 흐름과 자산·변경된 경계를 우선 분석할 수 있다.

공격 표면

공격 표면은 공격자가 시스템에 영향을 줄 수 있는 모든 인터페이스와 경로의 집합이다.

공격 표면에는 다음이 포함될 수 있다.

  • 공개 API와 웹 페이지
  • 네트워크 포트
  • 파일과 문서 파서
  • 명령행 인수
  • 플러그인과 확장
  • 관리자 인터페이스
  • 업데이트 기능
  • 계정 복구
  • 외부 서비스와 웹훅
  • 물리적 장치와 디버그 포트
  • 로컬 프로세스 간 통신
  • 로그와 오류 메시지
  • 개발·빌드와 배포 시스템

사용하지 않는 기능과 포트·계정을 제거하면 공격자가 이용할 수 있는 경로를 줄일 수 있다.

공격 표면을 줄이기 위해 모든 기능을 하나의 강한 권한을 가진 구성 요소에 모으면 침해 시 피해 범위가 커질 수 있다. 기능의 필요성과 격리·권한을 함께 판단한다.

신뢰 경계

신뢰 경계는 서로 다른 신뢰 수준과 권한을 가진 영역이 만나는 경계이다.

다음과 같은 위치에 신뢰 경계가 존재할 수 있다.

  • 사용자 입력과 서버
  • 인터넷과 내부 네트워크
  • 일반 사용자와 관리자 기능
  • 하나의 서비스와 다른 서비스
  • 응용 프로그램과 운영체제
  • 호스트와 가상 머신 또는 컨테이너
  • 플러그인과 핵심 프로그램
  • 개발 환경과 운영 환경
  • 조직과 외부 공급자
  • 안전 제어 영역과 일반 정보 영역

신뢰 경계를 넘는 입력과 요청은 출처·권한과 형식을 검증해야 한다.

내부 네트워크와 같은 위치에 있다는 이유만으로 모든 구성 요소를 신뢰하면 하나의 계정이나 서비스 침해가 전체 시스템으로 확산될 수 있다.

보안 요구사항

보안 요구사항은 “시스템은 안전해야 한다”와 같은 추상적인 표현이 아니라 보호할 자산과 위협·조건, 필요한 결과를 구체적으로 정의해야 한다.

예를 들면 다음과 같다.

  • 관리 기능은 다중 인증을 완료한 관리자만 사용할 수 있어야 한다.
  • 사용자는 자신에게 권한이 부여된 문서만 읽고 변경할 수 있어야 한다.
  • 인증 토큰은 저장소와 로그에 평문으로 기록되지 않아야 한다.
  • 비밀번호 재설정 요청은 계정의 존재 여부를 외부에 드러내지 않아야 한다.
  • 중요한 권한 변경은 변경 주체와 시각·대상을 감사 기록에 남겨야 한다.
  • 배포 산출물은 설치 전에 승인된 서명과 무결성을 검증해야 한다.
  • 중요한 보안 사건은 정해진 시간 안에 탐지되고 담당자에게 통보되어야 한다.
  • 서비스가 외부 인증 제공자에 연결할 수 없을 때 기존 권한을 임의로 확대해서는 안 된다.

보안 요구는 기능·품질·운영과 공급망 요구로 분산되어 나타날 수 있다. 별도의 보안 문서에만 두지 않고 설계·구현과 시험으로 추적해야 한다.

보안 설계 원칙

보안 설계에는 여러 일반 원칙을 적용할 수 있다.

최소 권한

사용자와 프로세스·서비스에는 필요한 작업을 수행하는 데 필요한 최소한의 권한만 부여한다.

읽기만 필요한 구성 요소에 쓰기 권한을 주거나 하나의 서비스 계정이 모든 데이터베이스와 배포 환경에 접근하게 하면 침해와 실수의 영향이 커진다.

권한은 역할과 자원·작업 범위, 시간과 환경에 따라 제한할 수 있다.

기본 거부

명시적으로 허용되지 않은 접근과 기능은 기본적으로 거부한다.

새로운 API와 데이터가 추가되었을 때 별도 규칙이 없다는 이유로 모든 사용자가 접근할 수 있게 하면 보안 누락이 발생하기 쉽다.

심층 방어

하나의 통제가 실패하더라도 다른 통제가 공격을 막거나 피해를 제한하도록 여러 보호 계층을 둔다.

인증만으로 모든 공격을 막는다고 가정하지 않고 권한 검사·입력 검증·프로세스 격리·암호화와 감사 기록을 함께 사용할 수 있다.

심층 방어는 같은 기능을 의미 없이 반복하는 것이 아니라 서로 다른 실패 원인과 공격 단계를 제한해야 한다.

권한 분리

중대한 작업에 필요한 권한을 여러 역할과 단계로 나눈다.

개발자가 혼자 코드를 작성하고 검토 없이 운영 배포와 감사 기록 삭제까지 수행할 수 있다면 오용과 계정 침해의 영향이 크다.

다만 모든 작은 작업에 여러 사람의 승인을 요구하면 형식적인 승인과 우회가 늘어날 수 있으므로 위험에 맞게 적용한다.

완전한 중재

보호된 자원에 접근할 때마다 필요한 권한을 확인한다. 초기 로그인 결과만을 영구히 신뢰하거나 캐시된 권한이 변경 후에도 계속 유지되지 않도록 한다.

실패 시 안전한 기본값

오류와 통신 단절·설정 누락이 발생했을 때 권한을 확대하거나 보호 기능을 비활성화하지 않는다.

안전 분야에서의 안전한 실패 상태와 보안 분야의 기본 거부가 충돌할 수 있으므로 실제 피해를 기준으로 설계해야 한다. 비상문이 정전 시 잠겨야 하는지 열려야 하는지는 화재 안전과 침입 방지 요구를 함께 분석해야 한다.

단순성

보안 구조가 지나치게 복잡하면 구성과 검토·운영에서 오류가 발생하기 쉽다.

불필요한 인증 방식과 예외 권한·암호 알고리즘을 줄이고 검증된 표준과 구성 요소를 사용한다.

개방된 설계

시스템의 보안이 설계와 알고리즘의 비밀에만 의존하지 않게 한다. 암호 키와 자격 증명은 비밀로 보호하되 설계가 공개되어도 안전성을 유지할 수 있어야 한다.

보안을 고려한 설계

보안을 고려한 설계는 구현 이후 취약점 검사와 방화벽을 추가하는 방식이 아니라 제품의 기본 구조와 사용자 경험에 보안을 포함하는 접근이다.

다음과 같은 결정을 초기 설계에서 다룬다.

  • 최소한의 데이터와 권한만 사용한다.
  • 신뢰 경계와 데이터 흐름을 명확히 한다.
  • 안전한 기본 설정을 제공한다.
  • 보안 기능을 사용자가 별도로 찾아 켜지 않아도 되게 한다.
  • 비밀 정보와 키의 생명주기를 설계한다.
  • 업데이트와 취약점 대응 경로를 제공한다.
  • 서비스와 데이터의 격리 범위를 정한다.
  • 로그와 탐지·복구 수단을 포함한다.
  • 외부 구성 요소와 공급망을 관리한다.
  • 제품 종료 뒤 데이터와 권한을 폐기할 수 있게 한다.

보안 기능이 사용하기 지나치게 어렵다면 사용자는 이를 비활성화하거나 비공식적인 우회 방법을 만들 수 있다. 사용성과 실제 업무 흐름을 함께 고려해야 한다.

안전한 기본 설정

제품은 설치 직후와 일반적인 설정에서 합리적인 보안을 제공해야 한다.

안전한 기본 설정에는 다음이 포함될 수 있다.

  • 사용하지 않는 서비스와 포트 비활성화
  • 기본 관리자 비밀번호 제거
  • 최소 권한 계정
  • 암호화된 통신
  • 보호된 업데이트
  • 외부 접근의 기본 차단
  • 안전한 세션과 쿠키 설정
  • 개인정보 수집의 최소화
  • 중요한 로그와 경고 활성화
  • 지원되는 보안 업데이트의 자동 제공

보안을 강화하기 위해 전문 지식과 복잡한 설정이 반드시 필요하다면 많은 사용자가 취약한 상태로 제품을 사용할 수 있다.

고급 사용자가 보호 수준을 조정할 수 있더라도 위험한 변경의 의미와 영향을 명확히 알려야 한다.

입력 검증

외부에서 들어오는 모든 데이터는 예상한 형식과 의미를 가진다고 가정할 수 없다.

입력 검증에서는 다음을 확인할 수 있다.

  • 자료형과 길이
  • 수치와 날짜의 범위
  • 문자 인코딩
  • 필수 값과 누락
  • 파일 형식과 구조
  • 허용된 명령과 값
  • 경로와 식별자
  • 중복과 순서
  • 요청 크기와 빈도
  • 권한과 상태 조건

입력 검증은 사용자 인터페이스에서만 수행하지 않는다. 공격자는 클라이언트를 우회하여 서버와 프로토콜에 직접 요청할 수 있다.

입력을 검증한 뒤에도 출력 위치에 맞는 안전한 처리와 인코딩이 필요하다. 데이터베이스 질의·운영체제 명령과 HTML 등 서로 다른 문맥에는 서로 다른 보호가 필요하다.

인증

인증은 사용자·장치와 서비스가 주장하는 신원이 맞는지 확인하는 활동이다.

인증 수단에는 다음이 있다.

  • 비밀번호
  • 일회용 코드
  • 보안 키
  • 인증서
  • 생체 정보
  • 장치 자격 증명
  • 외부 신원 제공자
  • 여러 요소의 조합

인증 설계에서는 로그인 성공뿐 아니라 다음을 다뤄야 한다.

  • 계정 생성
  • 비밀번호와 자격 증명 저장
  • 실패 횟수와 자동 공격 제한
  • 계정 복구
  • 자격 증명 변경과 폐기
  • 세션 생성과 만료
  • 장치 분실
  • 다중 인증
  • 관리자와 서비스 계정
  • 비정상적인 접근 탐지

계정 복구 절차가 본래 인증보다 약하면 공격자는 복구 기능을 이용할 수 있다.

생체 정보는 유출되었을 때 비밀번호처럼 쉽게 변경하기 어려우므로 저장·비교와 대체 인증을 신중하게 설계한다.

권한 부여

권한 부여는 인증된 주체가 특정 자원과 기능에 대해 어떤 행동을 수행할 수 있는지 결정한다.

권한 모델에는 다음이 사용될 수 있다.

  • 역할 기반 접근 통제
  • 속성 기반 접근 통제
  • 자원 소유권
  • 명시적인 접근 목록
  • capability
  • 정책 기반 결정
  • 조직과 계층 구조

권한 검사는 사용자 인터페이스에서 버튼을 숨기는 것만으로 구현되지 않는다. 실제 요청을 처리하는 서버와 구성 요소에서 확인해야 한다.

권한은 읽기·생성·수정·삭제와 승인·공유처럼 세부 행동에 따라 달라질 수 있다.

권한 변경은 기존 세션·캐시와 복제본에 반영되어야 하며, 중요한 권한 부여와 회수는 감사할 수 있어야 한다.

암호화

암호화는 저장하거나 전송하는 정보를 권한이 없는 주체가 이해하거나 변경하기 어렵게 한다.

암호화 설계에서는 다음을 다룬다.

  • 보호 대상 데이터
  • 저장과 전송 구간
  • 검증된 알고리즘과 프로토콜
  • 키 생성과 보관
  • 키 접근 권한
  • 교체와 폐기
  • 백업과 복구
  • 인증서 검증
  • 난수 생성
  • 이전 데이터의 재암호화
  • 규제와 성능 조건

자체적인 암호 알고리즘과 프로토콜을 만드는 것보다 널리 검토되고 지원되는 구현을 사용한다.

암호화를 사용하더라도 키가 소스 코드와 로그에 노출되거나 모든 서비스가 같은 키를 사용하면 보호 효과가 낮아진다.

암호화는 데이터 수집 자체의 정당성과 목적을 해결하지 않는다. 불필요한 개인정보를 암호화해 저장하는 것보다 처음부터 수집하지 않는 편이 위험을 더 줄일 수 있다.

비밀 정보 관리

비밀번호·API 토큰과 암호 키·인증서는 일반 설정과 소스 코드에서 분리하여 관리한다.

비밀 정보의 생명주기에는 다음이 포함된다.

  • 안전한 생성
  • 필요한 대상에 대한 배포
  • 최소 권한 접근
  • 사용 기록
  • 정기적 또는 사건 대응 교체
  • 만료
  • 폐기
  • 유출 탐지
  • 복구

버전 관리 이력에 비밀을 한 번 기록한 뒤 최신 파일에서 삭제해도 과거 커밋과 복제본에 남을 수 있다. 노출된 비밀은 삭제뿐 아니라 즉시 무효화하고 새 값으로 교체해야 한다.

개발·시험과 운영 환경에는 서로 다른 자격 증명을 사용한다.

로깅과 감사

보안 로그와 감사 기록은 공격과 권한 남용을 탐지하고 사건의 범위와 원인을 조사하는 데 사용된다.

기록할 수 있는 사건에는 다음이 있다.

  • 로그인 성공과 실패
  • 계정과 권한 변경
  • 중요 데이터 접근과 변경
  • 관리자 작업
  • 비밀 정보와 키 사용
  • 설정과 배포 변경
  • 보안 정책 위반
  • 데이터 내보내기와 삭제
  • 감사 기록에 대한 접근
  • 비정상적인 요청과 차단

로그에는 필요한 문맥과 시각·주체와 대상을 포함하되 비밀번호·토큰과 민감한 원문을 기록하지 않아야 한다.

감사 기록을 일반 사용자가 변경하거나 삭제할 수 있다면 침해 후 흔적을 제거할 수 있다. 별도의 보호와 보존 정책이 필요하다.

모든 사용자 행동을 무기한 기록하면 개인정보와 감시 문제가 발생할 수 있으므로 목적·접근 권한과 보존 기간을 정한다.

보안 시험

보안 시험은 보안 요구와 위협 모델을 기준으로 보호 수단이 실제로 작동하는지 평가한다.

활동에는 다음이 포함될 수 있다.

  • 코드와 설계 검토
  • 정적 보안 분석
  • 동적 보안 시험
  • 의존성 취약점 검사
  • 비밀 정보 탐지
  • 퍼징
  • 권한과 인증 시험
  • 침투 시험
  • 인프라와 설정 검사
  • 공급망과 서명 검증
  • 장애와 공격 시 복구 시험

자동 도구는 알려진 취약 패턴과 구성 문제를 빠르게 찾을 수 있지만 업무 권한의 오류와 설계 수준의 공격 경로를 완전히 이해하지 못한다.

침투 시험은 특정 시점과 범위에서 발견한 문제를 보여 준다. 이후 코드와 설정이 바뀌면 새로운 위험이 생길 수 있으므로 지속적인 보안 활동을 대체하지 않는다.

취약점 관리

취약점이 발견되면 영향을 받는 제품과 버전·노출과 공격 가능성을 분석하고 수정 또는 완화한다.

취약점 관리에는 다음이 포함될 수 있다.

  • 내부·외부 신고 접수
  • 재현과 기술 분석
  • 심각도와 실제 위험 평가
  • 영향받는 버전과 사용자 식별
  • 임시 완화
  • 수정 개발과 시험
  • 보안 릴리스
  • 사용자와 고객 통보
  • 취약점 공개 시점 조정
  • 근본 원인과 유사 결함 검색
  • 개발 과정 개선

심각도 점수만으로 수정 우선순위를 결정하지 않는다. 외부 노출과 실제 사용·보호 자산과 안전 영향을 함께 본다.

수정할 수 없는 오래된 버전에는 기능 비활성화·네트워크 격리와 업그레이드 안내를 제공할 수 있다.

취약점 공개

외부 연구자와 사용자가 보안 문제를 안전하게 신고할 수 있는 경로를 제공할 수 있다.

공개 정책에는 다음을 포함할 수 있다.

  • 신고 연락처와 암호화 방법
  • 대상 제품과 범위
  • 필요한 재현 정보
  • 신고자에게 기대하는 행동
  • 조직의 확인과 응답 절차
  • 공개 시점의 조정
  • 법적 대응과 선의의 연구 보호
  • 보상 프로그램 여부

신고를 무시하거나 신고자를 위협하면 취약점이 수정되지 않은 채 공개되거나 악용될 가능성이 커질 수 있다.

조정된 공개는 사용자를 보호할 수정 시간을 확보하면서도 취약점을 무기한 숨기지 않도록 균형을 정한다.

보안 사건 대응

보안 사건은 단순한 서비스 장애와 달리 공격자가 계속 접근하고 증거를 변경할 수 있다는 점을 고려해야 한다.

대응 과정에는 다음이 포함될 수 있다.

  1. 의심스러운 사건을 탐지하고 확인한다.
  2. 영향받는 계정·시스템과 데이터를 식별한다.
  3. 공격자의 추가 접근과 피해 확산을 제한한다.
  4. 로그와 디스크·메모리 등 증거를 보존한다.
  5. 침해된 자격 증명과 키를 폐기한다.
  6. 악성 코드와 취약점을 제거한다.
  7. 깨끗한 환경과 산출물로 복구한다.
  8. 사용자·고객과 규제 기관에 필요한 통보를 수행한다.
  9. 공격 경로와 대응 과정을 분석한다.
  10. 구조·정책과 탐지 수단을 개선한다.

너무 빠른 시스템 초기화는 중요한 증거를 잃게 할 수 있고, 증거 보존을 위해 대응을 늦추면 피해가 계속될 수 있다. 사건의 심각도와 법적 의무에 따라 역할과 우선순위를 정한다.

소프트웨어 공급망

소프트웨어 공급망은 조직이 직접 작성한 코드뿐 아니라 외부 패키지·컴파일러와 빌드 도구, 저장소·지속적 통합과 배포 시스템을 포함한다.

공급망 공격은 다음 지점에서 발생할 수 있다.

  • 개발자 계정
  • 소스 저장소
  • 외부 패키지와 저장소
  • 빌드 실행기
  • 코드 생성기와 컴파일러
  • 아티팩트 저장소
  • 서명 키
  • 업데이트 서버
  • 외부 공급자
  • 배포 자격 증명

공급망 보호에는 다음이 사용될 수 있다.

  • 다중 인증과 최소 권한
  • 보호된 개발선과 코드 검토
  • 의존성의 버전·출처와 무결성 고정
  • 격리되고 재현 가능한 빌드
  • 산출물 서명
  • 빌드 출처 증명
  • SBOM
  • 불변 아티팩트 저장소
  • 배포 권한 분리
  • 감사 기록
  • 공급자 평가와 지원 종료 관리

NIST SSDF는 개발 환경과 소프트웨어 구성 요소를 무단 접근과 변조에서 보호하고, 소프트웨어 릴리스의 무결성을 검증하며, 각 릴리스의 출처 자료를 수집·보호하는 관행을 포함한다.[124]

보안 개발 생명주기

보안은 개발 마지막에 수행하는 검사 단계가 아니라 생명주기 전체에 포함한다.

준비

  • 조직의 보안 책임과 교육을 정한다.
  • 개발·빌드와 시험 환경을 보호한다.
  • 지원할 보안 표준과 도구를 정한다.
  • 외부 구성 요소 정책을 만든다.
  • 취약점 신고와 대응 절차를 준비한다.

요구사항

  • 자산과 보안 목표를 식별한다.
  • 법률과 개인정보 요구를 확인한다.
  • 인증·권한과 감사 요구를 정의한다.
  • 공격과 복구 시나리오를 작성한다.
  • 수용 가능한 잔여 위험의 책임자를 정한다.

설계

  • 위협 모델링을 수행한다.
  • 신뢰 경계와 공격 표면을 분석한다.
  • 최소 권한과 격리를 적용한다.
  • 비밀 정보와 업데이트 구조를 설계한다.
  • 탐지·복구와 운영 요구를 포함한다.

구현

  • 안전한 코딩 규칙을 적용한다.
  • 입력과 상태를 검증한다.
  • 메모리와 자원을 안전하게 관리한다.
  • 검증된 암호와 라이브러리를 사용한다.
  • 코드 검토와 정적 분석을 수행한다.

시험

  • 보안 요구사항과 위협을 시험한다.
  • 인증과 권한 경계를 확인한다.
  • 퍼징과 동적 분석을 수행한다.
  • 공급망과 산출물 무결성을 확인한다.
  • 공격과 복구 절차를 시험한다.

배포와 운영

  • 안전한 기본 설정으로 배포한다.
  • 취약점과 보안 사건을 감시한다.
  • 자격 증명과 키를 교체한다.
  • 패치와 업데이트를 제공한다.
  • 로그와 증거를 보존한다.
  • 지원 종료 제품의 위험을 관리한다.

정보 보안 관리

제품 수준의 보안 활동은 조직의 정보 보안 관리 체계와 연결된다.

ISO/IEC 27001:2022는 조직이 정보 보안 위험을 관리하기 위한 정보 보안 관리 시스템을 수립·구현·유지하고 지속적으로 개선하기 위한 요구사항을 정의한다.[125]

조직 차원의 보안 관리에는 다음이 포함될 수 있다.

  • 정보와 시스템 자산 관리
  • 위험 평가와 처리
  • 보안 정책과 책임
  • 인력과 공급자 보안
  • 접근 통제
  • 암호와 키 관리
  • 운영과 네트워크 보호
  • 사건 대응
  • 업무 연속성
  • 내부 감사와 개선

인증이나 표준 준수는 특정 제품이 모든 공격에 안전하다는 의미가 아니다. 관리 체계와 통제가 정의된 범위에서 운영된다는 근거를 제공하며, 실제 제품의 설계와 구현·운영 품질을 계속 평가해야 한다.

기능 안전

기능 안전(Functional Safety)은 시스템이 입력과 고장을 감지하고 적절한 안전 기능을 수행함으로써 위험을 허용 가능한 수준으로 낮추는 데 관련된 안전이다.

예를 들어 다음과 같은 기능이 포함될 수 있다.

  • 과열을 감지하여 장치를 정지한다.
  • 위험 구역에 사람이 들어오면 기계 동작을 차단한다.
  • 센서가 비정상 값을 보내면 제한된 안전 모드로 전환한다.
  • 제동 제어에 장애가 발생하면 경고와 대체 제어를 제공한다.
  • 방사선량이 허용 범위를 넘으면 출력을 중단한다.

IEC 61508 시리즈는 전기·전자·프로그램 가능 전자 안전 관련 시스템과 제품의 생명주기에 적용되는 기능 안전 표준을 제공한다.[126]

IEC 61508-3은 안전 관련 시스템의 일부인 소프트웨어와 그러한 시스템을 개발·구성하는 데 사용되는 지원 도구에 적용되는 요구사항을 제공하고, 소프트웨어 안전 기능과 체계적 능력·안전 생명주기 활동을 다룬다.[127]

위험원

안전 분야에서 위험원(Hazard)은 사람·재산과 환경에 피해를 일으킬 잠재적 원천이나 상태이다.

소프트웨어와 관련된 위험원에는 다음이 있을 수 있다.

  • 잘못된 제어 명령
  • 제한을 넘는 속도·온도와 압력
  • 경고와 비상 정지의 실패
  • 센서 값의 잘못된 해석
  • 잘못된 환자와 약물 정보의 연결
  • 안전 상태에서의 의도하지 않은 이탈
  • 위치와 시간 정보의 오류
  • 동시에 수행되어서는 안 되는 작업의 실행
  • 오래된 데이터와 명령의 재사용
  • 사용자 인터페이스의 혼동
  • 자동화에 대한 과도한 신뢰

위험원 자체와 실제 피해를 일으키는 사건의 순서를 구분해야 한다. 하나의 소프트웨어 결함이 여러 조건과 결합해야 사고가 발생할 수도 있다.

위험 분석

안전 위험 분석에서는 다음을 수행할 수 있다.

  • 시스템과 사용 환경을 정의한다.
  • 가능한 위험원과 사고를 식별한다.
  • 원인·실패와 사건의 조합을 분석한다.
  • 피해의 심각도와 발생 가능성을 평가한다.
  • 위험 감소 목표를 정한다.
  • 안전 기능과 책임을 할당한다.
  • 잔여 위험을 평가하고 수용한다.
  • 운영과 폐기까지 위험을 추적한다.

사용되는 기법에는 다음과 같은 것들이 있다.

  • 위험원 분석
  • 고장 형태 및 영향 분석
  • 고장 나무 분석
  • 사건 나무 분석
  • 위험 및 운전성 분석
  • 상태와 제어 기반 분석
  • 체크리스트와 과거 사고 분석
  • 시뮬레이션과 시험

한 기법이 모든 종류의 위험을 발견하지는 않는다. 구성 요소 고장·사람과 소프트웨어의 상호작용과 복잡한 제어 관계에 따라 여러 방법을 사용할 수 있다.

안전 요구사항

안전 요구사항은 어떤 위험을 얼마나 줄여야 하는지와 시스템이 위험 조건에서 어떻게 반응해야 하는지를 정의한다.

예를 들면 다음과 같다.

  • 센서 값이 물리적으로 가능한 범위를 벗어나면 제어 출력을 중지해야 한다.
  • 두 개의 독립 센서가 일치하지 않으면 자동 운전을 해제하고 운영자에게 경고해야 한다.
  • 비상 정지 입력은 일반 제어 작업보다 높은 우선순위로 처리되어야 한다.
  • 안전 관련 통신이 정해진 시간 안에 완료되지 않으면 장치는 안전 상태로 전환되어야 한다.
  • 안전 기능의 자체 진단 실패는 운영자가 확인할 수 있어야 한다.
  • 재시작 이후 장치는 이전의 위험한 명령을 자동으로 다시 실행해서는 안 된다.

안전 요구사항은 시스템 수준의 위험에서 소프트웨어·하드웨어와 운영 절차로 할당한다. 소프트웨어가 책임지지 않는 위험 감소 수단도 전체 안전 논증에 포함해야 한다.

안전 상태

안전 상태는 특정 위험과 조건에서 피해 가능성을 허용 가능한 수준으로 낮추는 시스템 상태이다.

안전 상태는 항상 시스템을 즉시 종료하는 상태와 같지 않다.

  • 항공기와 생명 유지 장치는 단순히 전원을 끄는 것이 더 위험할 수 있다.
  • 철도 신호는 열차를 정지시키는 쪽이 일반적으로 안전할 수 있다.
  • 의료 장비는 치료를 중단하기 전에 사용자에게 경고하고 수동 제어를 제공해야 할 수 있다.
  • 데이터 시스템은 손상된 쓰기를 막기 위해 읽기 전용으로 전환할 수 있다.

어떤 상태가 안전한지는 위험원과 운영 문맥에 따라 결정한다.

하나의 위험에 안전한 상태가 다른 위험에는 안전하지 않을 수 있다. 화재 상황의 출입문과 침입 방지 요구처럼 충돌하는 안전·보안 조건을 분석해야 한다.

실패 안전과 고장 허용

실패 안전은 시스템이 실패했을 때 위험을 줄이는 상태로 이동하도록 하는 원리이다.

고장 허용은 일부 구성 요소가 실패해도 필요한 기능을 계속 제공하도록 하는 능력이다.

사용할 수 있는 방법에는 다음이 있다.

  • 중복 구성 요소
  • 다양한 구현
  • 감시 타이머
  • 자체 진단
  • 다수결
  • 격리
  • 제한된 성능의 저하 운전
  • 수동 제어
  • 체크포인트와 복구
  • 독립적인 안전 장치

중복된 구성 요소가 같은 설계와 소프트웨어 결함을 공유하면 동시에 잘못된 결과를 낼 수 있다. 공통 원인 고장을 분석해야 한다.

고장 허용 구조가 복잡성을 크게 늘리면 새로운 결함과 잘못된 전환이 발생할 수 있으므로 실제 위험 감소를 평가한다.

방어적 안전 설계

안전 관련 소프트웨어는 정상적인 입력과 환경만을 가정하지 않는다.

다음과 같은 조건을 고려한다.

  • 센서 값의 누락과 급격한 변화
  • 통신 지연·중복과 순서 변경
  • 메모리와 저장 공간 부족
  • 일부 구성 요소의 재시작
  • 시각과 타이머의 오류
  • 사용자 명령의 충돌
  • 오래된 설정과 데이터
  • 전원 중단과 부분 초기화
  • 하드웨어와 소프트웨어 버전 불일치
  • 동시에 발생하는 여러 고장

입력과 상태의 유효성을 검증하고, 불가능하거나 모순된 상태를 감지하며, 위험한 명령에는 추가적인 조건과 확인을 둘 수 있다.

안전 관련 계산과 판단을 일반 사용자 인터페이스·네트워크와 불필요하게 결합하지 않고 격리된 경계에 둘 수 있다.

안전 무결성

안전 관련 기능에는 위험 수준에 따라 필요한 신뢰와 개발·검증의 엄격성이 달라질 수 있다.

IEC 61508은 위험 기반 접근을 통해 안전 기능에 요구되는 성능과 안전 무결성을 결정하고, 전기·전자·프로그램 가능 전자 안전 관련 시스템이 허용 가능한 위험을 달성하도록 요구한다.[128]

위험이 높은 기능에는 다음과 같은 추가 활동이 필요할 수 있다.

  • 더 엄격한 요구사항과 추적성
  • 독립적인 설계와 검증
  • 제한된 언어 기능과 코딩 규칙
  • 정적·동적과 형식 분석
  • 높은 구조 커버리지
  • 고장 주입
  • 도구의 적격성 확인
  • 구성과 변경 통제
  • 운영과 유지보수 절차
  • 장기적인 안전 증거 보존

안전 수준은 제품의 마케팅 등급이 아니라 특정 안전 기능과 위험에 연결되어야 한다.

분야별 안전 표준

IEC 61508은 여러 산업 분야의 기능 안전 표준을 위한 기반 역할을 한다. 분야별 시스템은 서로 다른 위험·운영 환경과 규제 구조를 가지므로 별도의 표준이 사용될 수 있다.

예를 들면 다음과 같은 분야가 있다.

  • 자동차
  • 철도
  • 항공
  • 의료 기기
  • 산업 공정
  • 원자력
  • 기계
  • 로봇과 자율 시스템

분야별 표준은 소프트웨어 개발 절차뿐 아니라 시스템 위험·하드웨어와 운영 증거를 함께 요구할 수 있다.

단순히 일반적인 소프트웨어 품질 인증을 받았다는 이유로 특정 안전 분야의 요구를 충족한다고 볼 수 없다.

독립성과 다양성

안전 관련 검증에서는 개발자와 다른 사람이 요구사항·설계와 시험을 평가하는 독립성이 필요할 수 있다.

독립성 수준은 위험에 따라 달라질 수 있다.

  • 작성자가 자신의 산출물을 검토한다.
  • 같은 팀의 다른 사람이 검토한다.
  • 별도의 검증 팀이 평가한다.
  • 조직의 독립 부서가 승인한다.
  • 외부 인증 기관과 규제 기관이 평가한다.

독립성이 있다고 자동으로 결함을 발견하는 것은 아니다. 필요한 전문성·자료와 권한을 제공해야 한다.

다양한 구현과 분석 방법을 사용하면 하나의 방법이 놓치는 오류를 발견할 수 있지만 공통 요구사항과 도구의 결함은 공유될 수 있다.

형식 기법

형식 기법은 수학적으로 정의된 언어와 논리를 사용하여 요구사항·설계와 프로그램의 성질을 명세하고 분석한다.

사용할 수 있는 방법에는 다음이 있다.

  • 형식 명세
  • 모델 검사
  • 정리 증명
  • 정적 의미 분석
  • 타입과 효과 체계
  • 계약과 불변 조건 검증
  • 추상 해석

형식 기법은 가능한 상태와 실행을 체계적으로 분석하고 특정 성질의 위반이 없음을 증명하는 데 사용할 수 있다.

그러나 형식 모델이 실제 요구와 시스템 환경을 잘못 표현하면 증명은 잘못된 모델에 대해서만 성립한다. 모델과 현실의 대응, 도구와 가정도 검토해야 한다.

모든 시스템을 완전히 형식화하기보다 위험이 높은 알고리즘·프로토콜과 상태 기계에 선택적으로 적용할 수 있다.

안전 사례

안전 사례(Safety Case)는 시스템이 특정 환경과 용도에서 충분히 안전하다는 주장을 구조화하고, 그 주장을 뒷받침하는 논거와 증거를 연결한 자료이다.

증거에는 다음이 포함될 수 있다.

  • 위험 분석
  • 안전 요구사항
  • 설계와 격리 구조
  • 검토와 시험 결과
  • 형식 분석
  • 도구와 구성 관리
  • 고장 주입과 실제 시험
  • 운영 절차
  • 알려진 한계
  • 독립적인 평가
  • 잔여 위험의 승인

시험 결과를 많이 모으는 것만으로 안전 사례가 완성되지는 않는다. 각 증거가 어떤 위험과 주장에 연결되는지 설명해야 한다.

소프트웨어와 환경이 변경되면 기존 안전 논증과 증거에 미치는 영향을 분석한다.

안전과 사용성

안전 기능이 기술적으로 정확해도 사용자가 이해하고 적시에 사용할 수 없다면 안전하지 않을 수 있다.

다음과 같은 사용자 인터페이스 문제가 사고에 기여할 수 있다.

  • 비슷한 장치와 환자의 혼동
  • 중요한 경고가 다른 알림에 묻힘
  • 경고의 원인과 조치가 불명확함
  • 위험한 기능과 일반 기능의 버튼이 가까움
  • 단위와 시간대의 혼동
  • 현재 자동화 상태를 알기 어려움
  • 취소와 되돌리기 방법의 부재
  • 사용자의 확인을 지나치게 자주 요구하여 습관적 승인 유발
  • 색상과 소리에만 의존하는 경고

안전 설계에는 인간의 인지·작업 환경과 피로, 교육과 조직 절차를 포함해야 한다.

사용자 실수를 단순한 사용자 책임으로 처리하기보다 시스템이 실수를 예방하고 발견·복구할 수 있는지 분석한다.

자동화 편향

사용자는 자동화된 시스템의 결과를 실제보다 신뢰하거나, 시스템과 다른 판단을 내리는 것을 주저할 수 있다. 이를 자동화 편향과 관련된 문제로 설명할 수 있다.

위험을 줄이기 위해 다음을 고려할 수 있다.

  • 시스템의 능력과 한계를 명확히 표시한다.
  • 신뢰도와 불확실성을 설명한다.
  • 중요한 결정에는 사람이 확인할 수 있는 근거를 제공한다.
  • 자동화 결과를 거부하거나 수정할 수 있게 한다.
  • 사람이 개입해야 하는 조건을 정의한다.
  • 수동 기술과 상황 인식을 유지하도록 훈련한다.
  • 자동화가 실패했을 때 안전하게 전환한다.

형식적인 사람의 승인 단계만 추가한다고 실질적인 감독이 이루어지는 것은 아니다. 검토할 시간·정보와 실제로 결정을 바꿀 권한이 필요하다.

개인정보

개인정보 보호는 단순히 데이터가 외부 공격자에게 유출되지 않게 하는 것보다 넓은 문제이다. 합법적으로 접근 권한을 가진 조직이 정보를 어떤 목적으로 수집·분석하고 공유하며, 그 처리가 개인에게 어떤 영향을 주는지도 포함한다.

보안이 강한 시스템에서도 다음과 같은 개인정보 문제가 발생할 수 있다.

  • 서비스에 필요하지 않은 정보를 수집한다.
  • 원래 목적과 다른 분석에 사용한다.
  • 사용자가 예상하지 못한 주체와 공유한다.
  • 지나치게 오래 보존한다.
  • 개인을 평가·분류하고 불리한 결정을 내린다.
  • 삭제와 정정 방법을 제공하지 않는다.
  • 동의를 받았지만 사용자가 실질적으로 거부할 수 없다.
  • 익명 데이터가 다른 자료와 결합되어 다시 식별된다.

NIST Privacy Framework는 조직이 개인정보 위험을 식별하고 관리하면서 혁신적인 제품과 서비스를 개발하고 개인의 개인정보를 보호할 수 있도록 만든 자발적인 도구이다.[129]

개인정보 위험

개인정보 위험은 정보 유출의 가능성만을 뜻하지 않는다.

데이터 처리로 개인에게 다음과 같은 문제가 발생할 수 있다.

  • 감시받는다는 느낌과 행동 위축
  • 차별과 기회 상실
  • 경제적 손실
  • 평판 피해
  • 신체적 위험
  • 원하지 않는 공개
  • 조작과 과도한 맞춤화
  • 잘못된 정보에 따른 결정
  • 데이터 수정과 삭제의 어려움
  • 개인이 이해하거나 통제할 수 없는 프로파일링

개인정보 위험을 조직의 벌금과 평판 손실만으로 평가하면 실제 영향을 받는 개인의 피해가 가려질 수 있다.

데이터 주체와 취약한 집단·간접적으로 영향을 받는 사람을 포함하여 위험을 분석한다.

개인정보 보호 설계

개인정보를 고려한 설계에는 다음 원칙을 적용할 수 있다.

  • 필요한 데이터만 수집한다.
  • 사용 목적을 명확히 정한다.
  • 원래 목적과 다른 사용을 제한한다.
  • 데이터의 정확성과 정정 방법을 제공한다.
  • 필요한 기간만 보존한다.
  • 접근과 공유 범위를 제한한다.
  • 가능한 경우 익명화와 집계를 사용한다.
  • 사용자가 이해할 수 있는 설명과 선택을 제공한다.
  • 삭제와 내보내기·철회를 지원한다.
  • 개인정보 위험을 지속적으로 평가한다.

동의 화면을 제공했다는 사실만으로 모든 데이터 처리가 윤리적이거나 적절한 것은 아니다.

필수 기능과 무관한 데이터 수집에 동의하지 않으면 서비스를 사용할 수 없게 만드는 경우에는 동의의 자발성이 약할 수 있다.

데이터 최소화

데이터 최소화는 제품과 법적 목적에 필요한 정보만 수집·처리하고 불필요한 세부 정보와 보존을 줄이는 원칙이다.

데이터를 보유하지 않으면 유출·오용과 잘못된 결정의 위험도 줄어든다.

다음과 같은 질문을 사용할 수 있다.

  • 이 데이터가 기능에 실제로 필요한가
  • 더 낮은 정밀도와 집계값으로 목적을 달성할 수 있는가
  • 장치 안에서 처리하고 서버로 보내지 않을 수 있는가
  • 원본 대신 파생 결과만 보존할 수 있는가
  • 일정 시간이 지나면 자동으로 삭제할 수 있는가
  • 사용자가 선택적으로 제공할 수 있는가

“나중에 사용할 수 있다”는 이유만으로 데이터를 무기한 수집하면 목적과 책임이 불명확해진다.

익명화와 재식별

이름과 계정 식별자를 제거했다고 데이터가 반드시 익명이 되는 것은 아니다.

위치·시간과 나이, 행동 패턴 같은 여러 속성을 다른 데이터와 결합하면 개인을 다시 식별할 수 있다.

익명화에서는 다음을 고려한다.

  • 데이터의 고유한 조합
  • 외부에서 이용 가능한 자료
  • 표본의 크기
  • 지리와 시간의 정밀도
  • 반복 관찰
  • 공격자가 가진 배경 지식
  • 이후 추가되는 데이터
  • 분석 결과의 유출

가명화는 직접 식별자를 다른 값으로 바꾸어 접근 위험을 낮출 수 있지만 복원 키와 결합 데이터가 존재하면 개인정보로서 보호가 필요하다.

데이터 보존과 삭제

데이터를 오래 보관할수록 분석과 복구에 도움이 될 수 있지만 유출과 오용·법적 책임도 증가한다.

보존 정책에서는 다음을 정한다.

  • 데이터 종류와 목적
  • 보존 기간
  • 법률과 계약 의무
  • 삭제와 익명화 방법
  • 백업과 복제본
  • 로그와 캐시
  • 보존 연장 승인
  • 사용자의 삭제 요청
  • 서비스 종료
  • 삭제 확인과 감사

응용 프로그램의 주 데이터베이스에서 삭제했더라도 검색 색인·캐시와 백업·분석 시스템에 남을 수 있다.

백업에서 즉시 개별 데이터를 제거하기 어렵다면 복원 뒤 삭제가 다시 적용되도록 설계할 수 있다.

공정성과 차별

소프트웨어는 사람을 분류·추천하거나 자원과 기회에 대한 결정을 지원할 수 있다. 데이터와 규칙·모델이 특정 집단에 불리한 결과를 만들 수 있다.

공정성 문제는 개발자가 차별할 의도가 없더라도 발생할 수 있다.

  • 과거의 차별적 데이터를 학습한다.
  • 일부 집단의 데이터가 부족하다.
  • 대리 변수가 민감한 속성을 간접적으로 나타낸다.
  • 평균 성능은 높지만 특정 집단에서 오류가 집중된다.
  • 동일한 기준이 서로 다른 상황을 무시한다.
  • 시스템을 사용할 수 없는 사람이 절차에서 제외된다.
  • 오류를 이의 제기하거나 수정할 방법이 없다.

공정성은 하나의 수학적 지표로 완전히 정의되지 않는다. 서로 충돌하는 공정성 기준과 법적·사회적 맥락이 존재할 수 있다.

영향받는 집단과 도메인 전문가를 참여시키고 집단별 결과와 오류·사용 가능성을 평가한다.

접근성

접근성은 장애가 있는 사용자를 위한 별도의 선택 기능이 아니라 제품을 사용할 수 있는 사람의 범위와 권리에 관한 품질·윤리 문제이다.

다음 요소를 고려한다.

  • 키보드 조작
  • 화면 읽기 프로그램
  • 색상 외의 정보 표현
  • 명암과 글자 크기
  • 자막과 대체 텍스트
  • 시간 제한
  • 동작과 깜박임
  • 오류의 식별과 수정
  • 다양한 입력 장치
  • 인지적 복잡성
  • 언어와 이해 가능성

접근성 요구를 출시 직전에 확인하면 구조적인 사용자 인터페이스와 콘텐츠 문제를 수정하기 어렵다.

디자인 시스템·구성 요소와 완료 기준에 접근성을 포함하고 실제 보조 기술과 사용자를 대상으로 평가한다.

조작적 설계

사용자 인터페이스와 알고리즘은 사용자의 선택을 특정 방향으로 유도할 수 있다.

문제가 될 수 있는 설계에는 다음이 있다.

  • 해지와 개인정보 거부를 의도적으로 어렵게 한다.
  • 구매와 동의 버튼만 눈에 띄게 만든다.
  • 거부할 때 반복적으로 죄책감을 유발한다.
  • 실제보다 긴급하거나 희소한 것처럼 표시한다.
  • 사용자의 주의를 무한히 유지하도록 설계한다.
  • 광고와 일반 콘텐츠를 구분하기 어렵게 한다.
  • 결제와 구독 조건을 숨긴다.
  • 기본값으로 과도한 데이터 공유를 선택한다.

이러한 설계는 사용자가 형식적으로 버튼을 눌렀더라도 자율적이고 충분한 정보를 바탕으로 선택했다고 보기 어렵게 만들 수 있다.

제품 성과 지표가 클릭·체류 시간과 구매만을 강조하면 사용자의 장기적 복지와 권리가 희생될 수 있으므로 지표와 인센티브를 함께 검토한다.

인공지능과 자동화된 의사결정

인공지능 기반 시스템은 데이터와 모델·일반 소프트웨어, 사용자 인터페이스와 운영 규칙이 함께 결과를 만든다.

다음과 같은 위험을 고려해야 한다.

  • 학습 데이터의 편향과 오류
  • 존재하지 않는 정보의 생성
  • 예측의 불확실성
  • 설명하기 어려운 결정
  • 사용자와 개발자의 과도한 신뢰
  • 개인정보와 저작권 문제
  • 공격적 입력과 모델 조작
  • 운영 환경의 데이터 변화
  • 사람의 검토가 형식적으로만 존재하는 문제
  • 책임 소재의 불명확성
  • 높은 자원과 환경 비용
  • 위험한 목적의 오용

모델의 평균 정확도만으로 실제 품질과 윤리성을 판단하기 어렵다. 중요한 오류의 비용·집단별 성능과 사용 문맥, 사람이 개입하고 이의를 제기할 수 있는지를 함께 평가한다.

AI 도구가 제안한 코드와 분석 결과도 개발자의 전문적 검토와 시험·보안 검사를 거쳐야 한다.

설명 가능성과 투명성

사용자와 운영자는 시스템이 어떤 자료와 기준을 사용하여 중요한 결과를 만들었는지 이해할 필요가 있을 수 있다.

투명성에는 다음 정보가 포함될 수 있다.

  • 자동화된 시스템이 사용되었다는 사실
  • 입력으로 사용한 데이터 종류
  • 결과의 의미와 한계
  • 오류와 불확실성
  • 중요한 규칙과 판단 요소
  • 사람이 검토하는지 여부
  • 결과에 이의를 제기하고 수정할 방법
  • 데이터와 모델의 책임 조직
  • 기록과 감사 가능성

모든 소스 코드와 모델 내부를 공개하는 것이 항상 의미 있는 설명은 아니다. 대상 사용자가 자신의 권리와 행동을 판단할 수 있는 수준의 설명을 제공해야 한다.

영업 비밀과 보안상 제한이 있더라도 중요한 결정의 책임과 이의 제기 경로까지 숨겨서는 안 된다.

환경과 지속 가능성

소프트웨어는 데이터 센터·네트워크와 사용자 장치의 전력과 하드웨어 자원을 사용한다.

윤리적·사회적 영향에는 다음도 포함될 수 있다.

  • 높은 계산과 에너지 사용
  • 불필요한 데이터 저장과 전송
  • 빠른 장치 교체를 요구하는 소프트웨어
  • 오래된 장치의 지원 종료
  • 전자 폐기물
  • 특정 지역의 물과 전력 자원 사용
  • 공급망과 노동 환경
  • 사용자가 알지 못하는 백그라운드 작업

성능 최적화와 효율적인 데이터 처리·적절한 보존 정책은 비용뿐 아니라 환경 영향도 줄일 수 있다.

모든 기능에 환경 측정을 요구할 수는 없지만 대규모 계산과 장기 서비스·인공지능 모델에서는 자원과 제공 가치의 균형을 검토할 수 있다.

공개와 투명성

소프트웨어 조직은 제품의 기능·제약과 데이터 처리, 보안과 안전 상태에 관해 이해관계자에게 필요한 정보를 제공해야 한다.

공개할 수 있는 정보에는 다음이 있다.

  • 지원 환경과 기간
  • 알려진 중대한 제한
  • 데이터 수집과 사용
  • 자동화된 의사결정
  • 보안 업데이트와 취약점
  • 서비스 장애
  • 기능 폐기와 종료
  • 안전한 사용 조건
  • 사용자와 관리자 책임
  • 외부 공급자와 데이터 이전

보안을 이유로 모든 결함과 설계를 숨기는 방식은 사용자가 위험을 판단하고 대응하는 것을 막을 수 있다.

반대로 취약점의 세부 정보를 수정 전에 무분별하게 공개하면 사용자가 공격에 노출될 수 있으므로 공개 시기와 범위를 책임 있게 조정한다.

전문 윤리의 역할

법률은 사회가 금지하거나 요구하는 최소 기준을 제공하지만 모든 기술적 상황과 미래의 영향을 미리 정의하지 못한다.

전문 윤리는 다음과 같은 질문을 다룬다.

  • 합법적이지만 사용자에게 해로운 기능을 만들어도 되는가
  • 일정 때문에 중요한 시험을 생략할 수 있는가
  • 심각한 위험을 경영진이 무시할 때 어떻게 해야 하는가
  • 사용자가 이해하지 못하는 데이터 수집에 형식적인 동의만 받으면 충분한가
  • 자신의 능력 범위를 넘어서는 작업을 맡을 때 어떻게 해야 하는가
  • 생성형 인공지능의 결과를 검증하지 않고 사용할 수 있는가
  • 공격적 기술과 감시 시스템을 어디까지 개발해야 하는가
  • 고객과 고용주의 이익이 공공의 안전과 충돌하면 무엇을 우선해야 하는가

윤리적 판단은 개인의 선의에만 의존하지 않는다. 조직의 검토·문제 보고와 위험 수용 절차, 독립적인 감독이 필요하다.

공공의 이익

Software Engineering Code of Ethics는 소프트웨어 엔지니어가 공공의 이익과 일치하도록 행동해야 한다는 원칙을 가장 먼저 제시한다.[130]

공공의 이익에는 다음이 포함될 수 있다.

  • 사람의 안전과 건강
  • 개인정보와 자율성
  • 차별받지 않을 권리
  • 정보와 서비스에 대한 접근
  • 사회 기반 시설의 신뢰성
  • 민주적 절차와 정보 환경
  • 환경과 미래 세대
  • 취약한 집단의 보호

고객과 고용주의 요청을 충실히 수행하는 것도 전문적 책임이지만 공공에 중대한 피해를 일으키는 요청까지 무조건 따라야 한다는 뜻은 아니다.

고객과 고용주

소프트웨어 전문가는 고객과 고용주의 정당한 이익을 보호해야 한다.

다음과 같은 책임이 포함될 수 있다.

  • 기밀과 지식재산권 보호
  • 비용과 일정·위험에 대한 정직한 설명
  • 이해 충돌의 공개
  • 승인되지 않은 자원 사용 금지
  • 요구와 계약의 성실한 수행
  • 자신의 전문 능력 범위 설명
  • 중대한 결함과 위험의 보고
  • 불법적이고 비윤리적인 요구에 대한 문제 제기

고객의 기밀을 보호해야 하지만 제품이 사용자와 공공에 즉각적이고 심각한 위험을 일으키는 경우에는 더 높은 책임과 법적 의무가 적용될 수 있다.

제품에 대한 책임

전문가는 자신이 개발하거나 승인하는 소프트웨어가 가능한 한 높은 전문적 기준을 충족하도록 노력해야 한다.

제품 책임에는 다음이 포함될 수 있다.

  • 요구사항과 사용 목적의 이해
  • 적절한 설계와 시험
  • 보안·안전과 개인정보
  • 현실적인 비용과 일정
  • 결함과 한계의 기록
  • 정확한 문서
  • 외부 구성 요소와 라이선스
  • 유지보수와 업데이트 가능성
  • 사용 중단과 데이터 이동
  • 사용자의 능력과 환경 고려

완성되지 않았거나 충분히 검증되지 않은 기능을 정상 제품인 것처럼 표시해서는 안 된다.

실험적 기능과 알려진 위험이 있다면 사용자가 의미를 이해하고 적절히 선택할 수 있도록 설명해야 한다.

전문적 판단

전문가는 기술적 판단의 정직성과 독립성을 유지해야 한다.

다음과 같은 행동이 필요하다.

  • 사실과 추정을 구분한다.
  • 불확실성과 한계를 밝힌다.
  • 시험과 측정 결과를 왜곡하지 않는다.
  • 개인적·재정적 이해 충돌을 공개한다.
  • 자신의 능력을 과장하지 않는다.
  • 근거가 바뀌면 결정을 수정한다.
  • 다른 전문가의 검토를 받아들인다.
  • 위험을 과소평가하라는 압력에 저항한다.

경영진이 원하는 일정에 맞추기 위해 가능성이 낮은 추정만 제시하거나 실패한 시험을 숨기면 책임 있는 판단으로 볼 수 없다.

관리자의 책임

소프트웨어 프로젝트의 관리자는 일정과 예산뿐 아니라 팀의 전문적·윤리적 활동을 지원할 책임이 있다.

관리자는 다음을 보장해야 한다.

  • 현실적인 계획과 자원
  • 필요한 검토와 시험 시간
  • 보안·안전과 개인정보 전문성
  • 위험과 문제를 보고할 수 있는 환경
  • 품질을 희생하도록 유도하지 않는 평가 체계
  • 책임과 권한의 명확성
  • 외부 공급자에 대한 동일한 기준
  • 직원의 과도한 근무와 피로 방지
  • 윤리 문제와 내부 신고의 보호
  • 제품 종료 뒤의 사용자와 데이터 책임

관리자가 불가능한 일정과 범위를 고정한 뒤 개발자의 책임감에만 의존하면 결함과 은폐를 유도할 수 있다.

전문직에 대한 책임

전문가는 소프트웨어 공학 분야의 신뢰와 역량을 높이는 데 기여해야 한다.

다음이 포함될 수 있다.

  • 정확한 기술 정보와 연구 결과 제공
  • 표준과 모범 사례 개선
  • 교육과 멘토링
  • 동료의 공정한 평가
  • 결함과 사고에서 얻은 교훈 공유
  • 전문적 자격과 한계의 정직한 표시
  • 표절과 연구 부정 방지
  • 공공의 기술 이해 지원
  • 차별과 괴롭힘 없는 전문 공동체

직업 집단의 평판을 지키기 위해 문제를 숨기는 것이 아니라 문제를 투명하게 다루고 개선하는 것이 장기적인 신뢰에 도움이 된다.

동료에 대한 책임

동료와 협력할 때는 공정성과 존중·전문적인 지원을 유지해야 한다.

  • 다른 사람의 기여를 인정한다.
  • 검토 의견을 사람에 대한 공격으로 만들지 않는다.
  • 필요한 정보를 의도적으로 숨기지 않는다.
  • 차별과 괴롭힘을 용인하지 않는다.
  • 경험이 적은 구성원의 성장을 지원한다.
  • 동료가 만든 위험을 발견하면 적절히 알린다.
  • 문제를 개인에게 전가하지 않고 시스템적 원인을 분석한다.
  • 평가와 채용에서 관련 없는 개인적 속성을 사용하지 않는다.

동료를 보호한다는 이유로 심각한 결함과 비윤리적 행동을 숨겨서는 안 된다.

자신에 대한 책임

전문가는 자신의 지식과 판단을 지속적으로 개선하고 책임 있는 실무 능력을 유지해야 한다.

  • 새로운 기술과 위험을 학습한다.
  • 자신의 전문 범위를 이해한다.
  • 필요한 경우 전문가의 도움을 구한다.
  • 관련 법률과 표준을 확인한다.
  • 작업 결과를 검토하고 실수를 인정한다.
  • 건강과 피로가 판단에 미치는 영향을 관리한다.
  • 윤리적 문제를 인식하고 행동할 준비를 한다.
  • 자동화 도구의 결과를 비판적으로 검토한다.

모든 분야를 혼자 완벽히 알아야 한다는 뜻은 아니다. 부족한 전문성을 숨기지 않고 필요한 협력과 검토를 확보하는 것이 중요하다.

정직성과 표현

프로젝트와 제품에 관한 표현은 이해관계자가 실제 상태와 위험을 올바르게 판단할 수 있게 해야 한다.

다음과 같은 행동은 문제가 될 수 있다.

  • 프로토타입을 완성 제품처럼 제시한다.
  • 시험 범위와 한계를 숨긴다.
  • 보안 기능이 모든 공격을 막는다고 광고한다.
  • 정확도와 성능에서 유리한 수치만 선택한다.
  • 통계적 상관관계를 인과관계처럼 표현한다.
  • 인공지능의 결과를 객관적 사실처럼 제시한다.
  • 알려진 결함을 사용자에게 알리지 않는다.
  • 지원되지 않는 환경에서의 동작을 보장한다.
  • 오픈소스와 타인의 작업을 자신의 독자 기술처럼 표현한다.

불확실성을 설명하는 것은 전문성이 부족하다는 뜻이 아니라 책임 있는 판단의 일부이다.

이해 충돌

개인의 재정·경력과 조직적 이해가 기술 판단에 영향을 줄 수 있다.

예를 들면 다음과 같다.

  • 자신이 투자한 공급자의 제품을 추천한다.
  • 오류를 인정하면 평가가 낮아져 위험을 숨긴다.
  • 계약 수주를 위해 실현 가능성을 과장한다.
  • 특정 기술에 대한 개인적 선호를 요구사항처럼 제시한다.
  • 독립 검토자가 개발 결과에도 직접 책임을 가진다.
  • 보안 사고 공개 여부가 조직의 단기 주가와 충돌한다.

이해 충돌 자체가 항상 비윤리적인 것은 아니지만 관련자에게 공개하고 독립적인 검토와 결정 구조를 마련해야 한다.

지식재산권과 라이선스

소프트웨어 개발자는 코드·문서·데이터와 모델의 저작권·특허, 상표와 라이선스를 존중해야 한다.

다음과 같은 사항을 확인한다.

  • 외부 코드의 라이선스
  • 복사·수정과 재배포 조건
  • 저작권 고지
  • 상업적 사용 제한
  • 특허 조건
  • 데이터와 모델의 사용 권한
  • 직원과 계약자의 결과물 소유권
  • 생성형 인공지능 출력의 출처와 정책
  • 오픈소스 의무
  • 사용자에게 제공해야 하는 소스와 문서

인터넷에서 접근할 수 있다는 이유만으로 자유롭게 복사하고 재배포할 수 있는 것은 아니다.

라이선스 준수는 법무 부서만의 일이 아니라 의존성을 선택하고 코드를 작성하는 개발 과정에 포함된다.

보안 연구와 이중 용도

취약점 분석·침투 시험과 공격 기술은 방어와 연구에 사용될 수 있지만 악용될 수도 있다.

책임 있는 연구에서는 다음을 고려한다.

  • 명시적인 허가와 범위
  • 실제 사용자와 데이터에 대한 피해 제한
  • 필요한 최소한의 접근
  • 발견한 정보의 보호
  • 취약점 신고와 공개 조정
  • 시험 환경과 운영 환경의 구분
  • 도구와 코드의 공개가 만드는 위험
  • 법률과 계약

방어 목적이라는 주장만으로 권한 없는 시스템 접근과 데이터 수집이 정당화되지는 않는다.

반대로 보안 연구를 과도하게 제한하면 중요한 취약점이 발견되지 않을 수 있으므로 선의의 연구를 위한 명확한 정책과 보호가 필요하다.

내부 문제 제기

전문가가 심각한 위험·불법 행위와 조작을 발견했을 때 조직 내부의 적절한 경로를 통해 문제를 제기할 수 있어야 한다.

일반적인 경로에는 다음이 있을 수 있다.

  • 기술 책임자
  • 프로젝트와 제품 책임자
  • 보안·안전과 품질 조직
  • 법무와 윤리 담당자
  • 내부 감사
  • 경영진
  • 독립적인 신고 채널

문제를 제기할 때 다음 정보를 준비할 수 있다.

  • 확인된 사실
  • 추정과 불확실성
  • 영향을 받는 사람과 시스템
  • 위험의 심각성과 긴급성
  • 관련 요구사항과 법률
  • 이미 수행한 대응
  • 가능한 완화와 대안
  • 의사결정 기록

조직은 선의의 문제 제기에 대한 보복을 막고 독립적인 검토를 제공해야 한다.

외부 공개와 내부고발

내부 절차로 해결되지 않고 공공에 중대하고 임박한 피해가 예상되는 경우 외부 기관과 규제자·전문가의 도움을 고려할 수 있다.

이러한 결정은 기밀·개인정보와 법적 의무, 공개로 인한 추가 피해를 포함하므로 신중해야 한다.

가능한 경우 다음을 고려한다.

  • 내부 경로가 실제로 사용되었는가
  • 피해가 중대하고 근거가 충분한가
  • 공개 범위를 최소화할 수 있는가
  • 규제 기관과 전문 단체·법률 자문을 이용할 수 있는가
  • 개인과 민감한 정보를 보호할 수 있는가
  • 공개가 위험을 줄일 가능성이 있는가
  • 증거의 무결성을 유지할 수 있는가

전문 윤리는 무조건적인 조직 충성이나 무조건적인 공개를 요구하지 않는다. 공공의 보호와 사실의 정확성·비례성을 중심으로 판단해야 한다.

법률과 윤리의 관계

법률을 준수하는 것은 필수적이지만 윤리적 책임의 전체를 대신하지 않는다.

법률이 허용하더라도 다음과 같은 행위는 문제가 될 수 있다.

  • 취약한 사용자를 의도적으로 조작한다.
  • 이해하기 어려운 약관으로 광범위한 데이터 사용에 동의하게 한다.
  • 안전 위험을 알고도 최소 법적 기준만 충족한다.
  • 기술적으로 거부할 수 없는 감시를 확대한다.
  • 차별적 결과를 알면서도 사업상 이익 때문에 유지한다.
  • 보안 지원 종료를 충분한 통보 없이 수행한다.

반대로 서로 다른 지역의 법률과 윤리적 의무가 충돌할 수 있다. 법률·도메인과 윤리 전문가의 자문을 받고 영향을 받는 사람과 위험을 분석해야 한다.

조직 문화

보안·안전과 윤리는 규정 문서보다 조직의 실제 인센티브와 의사결정 방식에 크게 영향을 받는다.

문제가 되는 문화에는 다음과 같은 특징이 있다.

  • 일정 지연보다 위험 보고를 더 크게 처벌한다.
  • 결함을 발견한 사람에게 책임을 돌린다.
  • 보안과 품질을 다른 팀의 일로 취급한다.
  • 성공 지표만 공개하고 피해와 실패는 숨긴다.
  • 관리자 판단에 반대하기 어렵다.
  • 과도한 근무를 헌신으로 평가한다.
  • 사용자의 권리보다 단기 참여와 매출만 측정한다.
  • 외부 공급자와 자동화 결과를 검증하지 않는다.

책임 있는 문화는 문제를 조기에 제기하고, 불확실성을 인정하며, 사고에서 개인 비난보다 구조적인 개선을 찾는다.

다만 의도적인 위반과 무책임한 행동에 대한 책임까지 없애는 것은 아니다.

교육과 역량

모든 개발자가 전문 보안 분석가나 안전 공학자가 될 필요는 없지만 자신의 작업에 관련된 기본 위험과 책임을 이해해야 한다.

교육에는 다음이 포함될 수 있다.

  • 안전한 코딩과 입력 검증
  • 인증·권한과 비밀 관리
  • 개인정보와 데이터 최소화
  • 위협 모델링
  • 공급망과 외부 패키지
  • 안전 위험과 인간 요인
  • 접근성과 공정성
  • 라이선스와 지식재산권
  • 전문 윤리와 문제 보고
  • 사고와 실제 사례
  • 생성형 인공지능 도구의 책임 있는 사용

일회성 온라인 교육을 완료했다고 역량이 확보되는 것은 아니다. 코드 검토·설계 워크숍과 모의 사고, 실제 프로젝트 피드백으로 지속적으로 학습한다.

위험이 높은 분야에는 자격과 경험을 갖춘 전문 인력을 참여시키고 독립적인 검토를 제공한다.

검토와 승인

보안·안전과 윤리 위험이 큰 결정에는 일반 기능과 다른 검토가 필요할 수 있다.

검토 대상에는 다음이 있다.

  • 새로운 민감 데이터 수집
  • 강한 관리자와 원격 제어 기능
  • 생명과 신체에 영향을 주는 자동화
  • 사용자 행동을 평가하는 알고리즘
  • 암호와 인증 구조
  • 안전 기능의 변경
  • 광범위한 감시와 위치 추적
  • 공개 API와 데이터 공유
  • 인공지능 기반 의사결정
  • 보안 지원 종료
  • 되돌리기 어려운 데이터 변경

승인은 단순한 서명이나 버튼 클릭이 아니라 위험·대안과 증거를 검토하고 잔여 위험에 책임지는 결정이어야 한다.

결정 권한은 피해와 책임을 감당할 수 있는 적절한 조직 수준에 있어야 한다.

독립적인 평가

제품을 만든 팀은 구조와 목적을 잘 이해하지만 자신의 가정과 결함을 놓칠 수 있다.

독립적인 평가는 다음에서 사용될 수 있다.

  • 보안 침투 시험
  • 안전 검증
  • 개인정보 영향 평가
  • 규제와 인증
  • 알고리즘 공정성
  • 소프트웨어 공급망
  • 품질과 구성 감사
  • 윤리 위원회와 연구 검토

외부 평가가 제품의 안전과 윤리를 자동 보장하지는 않는다. 평가 범위와 시점·제공한 자료에 제한이 있을 수 있다.

발견된 문제를 수정하고 운영 변화에 따라 반복 평가해야 한다.

증거와 추적성

보안과 안전 주장에는 검증 가능한 증거가 필요하다.

연결할 수 있는 관계에는 다음이 있다.

  • 위험과 요구사항
  • 요구사항과 설계 통제
  • 설계와 구현
  • 구현과 코드 검토
  • 요구사항과 시험
  • 결함과 수정
  • 릴리스와 산출물
  • 배포와 운영 환경
  • 사고와 개선
  • 잔여 위험과 승인

“보안 검사를 수행했다”는 기록보다 어떤 버전과 범위·도구와 기준으로 수행했으며 어떤 결과를 어떻게 처리했는지가 중요하다.

자동화된 도구 결과도 도구의 버전과 설정·한계를 함께 기록해야 한다.

잔여 위험

모든 위험을 완전히 제거하는 것은 현실적으로 불가능할 수 있다. 통제를 적용한 뒤 남은 위험을 잔여 위험이라고 한다.

잔여 위험을 수용할 때는 다음을 확인한다.

  • 어떤 피해가 여전히 가능한가
  • 누구에게 영향을 주는가
  • 발생 가능성과 불확실성은 무엇인가
  • 추가 통제의 비용과 효과는 무엇인가
  • 사용자가 위험을 알고 선택할 수 있는가
  • 감시와 대응·복구 수단이 있는가
  • 누가 수용 결정을 내릴 권한을 가지는가
  • 언제 다시 평가해야 하는가

개발자가 일정 때문에 임의로 높은 보안·안전 위험을 수용해서는 안 된다.

위험의 피해를 받는 사람과 위험을 수용하는 조직이 다를 수 있으므로 공정성과 책임을 함께 고려한다.

보안·안전과 일정

일정이 촉박할 때 보안·안전과 시험을 축소하면 단기적으로 출시일을 맞출 수 있지만 이후 사고와 수정 비용이 크게 증가할 수 있다.

고정된 날짜에 맞추기 위해 조정할 수 있는 요소에는 다음이 있다.

  • 제공 기능의 범위
  • 사용자와 지역
  • 자동화 수준
  • 출시 단계
  • 비핵심 통합
  • 실험 기능
  • 운영 규모

다음은 단순한 일정 조정 수단으로 취급하기 어렵다.

  • 필수 안전 기능
  • 기본 인증과 권한
  • 개인정보 보호
  • 데이터 무결성
  • 법률과 규제
  • 중요한 복구 수단
  • 알려진 치명적 취약점

일정과 위험의 충돌은 숨기지 않고 의사결정 권한이 있는 이해관계자에게 명확하게 제시해야 한다.

보안·안전과 비용

가장 높은 보호 수준을 모든 기능에 적용하면 제품의 비용과 복잡성이 지나치게 커질 수 있다. 반대로 단기 비용을 줄이기 위해 기본 보호를 생략하면 사고 비용과 사용자 피해가 더 커질 수 있다.

위험 기반 접근에서는 다음을 고려한다.

  • 자산과 피해의 크기
  • 사용 환경과 노출
  • 공격자와 고장 가능성
  • 통제의 효과
  • 개발과 운영 비용
  • 사용자 경험
  • 유지보수와 지원 기간
  • 사고 시 복구 가능성
  • 규제와 사회적 책임

비용 절감의 결과로 위험을 부담하는 주체가 누구인지 확인해야 한다. 조직의 비용은 줄지만 사용자와 사회가 더 큰 위험을 부담할 수 있다.

보안과 공개 소프트웨어

소스 코드의 공개 여부만으로 소프트웨어의 보안성을 판단할 수 없다.

공개 소프트웨어는 여러 사람이 코드를 검토하고 독립적으로 빌드·수정할 수 있는 장점이 있을 수 있다. 그러나 실제 검토자와 유지보수 자원이 부족하거나 배포 패키지와 소스의 관계가 불명확할 수 있다.

비공개 소프트웨어는 공격자가 코드를 보기 어렵게 할 수 있지만 설계의 비밀에만 의존해서는 안 되며 외부 검토와 사용자 검증이 제한될 수 있다.

두 방식 모두 다음이 필요하다.

  • 책임 있는 유지보수
  • 취약점 신고와 대응
  • 안전한 빌드와 배포
  • 의존성 관리
  • 명확한 지원 정책
  • 코드 검토와 시험
  • 사용자에게 필요한 투명성

지원 종료의 책임

제품의 보안과 안전은 배포 후에도 외부 환경과 위협이 바뀌면서 달라진다.

지원 종료에서는 다음을 제공할 수 있다.

  • 종료 날짜와 영향받는 버전
  • 보안 수정 제공 기간
  • 대체 제품과 업그레이드 경로
  • 데이터 내보내기
  • 호환성과 이전 도구
  • 위험 완화 방법
  • 장치와 계정의 폐기
  • 외부 서비스와 키의 종료
  • 장기 보존과 삭제 정책

중요한 장치와 기반 시설이 지원 종료 후에도 계속 사용될 가능성을 고려해야 한다.

사용자가 현실적으로 교체할 수 없는 제품을 충분한 통보와 대안 없이 종료하면 보안·안전 위험이 사용자에게 전가될 수 있다.

서비스 종료와 데이터

서비스 종료 시 개인정보와 사용자의 작업 결과를 보호해야 한다.

다음이 필요할 수 있다.

  • 종료 일정의 사전 통보
  • 표준 형식의 데이터 내보내기
  • 다른 서비스로의 이전
  • 데이터 삭제와 보존 기준
  • 백업과 복제본 처리
  • 계정과 인증 토큰 폐기
  • 외부 공유와 공급자 계약 종료
  • 종료 이후 문의와 지원
  • 법적 의무와 감사

서비스를 종료한 뒤에도 사용자 데이터를 사업 자산으로 무기한 보관하거나 다른 목적으로 사용해서는 안 된다.

보안·안전과 윤리의 통합

보안·안전과 윤리를 각각 별도의 검토 문서로만 관리하면 실제 설계와 구현에서 충돌과 누락이 발생할 수 있다.

통합적인 흐름은 다음과 같이 구성할 수 있다.

  1. 시스템의 목적과 영향을 받는 사람을 식별한다.
  2. 보호할 자산과 안전 위험원을 정의한다.
  3. 공격·고장과 오용 시나리오를 분석한다.
  4. 개인정보·공정성과 접근성 영향을 평가한다.
  5. 보안·안전과 윤리 요구사항을 정의한다.
  6. 설계와 인터페이스·운영 통제로 구현한다.
  7. 독립적인 검토와 시험을 수행한다.
  8. 잔여 위험과 한계를 명시적으로 승인한다.
  9. 배포 뒤 실제 영향과 사고를 감시한다.
  10. 변경과 새로운 위협에 따라 반복 평가한다.
  11. 서비스 종료와 데이터 폐기까지 책임진다.

하나의 결정이 여러 영역에 다른 영향을 줄 수 있다.

  • 상세한 로그는 보안 조사에 도움이 되지만 개인정보 위험을 높일 수 있다.
  • 강한 잠금은 침입을 막지만 비상 탈출을 방해할 수 있다.
  • 자동화는 사람의 실수를 줄이지만 상황 인식과 책임을 약화할 수 있다.
  • 개인화는 사용성을 높일 수 있지만 감시와 조작을 확대할 수 있다.
  • 데이터 공유는 연구와 공익에 도움이 될 수 있지만 재식별 위험을 만들 수 있다.

이러한 상충 관계를 숨기지 않고 영향을 받는 이해관계자와 전문가가 함께 검토해야 한다.

전문적 실무의 지속성

보안·안전과 윤리는 제품 출시 전에 한 번 확인하고 종료되는 활동이 아니다.

새로운 취약점과 공격 기술이 나타나고, 사용자와 데이터 규모·사회적 사용 방식이 변한다. 외부 라이브러리와 운영체제의 지원이 종료되고, 원래 예상하지 않았던 분야에서 제품이 사용될 수도 있다.

따라서 다음을 지속적으로 수행한다.

  • 위협과 위험 재평가
  • 취약점과 사고 감시
  • 보안 업데이트
  • 안전 데이터와 현장 사고 분석
  • 개인정보 처리와 보존 검토
  • 알고리즘 결과와 집단별 영향 평가
  • 접근성과 사용자 피드백
  • 외부 구성 요소와 공급자 검토
  • 전문 교육
  • 정책과 윤리 원칙 개선
  • 지원 종료와 제품 폐기 계획

전문가는 자신이 직접 작성한 코드뿐 아니라 설계 결정·외부 도구와 조직의 압력이 사용자와 사회에 미치는 영향을 고려해야 한다.

좋은 소프트웨어 공학은 프로그램이 요구한 기능을 수행하는 데서 끝나지 않는다. 공격과 고장에 견디고, 실패가 사람에게 미치는 피해를 제한하며, 사용자의 권리와 자율성을 존중하고, 위험과 한계를 정직하게 설명할 수 있어야 한다.

보안은 신뢰할 수 없는 행위와 환경에서도 자산과 서비스를 보호하고, 안전은 시스템의 동작과 실패가 허용할 수 없는 피해로 이어지지 않게 한다. 전문 윤리는 이러한 기술적 결정을 누구를 위해 어떤 책임으로 내려야 하는지 판단하는 기준을 제공한다.

표준과 지식 체계

소프트웨어 공학은 요구사항·설계·구현·시험·배포와 운영처럼 서로 다른 전문 활동을 하나의 생명주기 안에서 연결한다. 조직과 산업마다 사용하는 기술과 절차가 다르기 때문에, 같은 용어와 산출물·책임·품질 수준을 공유하지 않으면 공급자와 발주자, 개발자와 시험자·운영자 사이에 해석 차이가 발생할 수 있다.

표준(Standard)은 제품·프로세스·서비스와 활동에 반복적으로 적용할 수 있도록 요구사항·규칙·지침이나 특성을 합의된 형태로 정리한 문서이다. 표준은 소프트웨어 생명주기 프로세스, 요구사항 작성, 아키텍처 기술, 시험·품질 평가, 유지보수, 보안과 전문 역량 등 다양한 범위를 다룬다.

지식 체계(Body of Knowledge)는 특정 전문 분야에서 일반적으로 인정되는 개념·활동·기법과 관련 지식의 범위를 구조적으로 분류한 자료이다. 지식 체계는 모든 내용을 하나의 교과서처럼 상세히 설명하기보다 분야의 경계를 정의하고, 주요 주제와 관련 문헌·표준을 연결하는 지도의 역할을 한다.

표준과 지식 체계는 서로 관련되지만 목적이 다르다.

  • 표준은 특정 범위에서 따라야 할 요구사항이나 공통 지침을 제공할 수 있다.
  • 지식 체계는 전문 분야에서 알아야 할 주제와 개념을 분류한다.
  • 방법론은 실제 프로젝트에서 활동을 수행하는 구체적인 접근을 제공한다.
  • 프로세스 모델은 활동의 순서와 반복·관계를 구성한다.
  • 프레임워크는 여러 개념과 실무를 조합할 기본 구조를 제공한다.
  • 규정은 법률이나 규제 기관에 의해 준수가 강제될 수 있다.
  • 조직의 절차는 표준과 방법론을 실제 환경에 맞게 구체화한다.

표준을 사용한다고 모든 프로젝트가 같은 개발 절차와 문서를 가져야 하는 것은 아니다. 표준이 정의하는 목적·결과와 요구사항을 유지하면서 제품의 규모·위험·계약과 생명주기 모델에 맞게 적용 범위를 조정할 수 있다.

ISO는 국제 표준을 여러 국가의 전문가가 합의하여 만든 문서로 설명하며, 표준은 제품을 만들거나 프로세스를 관리하고 서비스를 제공하는 여러 활동에 공통 기준을 제시한다.[131]

IEEE Computer Society의 SWEBOK Guide는 소프트웨어 공학 이론과 실무의 상호작용에서 형성된 일반적으로 인정되는 합의 기반 지식을 정리하며, SWEBOK V4.0은 18개의 지식 영역과 표준에 관한 부록으로 구성된다.[132][133]

표준의 목적

소프트웨어 공학 표준은 다음과 같은 목적에 사용될 수 있다.

  • 서로 다른 조직과 역할이 공통 용어를 사용하게 한다.
  • 생명주기에서 필요한 활동과 결과를 빠뜨리지 않도록 한다.
  • 발주자와 공급자 사이의 책임과 인수 기준을 정의한다.
  • 제품과 프로세스의 품질을 비교·평가할 기준을 제공한다.
  • 규제와 계약 준수를 위한 근거를 제공한다.
  • 조직의 절차와 도구 체계를 설계할 참조점을 제공한다.
  • 전문 교육과 자격 체계의 공통 범위를 정한다.
  • 여러 공급자와 구성 요소를 통합할 때 호환성을 높인다.
  • 감사와 독립적인 평가에서 사용할 객관적인 기준을 제공한다.
  • 프로젝트와 조직 사이에서 지식과 경험을 이전할 수 있게 한다.

표준의 목적은 모든 프로젝트를 같은 방식으로 만드는 데 있지 않다. 프로젝트마다 다른 활동을 수행하더라도 결과의 의미와 책임, 품질 기준을 공통으로 설명할 수 있게 하는 데 있다.

예를 들어 웹 서비스와 항공 제어 소프트웨어는 같은 생명주기 표준을 참고할 수 있지만 필요한 문서·독립성·추적성과 시험 강도는 크게 다를 수 있다.

표준의 종류

소프트웨어 공학에서 사용되는 표준은 다루는 대상과 강제 수준에 따라 여러 종류로 구분할 수 있다.

용어 표준

용어 표준은 개념과 정의를 통일한다.

같은 단어가 조직마다 다른 의미로 사용되면 요구사항과 계약·감사 결과를 정확히 비교하기 어렵다. 예를 들어 검증·확인, 결함·오류와 실패, 구성 항목과 기준선 같은 용어는 일상적인 의미와 전문적인 정의가 다를 수 있다.

ISO/IEC/IEEE 24765:2017은 시스템 및 소프트웨어 공학 전반에 적용되는 공통 어휘를 제공하고, 정의의 출처가 되는 관련 표준을 연결한다.[134]

프로세스 표준

프로세스 표준은 생명주기에서 수행할 수 있는 프로세스와 목적·결과를 정의한다.

프로세스 표준은 특정한 폭포수·애자일 방법론이나 조직도를 그대로 규정하지 않을 수 있다. 프로젝트가 선택한 생명주기 안에서 필요한 결과가 만들어지도록 공통 프로세스 구조를 제공한다.

제품과 산출물 표준

제품과 산출물 표준은 요구사항 문서·아키텍처 기술·시험 문서와 사용자 정보처럼 특정 산출물의 구조·내용과 품질을 정의한다.

표준을 따른 산출물도 내용이 잘못되면 품질이 낮을 수 있다. 형식을 만족하는 것과 실제 요구·설계를 올바르게 표현하는 것은 구분해야 한다.

품질 표준

품질 표준은 제품·데이터·서비스와 프로세스의 품질 모델·측정과 평가 방법을 제공한다.

품질 특성의 명칭만 사용하는 것으로 충분하지 않으며, 프로젝트에서 중요한 특성을 구체적인 요구와 측정 기준으로 변환해야 한다.

관리 체계 표준

관리 체계 표준은 조직이 품질·보안과 서비스 등의 정책·책임·위험 관리와 지속적 개선 체계를 수립하기 위한 요구사항을 정의한다.

관리 체계 인증은 특정 제품이 결함이나 취약점이 없음을 보증하는 것과 다르다. 정의된 범위 안에서 조직의 관리 체계가 표준 요구사항을 충족하는지를 평가한다.

인터페이스와 기술 표준

인터페이스 표준은 파일 형식·프로토콜·프로그래밍 언어·문자 인코딩과 API 같은 기술적 호환성을 정의한다.

이러한 표준은 소프트웨어 공학 프로세스 표준과 직접적인 목적은 다르지만, 여러 구현체와 시스템이 상호운용되는 기반을 제공한다.

전문 역량 표준

전문 역량 표준은 소프트웨어 및 시스템 공학 전문가의 지식·기술·역량을 설명하거나 자격 인증 체계를 비교·평가할 기준을 제공한다.

ISO/IEC 24773 표준군은 소프트웨어 및 시스템 공학 전문가 자격 체계에 사용할 일반 요구사항과 지식·기술·역량 기술 지침을 제공한다.[135]

국제 표준과 사실상 표준

국제 표준은 ISO·IEC와 IEEE 같은 표준화 기구가 공개된 절차와 합의를 통해 제정한 문서이다.

국가 표준은 각 국가의 표준화 기관이 제정하거나 국제 표준을 채택한 문서이다.

산업 표준은 특정 산업 협회·컨소시엄과 전문 단체가 만든 공통 규격이다.

사실상 표준은 공식적인 국제 표준으로 제정되지 않았더라도 시장과 개발 공동체에서 널리 사용되어 실질적인 기준이 된 기술과 방식이다.

예를 들어 특정 버전 관리 시스템이나 데이터 교환 형식·프레임워크가 널리 사용되면 사실상 표준의 역할을 할 수 있다. 그러나 널리 사용된다는 사실만으로 공개성·중립성과 장기적인 호환성이 보장되지는 않는다.

공식 표준도 실제 구현과 도구·교육이 부족하면 현장에서 거의 사용되지 않을 수 있다. 표준의 채택 여부는 기술적 완성도뿐 아니라 생태계와 도구 지원·비용과 기존 시스템에 영향을 받는다.

규범적 내용과 참고 내용

표준 문서에서는 따라야 할 요구사항과 이해를 돕기 위한 설명을 구분할 수 있다.

규범적 내용은 표준 준수를 주장하기 위해 충족해야 하는 요구사항과 규칙을 포함한다.

참고 내용은 예시·배경·권고와 해설처럼 표준의 이해와 적용을 돕지만 직접적인 준수 조건이 아닌 내용을 포함한다.

표준의 본문에 사용되는 표현도 의미가 다를 수 있다.

  • shall은 반드시 충족해야 하는 요구사항을 나타낼 수 있다.
  • should는 권고를 나타낼 수 있다.
  • may는 허용을 나타낼 수 있다.
  • can은 가능성과 능력을 나타낼 수 있다.

번역된 표준과 조직 절차에서는 이러한 강제 수준이 흐려질 수 있으므로 원문의 의미와 적용 정책을 확인해야 한다.

표준 준수

표준 준수 또는 적합성은 제품·프로세스·조직과 산출물이 지정된 표준의 요구사항을 충족하는 상태를 뜻한다.

준수를 주장하려면 다음을 명확히 해야 한다.

  • 어떤 표준과 판본을 적용했는가
  • 표준의 어떤 범위와 조항을 적용했는가
  • 적용 대상 제품·프로젝트와 조직은 무엇인가
  • 허용된 선택과 조정은 무엇인가
  • 요구사항을 충족한다는 증거는 무엇인가
  • 누가 평가했고 어떤 독립성을 가지는가
  • 예외와 미준수 항목은 무엇인가
  • 표준이 개정되면 언제 전환할 것인가

“ISO를 준수한다”와 같은 표현은 어떤 표준과 범위를 뜻하는지 알 수 없어 의미가 부족하다.

표준 준수는 제품이 모든 상황에서 고품질이고 안전하다는 절대적인 보증이 아니다. 표준의 범위와 요구사항 안에서 정해진 조건을 충족했다는 의미이다.

인증과 인정

인증은 독립된 기관이 제품·프로세스·관리 체계와 사람의 자격이 지정된 요구사항을 충족한다고 확인하는 활동이다.

인정은 인증이나 시험·검사를 수행하는 기관이 해당 활동을 수행할 능력과 공정성을 갖추었는지를 권한 있는 기관이 확인하는 체계이다.

ISO는 국제 표준을 개발하지만 일반적으로 조직과 제품을 직접 인증하지 않는다. 인증은 별도의 인증 기관이 수행하며, 일부 산업에서는 법률이나 계약에 따라 인증이 요구될 수 있다.[136]

모든 표준이 인증을 목적으로 만들어진 것은 아니다. 지침과 어휘·지식 체계는 조직이 자발적으로 활용할 수 있지만 공식 인증 대상이 아닐 수 있다.

인증서의 존재만 확인하지 않고 다음을 함께 봐야 한다.

  • 인증의 적용 범위
  • 인증 기관과 인정 상태
  • 적용된 표준 판본
  • 인증이 유효한 기간
  • 제외된 사업장·제품과 프로세스
  • 지속적인 감시와 갱신 여부

표준의 조정

조정(Tailoring)은 표준이나 공통 프로세스를 특정 조직·프로젝트와 제품의 특성에 맞게 선택·구체화하는 활동이다.

조정에서는 다음을 결정할 수 있다.

  • 적용할 프로세스와 활동
  • 생략하거나 결합할 활동
  • 역할과 책임
  • 산출물의 형식과 상세 수준
  • 검토와 승인 수준
  • 필요한 독립성
  • 도구와 자동화
  • 추적성과 보존 기간
  • 공급자와 외부 조직의 책임
  • 반복과 기준선의 주기

조정은 필요한 요구사항을 임의로 삭제하는 일이 아니다. 표준의 목적과 요구 결과·제품의 위험을 이해하고, 변경 이유와 대체 통제를 기록해야 한다.

소규모 내부 도구에 대규모 안전 시스템과 같은 문서와 승인을 요구하면 비용이 지나치게 커진다. 반대로 사람의 생명·중요 기반 시설에 영향을 주는 시스템에 일반 웹 서비스 수준의 통제만 적용하면 위험을 다루기 어렵다.

ISO/IEC/IEEE 24748-3:2020은 ISO/IEC/IEEE 12207의 소프트웨어 생명주기 프로세스를 조직과 프로젝트에서 정의·통제하고 개선하기 위한 적용 지침을 제공하며, 여러 생명주기 모델에 적합한 접근을 설명한다.[137]

표준의 판본과 개정

표준은 기술과 실무·법률 환경의 변화에 따라 개정되고 이전 판본이 폐기될 수 있다.

표준을 적용할 때는 다음을 관리해야 한다.

  • 사용 중인 정확한 판본
  • 개정판의 변경 내용
  • 계약과 규제에서 지정한 판본
  • 관련 표준 사이의 호환성
  • 전환 기간
  • 조직 절차와 도구의 수정
  • 기존 인증과 증거의 유효성
  • 교육과 공급자에 대한 영향

최신 판본이 공개되었다고 모든 프로젝트가 즉시 전환해야 하는 것은 아니다. 계약과 인증·도구와 기존 기준선에 따라 계획적으로 전환할 수 있다.

반대로 오래된 판본을 장기간 유지하면 새로운 보안·품질과 기술 환경이 반영되지 않을 수 있다.

표준 번호만 기록하지 않고 발행 연도를 함께 표시하면 어떤 판본을 뜻하는지 분명해진다.

표준 사이의 관계

소프트웨어 공학 표준은 하나의 문서가 모든 영역을 다루기보다 여러 표준이 역할을 나누고 서로 참조한다.

예를 들어 다음과 같이 연결할 수 있다.

  • 생명주기 표준이 전체 프로세스 틀을 제공한다.
  • 요구사항 표준이 요구사항 공학 활동과 산출물을 구체화한다.
  • 아키텍처 표준이 아키텍처 기술의 구조를 정의한다.
  • 시험 표준이 시험 프로세스·문서와 기법을 제공한다.
  • 품질 표준이 품질 모델과 평가 기준을 제공한다.
  • 유지보수 표준이 배포 이후의 변경 활동을 구체화한다.
  • 보안과 안전 표준이 특정 위험에 대한 추가 요구를 제공한다.
  • 용어 표준이 여러 문서에서 사용하는 정의를 연결한다.

표준을 개별 문서로만 읽으면 중복과 차이가 모순처럼 보일 수 있다. 각 표준의 범위와 상위·하위 관계, 적용 대상을 확인해야 한다.

ISO, IEC와 IEEE

소프트웨어 공학의 국제 표준에는 ISO·IEC와 IEEE가 함께 참여하는 경우가 많다.

ISO는 여러 산업과 관리·서비스 분야의 국제 표준을 개발하는 비정부 국제기구이다.

IEC는 전기·전자와 관련 기술의 국제 표준화를 담당한다.

IEEE는 전기·전자·컴퓨터와 소프트웨어 분야의 전문 단체이며 여러 기술·공학 표준을 개발한다.

정보 기술 분야의 많은 ISO와 IEC 공동 표준은 ISO/IEC JTC 1에서 개발된다. 시스템 및 소프트웨어 공학 분야는 주로 그 하위 위원회인 ISO/IEC JTC 1/SC 7에서 다룬다.

SC 7은 생명주기·요구사항·아키텍처·시험·품질·전문 역량과 사용자 정보 등 시스템 및 소프트웨어 공학에 관련된 다수의 표준을 관리한다.[138]

표준 번호에 ISO/IEC/IEEE가 함께 표시된 경우 세 조직의 공동 표준으로 발행된 것을 뜻한다.

ISO/IEC/IEEE 12207

ISO/IEC/IEEE 12207은 소프트웨어 생명주기 프로세스를 위한 공통 틀을 제공하는 중심 표준이다.

ISO/IEC/IEEE 12207:2017은 소프트웨어 시스템·제품과 서비스를 위한 생명주기 프로세스의 공통 구조와 용어를 제공하며, 조직과 프로젝트의 소프트웨어 생명주기 프로세스를 정의·통제하고 개선하는 데 사용할 수 있다.[139]

이 표준은 소프트웨어를 획득하거나 공급하고, 개발·운영·유지보수와 폐기하는 조직에 적용할 수 있다.

프로세스는 대체로 다음과 같은 범주를 포괄한다.

  • 계약과 조직 사이의 합의
  • 조직의 프로젝트 지원
  • 기술적 관리
  • 요구사항과 설계·구현
  • 통합·검증과 확인
  • 전환·운영과 유지보수
  • 구성·정보와 품질 관리
  • 위험·의사결정과 측정
  • 생명주기 모델과 인프라

12207은 모든 활동을 한 번씩 순차적으로 수행하도록 요구하는 폭포수 모델이 아니다. 프로세스는 반복적·점진적·병렬적으로 적용할 수 있으며 선택한 생명주기 모델에 맞게 조정된다.

ISO/IEC/IEEE 15288

ISO/IEC/IEEE 15288은 사람이 만든 시스템 전체의 생명주기 프로세스를 다룬다.

ISO/IEC/IEEE 15288:2023은 시스템의 개념 형성부터 개발·생산·이용·지원과 폐기까지 전체 생명주기에 적용할 수 있는 공통 프로세스 틀을 제공한다. 프로세스는 시스템과 그 구성 요소에 반복적·병행적·재귀적으로 적용할 수 있다.[140]

소프트웨어가 하드웨어·사람·운영 절차와 함께 더 큰 시스템의 일부라면 12207과 15288을 함께 사용할 수 있다.

예를 들어 자동차의 제어 소프트웨어는 독립된 프로그램으로만 평가할 수 없다. 센서·제어기와 기계 장치, 운전자·정비 절차와 외부 통신을 포함한 전체 시스템의 위험과 요구를 분석해야 한다.

12207과 15288은 대응되는 프로세스에서 같은 목적과 결과를 공유하도록 조정되어 있지만, 소프트웨어 공학과 시스템 공학에 필요한 활동과 작업의 상세 내용은 다를 수 있다.[141]

생명주기 관리 표준군

ISO/IEC/IEEE 24748 표준군은 시스템과 소프트웨어 생명주기 관리에 관한 적용 지침을 제공한다.

주요 문서에는 다음이 포함된다.

  • ISO/IEC/IEEE 24748-1은 시스템과 소프트웨어 생명주기 관리의 일반 지침을 제공한다.
  • ISO/IEC/IEEE 24748-2는 ISO/IEC/IEEE 15288의 적용 지침을 제공한다.
  • ISO/IEC/IEEE 24748-3은 ISO/IEC/IEEE 12207의 적용 지침을 제공한다.
  • ISO/IEC/IEEE 24748-4는 시스템 공학 관리 계획을 다룬다.
  • ISO/IEC/IEEE 24748-5는 소프트웨어 개발 계획을 다룬다.
  • ISO/IEC/IEEE 24748-6은 시스템과 소프트웨어 통합을 다룬다.
  • ISO/IEC/IEEE 24748-7000은 시스템 설계 과정에서 윤리적 문제를 다루는 모델 프로세스를 제공한다.

24748 표준군은 생명주기 프로세스의 목록을 반복하기보다 조직과 프로젝트가 프로세스를 실제 계획·적용하고 조정하는 방법을 지원한다.[142]

ISO/IEC/IEEE 29148

ISO/IEC/IEEE 29148은 시스템과 소프트웨어의 요구사항 공학을 다룬다.

ISO/IEC/IEEE 29148:2018은 요구사항 공학 활동에서 구현할 프로세스와 요구사항 관련 정보 항목의 내용, 요구사항의 특성과 형식을 정의한다.[143]

이 표준은 다음과 같은 내용을 다룬다.

  • 이해관계자 요구와 시스템 요구사항
  • 소프트웨어 요구사항
  • 요구사항의 도출과 분석
  • 요구사항의 표현
  • 검증과 확인
  • 추적성과 변경
  • 요구사항 명세의 내용
  • 요구사항 문장의 품질

29148을 사용한다고 모든 요구사항을 하나의 거대한 문서로 작성해야 하는 것은 아니다. 백로그·모델·인터페이스 명세와 자동 수용 시험처럼 여러 형식으로 관리할 수 있지만 필요한 의미와 추적성을 유지해야 한다.

ISO/IEC/IEEE 42010

ISO/IEC/IEEE 42010은 소프트웨어·시스템과 기업 등의 아키텍처를 표현하는 아키텍처 기술의 구조를 다룬다.

ISO/IEC/IEEE 42010:2022는 소프트웨어·시스템·기업·제품군과 서비스 등 여러 대상의 아키텍처 기술 구조와 표현에 관한 요구사항을 정의한다. 아키텍처 자체와 이를 표현한 아키텍처 기술을 구분하며, 관점·뷰·모델 종류와 아키텍처 기술 프레임워크 및 언어를 다룬다.[144]

표준의 중심 개념에는 다음이 있다.

  • 관심 대상
  • 이해관계자
  • 관심사
  • 아키텍처 기술
  • 관점
  • 모델과 모델 종류
  • 아키텍처 결정
  • 대응 관계와 일관성
  • 아키텍처 기술 프레임워크
  • 아키텍처 기술 언어

42010은 특정한 계층형·마이크로서비스와 같은 아키텍처 스타일을 요구하지 않는다. 여러 이해관계자의 관심사를 어떤 관점과 모델로 설명하고 서로 일관되게 유지할지를 정의한다.

ISO/IEC/IEEE 29119

ISO/IEC/IEEE 29119 표준군은 소프트웨어 시험의 공통 개념과 프로세스·문서화 및 시험 기법을 다룬다.

29119 표준군은 조직·프로젝트와 생명주기 모델에 관계없이 여러 형태의 소프트웨어 시험에 사용할 수 있는 국제적으로 합의된 체계를 제공한다.[145]

주요 구성은 다음과 같다.

  • ISO/IEC/IEEE 29119-1은 시험의 일반 개념을 정의한다.
  • ISO/IEC/IEEE 29119-2는 조직·프로젝트와 동적 시험 프로세스를 정의한다.
  • ISO/IEC/IEEE 29119-3은 시험 문서와 시험 산출물의 형식을 다룬다.
  • ISO/IEC/IEEE 29119-4는 시험 설계 기법을 다룬다.
  • ISO/IEC/IEEE 29119-5는 키워드 기반 시험을 다룬다.
  • 기술 보고서와 추가 문서는 AI 기반 시스템·모델 기반 시험 등 특정 분야를 다룬다.

ISO/IEC/IEEE 29119-1:2022는 표준군의 일반 개념과 핵심 용어를 정의한다.[146]

29119는 수동 시험과 자동 시험, 기능 및 비기능 시험과 스크립트형·탐색적 접근을 모두 배제하지 않는다. 조직은 위험과 규제·개발 방식에 맞게 필요한 시험 프로세스와 산출물을 조정할 수 있다.

ISO/IEC 25000 SQuaRE

SQuaRE(Systems and Software Quality Requirements and Evaluation)는 시스템·소프트웨어·데이터와 서비스의 품질 요구사항과 평가를 지원하는 ISO/IEC 25000 표준군이다.

SQuaRE 표준군은 여러 문서를 목적에 따라 조합하여 사용할 수 있도록 구성되며, 공통 모델과 용어·품질 요구·측정과 평가를 연결한다.[147]

주요 영역에는 다음이 있다.

  • 품질 관리
  • 품질 모델
  • 품질 측정
  • 품질 요구사항
  • 품질 평가
  • 특정 분야의 확장

ISO/IEC 25000:2014는 SQuaRE 표준군의 전체 구조와 공통 참조 모델·정의를 안내한다.[148]

ISO/IEC 25010

ISO/IEC 25010:2023은 ICT와 소프트웨어 제품의 품질을 명세·측정하고 평가하기 위한 제품 품질 모델을 정의한다.[149]

제품 품질 모델은 다음과 같은 상위 특성을 포함한다.

  • 기능 적합성
  • 성능 효율성
  • 호환성
  • 상호작용 능력
  • 신뢰성
  • 보안
  • 유지보수성
  • 유연성
  • 안전성

품질 모델의 특성을 그대로 요구사항 목록으로 복사해서는 안 된다. 제품에 중요한 특성을 선택하고 실제 사용 조건·목표와 측정 방법을 정의해야 한다.

데이터와 서비스 품질

SQuaRE에는 소프트웨어 제품뿐 아니라 데이터·IT 서비스와 클라우드 서비스의 품질을 다루는 문서도 포함된다.

데이터 중심 시스템과 인공지능에서는 소프트웨어 코드의 품질만으로 전체 결과를 설명하기 어렵다. 데이터의 정확성·완전성·일관성과 대표성, 서비스의 가용성과 지원 품질 등을 별도로 평가할 수 있다.

ISO/IEC/IEEE 14764

ISO/IEC/IEEE 14764는 소프트웨어 유지보수를 위한 지침을 제공한다.

ISO/IEC/IEEE 14764:2022는 ISO/IEC/IEEE 12207의 유지보수 프로세스·활동과 작업을 바탕으로 소프트웨어 유지보수의 계획·분석·구현·검토·이전과 종료를 구체화한다.[150]

유지보수는 결함 수정만이 아니라 다음을 포함한다.

  • 수정 유지보수
  • 적응 유지보수
  • 완전 유지보수
  • 예방 유지보수
  • 이전
  • 소프트웨어 종료
  • 유지보수 조직과 계약
  • 변경의 영향 분석
  • 구성과 문서 관리

유지보수 표준은 새로 개발하는 소프트웨어에도 중요하다. 초기 설계와 구현이 유지보수 가능성을 결정하기 때문이다.

정보 보안 표준

소프트웨어 보안은 제품 수준의 설계·구현뿐 아니라 조직의 관리 체계와 운영 위험 관리에 연결된다.

ISO/IEC 27001

ISO/IEC 27001:2022는 조직이 정보 보안 위험을 관리하기 위한 정보 보안 관리 시스템을 수립·구현·유지하고 지속적으로 개선하기 위한 요구사항을 정의한다.[151]

ISO/IEC 27001은 특정 프로그래밍 언어와 암호 알고리즘을 정하는 제품 개발 표준이 아니다. 조직의 위험 평가·정책·책임과 통제 체계를 관리한다.

NIST SSDF

NIST SP 800-218의 Secure Software Development Framework는 소프트웨어 취약점과 그 영향을 줄이기 위한 보안 개발 관행을 제공한다.

SSDF는 다음과 같은 상위 그룹으로 구성된다.

  • 조직의 준비
  • 소프트웨어의 보호
  • 안전한 소프트웨어 생산
  • 취약점 대응

SSDF는 특정 개발 방법론을 대체하지 않으며 기존 생명주기와 조직 프로세스에 보안 활동을 통합할 수 있도록 설계되었다.[152]

NIST 문서는 미국 정부 기관에서 만들어졌지만 소프트웨어 공급망과 보안 개발의 실무 기준으로 국제적으로도 참고된다.

기능 안전 표준

안전 관련 소프트웨어에는 일반 품질 표준 외에 산업별 기능 안전 표준이 적용될 수 있다.

IEC 61508

IEC 61508은 전기·전자와 프로그램 가능 전자 안전 관련 시스템의 기능 안전을 위한 기본 표준이다.

이 표준은 위험 기반 접근을 사용하여 안전 기능과 필요한 안전 무결성 수준을 정의하고, 개념부터 설계·구현·검증·운영과 폐기까지 안전 생명주기를 다룬다.[153]

IEC 61508-3은 안전 관련 시스템의 소프트웨어와 개발 지원 도구에 관한 요구사항을 구체화한다.[154]

분야별 파생 표준

IEC 61508을 기반으로 하거나 유사한 원칙을 사용하는 분야별 표준에는 자동차·철도·산업 공정과 기계·의료 장비 등의 표준이 있다.

각 분야는 위험과 운영 환경이 다르므로 같은 소프트웨어라도 적용되는 요구·증거와 독립성 수준이 달라질 수 있다.

일반적인 소프트웨어 공학 표준을 준수했다고 특정 산업의 기능 안전 요구를 자동으로 충족하는 것은 아니다.

품질 관리 표준

ISO 9001

ISO 9001은 조직의 품질 관리 시스템에 관한 일반 요구사항을 정의한다.

소프트웨어 조직도 ISO 9001을 적용할 수 있지만, 이 표준은 소프트웨어 생명주기·코딩과 시험의 상세 기법을 직접 정의하지 않는다.

조직은 고객 요구와 품질 정책·프로세스와 책임, 성과 평가와 지속적 개선을 관리하고, 소프트웨어 공학의 상세 활동에는 12207·29119와 SQuaRE 같은 분야별 표준을 함께 사용할 수 있다.

ISO 9001 인증은 특정 소프트웨어 제품이 결함 없이 작동한다는 제품 인증이 아니다.

프로세스 평가

조직은 소프트웨어 및 시스템 공학 프로세스의 수행 능력과 성숙도를 평가할 수 있다.

ISO/IEC 33000 표준군은 프로세스 평가의 개념·요구사항과 측정 체계를 제공하며, 이전의 ISO/IEC 15504 표준군을 계승한다.

프로세스 평가는 다음과 같은 목적에 사용할 수 있다.

  • 현재 프로세스의 강점과 약점 파악
  • 공급자 평가
  • 개선 우선순위 결정
  • 계약과 위험 관리
  • 여러 조직의 공통 기준 마련

프로세스 수준이 높다는 사실이 개별 제품의 품질을 자동으로 보장하지는 않는다. 잘 정의된 프로세스를 형식적으로 수행하면서 실제 제품의 결함과 사용자 문제를 놓칠 수도 있다.

반대로 소규모 팀이 공식적인 성숙도 평가 없이도 우수한 제품을 만들 수 있다. 다만 팀이 성장하고 규제·공급망이 복잡해지면 개인 경험에만 의존하기 어려워진다.

CMMI

CMMI(Capability Maturity Model Integration)는 조직의 개발·서비스와 공급자 관리 프로세스를 평가하고 개선하기 위한 모델이다.

CMMI는 ISO 국제 표준은 아니지만 소프트웨어와 시스템 개발 조직에서 널리 알려진 프로세스 개선 체계이다.

성숙도 모델은 일반적으로 개별 활동의 존재뿐 아니라 조직 전체에서 프로세스가 관리·측정되고 지속적으로 개선되는지를 평가한다.

CMMI 등급을 목표 자체로 삼으면 평가를 위한 문서와 절차만 증가할 수 있다. 실제 품질·전달과 사용자 성과가 개선되는지를 함께 확인해야 한다.

표준과 규제

일부 산업에서는 표준 준수가 자발적인 선택이 아니라 법률·규제·조달과 계약의 요구가 될 수 있다.

규제 대상에는 다음이 포함될 수 있다.

  • 의료 기기
  • 항공과 철도
  • 자동차
  • 원자력과 에너지
  • 금융
  • 개인정보
  • 통신
  • 정부와 국방
  • 중요 기반 시설
  • 산업 제어와 기계

규제 기관은 특정 표준을 직접 요구하거나, 표준을 안전성과 품질을 입증하는 인정된 방법으로 사용할 수 있다.

표준을 따르지 않는 다른 방법이 허용되더라도 동등하거나 더 높은 수준의 안전과 통제를 입증해야 할 수 있다.

여러 국가에 제품을 제공하면 서로 다른 규제와 표준 판본·인증을 동시에 관리해야 한다.

계약과 조달에서의 표준

발주자와 공급자는 계약에서 적용할 표준과 산출물·검토와 인수 조건을 지정할 수 있다.

계약에는 다음을 명확히 해야 한다.

  • 적용할 표준과 판본
  • 준수 범위
  • 조정과 예외 절차
  • 제출할 산출물
  • 검토와 승인 권한
  • 추적성과 기록
  • 시험과 인수 기준
  • 외부 구성 요소와 공급망
  • 유지보수와 지원
  • 감사와 자료 접근
  • 지식재산권과 사용 권한
  • 프로젝트 종료 뒤의 보존

계약에서 표준 번호만 나열하고 실제 적용 범위를 정하지 않으면 공급자와 발주자가 서로 다른 수준의 산출물을 예상할 수 있다.

표준의 모든 산출물을 기계적으로 요구하면 비용이 증가하고 실제 위험 관리보다 문서 작성에 집중하게 될 수 있다.

표준과 애자일 개발

표준 기반 개발과 애자일 개발은 반드시 반대되는 개념이 아니다.

생명주기 표준은 필요한 프로세스 목적과 결과를 정의하며, 애자일 방법은 이를 짧은 반복과 지속적인 피드백으로 수행할 수 있다.

예를 들어 다음과 같이 적용할 수 있다.

  • 요구사항 기준선 대신 버전 관리되는 제품 백로그와 수용 기준을 사용한다.
  • 긴 설계 문서 대신 중요한 아키텍처 결정과 여러 뷰를 지속적으로 관리한다.
  • 별도의 시험 단계 대신 모든 반복에서 자동 시험과 품질 검토를 수행한다.
  • 릴리스 직전 구성 감사를 자동화된 파이프라인과 불변 산출물로 지원한다.
  • 정기적인 프로세스 개선을 회고와 지표 분석에 연결한다.
  • 각 증분에서 요구사항·코드·시험과 릴리스의 추적성을 유지한다.

표준이 요구하는 것은 특정 문서 양이 아니라 필요한 정보와 책임·증거인 경우가 많다.

규제 프로젝트에서도 반복적·점진적 개발을 사용할 수 있지만 각 증분의 기준선과 추적성·독립 검토와 최종 인증 조건을 관리해야 한다.

표준과 DevOps

DevOps와 지속적 전달은 개발과 운영을 연결하고 자동화를 통해 빠른 피드백을 제공한다.

표준의 요구를 자동화된 도구 체계로 구현할 수 있다.

  • 버전 관리가 구성 식별과 변경 이력을 제공한다.
  • 코드 검토가 독립적인 기술 검토를 지원한다.
  • 지속적 통합이 빌드·정적 분석과 시험을 반복한다.
  • 아티팩트 저장소가 기준선과 릴리스 산출물을 보존한다.
  • SBOM과 출처 증명이 공급망 기록을 제공한다.
  • 배포 자동화가 승인된 산출물과 환경을 연결한다.
  • 관찰 도구가 운영 품질과 사건을 측정한다.
  • 정책 코드화가 일부 준수 조건을 자동 판정한다.

자동화된 증거가 존재하더라도 의미와 적합성을 사람이 검토해야 한다. 시험이 통과했다는 사실만으로 시험 범위와 요구사항이 올바르다는 것은 아니다.

표준과 오픈소스 소프트웨어

오픈소스 프로젝트도 표준을 적용하거나 사실상 표준을 형성할 수 있다.

공개 개발 환경에서는 다음 요소가 표준화의 역할을 할 수 있다.

  • 공개된 기여 규칙
  • 코드 형식과 API 정책
  • 버전과 호환성 정책
  • 코드 검토
  • 자동 시험
  • 보안 신고와 릴리스 정책
  • 공개 파일 형식과 프로토콜
  • 거버넌스와 의사결정 절차

공개된 구현이 널리 사용되면 다른 구현이 따라야 하는 사실상의 기준이 될 수 있다.

그러나 하나의 구현체의 동작을 공식 명세와 동일하게 취급하면 구현의 결함과 우연한 동작까지 호환성 요구로 고정될 수 있다.

가능한 경우 명세와 시험 묶음·참조 구현의 역할을 구분한다.

지식 체계

지식 체계는 전문 분야에서 일반적으로 인정되는 지식의 범위와 구조를 설명한다.

지식 체계는 다음과 같은 목적을 가진다.

  • 분야의 경계와 핵심 주제를 정의한다.
  • 교육과 훈련 과정의 기초를 제공한다.
  • 전문 자격과 역량 모델을 지원한다.
  • 연구와 실무 사이의 공통 언어를 제공한다.
  • 인접 분야와의 관계를 설명한다.
  • 표준과 주요 문헌을 연결한다.
  • 개인과 조직의 지식 격차를 분석하게 한다.
  • 분야가 발전하면서 새로운 주제를 반영한다.

지식 체계가 특정한 방법론과 도구를 공식적인 정답으로 지정하는 것은 아니다. 널리 인정된 개념과 실무를 정리하되 서로 다른 접근과 연구 결과를 포함할 수 있다.

SWEBOK

SWEBOK(Guide to the Software Engineering Body of Knowledge)은 IEEE Computer Society가 발행하는 소프트웨어 공학 지식 체계이다.

SWEBOK는 소프트웨어 공학 이론과 실무의 상호작용에서 형성된 일반적으로 인정되는 합의 기반 지식을 정리한다. 각 지식 영역은 핵심 주제와 관련 분야·참고 문헌을 제공한다.[155]

SWEBOK V4.0은 2024년 10월에 공개되었으며 18개의 지식 영역을 포함한다.[156]

주요 지식 영역은 다음과 같다.

  • 소프트웨어 요구사항
  • 소프트웨어 아키텍처
  • 소프트웨어 설계
  • 소프트웨어 구축
  • 소프트웨어 시험
  • 소프트웨어 공학 운영
  • 소프트웨어 유지보수
  • 소프트웨어 구성 관리
  • 소프트웨어 공학 관리
  • 소프트웨어 공학 프로세스
  • 소프트웨어 공학 모델과 방법
  • 소프트웨어 품질
  • 소프트웨어 보안
  • 소프트웨어 공학 전문 실무
  • 소프트웨어 공학 경제학
  • 컴퓨팅 기초
  • 수학적 기초
  • 공학 기초

V4.0에서는 소프트웨어 아키텍처·소프트웨어 공학 운영과 소프트웨어 보안이 별도 지식 영역으로 추가되었으며, 애자일과 DevOps가 여러 지식 영역에 반영되었다.[157]

SWEBOK는 다음을 목적으로 하지 않는다.

  • 모든 소프트웨어 공학 지식을 한 문서에 완전히 수록하지 않는다.
  • 모든 프로젝트가 따라야 할 개발 프로세스를 규정하지 않는다.
  • 특정 언어·도구와 방법론을 의무화하지 않는다.
  • 전문 실무에 필요한 경험과 판단을 대체하지 않는다.
  • 대학 교육과정 전체를 그대로 정의하지 않는다.

SWEBOK의 지식 영역은 서로 독립된 개발 단계가 아니다. 요구사항·설계·시험과 운영은 생명주기 전반에서 반복되고 서로 영향을 준다.

SWEBOK의 활용

SWEBOK는 다음과 같은 용도로 사용할 수 있다.

  • 소프트웨어 공학 교육과정 설계
  • 개인의 학습 계획
  • 조직의 직무와 역량 체계
  • 전문 자격 시험
  • 프로젝트 검토 체크리스트
  • 사내 교육과 기술 문서 분류
  • 연구 주제의 위치 파악
  • 관련 표준과 참고 자료 탐색
  • 소프트웨어 공학과 인접 분야의 경계 설명

지식 영역을 모두 안다고 전문적인 소프트웨어 엔지니어가 되는 것은 아니다. 실제 문제를 해결하고 상충 관계와 위험을 판단하며 여러 사람과 협력한 경험이 필요하다.

반대로 특정 기술에 능숙하더라도 요구사항·품질·운영과 전문 윤리 같은 지식이 부족하면 전체 제품의 책임을 수행하기 어렵다.

SEBoK

SEBoK(Guide to the Systems Engineering Body of Knowledge)은 시스템 공학의 주요 지식과 참고 자료를 구조적으로 정리한 지식 체계이다.

SEBoK는 시스템 공학의 핵심 지식 출처와 참고 문헌을 여러 독자에게 안내하는 살아 있는 자료이며, 공동체의 의견과 정기적인 개정을 통해 갱신된다.[158]

SEBoK는 다음을 다룬다.

  • 시스템과 시스템 사고
  • 생명주기와 시스템 정의
  • 시스템 실현과 배포
  • 시스템 공학 관리
  • 조직과 팀
  • 시스템군과 시스템의 시스템
  • 모델 기반 시스템 공학
  • 전문 분야와 다른 공학과의 관계
  • 교육과 역량
  • 표준과 주요 문헌

소프트웨어가 더 큰 사회기술적·물리적 시스템에 포함될수록 SWEBOK만으로 전체 문제를 설명하기 어렵다. SEBoK는 하드웨어·사람·조직과 운영 환경을 포함하는 시스템 수준의 관점을 제공한다.

SEBoK는 하나의 상세 교과서라기보다 검증된 지식과 주요 출처를 연결하는 안내서이다.[159]

PMBOK

PMBOK Guide는 Project Management Institute가 발행하는 프로젝트 관리 지식 체계이다.

PMBOK Guide는 프로젝트가 조직적 성과와 가치를 만들도록 관리하는 데 필요한 원칙과 실무를 정리하며, 예측형·적응형과 혼합형 접근을 포괄한다.[160]

PMBOK는 소프트웨어 공학에 한정되지 않지만 다음 영역에서 관련된다.

  • 프로젝트와 이해관계자
  • 범위와 일정
  • 비용과 자원
  • 위험
  • 품질
  • 조달
  • 의사소통
  • 변화
  • 가치와 성과

소프트웨어 프로젝트에서는 PMBOK의 일반 관리 지식과 SWEBOK의 기술·공학 지식을 함께 사용할 수 있다.

PMBOK의 프로젝트 관리 원칙이 소프트웨어 생명주기와 설계·시험의 전문 지식을 대신하지는 않는다.

BABOK

BABOK Guide는 International Institute of Business Analysis가 발행하는 비즈니스 분석 지식 체계이다.

BABOK Guide는 비즈니스 분석 분야에서 일반적으로 인정되는 실무와 과업·기법을 설명하고, 요구사항 생명주기 관리·전략 분석과 요구사항 분석 및 설계 정의 등을 다룬다.[161]

주요 지식 영역에는 다음이 있다.

  • 비즈니스 분석 계획과 감시
  • 도출과 협업
  • 요구사항 생명주기 관리
  • 전략 분석
  • 요구사항 분석과 설계 정의
  • 솔루션 평가

BABOK는 소프트웨어 요구사항 공학과 상당 부분 겹치지만 비즈니스 분석은 소프트웨어 개발 여부와 관계없이 조직의 필요·전략과 변화 전체를 다룰 수 있다.

요구사항 공학에서는 BABOK의 이해관계자·가치와 조직 분석 관점과 SWEBOK·ISO/IEC/IEEE 29148의 시스템 및 소프트웨어 명세 관점을 함께 활용할 수 있다.

교육과정 지침

지식 체계와 교육과정 지침은 관련되지만 같지 않다.

지식 체계는 전문 분야의 지식 범위를 정리하며, 교육과정 지침은 학위 과정에서 학생이 어떤 역량과 학습 경험을 가져야 하는지 제안한다.

ACM과 IEEE Computer Society의 Software Engineering 2014는 학부 소프트웨어 공학 학위 과정의 교육과정 설계를 위한 지침을 제공한다.[162]

교육과정은 다음을 함께 고려해야 한다.

  • 컴퓨터 과학과 수학의 기초
  • 요구사항·설계와 구현
  • 시험과 품질
  • 프로세스와 프로젝트
  • 전문 실무와 윤리
  • 팀 프로젝트
  • 실제 제약과 이해관계자
  • 지속적인 학습 능력

SWEBOK의 모든 항목을 같은 깊이로 가르치는 것이 교육과정의 목적은 아니다. 학습자의 수준과 교육 목표에 따라 핵심 개념·실습과 통합 경험을 선택한다.

자격과 전문 인증

소프트웨어 공학 분야에는 지식 체계와 표준을 기반으로 한 여러 전문 자격이 존재한다.

자격은 다음을 평가할 수 있다.

  • 기본 지식
  • 특정 기술과 플랫폼
  • 프로젝트와 프로세스 실무
  • 보안·품질과 안전
  • 경력과 실무 경험
  • 전문 윤리
  • 지속적인 교육

자격증은 특정 시험이나 경험 기준을 충족했다는 증거이며 모든 실제 문제를 해결할 능력을 절대적으로 보증하지는 않는다.

채용과 역할 배정에서는 자격뿐 아니라 실제 설계·구현과 협업 경험, 제품의 위험과 분야 지식을 함께 평가해야 한다.

ISO/IEC 24773 표준군은 소프트웨어 및 시스템 공학 전문가 자격 제도의 지식·기술과 역량 설명을 위한 공통 지침을 제공한다.[163]

표준과 지식 체계의 차이

표준과 지식 체계는 다음과 같이 구분할 수 있다.

구분표준지식 체계
주된 목적공통 요구·규칙과 지침 제공전문 지식의 범위와 구조 설명
적용 대상제품·프로세스·조직과 산출물교육·전문 실무와 역량
준수 여부적합성 평가가 가능할 수 있음일반적으로 준수 개념을 사용하지 않음
인증일부 표준은 인증에 사용됨직접적인 제품·조직 인증 기준이 아님
내용요구사항·절차·모델과 형식개념·주제·기법과 참고 문헌
조정프로젝트와 조직에 맞게 조정학습·직무에 필요한 영역을 선택
ISO/IEC/IEEE 12207, 29148SWEBOK, SEBoK, PMBOK, BABOK

SWEBOK의 특정 지식 영역을 안다는 것과 ISO 표준의 특정 요구사항을 준수한다는 것은 다른 주장이다.

표준은 무엇을 충족해야 하는지를 제시할 수 있고, 지식 체계는 그러한 작업을 이해하고 수행하는 데 필요한 지식의 범위를 설명한다.

표준과 모범 사례

모범 사례는 특정 조건에서 좋은 결과를 만들어 널리 권장되는 실무이다.

그러나 모범 사례가 모든 환경에서 최선인 것은 아니다.

  • 대규모 조직의 실무가 소규모 프로젝트에는 과도할 수 있다.
  • 웹 서비스의 빠른 배포 방식이 의료 장비에 적합하지 않을 수 있다.
  • 특정 언어와 클라우드에서 효과적인 방식이 임베디드 장치에서는 사용할 수 없을 수 있다.
  • 과거의 모범 사례가 새로운 기술과 위협 환경에서는 적절하지 않을 수 있다.

표준도 일반적인 공통 기준을 제공하지만 구체적인 상황의 전문적 판단을 완전히 대체하지 않는다.

실무를 채택할 때는 해결하려는 문제와 근거·적용 조건과 비용을 확인하고 실제 결과를 측정한다.

표준과 연구

표준은 이미 충분한 합의와 실무 경험이 형성된 내용을 중심으로 만들어지는 경우가 많다. 최신 연구와 실험적 기법이 표준에 즉시 반영되지는 않는다.

연구는 다음과 같은 역할을 한다.

  • 새로운 기법과 모델 제안
  • 기존 실무의 효과 검증
  • 도구와 방법 비교
  • 인간·조직과 사회적 영향 분석
  • 새로운 위험과 품질 특성 발견
  • 표준 개정의 근거 제공

표준에 없다는 이유만으로 새로운 방법이 잘못된 것은 아니다. 반대로 최신 논문에 소개되었다는 이유만으로 일반적인 실무에 검증된 것도 아니다.

안전과 규제 분야에서 새로운 기법을 사용할 때는 기존 표준의 목적을 어떻게 충족하며 어떤 추가 증거가 필요한지 설명해야 한다.

표준화 과정

표준은 일반적으로 제안·초안·검토와 투표·개정 과정을 거쳐 만들어진다.

표준화 과정에는 다음 주체가 참여할 수 있다.

  • 국가 표준 기관
  • 산업계
  • 대학과 연구 기관
  • 정부와 규제 기관
  • 전문 단체
  • 사용자와 소비자 조직
  • 시험과 인증 기관
  • 도구와 공급자

합의는 모든 참가자가 완전히 같은 의견을 가진다는 뜻이 아니라, 주요 반대와 대안을 검토하고 넓게 수용 가능한 결과를 만드는 과정이다.

표준 개발에는 시간이 걸리므로 빠르게 변하는 소프트웨어 기술을 즉시 따라가기 어렵다. 대신 특정 제품의 유행보다 장기간 사용할 수 있는 개념과 요구를 중심으로 작성할 수 있다.

표준화의 장점

표준화는 다음과 같은 장점을 가질 수 있다.

  • 공통 용어와 책임
  • 공급자 사이의 비교 가능성
  • 호환성과 상호운용성
  • 재사용 가능한 프로세스와 산출물
  • 교육과 전문 역량의 공통 기반
  • 품질과 안전의 최소 기준
  • 감사와 규제의 객관성
  • 장기 유지보수와 기록
  • 국제적인 거래와 협력
  • 특정 개인과 공급자에 대한 의존 감소

공개 인터페이스와 파일 형식의 표준화는 하나의 공급자가 서비스를 종료해도 다른 구현과 도구로 데이터를 이전할 가능성을 높인다.

프로세스 표준은 프로젝트 구성원이 바뀌어도 활동과 기록의 의미를 유지하는 데 도움이 된다.

표준화의 한계

표준화에는 다음과 같은 한계가 있다.

  • 문서와 준수 비용이 증가할 수 있다.
  • 새로운 기술의 적용이 느려질 수 있다.
  • 실제 문제보다 형식적 증거에 집중할 수 있다.
  • 작은 조직과 프로젝트에 과도한 부담이 될 수 있다.
  • 서로 다른 표준의 중복과 용어 차이가 발생할 수 있다.
  • 특정 산업과 대규모 조직의 관점이 과도하게 반영될 수 있다.
  • 인증이 품질의 대체 지표로 오용될 수 있다.
  • 오래된 판본이 계약과 규제로 장기간 유지될 수 있다.
  • 표준 문서의 가격과 접근성이 학습과 채택을 제한할 수 있다.
  • 실제 전문 판단과 조직 문화를 대신하지 못한다.

표준을 충족하는 문서를 만든 뒤 실제 개발과 운영에서는 따르지 않는 이중 프로세스가 생길 수도 있다.

준수 증거를 실제 도구와 작업 흐름에서 자동 생성하고, 필요한 정보만 유지하면 형식과 실무의 차이를 줄일 수 있다.

문서 중심 준수의 문제

표준을 문서 목록으로만 해석하면 다음과 같은 문제가 발생할 수 있다.

  • 실제로 사용되지 않는 문서를 작성한다.
  • 같은 정보를 여러 문서에 중복 기록한다.
  • 개발이 끝난 뒤 과거 활동을 소급하여 문서화한다.
  • 산출물의 존재만 확인하고 내용의 품질을 평가하지 않는다.
  • 변경과 코드·시험의 실제 상태가 문서와 달라진다.
  • 팀이 표준을 외부 감사를 위한 형식으로만 인식한다.
  • 중요한 위험보다 문서 양을 성숙도의 지표로 사용한다.

표준이 요구하는 정보와 결과를 현재 작업 도구에 통합할 수 있다.

예를 들어 요구사항은 버전 관리되는 저장소와 작업 시스템에서 관리하고, 추적성은 코드 변경과 자동 시험에서 생성하며, 기준선은 서명된 빌드와 아티팩트 저장소로 표현할 수 있다.

문서가 필요한 경우에도 실제 의사결정과 운영에 사용되는 정보가 되도록 한다.

증거 기반 준수

증거 기반 준수는 절차가 존재한다는 설명뿐 아니라 실제 제품과 프로세스가 요구사항을 충족한다는 객관적 자료를 연결한다.

증거에는 다음이 포함될 수 있다.

  • 승인된 요구사항과 기준선
  • 설계와 아키텍처 결정
  • 코드 검토 기록
  • 자동 빌드와 시험 결과
  • 정적·동적 분석
  • 추적성 관계
  • 구성과 릴리스 정보
  • SBOM과 빌드 출처
  • 운영 지표와 장애 기록
  • 교육과 역량 기록
  • 위험 평가와 승인
  • 독립적인 감사

증거의 양보다 요구사항과 주장에 적절하게 연결되는지가 중요하다.

같은 자동 시험 결과를 여러 품질 주장에 무리하게 사용하거나, 오래된 제품 버전의 증거를 현재 릴리스에 적용해서는 안 된다.

도구와 표준

도구는 표준의 적용과 증거 생성을 지원할 수 있다.

  • 요구사항 도구가 고유 식별과 추적성을 제공한다.
  • 모델링 도구가 아키텍처 뷰와 관계를 관리한다.
  • 버전 관리가 변경 이력과 기준선을 제공한다.
  • 시험 도구가 시험 절차와 결과를 기록한다.
  • 정적 분석이 코딩 규칙과 결함을 검사한다.
  • 지속적 통합이 반복 가능한 검증을 수행한다.
  • 아티팩트 저장소가 릴리스 구성을 보존한다.
  • 정책 코드화가 일부 준수 규칙을 자동 판정한다.
  • 관찰 도구가 운영 중 품질과 위험을 측정한다.

도구가 특정 표준을 지원한다고 광고하더라도 모든 요구사항을 자동으로 충족하는 것은 아니다.

도구의 설정·사용 절차와 생성 결과가 프로젝트의 조정된 프로세스에 적합한지 확인해야 한다.

표준과 인공지능

인공지능 기반 시스템은 코드뿐 아니라 데이터·모델과 운영 중 학습·확률적 결과를 포함하므로 기존 소프트웨어 표준만으로 다루기 어려운 특성이 있다.

ISO/IEC 5338:2023은 기계학습과 휴리스틱 기반 AI 시스템의 생명주기 프로세스를 정의하며, ISO/IEC/IEEE 15288과 12207을 기반으로 AI 특화 프로세스를 추가한다.[164]

AI 시스템에서는 다음을 추가로 관리할 수 있다.

  • 데이터 출처와 품질
  • 학습·검증과 시험 데이터
  • 모델 버전
  • 통계적 성능과 불확실성
  • 편향과 집단별 영향
  • 설명 가능성
  • 운영 데이터 분포 변화
  • 사람의 감독
  • 모델과 일반 소프트웨어의 통합
  • 재학습과 폐기

ISO/IEC TR 29119-11:2020은 AI 기반 시스템의 복잡성·비결정성과 대규모 데이터가 시험과 수용 기준에 만드는 문제를 설명한다.[165]

표준과 윤리

기술적 요구사항을 충족하는 시스템도 사용자와 사회에 윤리적 문제를 일으킬 수 있다.

ISO/IEC/IEEE 24748-7000:2022는 시스템 설계 과정에서 윤리적 문제를 식별하고 이해관계자와 가치·위험을 분석하기 위한 표준 모델 프로세스를 제공한다.[166]

윤리적 문제에는 다음이 포함될 수 있다.

  • 개인정보와 감시
  • 차별과 공정성
  • 접근성
  • 사용자 자율성과 조작
  • 안전과 공공의 이익
  • 노동과 조직 영향
  • 환경 지속 가능성
  • 자동화된 의사결정
  • 책임과 이의 제기
  • 서비스 종료와 데이터 권리

윤리 표준과 절차가 존재해도 가치 충돌의 답을 자동으로 계산해 주지는 않는다. 영향을 받는 사람과 전문가의 참여, 투명한 결정과 지속적인 평가가 필요하다.

조직의 표준 체계

조직은 외부 표준을 그대로 사용하기보다 자체 정책·프로세스와 템플릿·도구로 구체화할 수 있다.

조직 표준 체계에는 다음이 포함될 수 있다.

  • 적용할 외부 표준
  • 조직의 소프트웨어 생명주기
  • 요구사항과 설계 규칙
  • 코딩과 보안 표준
  • 시험과 완료 기준
  • 구성·빌드와 릴리스 정책
  • 운영과 장애 대응
  • 지원 기술과 플랫폼
  • 문서와 기록 보존
  • 품질과 위험 측정
  • 조정과 예외 절차
  • 교육과 책임자
  • 내부 감사와 개선

조직 표준은 여러 프로젝트에 안전한 기본 경로를 제공해야 한다.

모든 프로젝트에 같은 절차를 강제하기보다 위험 등급과 제품 유형별로 적용 수준을 정의할 수 있다.

프로젝트의 표준 계획

프로젝트는 착수 단계에서 적용할 표준과 조정 내용을 계획할 수 있다.

계획에는 다음이 포함될 수 있다.

  • 적용 표준과 판본
  • 계약과 규제 요구
  • 적용 범위
  • 조정·생략과 대체 활동
  • 산출물과 기준선
  • 역할과 독립성
  • 검토와 승인
  • 자동화와 도구
  • 준수 증거
  • 공급자 요구
  • 감사 일정
  • 표준 변경 대응
  • 프로젝트 종료 뒤의 보존

표준 적용을 프로젝트 후반의 감사 준비로 미루면 이미 만들어진 코드와 데이터·결정을 다시 정리해야 한다.

초기부터 개발 도구와 완료 조건에 통합하면 별도의 준수 작업과 실제 개발 사이의 차이를 줄일 수 있다.

표준 선택

프로젝트에 적용할 표준은 제품과 위험·산업에 따라 선택한다.

다음 질문을 사용할 수 있다.

  • 법률과 계약에서 요구하는 표준은 무엇인가
  • 시스템과 소프트웨어 중 무엇이 관심 대상인가
  • 안전·보안과 개인정보 위험은 어느 정도인가
  • 요구사항과 시험·품질에 필요한 공통 기준은 무엇인가
  • 외부 공급자와 고객이 사용하는 표준은 무엇인가
  • 인증과 감사가 필요한가
  • 조직이 실제로 적용할 역량과 도구가 있는가
  • 여러 표준의 중복을 어떻게 조정할 것인가
  • 제품의 지원 기간은 얼마나 긴가
  • 표준 판본이 현재 기술 환경에 적합한가

유명한 표준을 가능한 한 많이 적용하는 것이 좋은 선택은 아니다.

각 표준이 해결하는 문제와 요구되는 비용, 서로의 관계를 분석하고 최소한의 일관된 집합을 구성한다.

표준 적용의 평가

표준을 적용한 뒤에는 실제 효과를 평가해야 한다.

다음과 같은 정보를 확인할 수 있다.

  • 요구사항과 책임이 더 명확해졌는가
  • 결함과 위험을 더 일찍 발견하는가
  • 공급자와 통합 문제가 감소했는가
  • 감사 준비 비용이 줄었는가
  • 개발과 배포의 피드백이 빨라졌는가
  • 문서와 실제 시스템의 일치도가 높아졌는가
  • 사용되지 않는 산출물이 증가했는가
  • 팀이 절차를 우회하고 있는가
  • 자동화 가능한 수동 증거가 남아 있는가
  • 새로운 기술과 변경을 지나치게 방해하는가

표준 준수 자체를 최종 성과로 삼으면 실제 사용자 가치와 품질이 가려질 수 있다.

표준은 위험과 협업 문제를 줄이기 위한 수단이며, 효과가 낮은 조직 절차는 표준의 목적을 유지하면서 개선할 수 있다.

지식 체계의 활용 한계

지식 체계는 전문 지식의 지도를 제공하지만 다음과 같은 한계가 있다.

  • 모든 분야와 기술을 같은 깊이로 다루지 못한다.
  • 최신 연구와 도구가 반영되기까지 시간이 걸릴 수 있다.
  • 실제 프로젝트의 문맥과 상충 관계를 대신하지 못한다.
  • 지식 영역 사이의 연결이 목록보다 복잡하다.
  • 전문 경험과 암묵적 지식을 완전히 문서화하지 못한다.
  • 특정 국가와 산업의 관점이 상대적으로 적을 수 있다.
  • 개념을 아는 것과 실무에서 수행하는 능력은 다르다.

지식 체계의 목차를 프로젝트 단계로 그대로 사용하거나 모든 항목을 동일한 중요도로 적용해서는 안 된다.

개인의 역할과 제품·조직의 필요에 따라 학습 범위와 깊이를 정한다.

지속적인 전문 학습

소프트웨어 공학의 표준과 지식은 계속 변화한다.

새로운 프로그래밍 모델·클라우드와 인공지능, 보안 위협과 개인정보 규제가 등장하며 기존 시스템의 운영 경험이 새로운 실무로 정리된다.

전문가는 다음을 지속적으로 확인할 수 있다.

  • 표준의 새 판본과 폐기 상태
  • SWEBOK와 관련 지식 체계의 개정
  • 사용하는 기술의 공식 명세
  • 보안 공지와 취약점
  • 산업 규제
  • 연구 결과와 재현성
  • 사고와 실패 사례
  • 전문 윤리와 사회적 영향
  • 조직의 도구와 실제 프로세스
  • 자신의 지식과 경험의 한계

표준 번호와 용어를 암기하는 것보다 어떤 문제를 해결하기 위해 만들어졌고 실제 상황에서 어떻게 조정해야 하는지 이해하는 것이 중요하다.

표준과 지식 체계의 통합

표준과 지식 체계는 소프트웨어 공학 활동을 서로 다른 수준에서 지원한다.

지식 체계는 다음을 설명한다.

  • 소프트웨어 공학의 지식 영역은 무엇인가
  • 각 영역의 핵심 개념과 기법은 무엇인가
  • 인접 전문 분야와 어떻게 연결되는가
  • 더 깊이 학습할 자료는 무엇인가

표준은 다음을 설명할 수 있다.

  • 공통으로 어떤 프로세스와 결과가 필요한가
  • 특정 산출물과 품질을 어떻게 표현하는가
  • 준수와 평가를 위해 무엇을 확인해야 하는가
  • 여러 조직과 공급자가 어떤 기준으로 협력하는가

조직의 방법론과 도구는 이를 실제 작업으로 변환한다.

지식 체계
    └── 알아야 할 영역과 개념

표준
    └── 공통 요구사항과 지침

조직의 정책과 프로세스
    └── 조직 환경에 맞는 역할과 절차

프로젝트의 조정
    └── 제품과 위험에 맞는 적용 범위

도구와 자동화
    └── 반복 실행과 증거 수집

실제 제품과 운영 결과
    └── 품질·가치와 위험에 대한 최종 평가

이 구조에서 어느 하나도 다른 요소를 완전히 대체하지 않는다.

지식 체계만 사용하면 실제 책임과 준수 기준이 부족할 수 있고, 표준만 적용하면 그 요구를 올바르게 판단하고 수행

다른 분야와의 관계

소프트웨어 공학은 소프트웨어를 분석·설계·구현·시험·배포하고 운영하는 데 필요한 이론과 기술, 사람과 조직의 활동을 통합한다. 이 과정에서는 알고리즘과 계산 이론만으로 충분하지 않으며, 하드웨어·네트워크·사용자·조직·법률과 실제 업무 영역을 함께 이해해야 한다.

소프트웨어 공학은 컴퓨터 과학에서 계산과 프로그램의 이론적·기술적 기반을 얻고, 컴퓨터 공학과 전자공학을 통해 하드웨어와 임베디드 실행 환경을 다룬다. 복잡한 제품에서는 시스템 공학과 함께 소프트웨어·하드웨어·사람과 운영 절차를 하나의 시스템으로 통합한다. 사용자에게 실제로 사용 가능한 제품을 만들기 위해 인간-컴퓨터 상호작용과 디자인을 활용하고, 조직의 업무와 가치를 구현하기 위해 정보 시스템·경영·경제와 각 응용 분야의 전문 지식을 사용한다.

보안·안전·품질·프로젝트 관리와 운영도 소프트웨어 개발의 외부 지원 기능으로만 존재하지 않는다. 소프트웨어의 구조와 생명주기, 개발 조직과 실제 사용 결과에 직접 영향을 주는 인접 분야이다.

ACM과 IEEE Computer Society의 Computing Curricula는 컴퓨터 공학·컴퓨터 과학·사이버 보안·정보 시스템·정보기술·소프트웨어 공학과 데이터 과학을 서로 관련되지만 독자적인 교육·전문 분야로 구분한다.[167][168]

각 분야의 경계는 절대적이지 않다. 하나의 연구와 제품, 직무가 여러 분야에 동시에 속할 수 있으며 조직과 국가·교육 체계에 따라 같은 활동을 다른 이름으로 분류하기도 한다. 중요한 차이는 사용하는 프로그래밍 언어나 도구보다 중심적으로 해결하려는 문제와 책임의 범위에 있다.

컴퓨팅 분야 안에서의 위치

컴퓨팅은 컴퓨터와 계산을 이용하거나 연구하고, 계산 시스템과 소프트웨어를 만들어 사용하는 폭넓은 활동을 포함한다.

소프트웨어 공학은 컴퓨팅 분야 가운데 다음과 같은 문제에 중점을 둔다.

  • 실제 이해관계자의 요구를 분석한다.
  • 복잡한 소프트웨어의 구조와 인터페이스를 설계한다.
  • 여러 사람이 장기간 개발할 수 있는 코드를 만든다.
  • 품질과 위험을 체계적으로 검증한다.
  • 버전·변경과 제품 구성을 관리한다.
  • 실제 환경에 배포하고 운영한다.
  • 결함과 환경 변화에 대응하며 유지보수한다.
  • 프로젝트와 조직의 작업을 조정한다.
  • 보안·안전과 윤리적 책임을 관리한다.
  • 제품의 전체 생명주기와 종료를 고려한다.

다른 컴퓨팅 분야도 이러한 활동을 수행할 수 있다. 다만 소프트웨어 공학에서는 개별 알고리즘과 프로그램을 만드는 능력을 넘어, 복잡한 소프트웨어를 반복 가능하고 책임 있는 방식으로 개발·운영하는 과정 자체가 주요 연구와 실무 대상이 된다.

컴퓨터 과학

컴퓨터 과학은 계산과 정보 처리의 원리, 알고리즘·자료구조·프로그래밍 언어·운영체제·인공지능과 여러 계산 시스템을 연구한다.

소프트웨어 공학은 컴퓨터 과학의 다음 지식을 기초로 사용한다.

  • 알고리즘과 자료구조
  • 계산 가능성과 복잡도
  • 프로그래밍 언어와 타입 시스템
  • 컴파일러와 런타임
  • 운영체제
  • 데이터베이스
  • 컴퓨터 네트워크
  • 병렬·분산 컴퓨팅
  • 인공지능과 기계학습
  • 컴퓨터 그래픽스
  • 암호학
  • 형식 언어와 논리

ACM과 IEEE Computer Society의 CS2023 교육 지침은 알고리즘과 자료구조를 컴퓨터 과학과 소프트웨어 공학 모두의 기초로 설명한다.[169]

컴퓨터 과학과 소프트웨어 공학은 많은 교육 내용과 기술을 공유하지만 중심 질문에는 차이가 있다.

컴퓨터 과학은 다음과 같은 질문을 다룰 수 있다.

  • 어떤 문제를 계산할 수 있는가
  • 알고리즘의 시간과 공간 복잡도는 무엇인가
  • 프로그래밍 언어의 의미와 타입 규칙은 무엇인가
  • 운영체제와 분산 알고리즘은 어떻게 동작하는가
  • 새로운 계산 모델과 인공지능 기법을 어떻게 만들 수 있는가

소프트웨어 공학은 다음과 같은 질문에 더 직접적으로 집중한다.

  • 사용자의 실제 요구를 어떻게 발견하고 검증할 것인가
  • 여러 품질 요구를 만족하는 구조를 어떻게 설계할 것인가
  • 수백만 줄의 코드와 여러 팀의 변경을 어떻게 관리할 것인가
  • 결함과 위험을 생명주기 전체에서 어떻게 통제할 것인가
  • 소프트웨어를 어떻게 배포·운영하고 지속적으로 변경할 것인가
  • 개발 비용·일정과 조직적 책임을 어떻게 관리할 것인가

컴퓨터 과학의 연구 결과가 소프트웨어 공학에 적용되며, 소프트웨어 공학에서 발생한 대규모 시스템의 문제는 다시 컴퓨터 과학의 연구 주제가 된다.

예를 들어 새로운 분산 합의 알고리즘은 컴퓨터 과학의 연구 결과일 수 있다. 이를 실제 데이터베이스와 서비스에 적용하려면 요구사항·오류 처리·관찰 가능성·업그레이드·운영과 호환성을 포함한 소프트웨어 공학이 필요하다.

프로그래밍

프로그래밍은 프로그래밍 언어로 알고리즘과 동작을 표현하여 프로그램을 만드는 활동이다. 소프트웨어 공학의 핵심 활동이지만 전체와 같지는 않다.

프로그래밍은 주로 다음을 포함한다.

  • 프로그램의 논리 작성
  • 자료구조와 알고리즘 구현
  • 함수와 모듈 구성
  • 오류 처리
  • 디버깅
  • 코드 최적화
  • 프로그래밍 언어와 도구의 사용

소프트웨어 공학에는 프로그래밍 이외에도 다음이 포함된다.

  • 요구사항 공학
  • 아키텍처와 설계
  • 품질 보증과 시험 전략
  • 구성·변경과 릴리스 관리
  • 프로젝트와 조직 관리
  • 배포·운영과 유지보수
  • 보안·안전과 윤리
  • 사용자와 이해관계자의 참여
  • 비용과 위험 관리
  • 문서화와 지식 관리

작은 일회성 프로그램은 한 사람이 요구를 이해하고 바로 구현할 수 있다. 그러나 여러 사용자가 장기간 사용하는 운영체제·웹 서비스와 의료 장비 소프트웨어에서는 프로그래밍 능력만으로 요구·품질과 변경을 통제하기 어렵다.

코드가 실행된다는 사실과 소프트웨어 제품이 성공적으로 개발되었다는 사실은 같지 않다. 올바른 문제를 해결하고, 실제 환경에서 안전하게 운영되며, 다른 사람이 이해하고 수정할 수 있어야 한다.

컴퓨터 공학

컴퓨터 공학은 컴퓨터 하드웨어와 소프트웨어의 결합을 다루며 전자공학과 컴퓨터 과학의 지식을 함께 사용한다.

컴퓨터 공학과 소프트웨어 공학이 만나는 영역에는 다음이 있다.

  • 임베디드 시스템
  • 펌웨어
  • 운영체제 커널과 장치 드라이버
  • 마이크로컨트롤러
  • 실시간 시스템
  • 시스템 온 칩
  • 하드웨어 가속기
  • 로봇과 자동차
  • 통신 장치
  • 사물인터넷
  • 하드웨어 검증 도구
  • 하드웨어와 소프트웨어 공동 설계

컴퓨터 공학에서는 회로·프로세서와 메모리·입출력 장치, 전력과 물리적인 제약을 중심으로 시스템을 설계할 수 있다. 소프트웨어 공학에서는 해당 하드웨어에서 동작하는 소프트웨어의 구조·생명주기와 품질을 중심적으로 다룬다.

두 분야의 경계에서는 다음과 같은 결정을 함께 내려야 한다.

  • 어떤 기능을 하드웨어와 소프트웨어 중 어디에 구현할 것인가
  • 성능·전력과 비용을 어떻게 조정할 것인가
  • 장치의 메모리와 저장 공간을 어떻게 사용할 것인가
  • 하드웨어 오류를 소프트웨어에서 어떻게 감지할 것인가
  • 펌웨어를 어떻게 업데이트하고 복구할 것인가
  • 하드웨어와 소프트웨어 버전의 호환성을 어떻게 관리할 것인가
  • 실시간 요구를 어떻게 검증할 것인가
  • 디버그와 관찰 수단을 어떻게 제공할 것인가

일반 웹 응용 프로그램에서는 하드웨어를 추상화된 실행 환경으로 볼 수 있지만, 임베디드 시스템과 운영체제에서는 하드웨어의 구조가 소프트웨어 설계에 직접적인 제약을 준다.

전자공학과 제어공학

전자공학은 회로·신호·통신과 전기적 장치를 다루며, 제어공학은 동적인 물리 시스템의 상태를 측정하고 원하는 동작을 유지하는 방법을 연구한다.

소프트웨어 공학은 다음 분야에서 이들과 밀접하게 결합된다.

  • 산업 제어
  • 자동차
  • 항공과 우주
  • 의료 장비
  • 로봇
  • 발전과 전력망
  • 통신 장비
  • 센서와 계측
  • 자율 시스템
  • 소비자 전자제품

제어 알고리즘이 수학적으로 올바르더라도 소프트웨어에서 다음 문제가 발생할 수 있다.

  • 센서 데이터가 늦거나 누락된다.
  • 여러 작업의 실행 순서가 달라진다.
  • 수치 오차와 단위 변환이 발생한다.
  • 네트워크와 장치가 일시적으로 실패한다.
  • 소프트웨어 업데이트로 타이밍이 바뀐다.
  • 사용자 인터페이스가 잘못된 상태를 표시한다.
  • 로그와 진단 정보가 부족하다.
  • 복구 중 위험한 출력이 유지된다.

따라서 제어 이론과 물리적 모델은 구현·실시간 스케줄링·안전 설계와 시험, 하드웨어 인더루프 검증을 통해 실제 시스템에 통합된다.

시스템 공학

시스템 공학은 복잡한 시스템의 전체 생명주기에서 사용자와 이해관계자의 필요를 만족하도록 여러 구성 요소와 전문 분야를 정의·통합하고 관리하는 분야이다.

INCOSE는 시스템 공학을 복잡한 시스템의 개별 구성 요소가 공동 목표를 달성하도록 설계·통합하고 생명주기 전체에서 관리하는 총체적인 접근으로 설명한다.[170]

시스템에는 다음 요소가 포함될 수 있다.

  • 소프트웨어
  • 하드웨어
  • 사람
  • 데이터
  • 시설
  • 네트워크
  • 업무 절차
  • 조직
  • 공급자
  • 운영 환경
  • 지원과 유지보수 체계

소프트웨어 공학은 시스템 공학의 하위 구성 요소로 참여할 수 있다. 항공기·자동차와 의료 시스템에서는 시스템 수준의 요구사항과 위험이 소프트웨어·하드웨어와 운영 절차에 할당된다.

시스템 공학은 다음을 중심으로 다룬다.

  • 전체 시스템의 목적과 경계
  • 이해관계자의 필요
  • 시스템 요구사항
  • 하위 시스템의 분해와 할당
  • 하드웨어·소프트웨어와 사람의 역할
  • 시스템 인터페이스
  • 통합과 전체 시스템 검증
  • 운영과 지원
  • 전체 생명주기 비용
  • 시스템 폐기

소프트웨어 공학은 할당된 소프트웨어 요소에 대해 다음을 수행한다.

  • 소프트웨어 요구사항 구체화
  • 소프트웨어 아키텍처와 설계
  • 구현과 구성 관리
  • 소프트웨어 시험
  • 소프트웨어 배포와 유지보수
  • 시스템 통합 지원

ISO/IEC/IEEE 15288:2023은 구상·개발·생산·사용·지원과 폐기를 포함한 전체 시스템 생명주기 프로세스를 정의하며, 시스템 구조의 각 수준에 반복적·동시적으로 적용할 수 있다.[171]

ISO/IEC/IEEE 24748-1:2024는 시스템 생명주기 프로세스인 ISO/IEC/IEEE 15288과 소프트웨어 생명주기 프로세스인 ISO/IEC/IEEE 12207을 함께 보완하는 생명주기 관리 지침을 제공한다.[172]

소프트웨어만으로 구성된 것처럼 보이는 대규모 플랫폼도 사용자·조직·데이터 센터와 외부 서비스가 결합된 사회기술적 시스템으로 볼 수 있다. 이 경우 시스템 공학의 경계·인터페이스와 전체 생명주기 관점이 유용하다.

시스템 공학과의 경계

소프트웨어 공학과 시스템 공학의 경계는 대상 시스템에 따라 달라진다.

하나의 데스크톱 응용 프로그램에서는 소프트웨어 팀이 사용자 인터페이스·데이터와 운영 환경을 포함한 대부분의 시스템 결정을 수행할 수 있다.

자동차에서는 다음과 같이 책임이 나뉠 수 있다.

  • 시스템 공학은 차량 수준의 제동·조향과 안전 목표를 정의한다.
  • 전자공학은 센서·제어기와 전기 회로를 설계한다.
  • 기계공학은 물리적 구동 장치를 설계한다.
  • 소프트웨어 공학은 제어 프로그램·진단과 업데이트를 개발한다.
  • 안전 공학은 전체 위험과 증거를 평가한다.
  • 인간공학은 운전자와 장치의 상호작용을 분석한다.

하나의 소프트웨어 결함이 시스템 수준에서 어떤 피해를 일으키는지 이해하려면 상위 시스템과 물리적 환경을 알아야 한다.

반대로 시스템 수준의 요구를 소프트웨어에 지나치게 추상적으로 할당하면 실제로 시험할 수 없는 요구가 만들어질 수 있다. 시스템 공학과 소프트웨어 공학은 요구사항과 인터페이스·통합 계획을 반복적으로 조정해야 한다.

정보 시스템

정보 시스템은 조직이 정보를 수집·처리·저장하고 업무와 의사결정을 수행하도록 사람·프로세스·데이터와 기술을 결합한 시스템을 다룬다.

정보 시스템 분야에서는 다음과 같은 문제를 중심적으로 다룬다.

  • 조직의 업무 절차
  • 정보와 데이터의 흐름
  • 경영과 의사결정
  • 기업 시스템
  • 기술 도입과 조직 변화
  • 데이터 거버넌스
  • 시스템 조달
  • 사용자와 이해관계자
  • 사업 가치와 투자
  • 법률과 정책
  • 정보기술 관리

소프트웨어 공학은 정보 시스템을 구현하고 변경하는 기술적·공학적 방법을 제공한다.

예를 들어 기업의 주문 관리 시스템에서는 다음이 함께 필요하다.

  • 정보 시스템은 주문·결제·재고와 조직의 업무 관계를 분석한다.
  • 소프트웨어 공학은 이를 요구사항·아키텍처와 프로그램으로 구현한다.
  • 데이터베이스 분야는 데이터 구조와 질의를 설계한다.
  • 보안은 고객 정보와 권한을 보호한다.
  • 프로젝트와 변화 관리는 조직에 시스템을 도입한다.
  • 운영 분야는 실제 서비스를 유지한다.

업무의 의미를 이해하지 못한 채 소프트웨어만 구현하면 기존의 잘못된 절차를 자동화하거나 조직이 사용할 수 없는 시스템을 만들 수 있다.

정보기술

정보기술은 조직과 사용자가 컴퓨터·네트워크와 소프트웨어를 실제로 설치·운영하고 지원하는 데 중점을 둔다.

정보기술의 활동에는 다음이 포함될 수 있다.

  • 컴퓨터와 운영체제 관리
  • 네트워크 구축
  • 계정과 접근 권한
  • 기업용 소프트웨어 도입
  • 클라우드와 가상화
  • 사용자 지원
  • 장치와 자산 관리
  • 백업과 복구
  • 보안 운영
  • 서비스 관리

소프트웨어 공학은 새로운 소프트웨어를 만들고 변경하는 활동에 더 큰 비중을 두지만, 배포·운영과 DevOps에서는 정보기술과 밀접하게 겹친다.

조직 내부의 도구와 자동화는 소프트웨어 개발과 정보기술 운영의 경계를 약화시킨다. 인프라 코드·배포 파이프라인과 운영 자동화는 소프트웨어 공학 기법을 정보기술에 적용한 사례이다.

데이터베이스와 데이터 공학

데이터베이스 분야는 데이터를 구조화·저장하고 질의하며 일관성과 성능·복구를 제공하는 방법을 다룬다.

소프트웨어 공학과 데이터베이스 분야가 만나는 문제에는 다음이 있다.

  • 데이터 모델
  • 스키마 설계
  • 트랜잭션
  • 동시성
  • 인덱스와 질의 성능
  • 복제와 분산 저장
  • 백업과 복구
  • 데이터 보안
  • 스키마 이전
  • 데이터 생명주기
  • 데이터베이스와 프로그램의 인터페이스

응용 프로그램의 구조는 데이터 구조에 영향을 주고 데이터베이스의 특성은 소프트웨어 아키텍처를 제한한다.

서비스를 여러 구성 요소로 나눌 때 데이터 소유권과 트랜잭션 경계를 함께 결정해야 한다. 코드만 분리하고 여러 서비스가 같은 데이터 구조를 직접 변경하면 실제 결합은 그대로 남을 수 있다.

데이터 공학은 대규모 데이터를 수집·정제·변환하고 저장·제공하는 파이프라인과 기반 시스템을 만든다.

데이터 공학은 소프트웨어 공학의 다음 기법을 사용한다.

  • 요구사항과 데이터 계약
  • 버전 관리
  • 자동 시험
  • 배포 자동화
  • 관찰 가능성
  • 오류와 재처리
  • 구성 관리
  • 보안과 개인정보
  • 확장 가능한 아키텍처

다만 데이터 시스템에서는 프로그램 코드뿐 아니라 데이터 품질·스키마와 처리 이력이 제품의 동작을 결정하므로 별도의 데이터 검증과 계보 관리가 필요하다.

데이터 과학

데이터 과학은 데이터에서 지식과 예측·의사결정에 필요한 결과를 얻기 위해 통계·수학·컴퓨팅과 응용 분야의 지식을 결합한다.

ACM의 데이터 과학 교육 지침은 데이터 관리·기술 통계·시각화·예측과 처방 분석, 데이터 마이닝과 실습을 주요 역량으로 다룬다.[173]

데이터 과학은 다음에 중점을 둘 수 있다.

  • 연구 질문과 가설
  • 데이터 수집과 품질
  • 통계 분석
  • 탐색적 분석
  • 모델 구축과 평가
  • 시각화
  • 실험
  • 결과 해석
  • 불확실성
  • 응용 영역의 의미

소프트웨어 공학은 데이터 과학의 결과를 반복 가능하고 운영 가능한 제품으로 만드는 데 필요하다.

실험용 분석 코드가 실제 서비스에 적용될 때는 다음을 추가로 다뤄야 한다.

  • 입력과 출력 계약
  • 모듈과 API
  • 성능과 확장
  • 자동 시험
  • 데이터와 모델 버전
  • 배포
  • 접근 권한
  • 모니터링
  • 장애와 복구
  • 유지보수
  • 개인정보와 공정성

데이터 과학자는 모델의 통계적 적합성을 검증하고, 소프트웨어 엔지니어는 모델을 포함한 전체 시스템의 신뢰성과 운영 가능성을 설계할 수 있다. 실제 프로젝트에서는 두 역할이 겹치거나 한 팀 안에서 함께 수행된다.

인공지능과 기계학습

인공지능기계학습은 지각·추론·예측·언어와 의사결정 같은 기능을 계산 시스템으로 구현하는 방법을 다룬다.

기계학습 기반 소프트웨어는 일반적인 프로그램과 다른 구성 요소를 가진다.

  • 학습 데이터
  • 데이터 전처리
  • 모델 구조와 매개변수
  • 학습 코드
  • 평가 기준
  • 추론 서비스
  • 모델 저장소
  • 운영 데이터
  • 인간의 검토와 피드백

전통적인 소프트웨어에서는 코드 변경이 주요 동작 변화의 원인인 경우가 많다. 기계학습 시스템에서는 코드가 같아도 데이터·모델과 운영 환경의 분포 변화로 결과가 달라질 수 있다.

따라서 소프트웨어 공학 기법을 다음과 같이 확장해야 한다.

  • 데이터와 모델을 형상 항목으로 관리한다.
  • 학습 과정을 재현할 수 있게 한다.
  • 데이터 누출과 편향을 검사한다.
  • 모델과 일반 코드의 통합을 시험한다.
  • 집단과 환경별 품질을 측정한다.
  • 운영 중 데이터 분포와 성능 저하를 감시한다.
  • 모델 교체와 롤백을 관리한다.
  • 자동화된 결과의 설명과 이의 제기를 제공한다.
  • 인공지능의 실패를 전체 시스템의 안전·보안과 연결한다.

인공지능 연구가 새로운 모델과 학습 알고리즘을 만드는 데 중점을 둔다면, AI 소프트웨어 공학은 이러한 모델을 실제 제품의 요구·데이터·인터페이스와 운영 체계에 통합하는 문제를 다룬다.

수학

수학은 컴퓨터 과학과 소프트웨어 공학의 이론적 기반을 제공한다.

사용되는 분야에는 다음이 있다.

  • 이산수학
  • 논리
  • 집합론
  • 그래프 이론
  • 확률과 통계
  • 선형대수
  • 수치해석
  • 최적화
  • 정보이론
  • 계산기하학
  • 대수학
  • 미분방정식

소프트웨어 공학에서 수학은 다음과 같이 사용된다.

  • 알고리즘의 정확성과 복잡도 분석
  • 형식 명세와 검증
  • 암호 프로토콜
  • 확률적 위험 분석
  • 성능과 신뢰성 모델
  • 통계적 시험
  • 기계학습
  • 시뮬레이션
  • 그래픽스와 물리
  • 제어 시스템

모든 소프트웨어 프로젝트가 고급 수학을 직접 사용하지는 않는다. 그러나 요구사항을 정확하게 표현하고 논리적 관계와 경계 조건을 이해하는 능력은 대부분의 개발 활동에 필요하다.

수학적으로 증명된 알고리즘도 잘못된 요구사항·자료형과 단위, 구현 오류와 운영 환경 때문에 실제 시스템에서 실패할 수 있다. 수학적 정확성과 소프트웨어 공학적 검증을 함께 수행해야 한다.

통계와 실험

통계는 시험·성능·사용자 연구와 운영 데이터의 해석에 사용된다.

다음과 같은 활동에서 활용된다.

  • 결함과 장애 추세 분석
  • 성능 측정
  • 부하 시험 결과
  • 사용자 실험
  • A/B 시험
  • 품질 표본 검사
  • 신뢰성 추정
  • 위험과 불확실성 분석
  • 기계학습 평가
  • 프로젝트 추정

평균값만으로 시스템의 특성을 판단하면 사용자 일부가 경험하는 극단적인 지연과 오류를 놓칠 수 있다. 분포·백분위와 표본 수, 측정 오차를 고려해야 한다.

두 버전의 지표가 다르다는 사실만으로 변경이 원인이라고 단정할 수 없다. 실험 설계와 교란 요인, 통계적 유의성과 실제 영향의 크기를 함께 분석한다.

소프트웨어 공학에서는 측정값을 단순한 성과 목표로 사용하기보다 제품과 프로세스에 관한 가설을 평가하는 증거로 사용한다.

논리와 형식 방법

논리와 형식 방법은 시스템의 요구와 동작을 모호하지 않은 언어로 표현하고 분석하는 데 사용된다.

적용 영역에는 다음이 있다.

  • 타입 시스템
  • 프로그램 검증
  • 모델 검사
  • 정리 증명
  • 프로토콜 분석
  • 상태 기계
  • 불변 조건
  • 동시성
  • 보안 정책
  • 안전 관련 제어

형식 방법은 가능한 실행 상태를 체계적으로 분석하고 특정 오류가 존재하지 않음을 증명하는 데 사용할 수 있다.

그러나 실제 사용자의 필요와 물리적 환경을 잘못 모델링하면 형식적으로 올바른 시스템이 실제로는 잘못된 기능을 수행할 수 있다.

따라서 형식 명세도 요구사항 공학과 도메인 검토·실제 시험의 대상이 된다.

인간-컴퓨터 상호작용

인간-컴퓨터 상호작용(Human–Computer Interaction, HCI)은 사람이 컴퓨터 시스템과 상호작용하는 방법을 연구하고 유용하며 사용하기 쉬운 기술을 설계하는 학제간 분야이다.

ACM은 HCI를 컴퓨터 과학자·소프트웨어 엔지니어·심리학자·상호작용 및 그래픽 디자이너·사회학자와 인류학자의 전문성을 결합하는 분야로 설명한다.[174]

HCI는 다음을 다룬다.

  • 사용자와 사용 환경 조사
  • 상호작용 설계
  • 정보 구조
  • 화면과 입력
  • 사용자 연구
  • 프로토타이핑
  • 사용성 평가
  • 접근성
  • 인지와 인간 오류
  • 협업과 사회적 사용
  • 새로운 상호작용 장치
  • 문화와 언어 차이

소프트웨어 공학과 HCI는 요구사항·설계·시험에서 만난다.

소프트웨어 공학이 내부 구조와 품질·변경 가능성에 집중하고 HCI가 사용자 경험을 다룬다고 완전히 분리할 수는 없다. 사용자 인터페이스의 흐름은 도메인 모델과 상태 관리·비동기 처리와 오류 구조에 영향을 준다.

HCI에서 만든 프로토타입이 기술적으로 구현 불가능하거나 장기적인 유지보수 구조를 고려하지 않을 수 있고, 소프트웨어 엔지니어가 기술적으로 완전한 기능을 만들었지만 사용자가 이해하지 못할 수도 있다.

따라서 사용자 연구와 기술 설계는 순차적인 인수인계보다 반복적인 협업으로 수행하는 편이 적절하다.

사용자 경험 디자인

사용자 경험 디자인은 사용자가 제품을 발견·학습하고 목표를 달성하며 지원을 받는 전체 경험을 설계한다.

다음과 같은 영역이 포함될 수 있다.

  • 사용자 조사
  • 정보 구조
  • 상호작용 흐름
  • 시각 디자인
  • 콘텐츠와 문구
  • 접근성
  • 온보딩
  • 오류와 복구
  • 서비스와 지원
  • 브랜드와 감정적 경험

소프트웨어 요구사항은 사용자 경험 디자인의 결과를 기능과 품질 조건으로 구체화한다.

예를 들어 “쉽게 사용할 수 있어야 한다”는 목표는 다음과 같이 구체화될 수 있다.

  • 대표 사용자가 도움 없이 작업을 완료할 수 있어야 한다.
  • 오류가 발생하면 원인과 복구 방법을 제공해야 한다.
  • 키보드와 보조 기술로 주요 기능을 사용할 수 있어야 한다.
  • 처리 중 상태와 취소 가능 여부를 표시해야 한다.
  • 중요한 선택의 결과를 실행 전에 이해할 수 있어야 한다.

사용자 경험과 소프트웨어 구조를 별개로 관리하면 구현 과정에서 중요한 상호작용이 기술적 제약에 의해 손상될 수 있다.

심리학과 인지과학

심리학과 인지과학은 사람이 정보를 인식·기억하고 판단하며 실수하는 방식을 이해하는 데 도움을 준다.

소프트웨어 설계와 관련된 주제에는 다음이 있다.

  • 주의와 작업 기억
  • 학습
  • 정신 모형
  • 시각적 인식
  • 의사결정
  • 습관
  • 자동화 편향
  • 경고 피로
  • 오류와 회복
  • 신뢰
  • 동기와 행동 변화

운영자와 사용자의 실수를 개인의 부주의로만 설명하면 같은 문제가 반복될 수 있다. 인터페이스와 절차·조직이 실수를 유도하거나 발견하기 어렵게 만들었는지 분석해야 한다.

안전 관련 시스템에서는 인간의 반응 시간·피로와 환경적 스트레스가 소프트웨어 요구사항과 경고 설계에 직접 영향을 준다.

사회학과 조직 연구

소프트웨어는 조직과 사회의 기존 관계 안에서 사용되며 새로운 관계를 만들기도 한다.

사회학과 조직 연구는 다음 문제를 이해하는 데 도움을 준다.

  • 기술 도입에 대한 저항
  • 업무와 권력 관계
  • 공식 절차와 실제 관행의 차이
  • 협업과 의사소통
  • 팀과 조직 구조
  • 전문 공동체
  • 플랫폼과 사용자 집단
  • 감시와 통제
  • 기술로 인한 직무 변화
  • 사회적 불평등

조직의 업무를 단순한 화면과 데이터 흐름으로만 이해하면 비공식적인 협력과 예외 처리·책임 관계를 놓칠 수 있다.

새로운 시스템이 기존 작업을 자동화할 때 일부 사용자의 권한과 자율성을 줄이거나 다른 사람에게 추가 업무를 만들 수 있다. 이러한 변화는 기술적 요구사항과 함께 분석해야 한다.

경영학

경영학은 조직이 자원과 사람·제품과 시장을 관리하여 목표를 달성하는 방식을 다룬다.

소프트웨어 공학과 관련된 영역에는 다음이 있다.

  • 전략
  • 조직 관리
  • 회계와 재무
  • 마케팅
  • 운영 관리
  • 인사
  • 제품 관리
  • 공급망
  • 혁신
  • 기업가 정신
  • 위험 관리

소프트웨어 제품은 기술적으로 가능하다는 이유만으로 개발되지 않는다. 어떤 사용자에게 어떤 가치를 제공하고, 개발·운영 비용을 감당하며, 조직의 전략과 규제에 맞는지를 검토해야 한다.

경영 목표가 소프트웨어 요구사항과 우선순위에 영향을 주며, 소프트웨어의 기술적 제약과 위험도 사업 전략을 제한할 수 있다.

예를 들어 빠른 시장 진입을 위해 외부 플랫폼을 사용할 수 있지만 장기적으로 높은 사용료와 공급자 종속이 발생할 수 있다. 이러한 결정은 기술·재무와 제품 전략을 함께 고려해야 한다.

제품 관리

제품 관리는 제품이 어떤 사용자 문제를 해결하고 어떤 가치와 방향을 가져야 하는지를 지속적으로 결정한다.

제품 관리에는 다음 활동이 포함될 수 있다.

  • 사용자와 시장 조사
  • 제품 비전과 목표
  • 가치와 성과 정의
  • 기능과 투자 우선순위
  • 제품 로드맵
  • 가격과 출시
  • 사용자 피드백
  • 제품 지표
  • 제품의 성장과 종료
  • 이해관계자 조정

소프트웨어 공학은 제품 목표를 실제로 구현 가능한 요구사항·아키텍처와 릴리스로 변환한다.

제품 관리가 무엇을 왜 만들 것인가에 집중한다면 소프트웨어 공학은 어떻게 신뢰할 수 있고 지속 가능한 방식으로 만들 것인가를 다룬다고 구분할 수 있다. 실제로는 두 결정이 서로 영향을 준다.

기능의 가치와 기술 비용·위험을 분리하여 판단하면 실현 불가능한 계획이나 기술적으로 우수하지만 가치가 낮은 제품이 만들어질 수 있다.

프로젝트 관리

프로젝트 관리는 특정 목표와 결과를 만들기 위해 범위·일정·비용·인력·위험과 이해관계자를 조정한다.

소프트웨어 프로젝트 관리와 소프트웨어 공학 관리는 다음 영역에서 겹친다.

  • 프로젝트 착수와 범위
  • 작업과 일정 계획
  • 노력과 비용 추정
  • 위험 관리
  • 품질 계획
  • 이해관계자와 의사소통
  • 공급자와 계약
  • 변경 관리
  • 진행 측정
  • 프로젝트 종료

일반 프로젝트 관리의 원칙은 소프트웨어 프로젝트에도 적용되지만 소프트웨어에는 다음과 같은 특성이 있다.

  • 진행 상태가 물리적으로 잘 보이지 않는다.
  • 요구와 해결 방법의 불확실성이 크다.
  • 코드와 설계 변경 비용이 균일하지 않다.
  • 통합과 시험 위험이 후반에 집중될 수 있다.
  • 소프트웨어는 출시 후에도 계속 변경된다.
  • 사람과 팀의 지식이 주요 자산이다.
  • 자동화와 기술 부채가 전달 속도에 영향을 준다.

따라서 소프트웨어 프로젝트 관리는 작동하고 검증된 소프트웨어·남은 위험과 실제 피드백을 중심으로 진행 상태를 판단해야 한다.

프로젝트 관리가 기술적 설계와 품질 판단을 대신할 수 없으며, 소프트웨어 엔지니어도 일정·비용과 조직적 제약을 무시할 수 없다.

운영 관리

운영 관리는 조직의 제품과 서비스를 일상적으로 제공하는 과정과 자원·품질을 관리한다.

소프트웨어 서비스에서는 다음 영역과 연결된다.

  • 서비스 운영
  • 용량
  • 공급자
  • 비용
  • 지원
  • 장애
  • 변경
  • 업무 연속성
  • 사용자 서비스 수준
  • 운영 지표

소프트웨어 공학의 배포·관찰 가능성과 자동화는 운영 관리의 기술적 기반을 제공한다.

운영 과정에서 발견한 병목과 반복 수작업은 소프트웨어 요구사항과 아키텍처 개선으로 돌아가야 한다. 개발과 운영을 별개의 조직으로 완전히 분리하면 이러한 피드백이 늦어질 수 있다.

경제학

경제학은 희소한 자원과 선택·인센티브와 시장을 분석한다.

소프트웨어 공학과 관련된 경제적 문제에는 다음이 있다.

  • 개발과 운영 비용
  • 자체 개발과 구매
  • 기술 부채
  • 기능의 기회비용
  • 플랫폼과 네트워크 효과
  • 가격과 수익 모델
  • 오픈소스 생태계
  • 공급자 종속
  • 전환 비용
  • 유지보수와 지원
  • 보안과 품질에 대한 투자
  • 외부 효과

모든 품질 속성을 최대화할 수 없으므로 위험과 가치·비용을 비교해야 한다.

단기 비용을 줄이기 위해 시험과 구조 개선을 생략하면 이후의 변경과 장애 비용이 증가할 수 있다. 반대로 미래에 필요할 가능성만으로 지나치게 일반적인 구조를 만들면 현재의 기능과 일정 비용이 증가한다.

소프트웨어 경제학은 이러한 생명주기 비용과 불확실성·투자의 선택을 다룬다.

법학

소프트웨어의 개발과 사용은 여러 법률과 계약의 적용을 받는다.

관련 영역에는 다음이 있다.

  • 저작권
  • 특허
  • 상표
  • 영업 비밀
  • 오픈소스 라이선스
  • 개인정보
  • 소비자 보호
  • 전자상거래
  • 접근성
  • 안전과 제품 책임
  • 사이버 보안
  • 노동과 감시
  • 수출 통제
  • 산업별 규제
  • 계약과 서비스 수준
  • 기록과 증거

개발자는 모든 법률을 독자적으로 판단할 필요는 없지만 기술적 결정이 법적 요구에 영향을 줄 수 있음을 이해해야 한다.

예를 들어 데이터 삭제 요구는 사용자 인터페이스의 삭제 버튼만 추가하는 것으로 해결되지 않는다. 데이터베이스·백업과 로그·외부 공급자와 보존 정책 전체를 설계해야 한다.

라이선스 조건은 외부 패키지 선택과 제품 배포 방식에 영향을 준다. 안전 규제는 요구사항·시험과 변경 기록의 수준을 결정할 수 있다.

법률 담당자도 실제 시스템의 데이터 흐름과 기술적 제약을 알아야 올바른 판단을 내릴 수 있으므로 지속적인 협업이 필요하다.

사이버 보안

사이버 보안은 정보와 시스템·네트워크와 사회 기반 시설을 공격·무단 접근과 손상에서 보호하는 폭넓은 분야이다.

사이버 보안에는 다음이 포함될 수 있다.

  • 네트워크 보안
  • 시스템 보안
  • 응용 프로그램 보안
  • 암호학
  • 신원과 접근 관리
  • 보안 운영
  • 사건 대응
  • 디지털 포렌식
  • 위협 정보
  • 위험 관리
  • 공급망 보안
  • 정책과 거버넌스

소프트웨어 보안은 사이버 보안 가운데 소프트웨어의 요구사항·설계·구현과 생명주기에 직접 관련된 영역이다.

NIST의 Secure Software Development Framework는 많은 소프트웨어 생명주기 모델이 보안을 상세히 다루지 않으므로 안전한 소프트웨어 개발 관행을 각 생명주기 구현에 통합해야 한다고 설명한다.[175]

보안 담당자가 출시 전에 취약점 검사만 수행하는 구조로는 설계 수준의 권한과 데이터 흐름 문제를 늦게 발견할 수 있다.

보안 요구·위협 모델과 안전한 개발 환경, 코드 검토·시험과 취약점 대응을 소프트웨어 공학 과정에 통합해야 한다.

암호학

암호학은 정보의 기밀성·무결성·인증과 관련된 수학적 알고리즘과 프로토콜을 연구한다.

소프트웨어 공학은 암호 알고리즘을 실제 시스템에서 다음과 같이 사용한다.

  • 통신 암호화
  • 데이터 저장 보호
  • 비밀번호 저장
  • 디지털 서명
  • 인증서
  • 패키지와 업데이트 검증
  • 키 관리
  • 사용자와 서비스 인증

암호 알고리즘이 안전하더라도 구현과 통합이 잘못되면 시스템은 취약할 수 있다.

  • 약한 난수를 사용한다.
  • 인증서 검증을 생략한다.
  • 키를 소스 코드에 저장한다.
  • 같은 키를 지나치게 오래 사용한다.
  • 오류 메시지로 비밀 정보를 드러낸다.
  • 암호화되지 않은 복사본을 로그에 남긴다.
  • 안전하지 않은 기본 설정을 제공한다.

따라서 암호학적 정확성과 키의 생명주기·사용자 경험과 운영·복구를 함께 설계해야 한다.

안전 공학

안전 공학은 시스템과 작업이 사람·재산과 환경에 일으킬 수 있는 위험을 식별하고 허용 가능한 수준으로 낮춘다.

소프트웨어 안전은 안전 공학의 일부로 다음을 다룬다.

  • 소프트웨어가 위험원에 기여하는 방식
  • 안전 기능과 상태
  • 고장과 오류 처리
  • 독립성과 격리
  • 안전 요구사항
  • 검증과 증거
  • 변경과 구성 관리
  • 운영과 유지보수
  • 사용자와 인간 오류

소프트웨어 팀이 개별 기능의 시험만 통과했다고 전체 시스템이 안전한 것은 아니다.

센서·하드웨어와 통신·사용자의 행동이 결합된 시나리오를 시스템 수준에서 분석해야 한다. 안전 공학은 소프트웨어 공학에 위험의 우선순위와 필요한 개발 엄격성을 제공하고, 소프트웨어 공학은 안전 기능을 실제 구현·검증하는 방법을 제공한다.

신뢰성 공학

신뢰성 공학은 제품과 시스템이 정해진 조건과 기간 동안 요구 기능을 수행할 가능성과 고장 특성을 분석한다.

소프트웨어와 관련된 활동에는 다음이 있다.

  • 고장과 실패 모델
  • 가용성
  • 복구
  • 중복과 장애 조치
  • 신뢰성 시험
  • 운영 데이터 분석
  • 고장률과 수리 시간
  • 예방 유지보수
  • 위험과 용량

물리적 부품은 사용과 시간에 따라 마모될 수 있지만 소프트웨어 자체는 같은 방식으로 마모되지 않는다. 다만 환경·데이터와 변경이 누적되면서 새로운 실패 조건이 나타난다.

소프트웨어 신뢰성은 코드 결함뿐 아니라 배포·설정과 외부 서비스·운영 절차에 영향을 받는다.

사이트 신뢰성 공학은 소프트웨어 공학과 자동화를 대규모 서비스 운영에 적용하여 신뢰성과 변경 속도를 관리한다.

품질 경영

품질 경영은 조직이 제품과 서비스의 품질 목표를 정의하고 프로세스와 측정·개선을 통해 이를 지속적으로 달성하는 방법을 다룬다.

소프트웨어 공학과 연결되는 활동에는 다음이 있다.

  • 품질 계획
  • 요구사항과 표준
  • 품질 보증
  • 시험과 검토
  • 감사
  • 결함과 원인 분석
  • 프로세스 개선
  • 공급자 품질
  • 사용자 만족
  • 측정과 보고

품질 경영의 일반 원칙을 소프트웨어에 적용할 때는 코드와 소프트웨어 변경의 특성을 고려해야 한다.

문서와 절차를 많이 만든다고 품질이 높아지는 것은 아니며, 자동 시험과 실제 운영 피드백·구조적 개선을 통해 품질을 검증해야 한다.

산업공학

산업공학은 사람·기계·정보와 자원의 통합된 시스템을 분석하고 효율성과 품질을 개선한다.

소프트웨어 공학과 연결되는 영역에는 다음이 있다.

  • 프로세스 분석
  • 작업 흐름
  • 대기와 병목
  • 품질 관리
  • 통계적 측정
  • 자원 계획
  • 공급망
  • 인간공학
  • 운영 최적화
  • 자동화

소프트웨어 개발 과정도 작업 대기·인수인계와 반복적인 오류를 가진 생산 시스템으로 분석할 수 있다.

다만 소프트웨어 개발은 동일 제품을 반복 생산하는 제조 과정과 다르게, 요구와 해결 방법을 탐색하는 지식 작업의 성격이 크다. 제조의 효율화 기법을 그대로 적용하여 개발자의 모든 행동을 표준화하면 창의적 문제 해결과 학습을 방해할 수 있다.

린 소프트웨어 개발은 산업 생산에서 발전한 낭비 감소·흐름과 지속적 개선의 원리를 소프트웨어의 특성에 맞게 적용한다.

기계공학과 물리학

시뮬레이션·게임·로봇과 기계 제어 소프트웨어는 물리학과 기계공학의 모델을 구현한다.

관련 영역에는 다음이 있다.

  • 역학
  • 유체
  • 재료
  • 동역학
  • 기구학
  • 수치 시뮬레이션
  • 센서와 구동기
  • CAD와 제조
  • 디지털 트윈

소프트웨어 엔지니어는 도메인 전문가가 정의한 물리 모델을 정확한 자료형·알고리즘과 시간 적분으로 구현해야 한다.

단위와 좌표계·정밀도와 안정성 문제는 일반적인 문법 오류보다 더 심각한 결과를 만들 수 있다.

물리 모델의 정확도와 계산 비용 사이의 균형도 필요하다. 실시간 게임과 제어 시스템에서는 완전한 물리적 정확성보다 제한된 시간 안에 안정된 결과를 제공해야 할 수 있다.

그래픽 디자인과 시각화

그래픽 디자인은 정보를 시각적으로 조직하고 의미·계층과 정체성을 전달한다.

소프트웨어와 관련된 영역에는 다음이 있다.

  • 화면 배치
  • 타이포그래피
  • 색상
  • 아이콘
  • 시각적 계층
  • 애니메이션
  • 데이터 시각화
  • 브랜드
  • 접근성

그래픽 디자인은 단순한 장식이 아니다. 사용자가 정보와 상태·행동 가능성을 이해하는 데 영향을 준다.

소프트웨어 구현에서는 다양한 화면 크기와 언어·보조 기술, 동적 데이터와 오류 상태를 처리해야 한다.

정적인 화면 설계와 실제 동작하는 인터페이스 사이의 차이를 줄이기 위해 디자인 시스템·재사용 가능한 구성 요소와 자동 시각 시험을 사용할 수 있다.

언어학

언어학은 자연어의 구조와 의미·사용을 연구하며 소프트웨어의 여러 영역과 연결된다.

  • 요구사항 문장
  • 사용자 인터페이스 문구
  • 검색
  • 음성 인식과 합성
  • 자연어 처리
  • 번역과 국제화
  • 프로그래밍 언어
  • 대화형 인터페이스
  • 오류 메시지
  • 정보 검색

요구사항에서 같은 단어가 이해관계자마다 다른 의미를 가지면 구현과 수용에 문제가 생길 수 있다. 용어집과 도메인 모델을 통해 의미를 정리한다.

사용자 인터페이스의 문구는 기능과 오류·권한의 의미를 전달하므로 단순한 번역 대상이 아니다.

자연어 처리 시스템에서는 언어별 문법과 문화·편향과 데이터의 대표성을 고려해야 한다.

커뮤니케이션과 기술 문서

소프트웨어 공학은 여러 전문 분야와 이해관계자가 협력하는 활동이므로 의사소통 능력이 중요하다.

다음과 같은 자료를 작성할 수 있다.

  • 요구사항
  • 설계와 결정 기록
  • 코드와 API 문서
  • 시험 계획과 결과
  • 결함 보고
  • 프로젝트 상태
  • 운영 절차
  • 장애 보고
  • 사용자 문서
  • 보안과 안전 증거

기술적으로 정확하지만 독자가 이해할 수 없는 문서는 의사결정과 사용에 도움이 되지 않는다.

같은 시스템도 개발자·운영자와 사용자·경영진에게 필요한 정보와 상세 수준이 다르다.

문서는 의사소통을 대체하기보다 결정과 지식을 장기간 보존하고 서로 다른 시간과 장소에서 협력하게 한다.

교육학

교육용 소프트웨어와 개발자 도구·사용자 온보딩에서는 학습의 원리를 고려해야 한다.

교육학과 연결되는 문제에는 다음이 있다.

  • 학습 목표
  • 선수 지식
  • 설명과 예제
  • 연습과 피드백
  • 난이도 조정
  • 평가
  • 접근성과 포용
  • 학습 데이터
  • 교사와 학습자의 역할

정보를 많이 제공한다고 학습이 일어나는 것은 아니다. 사용자가 실제로 이해하고 적용할 수 있는 구조와 피드백을 설계해야 한다.

소프트웨어 팀 내부에서도 온보딩·교육과 지식 공유에 교육학적 접근을 사용할 수 있다.

도메인 공학

소프트웨어는 특정한 문제 영역의 개념과 규칙을 구현한다. 금융·의료·법률·게임과 제조에서는 서로 다른 도메인 지식이 필요하다.

도메인 공학은 특정 문제 영역에서 공통으로 나타나는 개념·변형과 재사용 가능한 자산을 체계적으로 분석하고 구축한다.

다음과 같은 활동을 포함할 수 있다.

  • 도메인 개념과 용어
  • 공통 기능
  • 제품별 변형
  • 참조 아키텍처
  • 공통 모듈
  • 제품군
  • 설정과 기능 모델
  • 도메인별 표준

도메인 공학은 여러 유사한 제품을 독립적으로 반복 개발하는 대신 공통성과 차이를 관리한다.

공통 플랫폼을 지나치게 일반화하면 개별 제품의 단순한 요구도 복잡하게 만들 수 있다. 실제로 반복되는 기능과 장기적인 제품 전략을 기준으로 재사용 범위를 정한다.

도메인 전문가

소프트웨어 엔지니어는 프로그램과 기술의 전문가일 수 있지만 의료·금융·법률과 산업 공정의 전문가는 아닐 수 있다.

도메인 전문가는 다음을 제공한다.

  • 실제 업무의 목적
  • 용어와 개념
  • 규칙과 예외
  • 위험과 우선순위
  • 법률과 표준
  • 실제 데이터
  • 사용 환경
  • 수용 기준
  • 잘못된 결과의 영향

도메인 전문가가 요구를 말하고 개발자가 그대로 구현하는 단순한 인수인계로는 충분하지 않을 수 있다.

도메인 규칙이 암묵적이거나 서로 다른 전문가의 의견이 충돌할 수 있으므로 모델·프로토타입과 실행 가능한 사례를 함께 검토한다.

소프트웨어 엔지니어도 도메인의 기본 구조를 학습해야 기술적 결정이 업무 의미를 손상하지 않는지 판단할 수 있다.

과학과 연구

과학 연구에서는 소프트웨어가 실험·시뮬레이션과 데이터 분석의 핵심 도구로 사용된다.

연구 소프트웨어에는 다음 문제가 있다.

  • 계산의 정확성
  • 실험 재현성
  • 데이터와 코드의 버전
  • 수치 안정성
  • 장기 보존
  • 성능
  • 연구자의 임시 코드
  • 다른 연구자의 재사용
  • 검증과 동료 평가
  • 하드웨어와 환경 차이

연구용 초기 코드는 가설을 빠르게 탐색하기 위해 만들어질 수 있다. 연구 결과와 장기적인 기반으로 사용되면 시험·문서와 구성 관리·재현 가능한 환경이 필요하다.

소프트웨어 공학의 모든 절차를 작은 실험에 동일하게 적용할 필요는 없지만 결과의 중요성과 재사용 범위에 따라 공학적 엄격성을 높여야 한다.

의료와 생명과학

의료 소프트웨어는 환자 정보·진단과 치료·의료 장비를 다루며 높은 안전·개인정보와 규제 요구를 가질 수 있다.

관련 전문 지식에는 다음이 있다.

  • 의학과 생물학
  • 임상 절차
  • 의료 용어와 데이터
  • 환자 안전
  • 의료기기 공학
  • 개인정보
  • 인간 요인
  • 규제와 품질
  • 통계와 연구 윤리

소프트웨어 엔지니어는 의료 전문가와 함께 잘못된 결과·지연과 사용자 오류가 환자에게 미칠 영향을 분석해야 한다.

정확도만 높은 인공지능 모델이라도 임상 절차와 맞지 않거나 특정 환자 집단에서 성능이 낮고 이의를 제기할 수 없다면 실제 의료 시스템에 적합하지 않을 수 있다.

금융

금융 소프트웨어는 거래·결제·시장과 위험을 다루며 정확성·보안·감사와 규제 요구가 중요하다.

필요한 지식에는 다음이 있다.

  • 회계
  • 금융 상품
  • 시장과 거래
  • 위험 관리
  • 규제
  • 사기 탐지
  • 개인정보
  • 분산 시스템
  • 수치 계산
  • 감사

금액의 자료형과 반올림·통화와 거래 시각, 중복 처리와 취소는 일반적인 프로그래밍 세부 사항처럼 보이지만 실제 재정적 결과를 만든다.

금융 도메인의 불변 조건과 감사 요구를 코드·데이터와 시험에 반영해야 한다.

게임 개발

게임 개발은 소프트웨어 공학과 그래픽스·물리·인공지능·사운드와 디자인·예술을 결합한다.

게임 개발에서는 다음 분야가 함께 참여한다.

  • 게임 디자인
  • 프로그래밍
  • 컴퓨터 그래픽스
  • 물리 시뮬레이션
  • 인공지능
  • 애니메이션
  • 사운드
  • 네트워크
  • 사용자 경험
  • 서사와 예술
  • 운영과 커뮤니티
  • 사업과 수익 모델

게임 엔진과 도구는 일반 소프트웨어 제품과 같은 아키텍처·시험과 구성 관리가 필요하다. 동시에 프레임 시간·입력 지연과 다양한 하드웨어, 콘텐츠 제작 파이프라인을 다뤄야 한다.

재미와 감정적 경험은 기능 명세만으로 완전히 정의하기 어려우므로 프로토타입·플레이테스트와 반복적인 디자인이 중요하다.

온라인 게임에서는 출시 뒤 서버 운영·부정행위 대응과 경제·커뮤니티 관리가 소프트웨어 공학과 연결된다.

웹 개발

웹 개발은 웹 브라우저와 서버·네트워크와 웹 표준을 이용하여 응용 프로그램과 콘텐츠를 만든다.

웹 개발은 소프트웨어 공학의 응용 영역이며 다음과 연결된다.

  • 프런트엔드와 사용자 인터페이스
  • 서버와 API
  • 데이터베이스
  • 네트워크
  • 보안
  • 접근성
  • 검색과 성능
  • 분산 시스템
  • 클라우드와 운영
  • 웹 표준
  • 개인정보

작은 정적 웹 페이지부터 세계적인 규모의 분산 서비스까지 모두 웹이라는 실행 환경을 사용하지만 필요한 공학적 규모는 다르다.

웹 프레임워크의 사용법과 소프트웨어 공학은 같지 않다. 프레임워크를 사용하더라도 요구사항·아키텍처·시험과 보안·운영을 별도로 설계해야 한다.

웹의 빠른 배포 가능성은 피드백을 빠르게 하지만, 호환성과 개인정보·공급망과 운영 장애의 범위도 크게 만들 수 있다.

모바일 개발

모바일 소프트웨어는 휴대용 장치의 운영체제·센서와 네트워크, 앱 배포 생태계의 제약을 받는다.

관련 문제에는 다음이 있다.

  • 배터리와 성능
  • 화면과 입력
  • 센서와 위치
  • 일시적인 네트워크
  • 백그라운드 실행
  • 권한
  • 개인정보
  • 운영체제 버전
  • 장치 다양성
  • 앱 심사와 배포
  • 오프라인 데이터
  • 접근성

서버와 달리 사용자의 장치에 설치된 버전을 즉시 모두 교체할 수 없으므로 여러 앱과 서버 버전의 호환성을 유지해야 한다.

모바일 개발은 HCI·보안과 분산 시스템·운영을 함께 요구하는 소프트웨어 공학 영역이다.

클라우드 컴퓨팅

클라우드 컴퓨팅은 필요에 따라 컴퓨팅·저장소와 네트워크, 관리 서비스를 제공한다.

소프트웨어 공학과 관련된 영역에는 다음이 있다.

  • 분산 아키텍처
  • 자동 확장
  • 인프라 코드화
  • 지속적 배포
  • 관찰 가능성
  • 장애와 복구
  • 비용 관리
  • 보안과 책임 분담
  • 지역과 데이터 규제
  • 공급자 종속

클라우드 서비스는 인프라 작업을 줄일 수 있지만 시스템의 책임이 사라지는 것은 아니다.

공급자가 하드웨어와 일부 플랫폼을 운영하더라도 응용 프로그램의 데이터·권한과 설정, 아키텍처와 사용자 보호는 개발 조직의 책임으로 남을 수 있다.

클라우드의 자원 생성이 쉬우면 비용과 복잡성이 빠르게 증가할 수 있으므로 기술·운영과 경제적 관점을 함께 사용해야 한다.

분산 시스템

분산 시스템은 여러 컴퓨터와 프로세스가 네트워크를 통해 하나의 목표를 수행한다.

분산 시스템 이론은 다음을 다룬다.

  • 통신
  • 시간과 순서
  • 합의
  • 복제
  • 일관성
  • 부분 실패
  • 분산 트랜잭션
  • 장애 모델
  • 확장성

소프트웨어 공학은 이를 실제 서비스에 적용하면서 다음을 추가로 다룬다.

  • 서비스 경계
  • API와 데이터 계약
  • 버전 호환성
  • 배포와 롤백
  • 인증과 권한
  • 관찰 가능성
  • 운영과 사건 대응
  • 비용
  • 팀의 소유권
  • 사용자 경험

분산 알고리즘이 이론적으로 올바르더라도 잘못된 시간 제한·재시도와 운영 설정으로 시스템이 실패할 수 있다.

소프트웨어 공학과 과학의 차이

과학은 자연·사회와 형식적 현상을 설명하고 예측하는 지식을 얻는 데 중심을 둔다. 공학은 제약과 상충 관계 속에서 원하는 목적을 달성하는 인공 시스템을 만든다.

소프트웨어 공학에서도 과학적 방법이 사용된다.

  • 가설을 세운다.
  • 측정과 실험을 수행한다.
  • 데이터를 분석한다.
  • 대안을 비교한다.
  • 결과를 재현한다.
  • 이론과 모델을 검증한다.

그러나 소프트웨어 공학의 최종 목표는 현상을 설명하는 데 그치지 않고 실제 사용 가능한 소프트웨어를 만드는 데 있다.

같은 문제에도 비용·일정과 조직·기존 시스템에 따라 여러 적절한 설계가 존재할 수 있다. 공학적 결정은 절대적인 최적해보다 주어진 문맥에서 허용 가능한 균형을 찾는다.

다른 공학 분야와의 공통점

소프트웨어 공학은 다른 공학 분야와 다음 원리를 공유한다.

  • 요구와 목적을 명확히 한다.
  • 제약과 위험을 분석한다.
  • 여러 설계 대안을 비교한다.
  • 모델과 프로토타입을 사용한다.
  • 구성 요소와 인터페이스를 정의한다.
  • 품질과 안전을 검증한다.
  • 변경과 구성을 관리한다.
  • 비용과 생명주기를 고려한다.
  • 전문 표준과 윤리를 따른다.
  • 실패와 운영 경험을 개선에 반영한다.

소프트웨어는 물리적인 재료와 다른 특성도 가진다.

  • 복사 비용이 매우 낮다.
  • 코드 변경으로 제품의 동작을 크게 바꿀 수 있다.
  • 내부 구조가 외부에서 잘 보이지 않는다.
  • 물리적으로 마모되지는 않지만 변경으로 복잡성이 누적된다.
  • 자동화된 시험과 배포가 가능하다.
  • 동일한 제품이 매우 다양한 하드웨어와 환경에서 실행된다.
  • 소프트웨어 자체가 다른 공학 활동의 설계와 제어 도구가 된다.

따라서 다른 공학 분야의 절차를 그대로 복사하기보다 공학 원리를 소프트웨어의 특성에 맞게 적용해야 한다.

학제간 협업

복잡한 소프트웨어 프로젝트에서는 어느 한 분야도 전체 문제를 독립적으로 해결하기 어렵다.

학제간 협업에서는 다음이 중요하다.

  • 공통 목표와 사용자
  • 용어와 개념의 정의
  • 분야 사이의 인터페이스
  • 가정과 제약
  • 결정 권한
  • 위험과 품질 기준
  • 공동 모델과 프로토타입
  • 통합과 검증 계획
  • 정보와 변경의 추적
  • 서로의 전문성에 대한 존중

전문가가 자신의 결과만 전달하는 순차적인 방식에서는 문제가 인터페이스와 통합 단계에서 늦게 드러날 수 있다.

예를 들어 의료 장비에서는 임상의·안전 전문가와 전자·기계·소프트웨어 엔지니어, 사용자 경험과 규제 담당자가 초기 요구사항과 위험 분석부터 함께 참여해야 한다.

소프트웨어 엔지니어가 모든 분야의 전문가가 될 필요는 없지만, 다른 전문 분야의 요구를 코드와 시스템 구조로 변환하고 기술적 결과를 이해 가능한 언어로 설명할 수 있어야 한다.

분야 사이의 책임

여러 분야가 참여하는 프로젝트에서는 문제가 분야 사이의 경계에 남지 않도록 책임을 명확히 해야 한다.

다음과 같은 상황이 발생할 수 있다.

  • 시스템 요구는 있지만 소프트웨어에 할당되지 않는다.
  • 디자인에는 화면이 있지만 오류와 로딩 상태가 없다.
  • 보안 정책은 있지만 실제 API에서 검사되지 않는다.
  • 데이터 모델은 있지만 데이터 품질 책임자가 없다.
  • 인공지능 모델은 있지만 운영 중 성능 감시가 없다.
  • 하드웨어는 안전 상태를 가정하지만 소프트웨어가 이를 구현하지 않는다.
  • 법적 요구는 있지만 삭제와 보존 구조가 없다.
  • 프로젝트는 종료되지만 운영 소유자가 없다.

각 분야의 산출물을 인수하는 것만으로 통합이 끝나지 않는다. 전체 사용자 흐름과 실패 시나리오를 기준으로 책임이 연결되는지 확인해야 한다.

경계의 변화

소프트웨어가 사회와 산업 전반에 확산되면서 소프트웨어 공학과 다른 분야의 경계도 계속 변하고 있다.

  • 클라우드와 DevOps는 개발과 운영의 경계를 줄였다.
  • 데이터 과학과 기계학습은 코드·데이터와 모델의 공동 관리를 요구한다.
  • 사이버 물리 시스템은 소프트웨어와 물리적 안전을 결합한다.
  • 플랫폼과 앱 생태계는 기술 설계와 시장·거버넌스를 연결한다.
  • 생성형 인공지능은 개발 도구와 저작권·책임 문제를 함께 만든다.
  • 개인정보와 알고리즘 규제는 법률을 시스템 설계에 직접 반영하게 한다.
  • 소프트웨어 정의 차량과 네트워크는 전통적인 하드웨어 제품의 생명주기를 변화시킨다.

새로운 직무와 분야가 등장하더라도 요구사항·구조·품질과 변경·운영을 체계적으로 관리하는 소프트웨어 공학의 기본 문제는 유지된다.

통합적 위치

소프트웨어 공학은 컴퓨터 과학의 응용 분야로만 한정되지 않으며, 프로그래밍과 프로젝트 관리의 결합만을 뜻하지도 않는다.

컴퓨터 과학은 계산과 프로그램의 원리를 제공하고, 수학과 통계는 분석과 검증의 기반을 제공한다. 컴퓨터 공학과 다른 공학 분야는 물리적 시스템과 실행 환경을 제공한다. 시스템 공학은 전체 시스템의 목적과 생명주기·통합을 다룬다.

HCI와 디자인·심리학은 사람이 실제로 사용할 수 있는 상호작용을 만든다. 정보 시스템과 경영·경제는 조직과 제품의 목적·가치와 자원 제약을 제공한다. 법률·보안과 안전·윤리는 시스템이 지켜야 하는 권리와 책임·위험의 경계를 정한다. 각 도메인의 전문가는 소프트웨어가 구현해야 하는 실제 개념과 규칙을 제공한다.

소프트웨어 공학의 역할은 이러한 지식을 단순히 모으는 데 있지 않다. 서로 다른 요구와 제약을 분석하고, 실행 가능한 구조와 코드·시험과 운영 체계로 통합하며, 변경되는 전체 생명주기에서 그 결과에 책임지는 데 있다.

활용 분야

소프트웨어 공학은 소프트웨어가 사용되는 거의 모든 분야에 적용된다. 개인이 사용하는 작은 응용 프로그램부터 운영체제·세계적인 웹 서비스·산업 설비와 우주선의 제어 시스템까지 규모와 목적은 서로 다르지만, 요구사항을 분석하고 구조를 설계하며 구현·시험·배포하고 지속적으로 변경한다는 기본 문제를 공유한다.

다만 모든 분야에 동일한 개발 절차와 품질 기준을 적용하지는 않는다. 오락용 모바일 앱의 일시적인 화면 오류와 의료 장비의 잘못된 투약 계산은 결과의 심각성이 다르다. 웹 서비스는 운영 중 빠르게 수정할 수 있지만, 인터넷과 분리된 산업 장치나 우주선의 소프트웨어는 배포 이후 접근과 교체가 제한될 수 있다. 범용 데스크톱 프로그램은 다양한 하드웨어와 사용자 환경을 지원해야 하고, 임베디드 장치는 제한된 메모리·전력과 실시간 조건을 충족해야 한다.

따라서 분야별 소프트웨어 공학에서는 다음 요소가 달라진다.

  • 요구사항의 안정성과 변경 속도
  • 사용자와 이해관계자의 종류
  • 시스템의 규모와 수명
  • 하드웨어와 실행 환경
  • 성능과 실시간성
  • 보안·안전과 개인정보 위험
  • 오류와 장애의 피해
  • 배포와 업데이트 가능성
  • 규제와 인증
  • 운영과 유지보수 방식
  • 외부 시스템과 공급자 의존성
  • 필요한 문서·시험과 증거의 수준

IEEE Computer Society의 SWEBOK V4.0a는 요구사항·아키텍처·설계·구축·시험·운영·유지보수·구성 관리·보안과 전문 실무를 포함하여 분야와 개발 방식에 관계없이 소프트웨어 공학에서 일반적으로 사용되는 지식을 정리한다.[176]

범용 응용 소프트웨어

응용 소프트웨어는 사용자가 문서 작성·통신·콘텐츠 제작·계산·정보 관리와 오락 같은 특정 작업을 수행하도록 돕는 소프트웨어이다.

대표적인 예에는 다음이 있다.

  • 문서 편집기
  • 스프레드시트
  • 프레젠테이션 도구
  • 전자우편 클라이언트
  • 웹 브라우저
  • 그래픽·영상과 음향 편집기
  • 개인 정보 관리 프로그램
  • 메신저와 협업 도구
  • 미디어 재생기
  • 회계와 재무 프로그램
  • 교육용 프로그램
  • 접근성 지원 도구

범용 응용 프로그램은 전문적인 기술 지식이 없는 사용자도 사용할 수 있어야 하므로 기능뿐 아니라 사용성·접근성·국제화와 오류 복구가 중요하다.

다양한 사용자 환경을 지원하는 프로그램에서는 다음을 고려해야 한다.

  • 여러 운영체제와 버전
  • 화면 크기와 입력 장치
  • 파일 형식과 호환성
  • 글꼴과 문자 인코딩
  • 지역·언어와 시간대
  • 사용자별 설정
  • 플러그인과 확장 기능
  • 오프라인과 네트워크 환경
  • 자동 저장과 데이터 복구
  • 업데이트와 이전 버전 호환성

문서 편집기와 콘텐츠 제작 도구에서는 사용자의 작업 결과가 중요한 자산이다. 프로그램 충돌과 저장 오류로 작업을 잃지 않도록 자동 저장·복구와 파일 무결성을 설계해야 한다.

파일 형식을 장기간 유지하는 제품은 이전 버전과 다른 프로그램에서 만들어진 자료를 읽고 쓸 수 있어야 한다. 형식의 변경과 확장 기능이 기존 문서를 손상하지 않도록 호환성과 이전을 관리한다.

시스템 소프트웨어

시스템 소프트웨어는 다른 소프트웨어가 실행되고 하드웨어와 자원을 사용할 수 있는 기반을 제공한다.

다음과 같은 소프트웨어가 포함된다.

  • 운영체제
  • 운영체제 커널
  • 장치 드라이버
  • 펌웨어
  • 부트로더
  • 컴파일러와 링커
  • 런타임과 가상 머신
  • 파일 시스템
  • 데이터베이스 관리 시스템
  • 가상화와 컨테이너 기반
  • 시스템 관리 도구
  • 네트워크 스택
  • 미들웨어

시스템 소프트웨어의 결함은 그 위에서 실행되는 많은 프로그램과 사용자에게 영향을 줄 수 있다. 따라서 인터페이스의 안정성·자원 격리와 오류 처리, 성능과 보안이 중요하다.

운영체제와 런타임은 다음과 같은 요구를 가진다.

  • 다양한 하드웨어 지원
  • 프로세스와 스레드 관리
  • 메모리와 저장소 관리
  • 장치와 입출력
  • 사용자와 권한
  • 오류와 장애 격리
  • 동시성과 동기화
  • 성능과 확장성
  • 보안 업데이트
  • 응용 프로그램 호환성
  • 시스템 진단과 복구

시스템 소프트웨어는 다른 프로그램의 동작에 대한 계약을 제공한다. 공개된 시스템 호출·ABI와 파일 형식이 변경되면 기존 프로그램이 실행되지 않을 수 있으므로 장기적인 호환성과 폐기 정책을 관리해야 한다.

커널·드라이버와 펌웨어는 높은 권한으로 실행되며 잘못된 메모리 접근과 동시성 결함이 시스템 전체의 중단이나 보안 침해로 이어질 수 있다. 코드 검토·정적 분석과 실제 하드웨어 시험, 다양한 오류 조건의 검증이 필요하다.

컴파일러와 런타임도 다른 소프트웨어를 만드는 기반이다. 잘못된 코드 생성과 최적화는 많은 프로그램에 같은 결함을 퍼뜨릴 수 있으므로 언어 사양·참조 시험과 여러 플랫폼의 검증이 중요하다.

프로그래밍 언어와 개발 도구

프로그래밍 언어 구현과 개발 도구도 소프트웨어 공학의 중요한 활용 영역이다.

다음이 포함될 수 있다.

  • 컴파일러
  • 인터프리터
  • 가상 머신
  • 디버거
  • 프로파일러
  • 코드 편집기와 통합 개발 환경
  • 빌드 시스템
  • 패키지 관리자
  • 정적 분석기
  • 시험 프레임워크
  • 코드 생성기
  • 버전 관리와 코드 검토 도구

이러한 도구는 다른 개발자의 생산성과 결과물의 정확성에 영향을 준다.

언어와 개발 도구에서는 다음이 중요하다.

  • 언어 사양과 구현의 일치
  • 오류 메시지와 진단
  • 빌드와 실행의 재현성
  • 대규모 코드베이스의 성능
  • 확장성과 플러그인 구조
  • 여러 운영체제와 아키텍처
  • 디버그 정보
  • 이전 버전과의 호환성
  • 패키지와 공급망 보안
  • 자동화 환경과의 통합

컴파일러의 오류는 사용자가 작성한 프로그램의 오류처럼 보일 수 있으므로 최소 재현 사례·회귀 시험과 명확한 버전 관리가 필요하다.

패키지 관리자는 많은 외부 코드를 자동으로 가져와 실행 환경에 포함하므로 버전 결정·무결성과 서명, 의존성 충돌과 지원 종료를 관리해야 한다.

웹 소프트웨어

웹 소프트웨어는 웹 브라우저·웹 서버와 인터넷 표준을 기반으로 사용자에게 콘텐츠와 응용 기능을 제공한다.

다음과 같은 형태가 있다.

  • 정적 웹사이트
  • 검색과 정보 서비스
  • 전자상거래
  • 소셜 네트워크
  • 온라인 문서와 협업
  • 동영상과 음악 서비스
  • 금융과 결제 서비스
  • 웹 기반 관리 도구
  • 교육과 공공 서비스
  • 소프트웨어형 서비스
  • 브라우저 기반 게임
  • 실시간 통신 서비스

웹 소프트웨어는 일반적으로 다음 구성 요소를 가진다.

  • 브라우저 사용자 인터페이스
  • 서버 응용 프로그램
  • API
  • 데이터베이스
  • 캐시
  • 메시지 시스템
  • 파일과 콘텐츠 저장소
  • 인증과 권한
  • 배포와 운영 인프라
  • 외부 서비스와 분석 도구

웹에서는 사용자가 별도의 설치 없이 새 버전을 이용할 수 있으므로 빠른 배포와 피드백이 가능하다. 그러나 하나의 잘못된 배포가 전체 사용자에게 즉시 영향을 줄 수 있다.

웹 소프트웨어에서는 다음이 중요하다.

  • 여러 브라우저와 장치의 호환성
  • 네트워크 지연과 일시적 단절
  • 대규모 동시 사용자
  • 인증과 세션
  • 웹 공격과 입력 검증
  • 개인정보와 추적
  • 검색과 접근성
  • 점진적 배포와 복구
  • 로그·메트릭과 추적
  • 외부 API와 공급자
  • 지속적인 운영

인터넷에 공개된 서비스는 신뢰할 수 없는 입력과 자동 공격에 지속적으로 노출된다. 보안은 출시 전 일회성 검사로 끝나지 않고 개발·배포와 운영 전체에 통합해야 한다.

NIST의 SSDF는 일반적인 소프트웨어 생명주기 모델이 보안을 상세히 포함하지 않는 경우가 많으므로 안전한 개발 관행을 각 생명주기 구현에 통합하도록 제시한다.[177]

클라우드 서비스

클라우드 컴퓨팅 환경에서는 컴퓨팅·저장소·데이터베이스와 네트워크를 필요한 만큼 생성하고 자동화된 방식으로 관리할 수 있다.

클라우드 소프트웨어에는 다음이 포함될 수 있다.

  • 가상 서버와 컨테이너 서비스
  • 관리형 데이터베이스
  • 객체 저장소
  • 서버리스 함수
  • 메시지와 이벤트 서비스
  • 콘텐츠 전송
  • 인공지능과 분석 서비스
  • 개발·빌드와 배포 플랫폼
  • 관찰과 보안 서비스
  • 여러 고객을 지원하는 SaaS

클라우드 환경의 소프트웨어 공학에서는 응용 프로그램 코드와 인프라·설정이 함께 관리된다.

다음과 같은 문제가 중요하다.

  • 자동 확장
  • 여러 가용 영역과 지역
  • 부분적인 장애
  • 서비스 간 인증
  • 데이터 복제와 일관성
  • 인프라 코드화
  • 비용과 사용량
  • 데이터 지역과 규제
  • 공급자 종속
  • 자원 한도
  • 관찰 가능성
  • 자동 복구
  • 다중 고객 격리

클라우드가 하드웨어 운영을 추상화하더라도 응용 프로그램의 데이터·권한과 오류 처리 책임까지 제거하지는 않는다.

관리형 서비스의 기능과 제한·가격이 변경되거나 서비스가 종료될 수 있으므로 외부 의존성과 이전 가능성을 평가한다.

분산 시스템

분산 시스템은 여러 컴퓨터와 프로세스가 네트워크를 통해 협력하여 하나의 기능을 제공한다.

분산 소프트웨어는 다음 영역에서 사용된다.

  • 대규모 웹 서비스
  • 검색 엔진
  • 데이터베이스
  • 클라우드 플랫폼
  • 콘텐츠 전송
  • 금융 거래
  • 통신
  • 온라인 게임
  • 물류와 공급망
  • 과학 계산
  • 블록체인과 분산 원장

분산 환경에서는 일부 구성 요소만 실패하는 부분 실패와 네트워크 지연·메시지 손실, 중복과 순서 변경이 발생한다.

다음 문제를 다뤄야 한다.

  • 서비스와 데이터의 경계
  • 통신 프로토콜
  • 시간과 순서
  • 데이터 일관성
  • 복제
  • 합의와 리더 선출
  • 재시도와 멱등성
  • 장애 탐지
  • 확장성과 부하 분산
  • 버전 호환성
  • 관찰과 추적
  • 단계적 배포

단일 프로세스에서는 함수 호출이 성공하거나 즉시 실패할 수 있지만 네트워크 호출에서는 요청이 처리되었으나 응답만 사라졌는지 구분하기 어려울 수 있다.

분산 시스템의 소프트웨어 공학은 이론적인 알고리즘뿐 아니라 운영 중의 진단·배포와 복구, 조직별 서비스 소유권을 포함한다.

모바일 소프트웨어

모바일 소프트웨어는 스마트폰·태블릿과 휴대용 장치에서 실행된다.

다음과 같은 응용이 포함된다.

  • 통신과 메신저
  • 소셜 미디어
  • 은행과 결제
  • 지도와 교통
  • 사진·영상과 음악
  • 게임
  • 건강과 운동
  • 교육
  • 쇼핑과 배달
  • 업무와 협업
  • 장치 제어

모바일 장치는 배터리·저장 공간과 네트워크가 제한되고 다양한 센서와 개인정보를 처리한다.

다음이 중요하다.

  • 화면 크기와 입력
  • 배터리와 자원 사용
  • 일시적인 네트워크
  • 오프라인 동작
  • 백그라운드 실행 제한
  • 위치·카메라와 마이크 권한
  • 장치와 운영체제 버전
  • 앱 배포와 심사
  • 사용자 데이터 보호
  • 접근성
  • 알림
  • 서버와 앱 버전 호환성

사용자가 업데이트를 바로 설치하지 않을 수 있으므로 여러 클라이언트 버전이 같은 서버와 통신할 수 있어야 한다.

운영체제의 권한과 백그라운드 정책이 변경되면 기존 프로그램이 작동하지 않을 수 있으므로 플랫폼 변화와 지원 범위를 지속적으로 관리한다.

데스크톱 소프트웨어

데스크톱 소프트웨어는 개인용 컴퓨터와 워크스테이션에서 실행된다.

대표적인 분야에는 다음이 있다.

  • 문서와 사무
  • 소프트웨어 개발
  • 그래픽과 영상
  • 음악과 음향
  • 과학과 공학 계산
  • CAD와 설계
  • 데이터 분석
  • 게임
  • 기업 내부 도구
  • 시스템 관리

데스크톱 프로그램은 로컬 파일과 장치·그래픽 자원에 직접 접근할 수 있고 오프라인에서도 동작할 수 있다.

다음과 같은 문제가 중요하다.

  • 여러 운영체제
  • CPU와 그래픽 장치
  • 파일 권한과 경로
  • 설치와 제거
  • 자동 업데이트
  • 사용자 설정
  • 플러그인
  • 충돌과 데이터 복구
  • 대형 파일과 성능
  • 운영체제 통합
  • 접근성
  • 장기적인 파일 호환성

웹 서비스와 달리 이미 배포된 프로그램을 제공자가 즉시 교체하기 어렵다. 업데이트 실패와 이전 버전 지원, 사용자별 환경 차이를 고려해야 한다.

서버 소프트웨어

서버 소프트웨어는 다른 프로그램과 사용자에게 네트워크를 통해 기능과 데이터를 제공한다.

다음과 같은 종류가 있다.

  • 웹 서버
  • 응용 프로그램 서버
  • 데이터베이스 서버
  • 파일과 저장소 서버
  • 인증 서버
  • 게임 서버
  • 전자우편 서버
  • 메시지 브로커
  • 검색 서버
  • 미디어 서버
  • 프록시와 게이트웨이

서버는 오랜 기간 중단 없이 실행되고 여러 사용자의 요청을 동시에 처리해야 한다.

중요한 요구에는 다음이 있다.

  • 동시성과 자원 제한
  • 성능과 처리량
  • 가용성과 복구
  • 권한과 격리
  • 요청 제한
  • 로그와 감사
  • 구성과 비밀 관리
  • 백업
  • 무중단 또는 단계적 업데이트
  • 버전 호환성
  • 용량 계획
  • 장애 대응

서버에서 작은 자원 누수도 장시간 실행 뒤 큰 장애로 이어질 수 있다. 장시간 시험과 운영 지표를 통해 누적 문제를 감시해야 한다.

기업용 소프트웨어

기업용 소프트웨어는 조직의 업무·인력과 자원·고객과 거래를 관리한다.

대표적인 예에는 다음이 있다.

  • 전사적 자원 관리
  • 고객 관계 관리
  • 공급망 관리
  • 인사와 급여
  • 회계
  • 문서와 기록 관리
  • 업무 흐름
  • 데이터 분석
  • 기업 포털
  • 자산 관리
  • 그룹웨어
  • 규제와 감사 시스템

기업용 시스템에서는 프로그램 자체보다 조직의 업무·권한과 데이터의 의미가 중요하다.

다음과 같은 문제가 나타난다.

  • 여러 부서의 상충하는 요구
  • 오래된 업무 규칙
  • 대규모 기존 데이터
  • 외부 제품과의 통합
  • 조직별 권한
  • 감사와 법률
  • 사용자 교육
  • 단계적인 조직 전환
  • 제품 맞춤화
  • 공급자와 라이선스
  • 장기적인 지원
  • 기존 시스템 폐기

새 시스템을 도입하면서 기존 업무를 그대로 복제하면 잘못된 절차까지 자동화할 수 있다. 요구사항 공학과 업무 분석을 통해 실제 목표와 필요한 변화를 확인해야 한다.

기업 시스템은 수십 년 동안 사용될 수 있으며 여러 세대의 기술과 데이터를 함께 유지한다. 초기 개발 비용보다 데이터 이전·통합과 유지보수 비용이 더 클 수 있다.

금융 소프트웨어

금융 소프트웨어는 은행·증권·보험·결제와 회계, 시장 거래와 위험 관리를 지원한다.

다음과 같은 소프트웨어가 포함된다.

  • 계좌와 원장
  • 결제
  • 신용과 대출
  • 증권 거래
  • 시장 데이터
  • 보험
  • 사기 탐지
  • 위험 계산
  • 규제 보고
  • 개인 재무 관리
  • 암호자산과 디지털 자산

금융에서는 다음 요구가 중요하다.

  • 금액과 거래의 정확성
  • 중복 처리 방지
  • 감사 가능성
  • 인증과 권한
  • 개인정보와 금융 정보 보호
  • 가용성과 재해 복구
  • 거래 순서와 시간
  • 규제 준수
  • 사기와 공격 탐지
  • 데이터 보존
  • 이전 시스템과의 호환성
  • 낮은 지연 시간

금융 거래는 단순히 요청이 성공했는지를 넘어 실제 원장과 외부 기관의 상태가 일치하는지 확인해야 한다.

네트워크 오류로 응답을 받지 못했다고 같은 거래를 다시 실행하면 중복 결제가 발생할 수 있으므로 고유 식별자와 멱등성·조정 절차가 필요하다.

실시간 시장과 결제 시스템에서는 매우 짧은 지연과 높은 처리량이 요구될 수 있지만 정확성·감사와 위험 통제를 성능보다 낮은 우선순위로 둘 수는 없다.

전자상거래

전자상거래 소프트웨어는 상품 검색부터 주문·결제·배송과 환불까지 사용자와 사업자의 거래를 지원한다.

구성 요소에는 다음이 포함될 수 있다.

  • 상품과 카탈로그
  • 검색과 추천
  • 가격과 할인
  • 장바구니
  • 주문
  • 결제
  • 재고
  • 배송
  • 고객 지원
  • 사용자 계정
  • 판매자 관리
  • 사기 탐지
  • 분석

전자상거래에서는 여러 서비스와 외부 공급자가 하나의 사용자 흐름에 참여한다.

결제는 성공했지만 주문이 생성되지 않거나 재고가 차감되었지만 배송 요청이 실패하는 부분적인 오류를 처리해야 한다.

가격과 할인 규칙은 기술적으로 복잡할 뿐 아니라 법률과 사용자 신뢰에 직접 영향을 준다.

대규모 행사와 특정 시간에 트래픽이 집중될 수 있으므로 용량 시험·대기열과 점진적인 성능 저하가 중요하다.

통신 소프트웨어

통신 분야의 소프트웨어는 전화·메시지·인터넷과 이동통신망을 구성하고 관리한다.

다음과 같은 영역이 있다.

  • 네트워크 장비의 제어 소프트웨어
  • 이동통신 핵심망
  • 기지국
  • 라우팅과 교환
  • 메시지와 음성
  • 과금
  • 가입자 관리
  • 네트워크 관리
  • 소프트웨어 정의 네트워크
  • 가상화된 네트워크 기능

통신 시스템은 매우 많은 사용자를 지원하고 장시간 중단 없이 운영되어야 한다.

중요한 요구에는 다음이 있다.

  • 낮은 지연과 높은 처리량
  • 네트워크 장애와 복구
  • 여러 장비와 표준의 호환성
  • 실시간 상태 관리
  • 보안과 사용자 식별
  • 과금의 정확성
  • 지역별 규제
  • 단계적인 장비와 프로토콜 이전
  • 장기 지원
  • 운영 자동화

네트워크 프로토콜과 장비 버전이 오랫동안 함께 존재하므로 호환성과 단계적 업데이트가 중요하다.

게임과 인터랙티브 미디어

게임 소프트웨어는 그래픽·물리·인공지능·음향과 사용자 입력을 실시간으로 결합하여 상호작용 경험을 제공한다.

게임 개발에는 다음과 같은 구성 요소가 있다.

  • 게임 엔진
  • 렌더링
  • 물리
  • 애니메이션
  • 인공지능
  • 입력
  • 사용자 인터페이스
  • 음향
  • 네트워크
  • 콘텐츠와 자산
  • 저장
  • 도구와 편집기
  • 서버와 운영
  • 플랫폼 서비스

게임에서는 기능의 정확성뿐 아니라 재미·반응성과 시각적·음향적 경험이 중요하다.

다음과 같은 요구가 있다.

  • 일정한 프레임 시간
  • 낮은 입력 지연
  • 다양한 그래픽 장치와 콘솔
  • 콘텐츠 제작 파이프라인
  • 대규모 자산과 빌드
  • 충돌과 저장 데이터 보호
  • 온라인 동기화
  • 치팅과 보안
  • 패치와 콘텐츠 업데이트
  • 접근성
  • 현지화
  • 플레이테스트

게임의 요구사항은 일반 업무 프로그램처럼 완전히 문서로 확정하기 어려울 수 있다. 프로토타입과 반복적인 플레이테스트를 통해 게임 규칙·난이도와 사용자 경험을 조정한다.

게임 엔진과 편집 도구는 게임 하나보다 더 긴 기간 사용되므로 일반적인 플랫폼 소프트웨어와 같은 아키텍처·호환성과 확장성이 필요하다.

온라인 게임에서는 서버 가용성·부정행위와 사용자 커뮤니티, 가상 경제도 소프트웨어 공학의 운영 문제에 포함된다.

미디어와 콘텐츠 제작

미디어 소프트웨어는 영상·음악·사진·출판과 방송 콘텐츠의 제작·편집·저장과 전송을 지원한다.

다음과 같은 분야가 있다.

  • 영상 편집
  • 3차원 모델링과 애니메이션
  • 음향 편집과 음악 제작
  • 이미지 편집
  • 디지털 출판
  • 실시간 방송
  • 미디어 관리
  • 인코딩과 스트리밍
  • 가상 제작

이 분야에서는 대규모 파일·색상과 시간의 정확성, 다양한 장치와 형식이 중요하다.

다음 요구를 다룬다.

  • 장시간 작업의 안정성
  • 비파괴 편집
  • 자동 저장과 복구
  • 그래픽·오디오 하드웨어 가속
  • 정확한 색상과 음향
  • 프레임과 시간 동기화
  • 플러그인
  • 파일과 코덱 호환성
  • 협업과 버전
  • 고해상도 데이터 성능
  • 렌더 팜과 분산 처리

콘텐츠 제작자는 프로그램의 기능만 사용하는 것이 아니라 복잡한 작업 흐름을 구성하므로 도구의 확장성과 자동화·스크립팅이 중요하다.

교육 소프트웨어

교육 소프트웨어는 학습·교육과 평가, 교육 기관의 운영을 지원한다.

예에는 다음이 있다.

  • 학습 관리 시스템
  • 온라인 강의
  • 디지털 교과서
  • 교육용 게임
  • 연습과 평가
  • 프로그래밍 학습 도구
  • 가상 실험실
  • 학생 정보 시스템
  • 협업과 과제 제출
  • 교사 지원 도구

교육 분야에서는 다음이 중요하다.

  • 학습 목표와 내용의 정확성
  • 연령과 선수 지식
  • 피드백
  • 접근성
  • 다양한 장치와 네트워크
  • 교사와 학습자의 역할
  • 학생 개인정보
  • 부정행위와 평가 신뢰성
  • 오프라인 지원
  • 여러 언어와 문화
  • 장기간의 학습 기록
  • 교육 과정과 제도의 변화

학습자가 프로그램을 오래 사용했다는 사실이 실제 학습을 의미하지는 않는다. 활동량과 클릭보다 학습 성과와 이해를 평가해야 한다.

학생을 평가하고 추천하는 알고리즘은 잘못된 결과와 편향이 교육 기회에 영향을 줄 수 있으므로 설명과 교사의 검토, 이의 제기 방법을 제공해야 한다.

의료와 건강

의료 소프트웨어는 환자 진료·의료 정보와 의료 장비, 건강 관리에 사용된다.

다음과 같은 형태가 있다.

  • 전자의무기록
  • 병원 정보 시스템
  • 의료 영상
  • 진단 지원
  • 처방과 투약
  • 환자 감시
  • 원격 의료
  • 의료기기 내장 소프트웨어
  • 독립형 의료 소프트웨어
  • 건강과 운동 응용 프로그램
  • 임상 연구 시스템
  • 생명과학 분석

의료 소프트웨어에서는 다음 요구가 중요하다.

  • 환자 안전
  • 임상적 정확성
  • 개인정보
  • 사용자와 환자 식별
  • 감사 기록
  • 의료 장비와 데이터 표준
  • 중단 없는 운영
  • 경고와 인간 요인
  • 규제와 품질 관리
  • 소프트웨어 변경의 영향
  • 데이터 보존
  • 보안과 취약점 대응

FDA는 소프트웨어 자체가 의료 기기로 기능하는 Software as a Medical Device를 의료 기기와 관련된 소프트웨어의 한 유형으로 설명하며, 이러한 소프트웨어가 의료 기기 플랫폼·상용 플랫폼과 가상 네트워크를 포함한 다양한 기술 환경에서 사용될 수 있다고 설명한다.[178]

의료 소프트웨어의 출력이 진단과 치료 결정에 사용될수록 잘못된 결과의 위험이 커질 수 있다.

사용자 인터페이스에서 환자·약품과 단위를 혼동하면 내부 계산이 정확해도 사고가 발생할 수 있으므로 의료 전문가·안전과 인간공학 전문가가 함께 설계해야 한다.

FDA는 의료기기 소프트웨어의 안전성과 유효성에 영향을 주는 위험을 중심으로 관련 소프트웨어 기능을 감독한다.[179]

과학 연구

과학 연구 소프트웨어는 실험·시뮬레이션과 데이터 분석, 연구 장비 제어에 사용된다.

분야에는 다음이 있다.

  • 물리학
  • 화학
  • 천문학
  • 지구과학
  • 생명과학
  • 기후와 기상
  • 사회과학
  • 계산수학
  • 고성능 컴퓨팅
  • 실험 장비
  • 연구 데이터 관리

연구 소프트웨어에서는 계산 결과의 재현성과 정확성이 중요하다.

다음이 필요할 수 있다.

  • 코드와 데이터의 버전
  • 실행 환경
  • 수치 알고리즘과 오차
  • 단위와 좌표계
  • 난수 시드
  • 실험 매개변수
  • 데이터 출처
  • 결과 검증
  • 동료 검토
  • 장기 보존
  • 고성능 병렬 처리
  • 다른 연구자의 재사용

연구자가 빠르게 만든 실험 코드는 가설 탐색에는 적합하지만 논문과 정책·장기 연구 기반에 사용되려면 시험과 문서·구성 관리가 필요하다.

과학적 재현성은 소스 코드만 공개하는 것으로 충분하지 않을 수 있다. 입력 데이터·라이브러리와 하드웨어, 실행 명령과 분석 절차를 함께 기록해야 한다.

고성능 컴퓨팅

고성능 컴퓨팅은 많은 프로세서·그래픽 처리 장치와 컴퓨터를 사용하여 대규모 계산을 수행한다.

활용 분야에는 다음이 있다.

  • 기후와 기상 예측
  • 분자와 재료 시뮬레이션
  • 천체 물리
  • 유체 역학
  • 핵물리
  • 유전체 분석
  • 인공지능 학습
  • 지진과 지질 분석
  • 공학 최적화
  • 대규모 데이터 처리

고성능 소프트웨어에서는 다음이 중요하다.

  • 병렬 알고리즘
  • 메모리와 데이터 이동
  • 여러 노드의 통신
  • 작업 스케줄러
  • 하드웨어별 최적화
  • 수치 정확성
  • 장애와 체크포인트
  • 결과 재현성
  • 성능 측정
  • 대규모 시험

프로세서 수를 늘린다고 성능이 비례하여 증가하지 않으며 통신·동기화와 순차 영역이 병목이 될 수 있다.

하드웨어와 컴파일러의 변경에 따라 결과와 성능이 달라질 수 있으므로 여러 환경의 검증과 기준 성능을 관리해야 한다.

인공지능과 기계학습

인공지능 소프트웨어는 학습 데이터와 모델을 사용하여 분류·예측·생성·추천과 의사결정을 수행한다.

활용 분야에는 다음이 있다.

  • 검색과 추천
  • 음성과 언어
  • 영상과 이미지
  • 의료
  • 금융
  • 자율 주행
  • 제조
  • 보안
  • 과학 연구
  • 교육
  • 창작 도구
  • 소프트웨어 개발 도구

일반 소프트웨어에서는 코드가 동작을 직접 정의하는 경우가 많지만 기계학습 시스템은 데이터·모델과 학습 과정이 동작에 큰 영향을 준다.

따라서 다음을 관리해야 한다.

  • 데이터 출처와 품질
  • 학습·검증과 시험 데이터 분리
  • 모델과 매개변수 버전
  • 학습 환경과 재현성
  • 집단과 조건별 성능
  • 잘못된 출력과 불확실성
  • 모델과 일반 코드의 통합
  • 운영 데이터 분포 변화
  • 모델 업데이트와 롤백
  • 개인정보와 저작권
  • 공정성과 설명
  • 사람의 감독

평균 정확도가 높더라도 중요한 집단에서 오류가 집중되거나 실제 사용 환경의 데이터가 학습 데이터와 다르면 제품 품질이 낮을 수 있다.

AI 기능은 모델 하나가 아니라 데이터 파이프라인·사용자 인터페이스와 규칙·운영 감시가 결합된 전체 소프트웨어 시스템으로 평가해야 한다.

FDA는 AI 기반 의료기기 소프트웨어에서도 개발·배포와 운영 전반의 생명주기 관리와 변경을 고려하는 접근을 다루고 있다.[180]

산업 자동화와 제조

산업 소프트웨어는 공장과 생산 설비·로봇과 공정을 감시하고 제어한다.

다음과 같은 시스템이 있다.

  • 산업 제어 시스템
  • PLC 프로그램
  • 제조 실행 시스템
  • 공정 감시
  • 로봇 제어
  • 품질 검사
  • 설비 관리
  • 디지털 트윈
  • 생산 계획
  • 창고와 물류
  • 예측 유지보수

산업 환경에서는 일반 사무용 소프트웨어와 다른 조건이 있다.

  • 장비가 수십 년 사용될 수 있다.
  • 생산 중단 비용이 크다.
  • 실시간성과 결정적인 동작이 필요하다.
  • 오래된 프로토콜과 장비가 존재한다.
  • 인터넷과 분리된 환경이 있을 수 있다.
  • 업데이트와 재시작이 제한된다.
  • 물리적인 안전 위험이 있다.
  • 장비 제조사와 여러 공급자에 의존한다.
  • 보안 사고가 실제 생산과 안전에 영향을 준다.

산업 소프트웨어의 변경은 실제 설비에서 바로 시험하기 어려울 수 있으므로 시뮬레이터·디지털 트윈과 하드웨어 인더루프 시험을 사용할 수 있다.

보안 패치를 적용하지 않으면 공격 위험이 커지지만 검증되지 않은 업데이트가 생산을 멈추거나 안전 기능에 영향을 줄 수 있으므로 단계적인 시험과 유지보수 창이 필요하다.

로봇과 자율 시스템

로봇과 자율 시스템은 센서·제어·인공지능과 물리적 장치를 소프트웨어로 통합한다.

활용 분야에는 다음이 있다.

  • 산업용 로봇
  • 물류 로봇
  • 드론
  • 서비스 로봇
  • 농업 로봇
  • 의료 로봇
  • 탐사 로봇
  • 자율 이동 장치
  • 무인 항공기
  • 가정용 로봇

로봇 소프트웨어는 다음을 처리한다.

  • 센서 데이터
  • 위치 추정
  • 지도와 경로 계획
  • 물체와 환경 인식
  • 동작 계획
  • 실시간 제어
  • 통신
  • 사용자와 원격 운영
  • 안전 정지
  • 진단과 업데이트

실제 환경은 시뮬레이션보다 복잡하며 조명·날씨와 장애물, 센서 노이즈와 사람의 행동이 달라질 수 있다.

시뮬레이션·시험장과 제한된 실제 환경을 단계적으로 사용하여 검증하고, 불확실한 상태에서는 속도를 줄이거나 사람에게 제어를 넘기는 안전한 동작을 설계한다.

자동차

자동차 소프트웨어는 차량의 제어·안전과 사용자 기능, 통신과 진단을 담당한다.

다음과 같은 영역에 사용된다.

  • 엔진과 동력계
  • 제동과 조향
  • 에어백과 안전
  • 운전자 보조
  • 자율 주행
  • 계기판
  • 인포테인먼트
  • 내비게이션
  • 배터리와 충전
  • 차량 통신
  • 진단
  • 원격 업데이트
  • 모바일과 클라우드 서비스

자동차에서는 실시간 동작·기능 안전과 보안, 긴 제품 수명과 하드웨어 제약이 중요하다.

차량의 여러 제어기가 서로 다른 공급자와 개발 주기를 가질 수 있으므로 인터페이스·시간과 버전 호환성을 관리해야 한다.

원격 업데이트는 결함과 보안 취약점을 수정할 수 있지만 업데이트 자체의 인증·부분 실패와 복구가 새로운 안전 문제를 만들 수 있다.

차량이 외부 네트워크에 연결되면서 인포테인먼트와 사용자 기능의 침해가 제어 영역으로 확산되지 않도록 격리와 신뢰 경계를 설계해야 한다.

항공과 우주

항공·우주 소프트웨어는 항공기·위성·발사체와 탐사선의 제어·항법과 임무 수행에 사용된다.

다음과 같은 기능을 담당한다.

  • 비행 제어
  • 항법과 유도
  • 통신
  • 전력과 열 관리
  • 센서와 장비 제어
  • 임무 계획
  • 지상 관제
  • 시뮬레이션
  • 시험과 데이터 분석
  • 고장 감지와 복구

이 분야에서는 다음과 같은 조건이 중요하다.

  • 사람과 임무의 안전
  • 극한 환경
  • 제한된 전력과 계산 자원
  • 실시간 동작
  • 통신 지연과 단절
  • 현장 수리의 어려움
  • 방사선과 하드웨어 오류
  • 긴 개발과 임무 기간
  • 엄격한 구성 관리
  • 독립적인 검증
  • 장기간의 증거 보존

우주선은 발사 이후 하드웨어를 직접 교체하기 어려우며 먼 탐사선은 통신에 긴 시간이 걸릴 수 있다. 소프트웨어가 일부 오류를 스스로 감지하고 제한된 상태로 복구할 수 있어야 한다.

NASA Software Engineering Handbook는 NASA 프로젝트에서 안전하고 신뢰할 수 있는 소프트웨어를 개발하기 위한 소프트웨어 공학·보증과 소프트웨어 안전 요구의 구현 지침을 제공한다.[181]

항공·우주 소프트웨어에서는 요구사항부터 코드·시험과 배포된 바이너리까지 강한 추적성과 기준선 관리가 필요할 수 있다.

철도와 교통

교통 소프트웨어는 철도·도로·항만과 대중교통의 이동과 안전·운영을 지원한다.

다음과 같은 시스템이 있다.

  • 철도 신호와 열차 제어
  • 교통 신호
  • 차량 배차
  • 항공 교통 관리
  • 대중교통 요금
  • 교통 정보
  • 물류 추적
  • 터널과 도로 감시
  • 자율 교통 시스템

교통 시스템은 넓은 지역의 물리적 장치와 통신망·운영자를 연결한다.

다음이 중요하다.

  • 안전한 상태
  • 실시간성과 지연
  • 통신 단절
  • 장치와 중앙 시스템의 일관성
  • 운영자와 인간 요인
  • 고가용성
  • 재해와 비상 대응
  • 오래된 설비와 호환성
  • 보안
  • 규제와 인증

철도 신호와 제어에서는 잘못된 명령보다 열차를 정지시키는 동작이 안전할 수 있지만, 전체 운행이 장기간 중단되면 다른 위험과 사회적 영향이 발생할 수 있다.

에너지와 사회 기반 시설

에너지와 기반 시설 소프트웨어는 전력·가스·수도와 통신 같은 필수 서비스를 제어하고 지원한다.

다음과 같은 영역이 있다.

  • 발전소
  • 전력망
  • 에너지 거래
  • 배전과 계량
  • 가스와 수도
  • 건물 관리
  • 원자력
  • 재생 에너지
  • 배터리와 저장
  • 기반 시설 감시

이 분야에서는 다음이 중요하다.

  • 높은 가용성
  • 안전과 환경
  • 실시간 제어
  • 넓은 지역의 분산 장치
  • 오래된 설비
  • 사이버 보안
  • 물리적 보안
  • 재해 복구
  • 규제
  • 수요와 용량 예측
  • 운영자의 상황 인식
  • 수동 대체 절차

사회 기반 시설은 소프트웨어 장애가 넓은 지역과 많은 사람에게 영향을 줄 수 있다.

관리 네트워크와 일반 업무 네트워크를 분리하고 외부 연결·원격 유지보수와 업데이트의 권한을 엄격하게 관리해야 한다.

자동화가 실패했을 때 운영자가 현재 상태를 이해하고 수동으로 안전한 제어를 수행할 수 있는지도 검토해야 한다.

국방과 공공 안전

국방과 공공 안전 소프트웨어는 지휘·통신·감시와 대응, 장비와 임무 수행을 지원한다.

다음과 같은 분야가 있다.

  • 지휘 통제
  • 통신과 정보
  • 레이더와 감시
  • 항법
  • 무기와 방어 시스템
  • 훈련과 시뮬레이션
  • 재난 대응
  • 경찰·소방과 응급 구조
  • 정보 분석
  • 보안 시스템

이 분야에서는 기밀성·무결성과 가용성, 안전·실시간성과 적대적인 환경에 대한 복원력이 중요하다.

다음 문제를 다룬다.

  • 제한된 네트워크
  • 전자전과 통신 방해
  • 강한 인증과 권한
  • 여러 기관과 동맹의 상호운용성
  • 장기적인 장비 수명
  • 공급망
  • 분류 정보
  • 물리적 장치
  • 인간의 최종 통제
  • 윤리와 국제법

공공 안전 시스템은 긴급 상황에서 일반 사용량보다 훨씬 높은 부하와 일부 기반 시설의 장애를 견뎌야 한다.

사용자가 스트레스와 제한된 정보 속에서 프로그램을 사용하므로 사용자 인터페이스와 훈련·운영 절차가 안전에 직접 영향을 준다.

정부와 공공 서비스

정부 소프트웨어는 행정·복지와 세금·허가, 기록과 시민 서비스를 지원한다.

다음과 같은 영역이 있다.

  • 주민과 신원
  • 세금
  • 사회 보장
  • 보건과 복지
  • 교육
  • 법원과 행정
  • 선거 지원
  • 허가와 등록
  • 공공 데이터
  • 기록과 문서
  • 조달과 재정
  • 재난 대응

공공 서비스는 다양한 연령·장애와 언어, 장치와 디지털 숙련도를 가진 사람이 사용한다.

따라서 다음이 중요하다.

  • 접근성
  • 명확한 언어
  • 개인정보
  • 공정성과 이의 제기
  • 법률과 행정 절차
  • 장기간의 기록
  • 투명성과 감사
  • 여러 기관의 데이터
  • 오래된 시스템
  • 공급자 종속
  • 서비스 중단의 사회적 영향
  • 온라인 외의 대체 절차

공공 시스템의 오류는 시민의 권리·복지와 법적 지위에 영향을 줄 수 있다. 자동 결정이 내려지는 경우 판단 근거와 수정·이의 제기 경로를 제공해야 한다.

정부 시스템은 정권과 정책·법률의 변화에도 데이터를 유지하면서 기능을 변경할 수 있어야 한다.

법률과 사법

법률 소프트웨어는 법률 문서·사건과 증거·계약과 규제 업무를 지원한다.

다음이 포함될 수 있다.

  • 사건 관리
  • 법률 검색
  • 전자 제출
  • 문서와 증거 관리
  • 계약 분석
  • 규제 준수
  • 전자 서명
  • 법률 정보
  • 법원 행정
  • 조사와 포렌식

이 분야에서는 다음이 중요하다.

  • 문서와 증거의 무결성
  • 접근 권한
  • 감사 기록
  • 개인정보와 기밀
  • 장기간의 보존
  • 정확한 검색과 인용
  • 법률과 절차의 변경
  • 설명 가능성
  • 전자 서명의 신뢰
  • 관할권과 데이터 위치

자동화된 분석과 인공지능의 결과가 법적 판단을 대신하거나 영향을 줄 때는 오류·편향과 설명 가능성을 신중히 평가해야 한다.

물류와 공급망

물류 소프트웨어는 상품·차량·창고와 주문의 이동을 계획하고 추적한다.

다음과 같은 시스템이 있다.

  • 창고 관리
  • 운송 관리
  • 재고
  • 배송 추적
  • 경로 계획
  • 주문 처리
  • 차량과 장비 관리
  • 통관
  • 수요 예측
  • 공급자 관리

물류에서는 여러 회사와 장치·지역이 하나의 흐름에 참여한다.

다음이 중요하다.

  • 실시간 위치와 상태
  • 외부 파트너 통합
  • 바코드와 센서
  • 모바일과 오프라인 환경
  • 시간대와 지역
  • 재고의 정확성
  • 부분적인 오류와 재처리
  • 급격한 수요 변화
  • 경로와 자원 최적화
  • 물리적 작업과 시스템 상태의 일치

소프트웨어에 배송 완료로 기록되었지만 실제 상품이 이동하지 않는 것처럼 디지털 상태와 물리적 세계가 다를 수 있다. 확인·조정과 예외 처리 절차가 필요하다.

농업과 환경

농업과 환경 소프트웨어는 생산·자원 관리와 자연환경의 관찰과 예측을 지원한다.

다음과 같은 영역이 있다.

  • 정밀 농업
  • 농기계 제어
  • 관개
  • 작물과 가축 관리
  • 위성과 드론 영상
  • 날씨와 토양 분석
  • 환경 감시
  • 산림과 수자원
  • 재해 예측
  • 탄소와 에너지 관리

현장에서는 네트워크와 전력이 불안정하고 먼지·습기와 온도 같은 환경 조건이 장치에 영향을 줄 수 있다.

다음이 중요하다.

  • 오프라인 동작
  • 저전력 장치
  • 센서의 정확성과 보정
  • 위치와 지도
  • 계절과 장기간 데이터
  • 현장 사용자 인터페이스
  • 장비와 공급자 호환성
  • 데이터 소유권
  • 예측의 불확실성
  • 환경과 안전 영향

알고리즘의 추천이 농약·물과 자원 사용에 영향을 주면 경제적 손실뿐 아니라 환경 피해로 이어질 수 있으므로 근거와 한계·사람의 판단을 함께 제공해야 한다.

건축과 건설

건축·건설 소프트웨어는 설계·시공과 시설 운영을 지원한다.

다음이 포함될 수 있다.

  • CAD
  • 건축 정보 모델링
  • 구조 해석
  • 일정과 비용
  • 현장 관리
  • 측량
  • 장비와 안전
  • 시설 관리
  • 디지털 트윈
  • 에너지 분석

이 분야에서는 여러 전문 분야와 공급자가 같은 모델과 문서를 사용한다.

다음이 중요하다.

  • 도면과 모델의 버전
  • 단위와 좌표계
  • 분야 사이의 충돌
  • 계약과 승인
  • 실제 시공 상태
  • 대형 파일과 성능
  • 장기간의 자료 보존
  • 표준 형식
  • 현장 모바일 사용
  • 안전과 규제

모델의 잘못된 치수와 단위는 실제 구조물의 문제로 이어질 수 있으므로 자동 검사와 전문 엔지니어의 검토를 함께 사용한다.

지리 정보와 지도

지리 정보 소프트웨어는 공간·위치와 지도 데이터를 저장·분석하고 시각화한다.

활용 분야에는 다음이 있다.

  • 지도와 내비게이션
  • 도시 계획
  • 재난 대응
  • 측량
  • 환경 관리
  • 물류
  • 농업
  • 국방
  • 부동산
  • 기반 시설

다음이 중요하다.

  • 좌표계와 투영
  • 위치 정확도
  • 대규모 공간 데이터
  • 오프라인 지도
  • 실시간 교통과 위치
  • 개인정보
  • 데이터 출처와 갱신
  • 여러 축척
  • 경로 계획
  • 시각화와 접근성

좌표계와 단위가 다른 데이터를 잘못 결합하면 지도상 위치와 계산 결과가 크게 어긋날 수 있다.

위치 정보는 개인의 생활과 이동을 드러낼 수 있으므로 수집·보존과 공유 범위를 제한해야 한다.

사물인터넷

사물인터넷은 센서·가전과 산업 장치가 네트워크에 연결되어 데이터를 교환하고 제어되는 시스템이다.

다음과 같은 제품이 있다.

  • 스마트 홈
  • 웨어러블 장치
  • 산업 센서
  • 도시 기반 시설
  • 차량과 물류 장치
  • 농업 장치
  • 의료와 건강 장치
  • 환경 감시
  • 에너지 계량

사물인터넷 시스템은 장치·통신·클라우드와 모바일 앱을 함께 포함한다.

다음 문제가 중요하다.

  • 제한된 CPU·메모리와 전력
  • 간헐적인 네트워크
  • 장치 식별과 인증
  • 원격 업데이트
  • 물리적 접근
  • 장기간의 지원
  • 데이터와 개인정보
  • 여러 제조사와 프로토콜
  • 장치의 안전한 초기화와 폐기
  • 대량 장치 관리
  • 침해된 장치의 격리

장치는 판매 후 여러 해 동안 사용될 수 있지만 제조사가 서버와 보안 업데이트를 중단하면 사용자에게 위험이 남을 수 있다.

초기 비밀번호와 업데이트 서명·키 관리 같은 보안 기능을 제품 설계에 포함해야 한다.

임베디드 시스템

임베디드 시스템은 특정 장치와 제품 안에서 제한된 기능을 수행하는 컴퓨터 시스템이다.

예에는 다음이 있다.

  • 가전제품
  • 카메라
  • 프린터
  • 네트워크 장비
  • 차량 제어기
  • 산업 장치
  • 의료 장비
  • 센서
  • 로봇
  • 항공 전자 장치

임베디드 소프트웨어에서는 다음이 중요하다.

  • 제한된 메모리와 저장 공간
  • 낮은 전력
  • 실시간성과 결정성
  • 하드웨어 레지스터와 장치
  • 부팅 시간
  • 오류와 감시 타이머
  • 원격 진단
  • 펌웨어 업데이트
  • 물리적 안전
  • 장기 지원
  • 생산과 장치별 설정
  • 현장 수리 가능성

장치가 판매된 이후 하드웨어 사양을 바꾸기 어려우므로 초기 자원 추정과 장기적인 기능 확장 여유를 고려해야 한다.

펌웨어 업데이트가 실패하면 장치가 부팅되지 않을 수 있으므로 이중 이미지·복구 모드와 업데이트 무결성을 설계할 수 있다.

실시간 시스템

실시간 시스템은 결과의 논리적 정확성뿐 아니라 정해진 시간 안에 결과를 제공하는 것이 중요하다.

활용 분야에는 다음이 있다.

  • 산업 제어
  • 자동차
  • 항공
  • 의료 장비
  • 로봇
  • 통신
  • 음향과 영상
  • 게임
  • 금융 거래
  • 센서 처리

실시간 시스템에서는 다음을 분석한다.

  • 작업의 최악 실행 시간
  • 우선순위
  • 스케줄링
  • 인터럽트
  • 자원 공유
  • 우선순위 역전
  • 시간 제한
  • 지연과 변동
  • 시각 동기화
  • 과부하 상태

평균적으로 빠르다는 사실만으로 실시간 요구를 충족하지 않는다. 중요한 작업이 최악 조건에서도 기한 안에 완료되는지를 확인해야 한다.

기한을 놓쳤을 때 단순히 늦은 결과를 제공할지 결과를 버리고 안전 상태로 전환할지도 도메인에 따라 결정한다.

안전 필수 시스템

안전 필수 시스템은 실패가 사람의 사망·부상이나 심각한 재산과 환경 피해로 이어질 수 있는 시스템이다.

예에는 다음이 있다.

  • 항공기 제어
  • 철도 신호
  • 의료 장비
  • 자동차 안전 기능
  • 원자력과 산업 제어
  • 비상 대응
  • 일부 로봇과 자율 시스템

이 분야에서는 일반적인 기능 개발보다 더 엄격한 활동이 필요할 수 있다.

  • 시스템 수준의 위험 분석
  • 안전 요구사항
  • 요구사항부터 시험까지 추적성
  • 독립적인 검증
  • 제한된 구현 방식
  • 정적·동적과 형식 분석
  • 고장 주입
  • 하드웨어와 실제 환경 시험
  • 구성과 변경 통제
  • 도구의 검증
  • 안전 사례와 증거
  • 장기적인 유지보수 기록

NASA Software Engineering Handbook는 NASA 프로젝트에서 소프트웨어 공학 요구와 함께 소프트웨어 보증·소프트웨어 안전 요구를 구현하기 위한 지침을 제공한다.[182]

위험 수준이 낮은 일반 소프트웨어와 같은 개발 속도와 문서 수준을 요구하기 어렵지만, 모든 절차를 무조건 늘리는 것도 품질을 자동으로 보장하지 않는다. 위험과 필요한 증거에 따라 활동을 선택한다.

보안 제품

보안 소프트웨어는 다른 시스템과 사용자를 공격·침해와 정보 손실에서 보호한다.

다음이 포함될 수 있다.

  • 백신과 악성 코드 분석
  • 방화벽
  • 침입 탐지와 방지
  • 신원과 접근 관리
  • 비밀과 키 관리
  • 암호화 도구
  • 취약점 분석
  • 보안 정보와 사건 관리
  • 디지털 포렌식
  • 소프트웨어 공급망 도구
  • 데이터 손실 방지
  • 보안 운영 자동화

보안 제품은 높은 권한과 민감한 정보를 다룰 수 있으므로 자체적인 침해가 큰 피해를 일으킬 수 있다.

다음이 중요하다.

  • 최소 권한
  • 격리
  • 안전한 업데이트
  • 공격 데이터 처리
  • 오탐과 미탐
  • 높은 가용성
  • 감사와 증거
  • 개인정보
  • 빠른 위협 대응
  • 여러 운영체제와 환경
  • 공격자에 의한 우회와 조작

보안 도구가 시스템 내부를 깊이 관찰하기 위해 높은 권한을 요구할 수 있지만 보호 대상보다 더 큰 공격 표면을 만들지 않도록 설계해야 한다.

오픈소스 소프트웨어

오픈 소스 소프트웨어는 소스 코드를 공개하고 라이선스가 허용하는 범위에서 사용·검토·수정과 배포할 수 있는 소프트웨어이다.

오픈소스 개발에서는 다음과 같은 특성이 있다.

  • 여러 조직과 개인의 분산된 기여
  • 공개된 코드 검토와 이슈
  • 다양한 사용자와 배포 환경
  • 포크와 파생 프로젝트
  • 자발적 기여자와 상업적 후원
  • 공개 릴리스와 패키지
  • 라이선스와 거버넌스
  • 장기 유지보수자의 부족 가능성

오픈소스에서도 요구사항·아키텍처·시험과 릴리스 관리가 필요하다.

프로젝트는 기여 규칙·책임자와 의사결정 방식, 보안 취약점의 비공개 신고 경로와 지원 정책을 정할 수 있다.

많은 제품이 외부 오픈소스 구성 요소에 의존하므로 프로젝트의 지속 가능성·라이선스와 보안 업데이트를 평가해야 한다.

상용 소프트웨어

상용 소프트웨어는 판매·구독과 서비스 계약을 통해 제공되는 제품을 포함한다.

상용 제품에서는 다음이 중요하다.

  • 시장과 사용자 가치
  • 출시 일정
  • 가격과 라이선스
  • 여러 고객과 제품 변형
  • 고객 지원
  • 설치와 업데이트
  • 장기 지원
  • 계약과 서비스 수준
  • 개인정보와 규제
  • 제품 분석과 지표
  • 경쟁과 호환성
  • 서비스 종료

기술적으로 우수한 제품도 사용자의 문제와 가격·지원 조건에 맞지 않으면 성공하기 어렵다.

기업 고객의 맞춤 기능을 계속 제품에 직접 추가하면 공통 제품의 복잡성과 시험 조합이 증가할 수 있으므로 설정·확장과 제품 변형을 체계적으로 관리해야 한다.

내부 업무 도구

조직 내부에서만 사용하는 소프트웨어도 소프트웨어 공학의 대상이다.

예에는 다음이 있다.

  • 관리 대시보드
  • 데이터 처리 스크립트
  • 배포와 운영 도구
  • 보고서 생성
  • 테스트 도구
  • 콘텐츠 관리
  • 사내 포털
  • 업무 자동화
  • 고객 지원 도구

내부 도구는 외부 제품보다 빠르고 가볍게 개발할 수 있지만 사용자와 업무가 해당 도구에 의존하게 되면 중요도가 커질 수 있다.

처음에는 한 사람이 사용하는 스크립트였지만 시간이 지나며 여러 팀의 핵심 업무와 배포를 담당할 수 있다.

중요도가 커지면 다음을 추가해야 한다.

  • 명확한 소유자
  • 버전 관리
  • 시험
  • 접근 권한
  • 데이터 보호
  • 문서와 지원
  • 운영과 백업
  • 변경과 폐기 정책

내부용이라는 이유로 개인정보·보안과 안정성 요구가 사라지지는 않는다.

소규모 프로젝트

개인·교육과 소규모 팀의 프로젝트에도 소프트웨어 공학 원칙을 적용할 수 있다.

다만 대규모 조직의 모든 문서와 승인 절차를 그대로 사용할 필요는 없다.

최소한 다음과 같은 활동이 도움이 될 수 있다.

  • 해결할 문제와 범위 정의
  • 간단한 요구사항과 완료 기준
  • 이해할 수 있는 구조
  • 버전 관리
  • 자동 빌드와 핵심 시험
  • 오류와 데이터 복구
  • 릴리스 식별
  • 사용자 피드백
  • 사용한 외부 구성 요소 관리
  • 기본 보안
  • 유지보수와 종료 계획

소규모 프로젝트에서는 한 사람이 여러 역할을 수행하지만 요구사항·시험·운영과 보안 같은 책임 자체가 사라지지는 않는다.

초기에는 가벼운 방식으로 시작하고 사용자·코드와 위험이 증가하면 필요한 공학 활동을 단계적으로 추가할 수 있다.

대규모 소프트웨어

대규모 소프트웨어는 많은 구성 요소와 팀·사용자, 장기간의 변경과 운영을 포함한다.

다음과 같은 특징이 있다.

  • 수백만 줄 이상의 코드
  • 여러 프로그래밍 언어
  • 다수의 저장소와 빌드
  • 여러 팀과 조직
  • 다양한 제품과 플랫폼
  • 많은 외부 의존성
  • 장기 지원 버전
  • 대규모 데이터
  • 세계 여러 지역의 운영
  • 규제와 계약
  • 지속적인 배포
  • 복잡한 장애

대규모 환경에서는 개별 개발자의 지식에만 의존할 수 없다.

다음이 필요하다.

  • 명확한 모듈과 서비스 경계
  • 코드와 데이터 소유권
  • 안정적인 인터페이스
  • 공통 빌드와 배포 플랫폼
  • 자동 시험
  • 구성과 릴리스 관리
  • 서비스 목록과 문서
  • 관찰 가능성
  • 조직적 의사결정
  • 지원과 폐기 정책

규모가 커질수록 관리 계층과 회의를 늘리는 것만으로 문제를 해결하기 어렵다. 시스템과 조직의 의존성을 줄이고 각 팀이 책임 영역을 독립적으로 변경·운영할 수 있게 설계해야 한다.

플랫폼과 생태계

플랫폼 소프트웨어는 다른 개발자와 제품이 그 위에서 기능을 만들 수 있도록 API·도구와 실행 환경을 제공한다.

예에는 다음이 있다.

  • 운영체제
  • 클라우드 플랫폼
  • 게임 엔진
  • 모바일 플랫폼
  • 웹 브라우저
  • 데이터베이스
  • 결제 플랫폼
  • 앱 마켓
  • 개발 프레임워크
  • 기업 내부 플랫폼

플랫폼은 일반 응용 프로그램보다 더 넓은 호환성과 장기적인 책임을 가진다.

다음이 중요하다.

  • 공개 API
  • 버전과 폐기
  • 확장과 플러그인
  • 개발자 문서
  • 샘플과 도구
  • 보안 격리
  • 자원 제한
  • 사용자와 개발자 지원
  • 생태계의 거버넌스
  • 패키지와 배포
  • 여러 제품의 요구 조정

플랫폼의 작은 인터페이스 변경이 많은 외부 프로그램을 손상시킬 수 있으므로 변경 전 영향과 이전 경로를 제공해야 한다.

플랫폼 제공자가 사용자와 개발자에게 서로 다른 이해를 가지므로 양쪽의 권리·품질과 보안 책임을 함께 고려해야 한다.

초장기 소프트웨어

일부 소프트웨어는 수십 년 동안 운영되며 원래의 개발자와 도구·하드웨어가 사라진 뒤에도 유지된다.

예에는 다음이 있다.

  • 금융 원장
  • 공공 행정
  • 철도와 항공
  • 산업 설비
  • 전력과 통신
  • 의료 기록
  • 과학 데이터
  • 국방 시스템

초장기 소프트웨어에서는 다음이 중요하다.

  • 읽을 수 있는 코드와 문서
  • 표준 형식
  • 데이터 이전
  • 도구 체인 보존
  • 지원 종료된 의존성
  • 지식 이전
  • 여러 세대의 하드웨어
  • 규제와 기록 보존
  • 점진적인 현대화
  • 보안 패치
  • 운영과 복구 절차

현재 유행하는 기술만을 기준으로 설계하면 수십 년의 제품 수명 동안 유지하기 어려울 수 있다.

외부 서비스와 폐쇄된 형식에 의존할 때는 공급자가 사라지거나 제품을 종료했을 때의 이전과 복구를 고려해야 한다.

실험과 프로토타입

실험용 소프트웨어와 프로토타입은 새로운 기술·사용자 경험과 사업 가설을 빠르게 확인하는 데 사용된다.

목적에는 다음이 있다.

  • 기술적 실현 가능성
  • 성능
  • 사용자 반응
  • 인터페이스
  • 알고리즘
  • 외부 서비스
  • 위험과 비용
  • 연구 가설

프로토타입은 정식 제품과 같은 완성도와 구조를 요구하지 않을 수 있다.

다만 프로토타입이 성공하여 그대로 실제 제품과 운영에 사용되는 경우가 많다. 실험 코드가 실제 사용자와 데이터를 다루기 시작하면 보안·시험과 유지보수 기준을 다시 평가해야 한다.

버려야 할 프로토타입과 발전시킬 초기 제품을 구분하고, 전자의 임시 구조가 후자에 무비판적으로 남지 않도록 한다.

사회적·문화적 소프트웨어

소프트웨어는 정보 전달·사회적 관계와 문화 활동에도 사용된다.

다음과 같은 영역이 있다.

  • 소셜 네트워크
  • 온라인 공동체
  • 뉴스와 미디어
  • 창작과 출판
  • 지식 공유
  • 문화유산
  • 시민 참여
  • 자원봉사
  • 언어와 번역
  • 데이트와 관계
  • 콘텐츠 추천

이러한 시스템에서는 기술적인 기능 외에 다음 영향이 중요하다.

  • 개인정보
  • 표현과 검열
  • 괴롭힘과 안전
  • 추천과 정보 편향
  • 허위 정보
  • 사용자 중독과 조작
  • 문화와 언어 차이
  • 아동과 취약한 사용자
  • 광고와 사업 모델
  • 콘텐츠 관리
  • 계정과 데이터 이동

참여 시간과 클릭을 높이는 기능이 사용자의 장기적 이익과 사회적 건강에 항상 도움이 되는 것은 아니다.

제품 지표와 알고리즘의 목표가 어떤 행동을 유도하며 누구에게 피해와 이익을 주는지 평가해야 한다.

분야별 조정

소프트웨어 공학의 원칙은 여러 분야에 공통으로 적용되지만 구체적인 활동의 강도와 순서는 조정해야 한다.

낮은 위험의 소규모 제품

다음 활동이 중심이 될 수 있다.

  • 사용자 문제와 핵심 요구
  • 단순한 아키텍처
  • 버전 관리
  • 코드 검토
  • 자동 시험
  • 지속적 배포
  • 사용자 피드백
  • 오류와 데이터 복구
  • 기본 보안

대규모 인터넷 서비스

다음 활동이 중요하다.

  • 분산 아키텍처
  • 자동 빌드·시험과 배포
  • 점진적 출시
  • 서비스 수준
  • 관찰 가능성
  • 장애 대응
  • 보안과 개인정보
  • 용량과 비용
  • 여러 팀의 소유권

장기 지원 제품

다음 활동이 중요하다.

  • 공개 인터페이스와 호환성
  • 장기 지원 버전
  • 설치와 업데이트
  • 데이터와 파일 형식
  • 지원 종료
  • 도구와 의존성 보존
  • 기술 부채와 현대화

규제·안전 필수 시스템

다음 활동이 중요하다.

  • 위험 분석
  • 엄격한 요구사항
  • 양방향 추적성
  • 독립적인 검증
  • 구성과 변경 통제
  • 공식 시험과 증거
  • 안전과 보안 평가
  • 운영과 유지보수 절차
  • 장기 기록
  • 인증과 감사

연구와 실험

다음 활동이 중요하다.

  • 빠른 탐색
  • 코드·데이터와 환경의 재현성
  • 계산 정확성
  • 연구 결과 검증
  • 필요에 따른 제품화
  • 장기 재사용 여부에 따른 공학 수준 조정

공통적인 적용 원리

활용 분야가 달라도 다음과 같은 소프트웨어 공학 원리는 널리 적용된다.

  • 사용자의 실제 문제와 목적을 이해한다.
  • 시스템의 경계와 이해관계자를 식별한다.
  • 기능과 품질·위험 요구를 함께 다룬다.
  • 책임과 인터페이스가 명확한 구조를 만든다.
  • 변경과 버전을 추적한다.
  • 자동화된 시험과 사람의 검토를 함께 사용한다.
  • 배포와 운영을 개발 초기부터 고려한다.
  • 실제 사용 환경의 피드백을 수집한다.
  • 외부 구성 요소와 공급망을 관리한다.
  • 보안·안전과 개인정보를 위험에 맞게 적용한다.
  • 유지보수와 지원 종료를 계획한다.
  • 규모와 위험에 맞게 절차와 문서를 조정한다.

소프트웨어 공학의 활용 범위가 넓다는 것은 모든 프로그램에 같은 대규모 절차를 적용해야 한다는 뜻이 아니다. 작은 프로그램에는 작고 명확한 공학 활동이 적합하며, 많은 사람의 생명과 권리·재산에 영향을 주는 시스템에는 더 엄격한 분석과 검증이 필요하다.

소프트웨어가 어떤 분야에 사용되는지를 아는 것만으로 충분하지 않다. 그 분야에서 무엇이 실패할 수 있고, 누구에게 어떤 피해가 발생하며, 어떤 환경에서 얼마나 오래 운영되고, 실제로 수정·복구할 수 있는지를 이해해야 한다.

소프트웨어 공학은 이러한 분야별 목적과 위험을 요구사항·구조·코드와 시험, 배포와 운영 체계로 변환한다. 그 결과 소프트웨어는 단순히 실행되는 프로그램을 넘어 실제 환경에서 지속적으로 사용·변경되고 책임 있게 관리되는 제품과 시스템이 된다.

장점과 한계

소프트웨어 공학은 소프트웨어 개발을 개인의 프로그래밍 능력과 즉흥적인 작업에만 의존하지 않고, 요구사항·설계·구현·시험·배포와 운영을 연결된 생명주기로 관리한다. 이를 통해 복잡한 소프트웨어를 여러 사람이 장기간 개발하고, 변경과 위험을 추적하며, 일정한 품질 수준으로 반복해서 전달할 수 있다.

그러나 소프트웨어 공학은 올바른 소프트웨어를 자동으로 만들어 주는 공식이나 하나의 고정된 개발 절차가 아니다. 요구사항의 불확실성·기술적 복잡성과 조직의 이해관계, 사람의 판단과 실제 사용 환경을 완전히 제거할 수 없으며, 부적절하게 적용하면 문서·승인과 도구만 증가시키는 관료적인 과정이 될 수 있다.

IEEE Computer Society는 소프트웨어 공학 프로세스를 고품질 시스템을 효율적이고 경제적으로 개발하기 위한 체계적·측정 가능하고 반복 가능한 접근으로 설명하면서도, 소프트웨어 개발이 창의성·의사소통과 협업을 필요로 하는 인간 중심의 활동임을 함께 강조한다.[183]

장점

복잡성의 구조화

소프트웨어 공학은 큰 문제를 요구사항·하위 시스템·모듈과 인터페이스로 나누어 다룰 수 있게 한다.

복잡한 소프트웨어에서는 모든 개발자가 전체 코드를 자세히 이해하기 어렵다. 아키텍처와 책임 경계·공개 인터페이스를 정의하면 각 팀과 구성 요소가 담당할 범위를 명확히 하고, 변경의 영향을 제한할 수 있다.

구조화는 다음을 지원한다.

  • 문제와 시스템 경계의 정의
  • 책임에 따른 모듈 분리
  • 구성 요소 사이의 인터페이스
  • 데이터와 상태의 소유권
  • 여러 팀의 병렬 개발
  • 부분적인 교체와 확장
  • 결함과 장애의 격리
  • 기술과 조직적 의사결정의 기록

복잡성을 완전히 제거하지는 못하지만 사람이 이해하고 변경할 수 있는 단위로 관리하도록 돕는다.

요구와 구현의 연결

요구사항 공학은 사용자가 말한 기능을 그대로 코드로 옮기는 데 그치지 않고 실제 문제와 목표·제약을 분석한다.

이를 통해 다음과 같은 실패를 줄일 수 있다.

  • 필요하지 않은 기능을 개발한다.
  • 이해관계자마다 다른 결과를 예상한다.
  • 중요한 품질과 예외 조건을 놓친다.
  • 사용자의 실제 업무와 맞지 않는 흐름을 만든다.
  • 구현할 수 없거나 검증할 수 없는 요구를 확정한다.
  • 보안·안전과 운영 요구를 출시 직전에 발견한다.

요구사항·설계와 시험 사이의 추적성을 유지하면 어떤 기능이 왜 존재하고 어떻게 검증되는지 확인하기 쉬워진다.

품질의 체계적 관리

소프트웨어 품질을 개발자의 주의와 최종 시험에만 맡기지 않고 생명주기 전체에서 관리할 수 있다.

다음과 같은 활동을 조합한다.

  • 요구사항과 수용 기준
  • 아키텍처와 설계 검토
  • 코드 검토
  • 정적·동적 분석
  • 단위·통합과 시스템 시험
  • 성능·보안과 사용성 평가
  • 자동 빌드와 지속적 통합
  • 운영 모니터링
  • 결함과 장애의 원인 분석
  • 회귀 시험

품질 활동을 조기에 수행하면 잘못된 요구와 구조를 구현 후반이나 운영 환경에서 발견하는 위험을 줄일 수 있다.

변경 관리

소프트웨어는 배포 이후에도 계속 변경된다. 소프트웨어 공학은 변경을 예외적인 사건이 아니라 제품 생명주기의 정상적인 활동으로 다룬다.

버전 관리·구성 관리와 변경 영향 분석을 통해 다음을 확인할 수 있다.

  • 누가 무엇을 변경했는가
  • 변경한 이유는 무엇인가
  • 어떤 요구와 결함에 연결되는가
  • 영향을 받는 구성 요소는 무엇인가
  • 어떤 시험을 수행했는가
  • 어떤 버전과 환경에 배포되었는가
  • 문제가 생기면 어떻게 복구할 것인가

이를 통해 여러 개발자의 변경을 통합하고, 제품별·고객별 구성과 장기 지원 버전을 관리할 수 있다.

협업과 책임의 명확화

소프트웨어 공학은 개발자뿐 아니라 사용자·기획자와 디자이너·시험·보안과 운영 담당자가 함께 작업할 수 있는 역할과 산출물·의사결정 구조를 제공한다.

공통 목표와 용어·인터페이스와 완료 조건을 정의하면 전문 분야 사이의 오해를 줄일 수 있다.

다음과 같은 책임도 명확히 할 수 있다.

  • 제품 목표와 우선순위
  • 요구사항의 승인
  • 기술적 구조
  • 코드와 서비스 소유권
  • 품질과 릴리스 기준
  • 보안·안전 위험의 수용
  • 배포와 운영
  • 장애 대응
  • 유지보수와 지원 종료

책임의 명확화는 모든 결정을 한 사람에게 집중하는 것이 아니라 필요한 판단을 적절한 역할과 수준에 배치하는 것이다.

예측과 계획의 개선

추정·위험 관리와 단계적인 전달은 프로젝트의 일정·비용과 결과를 더 현실적으로 계획하도록 돕는다.

소프트웨어 공학은 미래를 정확히 예측하지는 못하지만 다음을 가능하게 한다.

  • 작업과 의존성의 가시화
  • 기술적 불확실성의 조기 검증
  • 범위와 일정의 상충 관계 분석
  • 위험에 따른 우선순위
  • 작동하는 소프트웨어를 이용한 진행 확인
  • 실제 처리량과 품질 자료의 활용
  • 계획과 실제의 차이에 따른 재계획
  • 프로젝트 중단과 축소의 근거 마련

초기 추정을 절대적인 약속으로 고정하기보다 새롭게 발견된 정보를 계획에 반영할 수 있다.

반복 가능성과 자동화

빌드·시험·배포와 인프라를 자동화하면 개발자의 개인 환경과 수동 절차에 대한 의존을 줄일 수 있다.

자동화는 다음과 같은 장점을 제공한다.

  • 같은 절차의 반복
  • 빠른 피드백
  • 사람의 입력 오류 감소
  • 여러 플랫폼과 환경의 일관된 시험
  • 배포와 복구 시간 단축
  • 실행 결과와 이력의 기록
  • 대규모 시스템의 관리
  • 보안과 품질 규칙의 일관된 적용

자동화된 절차도 코드와 마찬가지로 검토·시험하고 지속적으로 유지해야 한다.

유지보수성

소프트웨어의 사용 기간은 최초 개발 기간보다 훨씬 길 수 있다. 소프트웨어 공학은 이후의 수정·확장과 운영을 초기 설계부터 고려한다.

유지보수성을 높이는 요소에는 다음이 있다.

  • 명확한 모듈과 책임
  • 안정적인 인터페이스
  • 자동화된 시험
  • 문서와 결정 기록
  • 재현 가능한 빌드
  • 관찰 가능성
  • 데이터와 API의 호환성
  • 외부 의존성 관리
  • 지원과 폐기 정책
  • 팀 사이의 지식 공유

이를 통해 새로운 개발자가 시스템을 이해하고 기존 기능을 손상시키지 않으면서 변경할 가능성을 높인다.

위험의 조기 발견

위험 분석·프로토타입과 점진적 개발을 통해 기술·제품과 운영 위험을 프로젝트 초기에 확인할 수 있다.

예를 들어 다음을 먼저 검증할 수 있다.

  • 요구된 성능을 달성할 수 있는가
  • 외부 시스템과 실제로 연동되는가
  • 사용자가 작업 흐름을 이해하는가
  • 데이터 이전이 가능한가
  • 선택한 기술이 대상 장치를 지원하는가
  • 보안과 안전 요구를 충족할 수 있는가
  • 운영 조직이 서비스를 관리할 수 있는가

위험이 큰 문제를 프로젝트 후반까지 미루지 않으면 실패 비용을 줄이고 설계와 범위를 조정할 수 있다.

보안·안전과 사회적 책임

소프트웨어 공학은 프로그램의 기능뿐 아니라 사용자가 받을 수 있는 피해와 조직의 책임을 체계적으로 다룰 수 있다.

보안 개발·안전 분석과 전문 윤리를 통해 다음을 고려한다.

  • 공격과 오용
  • 사람과 환경에 대한 피해
  • 개인정보
  • 접근성과 공정성
  • 공급망
  • 장애와 복구
  • 알려진 위험의 공개
  • 지원 종료와 데이터 이전
  • 공공의 이익

Software Engineering Code of Ethics는 소프트웨어 엔지니어가 공공의 이익에 맞게 행동하고 자신의 작업에 책임을 지며, 제품의 분석·명세·설계·개발·시험과 유지보수에서 전문적인 기준을 지켜야 한다고 제시한다.[184]

지식의 축적과 재사용

소프트웨어 공학은 프로젝트 경험을 개인의 기억에만 남기지 않고 조직과 전문 분야의 지식으로 축적한다.

다음과 같은 형태로 지식을 보존할 수 있다.

  • 요구사항과 도메인 모델
  • 아키텍처와 설계 결정
  • 재사용 가능한 구성 요소
  • 시험과 품질 기준
  • 코딩과 보안 지침
  • 자동화 도구
  • 장애와 사후 분석
  • 개발 방법론
  • 표준과 지식 체계
  • 교육과 전문 공동체

SWEBOK는 소프트웨어 공학 전문 분야에 축적된 전체 지식을 하나의 문서에 모두 담을 수 없다는 점을 전제로, 일반적으로 인정되는 지식으로 안내하는 체계를 제공한다.[185]

한계

완전한 예측의 불가능성

소프트웨어 프로젝트는 시작 시점에 요구사항과 기술적 해결 방법을 모두 알기 어렵다.

다음과 같은 요소가 계속 변할 수 있다.

  • 사용자와 시장의 요구
  • 법률과 정책
  • 운영체제와 하드웨어
  • 외부 서비스와 API
  • 보안 위협
  • 데이터와 사용량
  • 조직의 우선순위
  • 개발 팀과 공급자
  • 실제 사용자 행동

따라서 체계적인 추정과 계획을 사용하더라도 일정·비용과 결함 수를 정확하게 예측할 수는 없다.

지나치게 확정적인 장기 계획은 실제 불확실성을 없애지 않고, 변경을 숨기거나 품질 활동을 생략하게 만들 수 있다.

올바른 요구를 보장하지 못함

요구사항 공학을 수행하더라도 사용자가 진정으로 필요로 하는 제품을 반드시 만들 수 있는 것은 아니다.

사용자가 자신의 필요를 정확히 설명하지 못할 수 있고, 여러 이해관계자의 목표가 충돌할 수 있다. 새로운 제품에서는 실제 사용 전까지 어떤 기능이 가치 있는지 알기 어려울 수도 있다.

정확하게 구현된 소프트웨어라도 다음과 같은 이유로 실패할 수 있다.

  • 해결할 가치가 낮은 문제를 선택했다.
  • 사용자가 기존 절차를 바꾸지 않는다.
  • 제품의 비용과 학습 부담이 크다.
  • 경쟁 제품과 시장 환경이 변했다.
  • 사회적·법률적 수용성이 부족하다.
  • 측정한 목표가 실제 사용자 가치와 다르다.

소프트웨어 공학은 이러한 위험을 줄일 수 있지만 제품·사업과 사회적 판단을 대신하지는 못한다.

사람과 조직에 대한 의존

소프트웨어 개발은 지식과 의사소통·창의성을 요구하는 사람 중심의 활동이다.

같은 방법과 도구를 사용해도 팀의 경험·협업과 조직 문화에 따라 결과가 달라질 수 있다.

다음과 같은 조직 문제는 기술적 절차만으로 해결하기 어렵다.

  • 목표와 권한의 충돌
  • 위험과 실패를 숨기는 문화
  • 비현실적인 일정
  • 부서 사이의 경쟁
  • 책임 없는 승인
  • 잦은 인력 교체
  • 지식의 독점
  • 사용자의 참여 부족
  • 장기 품질보다 단기 지표를 우선하는 평가

IEEE Computer Society는 소프트웨어 공학 프로세스가 자동화와 정량적 방법을 사용하더라도 창의성·의사소통과 협업을 필요로 하는 인간 중심의 실무임을 설명한다.[186]

방법론의 보편적 적용 불가능

모든 프로젝트에 가장 좋은 하나의 소프트웨어 개발 방법론은 존재하지 않는다.

다음에 따라 적합한 접근이 달라진다.

  • 프로젝트 규모
  • 요구사항의 변화
  • 안전과 규제
  • 팀의 위치와 경험
  • 제품의 수명
  • 하드웨어와 배포 환경
  • 고객 계약
  • 운영 방식
  • 실패 비용
  • 조직 문화

웹 제품의 지속적 배포 방식을 의료 장비와 우주 시스템에 그대로 적용하기 어렵고, 안전 필수 시스템의 모든 공식 절차를 개인용 소규모 도구에 적용하는 것도 비효율적이다.

방법론의 이름과 의식을 그대로 따르기보다 실제 위험과 피드백·증거의 필요에 맞게 조정해야 한다.

절차의 관료화

문서·검토와 승인 절차는 지식과 책임을 관리하는 데 유용하지만 목적 없이 늘어나면 개발을 방해할 수 있다.

관료화된 과정에서는 다음 문제가 나타날 수 있다.

  • 실제로 사용하지 않는 문서를 작성한다.
  • 같은 정보를 여러 도구에 반복 입력한다.
  • 품질과 무관한 형식만 검사한다.
  • 승인자가 내용을 이해하지 않고 승인한다.
  • 작은 변경도 긴 대기열을 거친다.
  • 실제 문제보다 절차 준수를 우선한다.
  • 팀이 책임 있는 판단 대신 규칙 뒤에 숨는다.

프로세스의 산출물이 실제 의사결정·검증과 운영에 사용되는지 지속적으로 평가해야 한다.

절차를 줄이는 것과 공학 활동을 생략하는 것도 구분해야 한다. 불필요한 문서를 제거하더라도 요구 분석·시험과 위험 관리는 다른 방식으로 수행되어야 한다.

측정의 한계

소프트웨어의 생산성과 품질을 하나의 숫자로 정확하게 표현하기 어렵다.

다음 지표는 일부 정보만 제공한다.

  • 코드 줄 수
  • 커밋 수
  • 완료한 작업 수
  • 결함 수
  • 시험 커버리지
  • 개발 속도
  • 배포 빈도
  • 가동 시간
  • 일정 준수율

코드가 적다고 항상 좋은 설계는 아니며, 결함 보고가 적다는 사실이 품질이 높다는 의미가 아닐 수 있다. 시험 커버리지가 높아도 중요한 결과를 검증하지 않을 수 있다.

측정값을 목표로 사용하면 실제 품질보다 수치를 개선하는 행동이 나타날 수 있다.

NIST의 소프트웨어 측정 관련 논의에서도 모든 상황에 적용할 하나의 정적·동적 지표를 권고하는 것은 불가능하며, 소프트웨어 측정에는 여러 관점을 함께 사용해야 한다고 지적한다.[187]

복잡성의 제거 불가능

모듈화·추상화와 자동화는 복잡성을 관리하지만 모든 복잡성을 제거하지는 못한다.

소프트웨어는 다음과 같은 복잡성을 가진다.

  • 많은 상태와 실행 경로
  • 동시성과 비결정성
  • 여러 구성 요소의 상호작용
  • 외부 시스템과 네트워크
  • 오래된 데이터와 호환성
  • 다양한 사용자와 장치
  • 여러 버전과 설정
  • 조직과 공급자 관계

복잡성을 숨기는 추상화도 내부 실패와 성능 특성을 완전히 없애지 못한다.

기능과 예외를 계속 추가하면 관리 기법이 개선되어도 전체 복잡성이 증가할 수 있다. 불필요한 기능과 상태·의존성을 제거하는 제품과 아키텍처 결정이 함께 필요하다.

결함의 완전한 제거 불가능

시험과 형식 검증을 사용하더라도 규모가 큰 일반 소프트웨어에서 모든 결함이 없음을 보장하기는 어렵다.

시험은 실행한 입력과 조건을 확인하며, 가능한 모든 상태와 환경을 다룰 수 없는 경우가 많다. 형식 기법도 모델과 명세가 실제 요구를 올바르게 표현한다는 전제에 의존한다.

결함을 줄이는 것과 함께 다음을 설계해야 한다.

  • 결함의 조기 탐지
  • 장애의 격리
  • 안전한 실패
  • 데이터와 서비스 복구
  • 점진적인 배포
  • 이전 버전으로의 전환
  • 운영 관찰
  • 취약점과 사고 대응

안전 필수 시스템에서는 위험에 따라 더 강한 분석과 증거를 요구하지만 절차와 인증만으로 절대적인 안전이 보장되지는 않는다.

비용과 시간의 증가

소프트웨어 공학 활동에는 추가적인 시간과 비용이 필요하다.

  • 요구사항 분석
  • 설계와 검토
  • 자동 시험
  • 빌드와 배포 자동화
  • 문서
  • 보안과 안전 분석
  • 구성 관리
  • 사용자 연구
  • 운영과 관찰
  • 전문 인력과 도구

일회성 실험과 매우 작은 프로그램에서는 복잡한 공학 체계를 구축하는 비용이 얻는 이익보다 클 수 있다.

반대로 중요한 소프트웨어에서 이러한 활동을 생략하면 초기 비용은 낮아도 결함·장애와 유지보수 비용이 증가할 수 있다.

프로젝트의 규모와 수명·실패 위험에 맞는 수준으로 공학 활동을 조정해야 한다.

기술과 도구에 대한 의존

자동화와 개발 도구는 생산성을 높이지만 새로운 의존성과 위험을 만든다.

  • 도구의 결함
  • 공급자의 가격과 정책 변경
  • 서비스 종료
  • 독점 형식
  • 플러그인과 공급망 침해
  • 오래된 도구 체인
  • 자동화의 잘못된 판정
  • 소수 담당자에게 집중된 운영 지식

도구가 대신 처리하던 작업의 원리를 팀이 이해하지 못하면 도구 장애와 이전에 대응하기 어렵다.

핵심 자료와 빌드·배포 절차를 복구할 수 있게 하고 도구 자체도 생명주기와 보안 관리의 대상으로 다뤄야 한다.

기존 시스템과 현실적인 제약

새로운 소프트웨어는 완전히 깨끗한 환경에서 만들어지는 경우보다 기존 데이터·프로그램과 조직에 통합되는 경우가 많다.

다음과 같은 제약이 존재할 수 있다.

  • 문서가 없는 오래된 코드
  • 지원 종료된 플랫폼
  • 교체하기 어려운 데이터 형식
  • 알려지지 않은 업무 규칙
  • 외부 공급자
  • 장기간 유지된 사용자 습관
  • 규제와 계약
  • 중단할 수 없는 운영
  • 제한된 예산과 인력

이상적인 아키텍처와 방법론을 적용할 수 없으며 위험과 비용을 고려한 점진적인 개선이 필요하다.

전체 재작성도 기존 시스템의 암묵적인 기능과 예외를 잃을 수 있으므로 항상 근본적인 해결책이 되지는 않는다.

사회적 결과의 예측 한계

소프트웨어가 사회에서 어떻게 사용되고 어떤 영향을 만들지는 개발 당시의 의도를 넘어설 수 있다.

  • 원래 목적과 다른 방식으로 사용된다.
  • 대규모 사용으로 사회적 관계가 변한다.
  • 알고리즘이 특정 집단에 불리하게 작동한다.
  • 사용자가 자동화를 지나치게 신뢰한다.
  • 사업 모델이 조작적인 설계를 유도한다.
  • 공격자와 조직이 기능을 악용한다.
  • 기술이 일자리와 권력 관계를 바꾼다.

윤리 검토와 영향 평가를 수행해도 모든 장기적 결과를 예측할 수는 없다.

운영 중 실제 영향을 관찰하고 피해가 발견되면 기능·정책과 제품 목표를 수정하거나 서비스를 종료할 수 있어야 한다.

전문 지식의 경계

소프트웨어 엔지니어는 의료·금융·법률과 물리 시스템 등 모든 응용 분야의 전문가가 아니다.

기술적으로 올바른 구현도 도메인의 개념과 위험을 잘못 이해하면 잘못된 결과를 만들 수 있다.

전문가와 협력하더라도 다음과 같은 문제가 남을 수 있다.

  • 도메인 지식이 암묵적이다.
  • 전문가 사이에서도 의견이 다르다.
  • 법률과 업무 규칙이 변한다.
  • 예외와 실제 관행이 문서와 다르다.
  • 기술적 모델이 현실을 지나치게 단순화한다.

소프트웨어 공학은 도메인 지식을 구조화하고 구현하도록 돕지만 그 지식을 대신 만들어 주지는 않는다.

장점과 한계의 관계

소프트웨어 공학의 장점과 한계는 서로 독립적이지 않다.

문서화는 지식과 추적성을 높이지만 과도하면 관료화된다. 자동화는 반복성과 속도를 높이지만 잘못된 절차를 빠르게 확산할 수 있다. 아키텍처는 복잡성을 분리하지만 지나친 추상화는 새로운 복잡성을 만든다. 표준화는 일관성을 제공하지만 새로운 환경과 특수한 문제에 맞지 않을 수 있다.

측정은 상태와 개선을 이해하게 하지만 잘못된 지표는 행동을 왜곡한다. 계획은 의존성과 위험을 드러내지만 불확실한 미래를 확정된 것으로 취급하게 만들 수 있다. 코드 검토와 승인은 결함을 줄이지만 책임이 형식적인 절차에 분산될 수도 있다.

따라서 소프트웨어 공학의 활동은 존재 여부만으로 평가하지 않고 다음을 확인해야 한다.

  • 어떤 문제와 위험을 해결하는가
  • 실제 의사결정과 품질에 사용되는가
  • 비용과 지연에 비해 효과가 있는가
  • 프로젝트의 규모와 수명에 적합한가
  • 사람들이 의미와 책임을 이해하는가
  • 변화하는 환경에 맞게 개선되는가
  • 제거하거나 단순화할 수 있는가

소프트웨어 공학은 불확실성과 결함을 완전히 없애는 분야가 아니다. 이를 조기에 드러내고, 합리적인 근거에 따라 결정하며, 실패가 발생했을 때 영향을 제한하고 학습할 수 있게 하는 분야이다.

장점은 더 많은 절차와 도구를 사용하는 데서 생기지 않는다. 실제 문제와 위험에 맞는 공학 활동을 선택하고, 작동하는 소프트웨어와 사용자·운영 결과를 통해 그 효과를 확인할 때 나타난다.

관련 문서

  1. NATO: Garmisch Conference and the emergence of software engineering
  2. IEEE Computer Society: Software Engineering Body of Knowledge
  3. Computer History Museum: Software & Languages Timeline
  4. Computer History Museum: Programming the ENIAC
  5. Computer History Museum: 1948 Timeline
  6. Computer History Museum: The Stored Program
  7. Computer History Museum: History of FORTRAN and FORTRAN II
  8. Computer History Museum: Software & Languages Timeline
  9. Computer History Museum Software Preservation Group: Operating Systems
  10. Computer History Museum: Fernando Corbató
  11. Computer History Museum: UNIX Operating System
  12. NATO: Garmisch Conference
  13. Computer History Museum: Software Becomes a Product
  14. Computer History Museum: The Lisa
  15. GNU Project: Overview of the GNU System
  16. GNU Project: Initial Announcement
  17. Computer History Museum: Linux is Announced
  18. Open Source Initiative: History of the OSI
  19. Open Source Initiative: The Open Source Definition
  20. CERN: The Birth of the World Wide Web
  21. Amazon Web Services: Our Origins
  22. ISO: ISO/IEC 25010:2023
  23. NIST: Secure Software Development Framework Version 1.1
  24. Carnegie Mellon University Software Engineering Institute: Architecture Tradeoff Analysis Method
  25. ISO: ISO/IEC 25010:2023
  26. Carnegie Mellon University Software Engineering Institute: Software Architecture
  27. ISO: ISO/IEC/IEEE 12207:2026 — Software life cycle processes
  28. Carnegie Mellon University Software Engineering Institute: Spiral Development — Experience, Principles, and Refinements
  29. IEEE Computer Society: SWEBOK — Software Engineering Process
  30. Manifesto for Agile Software Development
  31. Principles behind the Agile Manifesto
  32. ISO: ISO/IEC/IEEE 29148:2018 — Requirements engineering
  33. IEEE Computer Society: Software Requirements Course
  34. NASA: Fundamentals of Systems Engineering — Verification and Validation
  35. INCOSE: Requirements and Traceability
  36. Manifesto for Agile Software Development
  37. ISO: ISO/IEC/IEEE 42010:2022 — Architecture description
  38. IEEE Computer Society: SWEBOK — Software Architecture
  39. Carnegie Mellon University Software Engineering Institute: Quality Attribute Workshop Collection
  40. Carnegie Mellon University Software Engineering Institute: Reasoning About Software Quality Attributes
  41. Carnegie Mellon University Software Engineering Institute: Architecture Tradeoff Analysis Method Collection
  42. IEEE Computer Society: SWEBOK Software Architecture Topics
  43. Carnegie Mellon University Software Engineering Institute: The Architecture Tradeoff Analysis Method
  44. ISO: ISO/IEC/IEEE 42010:2022
  45. Object Management Group: Unified Modeling Language
  46. IEEE Computer Society: Guide to the Software Engineering Body of Knowledge
  47. IEEE Computer Society: SWEBOK Knowledge Areas
  48. Reproducible Builds: Definitions
  49. NIST: Secure Software Development Framework Version 1.1
  50. Git: About Version Control
  51. Git: Branches in a Nutshell
  52. Semantic Versioning 2.0.0
  53. Git: Tagging
  54. SPDX: Overview
  55. NIST: Secure Software Development Framework Version 1.1
  56. IEEE Computer Society: SWEBOK — Software Configuration Management
  57. ISO: ISO/IEC/IEEE 29119-1:2022 — Software testing — General concepts
  58. ISO/IEC JTC 1/SC 7: ISO/IEC/IEEE 29119 series
  59. IEEE Computer Society: SWEBOK Knowledge Areas
  60. ISO: ISO/IEC 25010:2023 — Product quality model
  61. IEEE Computer Society: SWEBOK — Software Quality
  62. ISO: ISO/IEC/IEEE 29119-4:2015 — Test techniques
  63. NIST: Guidelines on Minimum Standards for Developer Verification of Software
  64. NIST: Secure Software Development Framework Version 1.1
  65. ISO: ISO/IEC TR 29119-11:2020 — Testing of AI-based systems
  66. ISO: ISO/IEC/IEEE 14764:2022 — Software maintenance
  67. IEEE Computer Society: SWEBOK Evolution
  68. Google SRE: Release Engineering
  69. Kubernetes: Update a Deployment Without Downtime
  70. Google SRE Workbook: Canarying Releases
  71. Google SRE: Introduction
  72. Google SRE: Service Level Objectives
  73. Google SRE: Monitoring Distributed Systems
  74. Google SRE: Postmortem Culture
  75. Google SRE: Eliminating Toil
  76. NIST CSRC: Contingency Planning
  77. NIST: Secure Software Development Framework Version 1.1
  78. DORA: Software delivery performance metrics
  79. IEEE Computer Society: SWEBOK — Software Engineering Process
  80. The Scrum Guide
  81. Winston W. Royce: Managing the Development of Large Software Systems
  82. Carnegie Mellon University Software Engineering Institute: Spiral Development — Experience, Principles, and Refinements
  83. Agile Manifesto: History
  84. Manifesto for Agile Software Development
  85. Principles behind the Agile Manifesto
  86. The 2020 Scrum Guide
  87. The Kanban Guide
  88. Scaled Agile Framework
  89. IEEE Computer Society: SWEBOK — Software Engineering Process Topics
  90. Manifesto for Agile Software Development
  91. ISO: ISO 21502:2020 — Guidance on project management
  92. IEEE Computer Society: SWEBOK Knowledge Areas
  93. Project Management Institute: PMBOK Guide
  94. ISO: ISO 21500:2021 — Context and concepts
  95. Principles behind the Agile Manifesto
  96. The Scrum Guide
  97. ISO: Improving project management with ISO 21502
  98. Project Management Institute: 12 Principles of Project Management
  99. The Scrum Guide
  100. ISO: ISO 21502:2020 — Guidance on project management
  101. Manifesto for Agile Software Development
  102. Scrum Guides: Official current version
  103. ISO: ISO 21500:2021 — Context and concepts
  104. IEEE Computer Society: Software Engineering Professional Practice
  105. Principles behind the Agile Manifesto
  106. IEEE Computer Society: SWEBOK Knowledge Areas
  107. Language Server Protocol
  108. Reproducible Builds: Definitions
  109. NIST: Secure Software Development Framework Version 1.1
  110. DORA: Test automation
  111. ISO: ISO/IEC 5962:2021 — SPDX Specification
  112. SPDX: Overview
  113. DORA: Continuous integration
  114. DORA: Continuous delivery
  115. DORA: Deployment automation
  116. HashiCorp Developer: What is Terraform
  117. OpenTelemetry Documentation
  118. OpenTelemetry: What is OpenTelemetry?
  119. NIST: Secure Software Development Framework
  120. NIST NCCoE: Secure Software Development, Security, and Operations
  121. NIST: Secure Software Development Framework Version 1.1
  122. IEC: Safety and functional safety
  123. ACM: Software Engineering Code of Ethics and Professional Practice
  124. NIST: Secure Software Development Framework Version 1.1
  125. ISO: ISO/IEC 27001:2022 — Information security management systems
  126. IEC: Safety and functional safety
  127. IEC: IEC 61508-3:2010
  128. IEC: Overview of IEC 61508 and Functional Safety
  129. NIST: Privacy Framework
  130. ACM: Software Engineering Code of Ethics and Professional Practice
  131. ISO: Standards
  132. IEEE Computer Society: Software Engineering Body of Knowledge
  133. IEEE Computer Society: SWEBOK V4.0 Topics
  134. ISO: ISO/IEC/IEEE 24765:2017 — Systems and software engineering vocabulary
  135. ISO/IEC JTC 1/SC 7: Software and systems engineering standards catalogue
  136. ISO: Certification
  137. ISO: ISO/IEC/IEEE 24748-3:2020 — Guidelines for the application of software life cycle processes
  138. ISO: ISO/IEC JTC 1/SC 7 — Software and systems engineering
  139. ISO: ISO/IEC/IEEE 12207:2017 — Software life cycle processes
  140. ISO: ISO/IEC/IEEE 15288:2023 — System life cycle processes
  141. ISO: ISO/IEC/IEEE 12207:2017
  142. ISO/IEC JTC 1/SC 7: Standards catalogue
  143. ISO/IEC JTC 1/SC 7: ISO/IEC/IEEE 29148:2018
  144. ISO: ISO/IEC/IEEE 42010:2022 — Architecture description
  145. ISO/IEC JTC 1/SC 7: ISO/IEC/IEEE 29119 series
  146. ISO: ISO/IEC/IEEE 29119-1:2022 — General concepts
  147. ISO/IEC JTC 1/SC 7: ISO/IEC 25000 SQuaRE series
  148. ISO: ISO/IEC 25000:2014 — Guide to SQuaRE
  149. ISO/IEC JTC 1/SC 7: ISO/IEC 25010:2023
  150. ISO: ISO/IEC/IEEE 14764:2022 — Software maintenance
  151. ISO: ISO/IEC 27001 — Information security management systems
  152. NIST: Secure Software Development Framework Version 1.1
  153. IEC: Functional Safety
  154. IEC: IEC 61508-3:2010
  155. IEEE Computer Society: Software Engineering Body of Knowledge
  156. IEEE Computer Society: SWEBOK Summit
  157. IEEE Computer Society: SWEBOK Evolution
  158. INCOSE: Systems Engineering Body of Knowledge
  159. SEBoK: Guide to the Systems Engineering Body of Knowledge
  160. Project Management Institute: PMBOK Guide
  161. IIBA: A Guide to the Business Analysis Body of Knowledge
  162. ACM: Software Engineering 2014 Curriculum Guidelines
  163. ISO/IEC JTC 1/SC 7: Standards catalogue
  164. ISO: ISO/IEC 5338:2023 — AI system life cycle processes
  165. ISO: ISO/IEC TR 29119-11:2020 — Testing of AI-based systems
  166. ISO/IEC JTC 1/SC 7: Standards catalogue
  167. ACM: Curricula Recommendations
  168. ACM and IEEE Computer Society: Computing Curricula 2020
  169. ACM, IEEE Computer Society and AAAI: Computer Science Curricula 2023
  170. INCOSE: About Systems Engineering
  171. ISO: ISO/IEC/IEEE 15288:2023 — System life cycle processes
  172. ISO: ISO/IEC/IEEE 24748-1:2024 — Life cycle management
  173. ACM Data Science Task Force: Computing Competencies for Undergraduate Data Science Curricula
  174. ACM: Human Computer Interaction
  175. NIST: Secure Software Development Framework
  176. IEEE Computer Society: SWEBOK Version 4
  177. NIST: Secure Software Development Framework
  178. U.S. Food and Drug Administration: Software as a Medical Device
  179. U.S. Food and Drug Administration: Device Software Functions and Mobile Medical Applications
  180. U.S. Food and Drug Administration: Artificial Intelligence in Software as a Medical Device
  181. NASA: Software Engineering Handbook
  182. NASA: Software Engineering Handbook
  183. IEEE Computer Society: The Software Engineering Process
  184. ACM: Software Engineering Code of Ethics and Professional Practice
  185. IEEE Computer Society: Software Engineering Body of Knowledge
  186. IEEE Computer Society: The Software Engineering Process
  187. NIST: What Happened to Software Metrics?