본문으로 건너뛰기
고급약 30분

정적 분석 결과를 준수 증거로 — GEP·재분류 계획·편차 기록·준수 요약서 만들기

정적 분석 도구가 뱉은 수천 건의 경고는 그 자체로 증거가 아니다. MISRA Compliance 체계의 네 문서 — 지침별 확인 수단을 정한 GEP, 범주 조정을 기록한 재분류 계획, 편차 허가와 편차 기록, 지침별 준수 요약서 — 로 결과를 구조화하고, 위반 트리아지·채택 코드 분리·시험소 독립 재수행 대조표·CI 게이트까지 설계한다.

  • #MISRA-Compliance
  • #정적분석
  • #편차관리
  • #준수매트릭스
  • #기능안전
  • #CI

개념

도구 리포트는 증거가 아니다

레슨 4의 첫 분석 장면으로 돌아가자. 기존 코드에 MISRA 검사를 돌렸더니 경고가 3,812건 나왔다. 이 리포트를 심사에 그대로 내면 어떤 질문이 돌아올까.

  • 이 도구는 모든 지침을 검사하는가? 검사하지 않는 지침은 어떻게 확인했는가?
  • 3,812건 중 실제 위반은 몇 건이고 오탐은 몇 건인가?
  • 남아 있는 위반은 왜 남아 있는가? 누가 승인했는가?
  • 결국 이 프로젝트는 어느 지침을 준수하고 어느 지침을 준수하지 않는가?

리포트는 이 질문에 답하지 못한다. 답하려면 리포트를 구조화된 문서 세트 로 바꿔야 한다. MISRA는 이 구조를 MISRA Compliance 라는 별도 문서로 정해 두었다(현행 판은 2020판). 이 레슨은 그 문서 세트를 만드는 법이다.

네 가지 산출물

MISRA Compliance 체계의 산출물은 넷이다.

① GEP  지침 적용 계획(Guideline Enforcement Plan)
        지침마다 무엇으로 확인하는가 — 도구 규칙 / 컴파일러 / 수동 리뷰
 
② GRP  지침 재분류 계획(Guideline Re-categorization Plan)
        프로젝트가 범주를 어떻게 조정했는가
 
③ 편차  편차 허가(Deviation Permit) — 재사용 가능한 승인된 편차 사유
        편차 기록(Deviation Record) — 특정 위반 한 건을 허가에 연결한 기록
 
④ GCS  지침 준수 요약서(Guideline Compliance Summary)
        지침마다 최종 준수 상태

네 문서의 순서가 곧 작업 순서다. 무엇으로 확인할지 정하고(①), 기준을 조정하고(②), 남는 위반을 처리하고(③), 결과를 선언한다(④). 도구 리포트는 ①과 ③ 사이의 원자료다.

① GEP — 지침마다 "무엇으로 확인하는가"

GEP는 모든 지침에 대해 확인 수단을 한 줄씩 적는 표다.

| 지침 | 종류 | 범주 | 결정 가능성 | 분석 범위 | 도구 규칙 ID | 컴파일러 | 수동 리뷰 | 비고 |
|---|---|---|---|---|---|---|---|---|
| Rule A | 규칙 | 요구 | 결정 가능 | 단일 TU | TOOL-1042 | — | — | |
| Rule B | 규칙 | 필수 | 결정 불가능 | 시스템 | TOOL-0911 | -Wuninitialized | 초기화 리뷰 체크리스트 CL-07 | 도구 미탐 가능 |
| Dir C | 지시 | 요구 | — | — | — | — | 설계 리뷰 DR-3 | 구현 정의 동작 의존 목록 문서 |
| Rule D | 규칙 | 권고 | 결정 가능 | 단일 TU | (미지원) | — | 코드 리뷰 | 도구 미지원 |

GEP를 쓰는 과정에서 도구가 검사하지 않는 지침 이 드러난다. 도구 벤더가 "MISRA C 지원"이라고 광고해도 모든 지침을 검사하는 것은 아니다. 미지원 지침에 수동 리뷰를 배정하지 않으면 그 지침은 확인되지 않은 채 준수로 선언 된다. 레슨 4에서 본 대로 지시와 결정 불가능 규칙은 수동 확인 열이 사실상 필수다.

GEP는 레슨 3의 도구 등록부 와 짝이다. GEP의 "도구 규칙 ID"는 특정 도구 버전에 묶여 있으므로, 도구 버전이 바뀌면 GEP도 다시 확인한다.

