순환 복잡도 계산기 - McCabe 지표 도구
McCabe의 그래프 공식 M = E − N + 2P 또는 결정 수 간편식 M = D + 1로 순환 복잡도를 계산해 소프트웨어 품질을 평가합니다.
계산 방법을 선택하고 그래프 지표 또는 결정 수를 입력하면 McCabe 복잡도 점수와 위험 분류를 확인할 수 있습니다.
순환 복잡도 계산기 - McCabe 지표 도구
McCabe의 그래프 공식 M = E − N + 2P 또는 결정 수 간편식 M = D + 1로 순환 복잡도를 계산해 소프트웨어 품질을 평가합니다.
제어 흐름 그래프가 있을 때 이 방법을 사용하세요. 방향 간선 수(E), 노드 수(N), 연결 요소 수(P, 단일 함수는 보통 1)를 셉니다.
순환 복잡도 계산기 소개
순환 복잡도는 Thomas J. McCabe가 1976년에 제안한 소프트웨어 품질 지표입니다. 소스 코드의 선형 독립 경로 수를 세어 프로그램의 구조적 복잡성을 정량화합니다. 복잡도가 높을수록 모든 분기를 실행하기 위한 테스트 케이스 수가 늘어나고, 코드를 이해·수정·유지보수하기도 어려워집니다.
이 지표는 그래프 이론에 기반합니다. 프로그램은 제어 흐름 그래프(CFG)로 모델링되며, 각 노드는 단일 진입점과 단일 종료점을 가진 직선형 명령 묶음인 기본 블록을 나타내고, 각 방향 간선은 한 블록에서 다른 블록으로의 제어 전이를 나타냅니다. 조건문, 반복문, 예외 처리기는 분기를 만들며 간선 수와 독립 경로 수를 늘립니다.
McCabe 공식은 M = E − N + 2P이며, 여기서 E는 CFG의 간선 수, N은 노드 수, P는 연결 요소 수(단일 함수나 프로시저는 보통 1)입니다. 분기가 전혀 없는 완전히 선형적인 프로그램에서는 M이 1입니다. 이진 결정 지점이 하나 추가될 때마다 복잡도는 정확히 1씩 증가합니다. case가 k개인 switch 문은 k개의 새로운 경로를 만들기 때문에 복잡도를 k만큼 증가시킵니다.
실무에서는 더 단순한 세기 규칙으로도 구조화된 코드에 대해 같은 결과를 얻을 수 있습니다. M = D + 1에서 D는 전체 결정 지점 수입니다. 결정 지점은 실행이 둘 이상의 경로로 나뉘는 모든 구조를 뜻합니다. if 또는 else-if 절, switch의 case, for·while·do-while 루프 헤더, 삼항 연산자, 단락 평가로 분기를 만드는 논리 AND/OR, catch 블록이 여기에 포함됩니다.
업계 가이드라인은 일반적으로 1–4를 낮은 위험, 5–7을 보통, 8–10을 높은 위험(리팩터링 고려), 10 초과를 매우 높은 위험(함수 분리를 강력 권장)으로 봅니다. 복잡도 값은 전체 분기 커버리지를 달성하는 데 필요한 최소 테스트 케이스 수도 알려줍니다. 예를 들어 순환 복잡도 8인 함수는 모든 독립 경로를 실행하려면 최소 8개의 테스트 케이스가 필요합니다.
순환 복잡도가 무엇을 측정하고 무엇을 측정하지 않는지 이해하는 것이 중요합니다. 코드 줄 수, 성능, 알고리즘의 정당성을 직접 측정하지는 않습니다. 매우 길지만 완전히 순차적인 함수의 복잡도는 1일 수 있고, 조건이 깊게 중첩된 짧은 함수는 20이 될 수도 있습니다. 이 지표는 테스트 비용의 핵심 원인이고 잠재 결함의 가장 흔한 원인인 결정 경로 구조를 포착합니다. 코드 리뷰와 다른 품질 지표와 함께 사용하면, 순환 복잡도는 리팩터링과 테스트에서 우선순위를 둘 함수를 식별하는 데 유용한 기준이 됩니다.
순환 복잡도 예시
현실적인 코드 구조에서 두 계산 방법을 모두 보여 주는 세 가지 예시입니다.
| 입력 | M | 설명 |
|---|---|---|
| E = 9, N = 8, P = 1 | M = 3 | 그래프 방식: 9 − 8 + 2×1 = 3. if 문 2개와 반복문 1개가 있는 단순한 함수입니다. |
| D = 4 decisions | M = 5 | 결정 방식: 4 + 1 = 5. if-else 체인 2개가 있는 함수입니다. 중간 위험이며 5개의 테스트 케이스로 관리할 수 있습니다. |
| E = 14, N = 10, P = 1 | M = 6 | 그래프 방식: 14 − 10 + 2 = 6. case 5개가 있는 switch입니다. 중간 수준의 복잡도로, 각 분기를 문서화할 가치가 있습니다. |
순환 복잡도 계산기 사용 방법
- 계산 방법을 선택하세요. 코드의 제어 흐름 그래프를 그려 두었거나 확인할 수 있다면 그래프 기반을 사용합니다. 결정 키워드를 세어 빠르게 추정하려면 결정 기반을 사용합니다.
- 그래프 기반: 간선 수(E), 노드 수(N), 연결 요소 수(P)를 입력합니다. 단일 함수라면 P는 1입니다. 여러 개의 연결되지 않은 부분을 함께 분석할 때만 실제 개수를 입력하세요.
- 결정 기반: if, else-if, case, for, while, do-while, 삼항 연산자(?:), catch, 그리고 새 분기를 만드는 단락 논리 연산자(&&, ||)를 모두 세어 합계를 D로 입력합니다.
- 계산을 클릭하세요. 결과에는 McCabe 복잡도 M과 낮음(1–4), 보통(5–7), 높음(8–10), 매우 높음(>10) 위험 분류가 표시됩니다.
- 복잡도 값을 전체 분기 커버리지를 위해 필요한 최소 테스트 케이스 수로 보고, M > 10인 함수는 리팩터링을 고려하세요.
순환 복잡도 FAQ
순환 복잡도는 무엇을 측정하나요?
함수의 제어 흐름 그래프에서 선형 독립 경로의 수, 즉 서로 다른 실행 경로가 몇 개인지를 측정합니다. 결정 지점(if, 반복문, case)이 하나 늘어날 때마다 경로도 하나씩 늘어납니다. 이 값은 전체 분기 커버리지를 달성하는 데 필요한 최소 테스트 케이스 수와 같습니다.
좋은 순환 복잡도 값은 얼마인가요?
McCabe의 원래 권장 사항은 함수의 M이 10 이하이어야 한다는 것입니다. 1–4는 낮은 위험으로 테스트가 쉽고, 5–7은 보통, 8–10은 높은 위험, 10 초과는 매우 높은 위험으로 더 작고 집중된 함수로의 리팩터링이 강하게 권장됩니다.
그래프 방식과 결정 수 방식은 같은가요?
GOTO 문이 없는 구조화 프로그램에서는 같은 결과를 줍니다. 결정 수 간편식 M = D + 1은 분기 키워드를 모두 세고 1을 더합니다. 그래프 방식 M = E − N + 2P는 그래프의 간선과 노드를 셉니다. 두 방식 모두 같은 구조 정보를 포착합니다.
switch 문의 각 case를 따로 세어야 하나요?
예. 각 case 레이블은 독립적인 분기이므로 case가 5개인 switch는 결정 수에 5를 더합니다(CFG 간선도 5개 늘어납니다). 일부 정적 분석 도구는 개별 case가 아니라 case 그룹 수만 세기도 합니다. 일관된 측정을 위해 항상 도구 문서를 확인하세요.
순환 복잡도는 테스트와 어떤 관련이 있나요?
복잡도 M은 모든 분기를 최소 한 번씩 통과하기 위해 필요한 독립 테스트 케이스의 최소 수와 같습니다. M = 8인 함수는 완전한 분기 커버리지를 위해 최소 8개의 신중하게 설계된 테스트 케이스가 필요합니다. 복잡도가 높을수록 테스트 공수가 늘고 결함 가능성과 유지보수 부담도 커집니다. 개별 함수를 M = 10 미만으로 유지해야 하는 강한 이유입니다.
순환 복잡도는 모든 프로그래밍 언어에 적용되나요?
예. 조건 및 반복 제어 구조가 있는 모든 언어에 적용됩니다. 언어별 결정 지점 표기는 조금씩 다릅니다. Python은 elif, Ruby는 case/when, SQL은 CASE/WHEN을 사용하지만 세는 원리는 같습니다. Java, Python, JavaScript, C# 및 대부분의 주류 언어용 자동화 도구는 McCabe 복잡도를 표준 품질 지표로 구현합니다.