소프트웨어 공학 100 주제 시리즈의 91번째 글이다. (카테고리: 유지보수·진화·사람)

한 줄 요약

출시 후의 변경은 “버그 수정” 하나로 뭉뚱그리면 계획이 안 된다. ISO/IEC/IEEE 14764 는 변경 요청을 수정(correction) 과 개선(enhancement) 으로 먼저 나누고, 그 안을 교정·예방 / 적응·완전화·추가로 다시 나눈다. 전통적으로 “네 유형” 이라 불렀고, 2022년판에서 다섯 번째인 추가(additive)가 정식으로 들어왔다.

왜 필요한가

릴리스가 끝나면 팀의 일은 이슈 트래커 하나로 들어온다. 결제 실패 버그, 운영체제 업그레이드 대응, 응답 속도 개선, 새 리포트 화면이 모두 “티켓” 이다. 분류가 없으면 세 가지 문제가 생긴다.

  1. 예산과 계약이 엉킨다. 외주 유지보수 계약에서 “하자 보수” 와 “기능 추가” 는 보통 다른 돈이다. 둘을 구분하지 못하면 매번 협상이 된다.
  2. 품질 신호가 사라진다. 교정 작업 비율이 늘어나는지, 환경 변화 대응이 늘어나는지는 서로 다른 문제를 가리킨다. 전자는 품질, 후자는 의존성 관리다.
  3. “유지보수 = 버그 수정” 이라는 착각. 실제로는 출시 후 작업의 상당 부분이 환경 적응과 기능 개선이다. 이걸 모르면 유지보수 조직은 늘 인력이 부족하다는 말만 듣는다.

핵심 개념

기원: Swanson 의 세 범주

유형 분류의 출발점은 E. Burton Swanson 의 1976년 ICSE 논문 “The Dimensions of Maintenance” 다. 그는 유지보수를 교정(corrective)·적응(adaptive)·완전화(perfective) 의 세 범주로 나눴다. 이후 예방(preventive) 이 더해져 “네 유형” 이 교과서 표준이 됐고, 2006년판(ISO/IEC 14764:2006)도 이 네 유형을 썼다.

2022년판의 정의

현행판은 ISO/IEC/IEEE 14764:2022 (3판, 2022-01) 다. 2006년판을 대체하며, 변경점으로 ISO/IEC/IEEE 12207:2017 과의 정렬과 “현대적 유지보수 접근의 도입” 을 든다. 범위는 12207:2017 의 유지보수 프로세스(6.4.13)를 상세화한 것이고, 백업·복구 같은 운영 업무는 다루지 않는다. 대신 폐기(disposal) 프로세스는 포함한다.

표준 3.1 절의 정의를 옮긴다(번역은 필자).

유형 정의 (14764:2022) 상위 분류
교정(corrective) 인도 후 발견된 문제를 고치기 위한 수정 수정(correction)
예방(preventive) 잠재 결함이 운영 시스템에서 발현되기 전에 고치는 인도 후 수정 수정(correction)
적응(adaptive) 바뀌었거나 바뀌고 있는 환경에서 제품을 계속 쓸 수 있게 하는 인도 후 수정 개선(enhancement)
완전화(perfective) 사용자를 위한 개선, 사용자 정보 개선, 성능·유지보수성 등 속성 향상을 위한 수정 개선(enhancement)
추가(additive) 제품 사용을 향상하기 위해 기능·특징을 더하는 인도 후 수정 개선(enhancement)

여기에 긴급(emergency) 유지보수 가 따로 정의된다. “교정 유지보수를 하기 전까지 시스템을 임시로 가동 상태로 유지하기 위한 비계획 수정” 이고, 표준은 이를 교정 유형의 하나로 볼 수 있다고 적는다. 장애 중 기능을 일부 끄는 핫픽스가 여기에 해당한다.

상위 분류의 정의도 중요하다. 수정(correction) 은 정의된 운영 요구를 다시 만족하도록 문제를 해결하는 변경이고, 개선(enhancement) 은 “새 요구를 구현하는 변경” 이다. 표준은 “개선은 수정이 아니다” 라고 못박는다.

                  변경 요청(MR, modification request)
                           │
          ┌────────────────┴────────────────┐
     수정(correction)                  개선(enhancement)
   요구를 다시 만족시킨다              새 요구를 구현한다
      │           │                 │         │         │
   교정         예방              적응      완전화      추가
 (긴급 포함)  (잠재 결함)        (환경)   (속성 향상)  (기능 추가)