② GRP — 범주를 조정하는 규칙

프로젝트는 지침의 범주를 조정할 수 있다. 규칙은 비대칭이다.

원래 범주올릴 수 있는 곳내릴 수 있는 곳
필수—없음
요구필수없음
권고요구·필수적용 제외(Disapplied)

즉 느슨하게 만드는 것은 권고 → 적용 제외 하나뿐 이다. 요구 지침을 권고로 내리는 것은 허용되지 않는다. 반대로 발주처나 사내 안전 정책이 권고 지침을 요구로 올리는 것은 흔하다.

GRP의 각 줄에는 누가, 왜 조정했는지가 남아야 한다. 권고 지침을 적용 제외로 내렸다면, 그 지침이 이 프로젝트에서 왜 의미가 없는지(예: 해당 언어 기능을 쓰지 않음, 다른 안전 대책이 같은 위험을 다룸)가 근거다. 모듈 34 레슨 2의 권고 조항 미충족 사유와 같은 형식이다.

위반 트리아지 — 경고 한 건이 가는 네 갈래

도구 경고는 곧바로 위반이 아니다. 한 건씩 네 갈래로 보낸다.

도구 경고
  │
  ├─ 오탐(false positive)       도구가 틀렸다
  │     → 억제(suppression) + 오탐 근거 기록. 편차가 아니다
  │
  ├─ 설정 문제                  빌드 정의·포함 경로·매크로 설정이 틀려 생긴 경고
  │     → 분석 설정 수정 후 재분석. 이 갈래가 많으면 GEP 재검토
  │
  ├─ 진양성 — 고친다             실제 위반. 수정 가능
  │     → 코드 수정 + 재분석으로 소멸 확인
  │
  └─ 진양성 — 남긴다             실제 위반. 수정이 더 위험하거나 불가능
        → 필수 지침이면 불가 (고쳐야 함)
        → 요구 지침이면 편차 절차 (③)
        → 권고 지침이면 준수 요약서에 위반으로 기록 또는 GRP 로 적용 제외 검토

첫 갈래와 마지막 갈래를 섞는 것이 가장 흔한 실수다. 오탐 억제는 "위반이 없다"는 주장 이고, 편차는 "위반이 있지만 허용한다"는 주장 이다. 오탐을 편차로 처리하면 편차 수가 부풀어 심사에서 관리 수준이 낮아 보이고, 편차를 오탐으로 처리하면 실제 위반을 숨긴 것 이 된다.

설정 문제 갈래도 과소평가하면 안 된다. 첫 분석의 수천 건 중 상당수가 포함 경로 누락이나 컴파일러 확장 매크로를 도구가 모르는 데서 나온다. 레슨 4에서 시스템 범위 규칙은 전체 프로젝트를 한 번에 분석해야 한다고 했는데, 그 분석이 실제 빌드와 같은 설정 으로 돌지 않으면 결과 전체를 믿을 수 없다.

③ 편차 — 허가와 기록을 나누는 이유

편차는 두 층으로 관리한다.

편차 허가(permit) 는 재사용 가능한 승인 사유 다. "메모리 맵 레지스터 접근을 위한 정수 → 포인터 변환"처럼, 같은 이유로 여러 곳에서 반복될 위반을 한 번 심사해 승인해 둔다.

편차 기록(record) 은 위반 한 건 을 허가에 연결한다.

[편차 허가 DP-004]
지침          포인터·정수 변환 관련 요구 규칙
허용 상황      MCU 주변장치 레지스터 주소 접근. HAL 계층 파일에 한정
사유          하드웨어 접근에 다른 표현 방법이 없음
안전 영향 분석  주소 상수는 벤더 헤더와 대조 검증. 접근 함수는 단위 시험 대상
대체 조치      HAL 외부에서 사용 시 정적 분석 게이트로 차단
승인          안전 관리자 / 2026-06-12
 
[편차 기록 DR-0187]
허가          DP-004
위치          hal/adc.c:88
위반 경고 ID   TOOL-0503 #a91f
코드 버전      commit 3f2c9e1
확인자         (검증자 역할 — 레슨 3 독립성)

두 층으로 나누면 좋은 점이 셋이다. 첫째, 같은 사유를 수십 번 새로 심사하지 않는다. 둘째, 허가의 "허용 상황"을 벗어난 위반 이 기록으로 연결될 수 없어 자동으로 드러난다(HAL 밖에서 같은 변환이 나오면 연결할 허가가 없다). 셋째, 허가가 철회되면 연결된 기록 전체를 한 번에 찾을 수 있다.

