Coding Conventions are a set of guidelines for a specific programming language that recommend programming style and practices for each aspect of a program written in that language.
소스 코드의 가독성·유지보수성·안전성·보안성을 확보하기 위한 프로그래밍 언어별 가이드라인.
등장 배경 — Code Smells
가독성/유지보수가 어려운 코드:
- 라인이 너무 김 (e.g., 130 > 79 chars)
- 클래스/메서드 크기 과다
- 미사용 변수
잠재적 리스크가 있는 코드:
- 순환 복잡도 과다
- 변수 미초기화
- 불필요한 전역 변수
→ 일관된 코딩 표준 적용으로 예방.
언어별 대표 표준
| 언어 | 표준 |
|---|---|
| C | MISRA-C 2012, CERT C Coding Standard, HIS Source Code Metrics |
| C++ | JSF AV C++ Coding Standard, MISRA C++ |
| Java | CERT Oracle Coding Standard for Java, PMD Rule Set, Java 시큐어 코딩 가이드 |
| Python | Style Guide for Python Code (PEP 8) |
MISRA-C 2012
C 언어 기반 프로그램의 신뢰성, 안전성, 호환성을 확보하기 위해 MISRA에서 개발한 156개 Rule Set(22개 카테고리). 정적 분석 도구로 자동 검증.
주요 Rule 예시
| Rule No. | 분류 | Description |
|---|---|---|
| 1.1 | 표준 C 환경 | C 표준과 사용하는 컴파일러의 번역 제한을 준수해야 한다 |
| 2.1 | 사용하지 않는 코드 | 도달할 수 없는 코드(unreachable code)가 있으면 안된다 |
| 5.4 | 식별자 | 매크로의 식별자는 구별해야 한다 |
| 9.1 | 초기화 | 모든 변수는 읽기 전에 할당해야 한다 |
| 11.1 | 포인터 타입 변환 | 함수 포인터와 다른 타입 간의 형 변환을 하면 안된다 |
| 15.1 | 제어 흐름 | goto 문은 사용하면 안된다 |
| 17.2 | 함수 | 함수는 묵시적으로 선언하면 안된다 |
MISRA-C 2012 룰셋 22카테고리 요약
| # | 룰 명 | 가이드 수 |
|---|---|---|
| 1 | C 표준 (A standard C environment) | 3 |
| 2 | 사용하지 않는 코드 (Unused code) | 7 |
| 3 | 주석 (Comments) | 2 |
| 4 | 문자셋과 어휘 요소 (Character sets and lexical conventions) | 2 |
| 5 | 식별자 (Identifiers) | 9 |
| 6 | 타입 (Types) | 2 |
| 7 | 리터럴과 상수 (Literals and constants) | 4 |
| 8 | 선언과 정의 (Declarations and definitions) | 14 |
| 9 | 초기화 (Initialization) | 5 |
| 10 | 에센셜 타입 모델 (The essential type model) | 8 |
| 11 | 포인터 타입 변환 (Pointer type conversions) | 9 |
| 12 | 표현식 (Expressions) | 6 |
| 13 | 부작용 (Side effects) | 6 |
| 14 | 제어문 표현식 (Control statements expressions) | 4 |
| 15 | 제어흐름 (Control flow) | 7 |
| 16 | Switch문 (Switch statements) | 7 |
| 17 | 함수 (Functions) | 8 |
| 18 | 포인터와 배열 (Pointers and arrays) | 8 |
| 19 | 저장 영역 덮어쓰기 (Overlapping storage) | 2 |
| 20 | 전처리 지시자 (Preprocessing directives) | 14 |
| 21 | 표준 라이브러리 (Standard libraries) | 21 |
| 22 | 자원 (Resources) | 10 |
| 합계 | 156 |
MISRA-C 2012 세분화 레벨
2012판부터 규칙 수준을 3레벨로 세분화하여 적용 유연성 제공.
| 레벨 | 의미 |
|---|---|
| Mandatory | 반드시 준수 — 위반 시 안전성/신뢰성에 심각한 영향. 예외 불허 |
| Required | 반드시 준수하되, 정당한 사유가 있으면 예외 허용 |
| Advisory | 가능하면 준수. 필수 사항은 아님 |
MISRA-C 변천사
| 구분 | Published | Guidelines | Languages | 특징 |
|---|---|---|---|---|
| MISRA-C: 1998 | 1998.04 | 127 | C90 | 초판 |
| MISRA-C: 2004 | 2004.10 | 142 | C90 | |
| MISRA-C: 2012 | 2013.03 | 169 | C90, C99 | 규칙 수준 세분화 (Mandatory/Required/Advisory) |
| MISRA-C: 2012 Amendment 1 | 2016.04 | 173 | C90, C99 | |
| MISRA-C: 2012 Amendment 2 | 2020.02 | 175 | C90, C99, C11, C18 | |
| MISRA-C: 2023 | 2023.10 | 179 | C90, C99, C11, C18 | C11/C18 공식 지원, 멀티스레딩·메모리 안전성 강화, 오탐(False-Positive) 감소 |
| MISRA-C: 2025 | 출시 예정 | — | — | Perforce 보고서에 따르면 자동차 개발자의 **53%**가 자신의 개발에 영향을 줄 것으로 예상 |
2023판 주요 변화
- C11 (2011) — 멀티스레딩 지원, 정적 어설션 등 현대 기능 반영
- C18 (2018) — C11 버그 수정·개선 반영
- 멀티스레딩 환경 안전 프로그래밍 규칙 추가
- 메모리 안전성 강화를 위한 규칙 개선
- 최신 정적 분석 도구 및 코드 품질 평가 방법 반영 (가이드 제공·오탐 감소)
MISRA 발생 가능한 오류 4유형
MISRA가 탐지하려는 오류의 원인별 분류.
| 유형 | 설명 | 예시 (MISRA-C 2012 Rule) |
|---|---|---|
| 개발자의 C언어 이해 부족 | C 언어의 동작 방식을 잘못 이해하여 발생 | 산술 변환 관련 오류 (Rule 10.1) |
| 개발자의 단순 실수 | 타이핑 오류, 변수 사용 실수 등 | 대입 =과 비교 == 혼동 (Rule 13.5) |
| 컴파일러와 개발자 기대 불일치 | 개발자 예상 동작과 실제 컴파일된 코드 동작 차이 | sizeof(char) 기대 불일치 등 Undefined Behavior (Rule 1.3) |
| 컴파일러 자체 오류 | 특정 컴파일러의 버그 또는 잘못된 최적화 | volatile 변수를 컴파일러가 최적화 제거 (Rule 8.9) |
코딩 표준의 적용 효과
- 의미 있는 파일명/메서드/변수명 사용
- 클래스와 메서드는 간결하게 작성
- 사용되지 않는 코드 제거
- 필요한 코드에 주석 작성
- 변수는 항상 초기화
- 전역 변수를 사용하지 않음
→ 가독성/유지보수 향상 + 소프트웨어 품질 향상 (Safety, Security 개선).
도요타 급발진 사례
“Toyota Did Not Follow Own Coding Standard — 80,000 Violations of MISRA-C Rule”
자체 코딩 표준조차 준수하지 않은 도요타 ECU 펌웨어. 급발진 사고의 원인 중 하나로 지목됨.
예제
Rule #1 — 지역 변수 초기화
// AS-IS (X)
int a, b;
while (b++ < 100000) { a++; }
// TO-BE (O)
int a=0, b=0;
while (b++ < 100000) { a++; }Rule #2 — 버퍼 오버플로우 방지
// AS-IS (X) — idx == 10일 때 buf[10] 접근 (배열 범위 초과)
int idx; int buf[10];
scanf("%d", &idx);
if (idx >= 0 && idx <= 10) // 잘못된 경계
buf[idx] = 10;
// TO-BE (O)
if (idx >= 0 && idx < 10)
buf[idx] = 10;Rule #3 — 0으로 나누기 방지
// AS-IS (X) — i<=10이면 a==0인 채로 cnt/a 수행 → Divide by Zero
int func(int i) {
int a=0; int cnt=100;
if (i>10) { a=random(); }
int b = cnt / a; // 사고 발생 가능
}
// TO-BE (O)
if (a > 0) {
int b = cnt / a;
}HIS Source Code Metrics
HIS(Hersteller Initiative Software)가 제시한 자동차 C 코드 메트릭 기준. 함수 단위로 9개 지표를 측정한다. 정량 메트릭 전반은 소스코드 메트릭 참조.
| Metric | 설명 | HIS 기준 범위 | 방위사업청 기준 |
|---|---|---|---|
| COMF (Comment Density) | 코드 라인 당 주석 라인 수 | > 0.2 | — |
| PATH | 함수 내 실행 가능한 경로 수 | 1~80 | — |
| GOTO | goto 문의 개수 | 0 | — |
| v(G) (순환 복잡도) | 코드 내 조건문 수 + 1 | 1~10 | 20 이하 |
| CALLING | 다른 함수를 호출하는 건수 | 0~5 | 8 이하 |
| CALLS | 다른 함수로부터의 피호출 건수 | 0~7 | 10 이하 |
| PARAM | 함수 인터페이스의 파라미터 수 | 0~5 | 8 이하 |
| STMT | 함수 당 명령어(구문) 수 | 1~50 | 200 이하 |
| LEVEL | 한 함수의 중첩 호출(Call Level) 수 | 0~4 | 6 이하 |
| RETURN | 한 함수 내 반환점(Return) 수 | 0~1 | — |
RETURN 기준
단일 진출점 원칙에 따라
0~1을 채택. 일부는0~4까지 허용 범위로 제시하므로, 적용 프로젝트의 기준 문서를 우선한다.0~1해석은 ISO 26262 Table 6 1a “One entry and one exit point” 권장과 정합한다.