왜 ‘추가’ 를 따로 뺐나

2022년판은 추가 유지보수를 완전화와 구분하는 이유로, 비교적 큰 기능 추가를 인도 후에 할 때 공급자와 인수자 사이에서 유지보수 전략·자원·계약·서비스 수준을 따로 협상할 수 있게 하려는 것이라고 설명한다. 또 신뢰성(dependability) 맥락에서 “이전 수준으로의 복구” 를 유지보수라고 부를 때는 추가 유지보수를 정의에서 빼도 된다고 적는다. 결국 계약과 측정의 경계를 분명히 하려는 장치다. 표준 스스로도 “일부 조직에서는 적응 유지보수를 개선으로 보지 않는다” 는 주석을 달아, 분류가 조직마다 다를 수 있음을 인정한다.

같은 MR 이 여러 유형이 될 수 있다

표준의 주석 하나가 실무적으로 유용하다. 이미 바뀐 환경에 맞추는 적응 작업은 수정으로 분류된 MR 에서도 나올 수 있다. 예컨대 “새 OS 에서 앱이 죽는다” 는 장애 신고는 수정 MR 로 들어오지만, 실제 작업은 적응 유지보수다. 또 같은 장애의 재발을 막는 방법으로, 잠재 결함을 고치는 예방 유지보수와 사람의 실수를 막도록 UI 를 개선하는 완전화 유지보수를 함께 든다. 분류는 원인 분석 이후에 확정하는 것이 맞다.

프로세스 안에서의 위치