편차 기록의 "코드 버전" 칸이 중요하다. 코드가 바뀌면 줄 번호가 움직이고, 도구 경고 ID도 바뀔 수 있다. 어느 버전의 어느 위반에 대한 편차인지 가 고정되어야 모듈 32 레슨 4의 원자료 추적성이 성립한다.

④ GCS — 지침별 최종 상태

준수 요약서는 모든 지침에 대해 하나의 상태를 선언한다.

상태뜻
준수위반 없음
편차 포함 준수남은 위반이 모두 승인된 편차로 처리됨
위반편차 없이 남은 위반이 있음 (권고 지침에서만 가능해야 한다)
적용 제외GRP로 적용 제외됨

프로젝트가 "MISRA 준수"를 주장 하려면, 필수 지침은 전부 "준수", 요구 지침은 "준수" 또는 "편차 포함 준수"여야 한다. 요구 지침에 "위반"이 하나라도 있으면 그 주장은 성립하지 않는다.

GCS는 GEP·GRP·편차 기록의 합성 결과 여야 한다. 사람이 손으로 상태를 채우면 편차 기록 수와 요약서가 어긋나는 일이 생긴다. 스크립트로 네 문서를 대조해 GCS를 생성하고, 불일치를 검증 실패로 처리하는 것이 실무 정석이다.

채택 코드 — 우리가 쓰지 않은 코드

프로젝트에는 직접 작성하지 않은 코드가 섞인다. 벤더 HAL, RTOS, 통신 스택, 코드 생성기가 만든 코드, 과거 프로젝트에서 가져온 레거시 모듈. MISRA Compliance는 이런 코드를 채택 코드(adopted code) 로 따로 다루도록 한다.

채택 코드를 자체 코드와 섞어 분석하면 두 문제가 생긴다. 고칠 수 없는 위반이 수백 건 섞여 트리아지를 마비시키고, 준수 주장의 범위가 모호해진다. 그래서 준수 주장의 범위를 명시 하고, 채택 코드는 공급자의 준수 증거(공급자 GCS)를 받거나 별도 범주로 분리해 관리한다.

