https://wiki.daumkakao.com/pages/viewpage.action?pageId=1622101247
인지 복잡도
(Cognitive Complexity)
코드의 가독성과 이해의 난이도를 측정.
코드 흐름을 이해하는 데 필요한 정신적 부담을 계산.
목적:
코드 이해 및 가독성 향상
주요요인:
분기, 중첩, 흐름 단절
측정 방식:
코드 읽기 및 흐름 이해 난이도
관점:
인간 중심
🤔 why 인지 복잡도?
코드 품질과 제일 관련있는 복잡도
순환 복잡도는 테스트 설계와 논리적 복잡성 평가에 유용하지만, 코드 품질과 직접적인 연관성은 적음.
단순히 분기 수를 세므로, 코드 가독성이나 유지보수성을 직접적으로 반영하지 못함.
동일한 순환 복잡도를 가진 코드라도, 가독성과 이해 난이도는 크게 다를 수 있음.
인지 복잡도는 사람이 코드를 읽고 이해하는 데 초점을 맞춰 유지보수성, 협업, 가독성과 더 밀접한 관련이 있음.
따라서, 코드 품질 평가에는 인지 복잡도가 더 적합한 지표로 간주
인지 복잡도 확인 도구
비교 항목 | cognitive-complexity-show | SonarQube for IDE (SonarLint) | SCAN (10.3.1버전 기준) |
---|---|---|---|
점수 확인 가능 범위 | 15점 이하도 확인 가능 | 15점 이하 점수 확인 불가 | 15점 이하 점수 확인 불가 |
반응 속도 | 비교적 빠르고 가벼움 | 상대적으로 무거울 수 있음 | PR로 올린 후 확인 가능 |
소나큐브(SonarQube) 호환성 | 특정 버전과의 호환성이 명확하지 않음 | 공식 소나큐브 IDE 확장 기능 (표준 도구) | 소나큐브 기준이나 버전이 낮음 |
복잡도 증가 위치 표시 | 위치 표시 기능 없음 | Show all locations for Issue 기능 제공하나 잘못된 부분 존재 | 위치 표시 기능 없음 |
기본값 연산자(??, |) 점수 증가 | SCAN과 동일하게 점수 증가 | 점수 증가하지 않음 | 점수 증가 |
함수 중첩 구조 처리 | - 내부 함수는 개별 계산 - 외부 함수는 내부 함수를 제외한 부분만 계산 - 내부 함수에 무조건 중첩 점수를 가중 | - 내부 함수는 개별 계산 - 외부 함수는 내부 함수를 제외한 부분만 계산 - 내부 함수에 중첩 점수를 가중하지 않음 | - 다음 상황에서 각각 다르게 측정함 - case 1. 내부 함수들 + 논리 연산자가 들어간 단순 선언문 - case 2. 내부 함수들 + 논리 연산자가 들어간 단순 선언문 외의 점수가 증가하는 코드 |
다른 코드 이슈 확인 가능 여부 | 복잡도만 측정 가능 | 코드 내 다른 이슈도 함께 확인 가능 | 코드 내 다른 이슈도 함께 확인 가능 |
업데이트 및 변경 안내 | 변경 내용 안내 부족 | 익스텐션 업데이트 시점마다 계산법이 달라질 가능성 있음 | 최신 버전과 항상 동일하지 않음 |
조건 (condition)
if else
if, else if, else exploding head +1
3항 연산자(ternary operator) exploding head +1
early return 으로 점수 줄이기 가능
switch
switch 문 exploding head +1
각 case 문에서는 증가 없음
단, case 안에서 if, for문 등 사용 시 중첩 증가 exploding head +2
break, default에서도 별도 증가 없음
if문과 비교했을 때 분기 케이스가 많을수록 효과적
반복 (loop)
while, for, for…of, for…in 문 exploding head +1
forEach 사용시 증가 없음
map, filter 등 배열 순회 고차 함수 메서드 점수 증가 없음
단, 고차함수의 콜백함수 내 흐름 끊는 요소가 존재하는 경우 중첩 함수 구조 적용되어 계산
논리 연산 (logical)
OR 연산자(||), AND 연산자(&&) exploding head +1
연산자 흐름 변경 exploding head +1
같은 연산자 반복 사용은 추가 증가 없음
단, 결합된 not 연산자 추가 사용 시 점수 증가 exploding head +1
조건문 등과 함께 사용시 별도로 증가
중첩 (nesting)
인지 복잡도의 가장 큰 특징은 중첩 구조에 가산점 부여 exploding head +α
중첩이 많아질수록 사람이 이해하는 데 드는 노력이 급격히 증가하기 때문에, 복잡도도 가중된 방식으로 증가
첫 번째 조건/반복/catch: exploding head +1
두 번째 조건/반복/catch: exploding head +2
세 번째 조건/반복/catch: exploding head +3
단,중첩문 안에서도 else if와 else는 if와 달리 가중치를 부여하지 않음 exploding head +1
삼항 연산자에서도 동일하게 중첩 구조 적용됨
warning 중첩 함수 구조
현재 스캔의 javascript sonar lint 버전은 10.5 아래인 10.3.1.21905으로,
중첩함수의 복잡도가 부모에 추가되는 경우를 제외하는 계산법이 반영되기 이전 상태
팀 내 복잡도가 매우 높은 코드를 보면 대부분이 중첩함수 구조로 내부 함수의 복잡도 점수가 모두 합쳐져 있는 형태
SCAN에서 10.5 이상의 버전으로 업데이트되면 점수가 높게 측정되는 부분이 줄어들 것으로 보임
1. 내부 함수들 + (논리 연산자가 들어간 단순 선언문)
외부 함수와 내부 함수가 각각 계산
외부 함수는 내부 함수를 제외한 나머지 부분을 계산함
내부 함수는 중첩 구조로 판단하지 않고 가중치를 부가하지 않은 상태로 점수가 측정됨
2. 내부 함수들 + 논리 연산자가 들어간 단순 선언문 외의 점수가 증가하는 코드
외부 함수와 내부 함수가 합쳐져 계산
외부 함수에만 경고 표시
내부 함수는 중첩된 구조로 가중치가 부가된 상태로 점수가 측정됨
논리 연산자가 들어간 선언문 외 점수가 증가하는 경우 포함
if, for, while, switch 등은 코드의 논리적 흐름을 변경하는 요소로 판단하여 상위 함수의 흐름이 바뀌는 경우만 상위 함수의 복잡도로 반영
if문 ternary operator, switch 등의 조건문
while, for, for of 등 복잡도가 증가하는 반복문
try/catch
try catch
catch문에서 복잡도 증가 exploding head +1
catch문 안에서는 중첩 증가 exploding head +2
try, finally 점수 증가 없음