14764 는 유형 정의만 있는 문서가 아니다. 본문은 유지보수 전략·계획, 문제·변경 분석(MR/PR 타당성 검토, 재현·검증, 승인), 변경 구현과 리뷰, 그리고 폐기(disposal) 까지 다룬다. 폐기 절에는 폐기 전략, 사용자 통지, 기록 보관이 들어 있다. API 폐기 정책(SE100 #094 에서 다룬다)이 이 마지막 단계의 구체화다.

소프트웨어는 왜 계속 변하는가

유형 분류가 “무엇을” 고치는지라면, M. M. Lehman 의 연구는 “왜 멈출 수 없는지” 를 설명한다. Lehman 은 Programs, Life Cycles, and Laws of Software Evolution (Proceedings of the IEEE, 68(9), 1980)에서 실세계 문제를 다루는 프로그램(E-type)은 계속 변경되지 않으면 점점 덜 유용해지고, 변경이 쌓일수록 복잡도를 줄이는 일을 따로 하지 않는 한 복잡도가 증가한다 고 정리했다. 앞의 것이 적응·완전화·추가의 근거이고, 뒤의 것이 예방 유지보수와 리팩터링의 근거다. 기술 부채의 경제학은 기술 부채 글에서 다뤘다.

실무 적용

티켓 분류 규칙 예

이슈 트래커에 유형 라벨을 두고, 분석 후 확정한다. 아래는 분류를 돕는 간단한 판정 함수다.

from enum import Enum

class MType(Enum):
    EMERGENCY = "corrective/emergency"
    CORRECTIVE = "corrective"
    PREVENTIVE = "preventive"
    ADAPTIVE = "adaptive"
    PERFECTIVE = "perfective"
    ADDITIVE = "additive"

def classify(t: dict) -> MType:
    """t: 원인 분석이 끝난 티켓의 속성"""
    if t["breaks_existing_requirement"]:          # 정의된 요구를 못 지키고 있다
        if t["in_production_incident"] and t["temporary_fix"]:
            return MType.EMERGENCY
        if t["failure_observed"]:
            return MType.CORRECTIVE
        return MType.PREVENTIVE                     # 아직 발현 안 된 잠재 결함
    if t["environment_changed"]:                    # OS, 런타임, 외부 API, 법규
        return MType.ADAPTIVE
    if t["new_capability"]:                         # 사용자가 못 하던 일을 하게 됨
        return MType.ADDITIVE
    return MType.PERFECTIVE                         # 성능, 사용성, 유지보수성
티켓 판정 이유
결제 장애 중 해외카드 결제 임시 차단 긴급(교정) 운영 유지용 임시 조치
위 장애의 근본 원인 수정 교정 관측된 실패
정적 분석이 찾은 미발현 널 역참조 예방 잠재 결함
런타임 지원 종료 대응 버전 업 적응 환경 변화
목록 API 응답 시간 단축 완전화 속성 향상
관리자 CSV 내보내기 신설 추가 새 기능

지표로 쓰기

  • 유형별 비율의 추세 를 본다. 교정 비율이 오르면 테스트·리뷰를, 적응 비율이 오르면 의존성 관리와 업그레이드 주기를 의심한다.
  • 예방 작업을 별도 예산 으로 둔다. 실패가 나기 전에 하는 일이라 기능과 경쟁시키면 늘 밀린다.
  • 계약서에 유형 정의를 그대로 인용하면 분쟁이 줄어든다. 특히 “추가” 를 유지보수 범위에 넣을지를 명시한다.

흔한 오해와 함정

  • “유지보수는 버그 수정이다.” 표준의 다섯 유형 중 실패를 고치는 것은 교정 하나다(긴급 포함). 나머지는 환경 대응·속성 향상·기능 추가다.
  • “네 유형이 표준이다.” 교과서는 오래 네 유형을 가르쳤지만 현행 2022년판에는 추가 유형이 정의되어 있다. 인용할 때 판(edition)을 밝힌다.
  • “리팩터링은 완전화다.” 맥락에 따라 다르다. 잠재 결함 제거가 목적이면 예방, 유지보수성 향상이 목적이면 완전화로 볼 수 있다. 목적을 기록하는 것이 라벨보다 중요하다.
  • 접수 시점에 분류를 확정한다. 신고자는 증상을 보고할 뿐이다. 원인 분석 후 재분류를 허용해야 통계가 맞는다.
  • 운영 업무까지 유지보수로 센다. 14764 는 백업·복구·시스템 관리 같은 운영 기능을 범위에서 뺀다. SRE 의 토일(toil)과 유지보수 변경은 구분해서 측정한다.

확인 문제

  1. 14764:2022 에서 “수정(correction)” 과 “개선(enhancement)” 을 가르는 기준은 무엇인가?
  2. 예방 유지보수와 교정 유지보수의 차이를 정의에 근거해 설명하라.
  3. 운영 중인 서비스가 의존하는 외부 결제 API 가 필드명을 바꿨다. 어느 유형인가? 장애 신고로 들어왔다면 분류가 달라지는가?
  4. 2022년판이 추가(additive) 유형을 완전화와 구분한 실무적 이유는?
  5. Lehman 의 관찰 두 가지를 유지보수 유형과 연결하라.

풀이

  1. 수정은 정의된 운영 요구를 다시 만족시키는 변경이고, 개선은 새 요구를 구현하는 변경이다. 기존 요구를 기준으로 “못 지키는 것을 고치는가, 요구 자체가 새로운가” 로 가른다.
  2. 교정은 인도 후 발견된(관측된) 문제를 고치는 것이고, 예방은 잠재 결함을 운영 시스템에서 발현되기 전에 고치는 것이다.
  3. 환경 변화에 맞추는 것이므로 적응이다. 장애 신고(수정 MR)로 들어와도 작업 자체는 적응 유지보수로 볼 수 있다는 것이 표준 주석의 취지다. 다만 장애 중 임시로 해당 결제수단을 막았다면 그 조치는 긴급 유지보수다.
  4. 비교적 큰 기능 추가를 인도 후에 할 때 유지보수 전략·자원·계약·서비스 수준을 따로 협상할 수 있게 하고, 신뢰성 맥락의 “복구” 로서의 유지보수와 경계를 분명히 하기 위해서다.
  5. “계속 변경하지 않으면 덜 유용해진다” 는 적응·완전화·추가 유지보수의 필요를, “복잡도는 줄이려는 노력 없이는 증가한다” 는 예방 유지보수와 리팩터링의 필요를 설명한다.

더 읽을거리 (References)