준수 주장 범위
  자체 작성 코드       src/app/**, src/safety/**          → 전체 체계 적용
  생성 코드           gen/**                              → 생성기 설정 + 샘플 분석 + 공급자 증거
  벤더 HAL           vendor/hal/**                        → 공급자 준수 증거 + 경계 인터페이스만 분석
  레거시 모듈         legacy/can_stack/**                   → 별도 편차 허가 묶음, 변경 시 전체 체계로 편입

마지막 줄의 "변경 시 편입"이 실무 규칙으로 중요하다. 레거시를 한 줄이라도 고치면, 그 파일은 채택 코드가 아니라 우리가 책임지는 코드 가 된다.

시험소의 독립 재수행 — 두 결과를 대조하는 표

시험소가 코딩 규칙 시험을 할 때 흔한 방식은 제조사와 같은 코드를 시험소 환경에서 다시 분석 하는 것이다. 그러면 두 결과가 생기고, 그 차이를 설명하는 것이 성적서의 핵심이 된다.

| 지침 | 제조사 GCS 상태 | 제조사 위반·편차 수 | 시험소 검출 수 | 차이 | 차이 원인 분류 | 판정 |
|---|---|---|---|---|---|---|
| Rule A | 준수 | 0 / 0 | 0 | 0 | — | 일치 |
| Rule B | 편차 포함 준수 | 3 / 3 | 5 | +2 | 분석 범위 차이(제조사: 파일 단위) | 불일치 — 추가 2건 제조사 확인 요청 |
| Rule C | 준수 | 0 / 0 | 12 | +12 | 도구 차이 — 시험소 도구 오탐 확인 11, 진양성 1 | 진양성 1건 보고 |

"차이 원인 분류"는 대체로 네 가지다 — 도구 차이, 도구 버전 차이, 분석 설정(빌드·포함 경로·매크로) 차이, 분석 범위(파일 단위/시스템) 차이. 그래서 시험소는 착수 전에 제조사로부터 분석 대상 파일 목록, 빌드 설정, 도구와 버전, GEP·GRP·편차 기록 을 원자료로 받는다. 이것이 없으면 차이를 설명할 수 없고, 설명되지 않은 차이는 판정을 막는다.

성적서의 판정 문장도 여기서 정해진다. 코딩 규칙 시험 성적서가 말할 수 있는 것은 "지정한 도구·버전· 설정으로 지정한 코드를 분석한 결과, 지침별 검출 수와 제조사 준수 요약서와의 대조 결과는 이러하다" 까지다. "MISRA C 준수 제품"이라는 문장은 모듈 32 레슨 6에서 본 대로 의견의 영역이고, 준수 체계(GEP·GRP·편차) 검토를 포함했을 때만 근거를 갖는다.

CI에 넣는 법 — 새 위반 0 게이트

마지막으로 이 체계를 일상 개발에 넣는다. 모듈 14에서 품질 게이트를 CI에 넣는 법을 배웠다. MISRA에서는 기준선 방식 이 현실적이다.

기준선    현재 main 의 위반 목록(편차·오탐 포함)을 고정 스냅숏으로 저장
게이트    PR 에서 새로 생긴 위반이
            필수 지침          → 무조건 실패
            요구 지침          → 편차 기록(허가 연결) 없으면 실패
            권고 지침          → 경고 + 리뷰어 확인
          오탐 억제 추가       → 억제 근거 필수, 리뷰어 승인
정기     기준선 위반 수 감소 추세를 대시보드에 표시 (모듈 22 레슨 8)

"오탐 억제 추가"를 게이트에 넣는 것이 핵심이다. 억제를 자유롭게 추가할 수 있으면 게이트는 억제 주석으로 우회된다. 억제도 코드 변경과 같은 리뷰 대상 이다.

실무에서 왜 필요한가

MISRA 도입 프로젝트의 성패는 도구가 아니라 이 네 문서가 언제 생기는가 로 갈린다. 개발 막바지에 도구를 처음 돌리고 네 문서를 급히 만들면, 편차가 수백 건 쌓이고 그 대부분이 "일정상 수정 불가"라는 한 줄 사유를 갖는다. 이런 편차는 심사에서 받아들여지지 않는다. 반대로 개발 초기에 GEP·GRP를 합의하고 CI 게이트를 켜면, 편차는 하드웨어 접근 같은 진짜 불가피한 사유 로만 생긴다.

오탐과 편차를 구분하는 습관은 조직의 신뢰를 지킨다. 오탐을 편차로 뭉뚱그리면 편차 수가 부풀고, 편차를 오탐으로 숨기면 실제 위반이 사라진다. 두 경우 모두 심사자는 나머지 기록 전체 를 의심하게 된다.

시험소 입장에서는 대조표가 시험 기간을 정한다. 원자료(파일 목록·빌드 설정·도구 버전)를 착수 전에 받으면 차이 분석이 기계적으로 끝나고, 받지 못하면 차이 원인을 찾느라 왕복이 반복된다. 모듈 33 레슨 5에서 결함 라운드 수가 준비 수준의 함수라고 했던 것이 여기서도 똑같다.

실습 과제

과제 1 — GEP 열 줄 만들기 (20분)

레슨 4에서 다룬 유형(반환값 무시, 본질적 자료형 혼합, 단일 출구, 동적 할당, 초기화 전 사용)과 지시 두 개를 포함해 열 줄짜리 GEP를 만든다. 사용하는 정적 분석 도구 하나를 정하고(무료 도구도 좋다), 그 도구가 검사하지 않는 지침을 실제 문서에서 찾아 수동 리뷰를 배정한다.

과제 2 — 트리아지 연습 (20분)

아래 경고 여섯 건을 본문의 네 갈래로 보내고, 각 건에 필요한 기록을 적는다.

W1  필수 규칙 — 초기화 전 사용 의심. 실제로는 앞선 함수 호출이 out 파라미터로 설정
W2  요구 규칙 — 정수→포인터 변환. hal/gpio.c, 레지스터 주소
W3  요구 규칙 — 정수→포인터 변환. app/logger.c, 디버그 편의
W4  권고 규칙 — 중간 return. MISRA C:2012 적용 프로젝트
W5  요구 규칙 — 알 수 없는 매크로 __irq 때문에 선언 해석 실패
W6  요구 규칙 — 반환값 무시. memcpy 반환값

W2와 W3는 같은 규칙이지만 처리가 달라야 한다. 본문의 편차 허가 DP-004를 기준으로 이유를 설명한다.

과제 3 — 독립 재수행 대조표 (15분)

제조사와 시험소의 결과가 다음과 같다. 본문 형식의 대조표를 만들고 차이 원인 분류와 다음 조치를 적는다.

제조사: 도구 X 7.2, 파일 단위 분석, GCS 전 지침 준수 또는 편차 포함 준수, 편차 42건
시험소: 도구 X 7.4, 시스템 분석, 동일 코드 커밋
결과 차이: 시스템 범위 규칙 두 개에서 시험소 +9건, 결정 가능 규칙 하나에서 시험소 -3건

과제 4 (선택) — CI 게이트 규칙 작성 (15분)

본문의 기준선 방식을 사용하는 CI 파이프라인 단계(도구 실행 → 기준선 비교 → 범주별 판정 → 억제 추가 검사)를 의사 코드나 YAML 개요로 작성한다. 억제 주석 추가를 감지하는 방법을 반드시 포함한다.

자가 체크리스트

  • 도구 리포트가 그 자체로 증거가 되지 못하는 이유를 네 가지 질문으로 설명할 수 있다
  • GEP·GRP·편차(허가·기록)·GCS의 역할과 작업 순서를 안다
  • GEP 작성으로 도구가 검사하지 않는 지침이 드러나는 이유를 안다
  • 재분류가 허용되는 방향과, 요구 지침을 권고로 내릴 수 없다는 것을 안다
  • 경고 트리아지의 네 갈래와 오탐 억제·편차의 차이를 설명할 수 있다
  • 편차 허가와 편차 기록을 나누는 세 가지 이점을 안다
  • 편차 기록에 코드 버전을 고정해야 하는 이유를 안다
  • "MISRA 준수" 주장이 성립하려면 필수·요구 지침이 어떤 상태여야 하는지 말할 수 있다
  • 채택 코드를 분리하는 이유와 준수 주장 범위를 적는 방법을 안다
  • 독립 재수행 결과 차이의 네 가지 원인과, 착수 전에 받아야 할 원자료를 안다
  • 코딩 규칙 시험 성적서가 판정할 수 있는 범위를 설명할 수 있다
  • 기준선 방식 CI 게이트와 억제 추가 검사의 필요성을 설명할 수 있다

흔한 실수

도구 리포트를 그대로 제출한다. GEP·GRP·편차·GCS로 구조화되지 않은 리포트는 질문에 답하지 못한다.

GEP 없이 "도구가 MISRA를 지원한다"로 끝낸다. 도구가 검사하지 않는 지침이 확인되지 않은 채 준수로 선언된다.

오탐을 편차로, 편차를 오탐으로 처리한다. 전자는 관리 수준을 낮아 보이게 하고, 후자는 위반을 숨긴다.

편차 사유를 "일정상 수정 불가"로 쓴다. 안전 영향 분석과 대체 조치가 없는 편차는 받아들여지지 않는다.

GCS를 손으로 채운다. 편차 기록 수와 요약서가 어긋난다. 네 문서를 대조해 생성한다.

채택 코드를 자체 코드와 섞어 분석한다. 고칠 수 없는 위반이 트리아지를 마비시키고 주장 범위가 흐려진다.

독립 재수행에서 원자료를 받지 않고 시작한다. 결과 차이를 설명할 수 없어 판정이 막힌다.

CI에서 억제 주석 추가를 검사하지 않는다. 게이트가 억제 주석으로 우회된다.

참고 자료

낯선 말 풀이

이 레슨에 나온 약어입니다. 본문에서도 처음 나올 때 점선으로 표시해 두었습니다 (제목과 링크 글자는 그대로 둡니다).

MISRA — 미스라
안전이 중요한 분야에서 "이런 식으로는 코드를 쓰지 말라"를 모아 둔 규칙집.
ID — 식별자
무엇 하나를 다른 것과 구별하기 위해 붙인 이름이나 번호.
RTOS — 실시간 운영체제
"정해진 시간 안에 반드시 처리"를 보장하도록 만든 바탕 프로그램.
CI — 지속적 통합
코드를 올릴 때마다 자동으로 합쳐서 빌드하고 시험까지 돌리는 방식.
YAML — 야믈
들여쓰기로 구조를 나타내는 설정 파일 형식. 사람이 읽기 쉬운 쪽으로 만든 것이다.
PDF — 피디에프
어디서 열어도 모양이 같게 나오도록 만든 문서 형식.
KOLAS — 한국인정기구
시험·검사를 하는 기관이 믿을 만한지 국가가 인정해 주는 제도. 인정받은 기관의 성적서는 공식 문서로 통한다.

용어집 전체 보기