정적코드분석/코딩표준

정적 코드 분석 도구 도입에서 활용까지

2015년 5월 21일 STEN에서 “파수닷컴 자동차 코딩 표준(MISRA-C:2004)의 실무 적용“이라는 주제로 발표한 적이 있었습니다. 해당 발표는 크게 2부로 나뉘어져 있었는데, 1부는  MISRA-C:2004 에 대한 소개 및 간단한 규칙 설명, 2부로 정적 코드 분석도구(Static code analysis tool) 도입 및 활용법에 대한 내용이었습니다. 2부 강의 내용은 많은 사람들에게 도움이 되겠다 생각되어 글로 정리합니다.

bug finding

좋은 정적 코드 분석 도구 선택하기

많은 분들이 좋은 정적 코드 분석 도구가 갖춰야 할 조건을 잘 아시지만, 그 중에는 그저 “결함을 많이 발견하는 도구가 좋은 도구”라고 아시는 분이 계십니다. 하지만 이는 사실이 아닙니다.

True/False Positive/Negative

여기 화재경보기가 있습니다. 화재경보기는 불이 날때 큰 소리로 경보를 울려 주위 사람들이 재빨리 화재를 인지하기 위해 설치합니다. 하지만 화재경보기도 기계인 만큼 완벽하지 않습니다. 불이 났음에도 울리지 않을 수 있고, 불이 나지 않았는데도 불구하고 경보를 울릴 수 있습니다. 이를 4가지 상황으로 정리할 수 있는데요.

  1. 불이 났으나 경보가 울리지 않는 경우
  2. 불이 나서 경보가 울리는 경우
  3. 불이 나지 않았고 경보가 울리지 않는 경우
  4. 불이 나지 않았지만 경보가 울리는 경우

이를 혼동행렬(Confusion Matrix) 를 통해서 정리하면 아래와 같습니다. 

Confusion Matrix 왼쪽의 실제(Actual) 부분을 화재 발생으로 생각하고 예측(Predicted)을 경보로 생각해봅시다. 그렇다면 앞서 발생한 화재 경보기의 대응은 아래와 같이 적을 수 있습니다.

  1. 불이 났으나(True) 경보가 울리지 않는 경우(Negative)
  2. 불이 나서(True) 경보가 울리는 경우 (Positive)
  3. 불이 나지 않았고(False) 경보가 울리지 않는 경우 (Negative)
  4. 불이 나지 않았지만(False) 경보가 울리는 경우 (Positive)

화재 경보기가 제대로 동작한다면 언제나 2번과 3번처럼 동작해야 합니다. 하지만 구글에서 “화재경보기 오작동”이라는 질의어로 검색하면 관련 항목이 2만개 이상이 될 정도로 화재경보기도 오작동이 많습니다. 불행히도 정적 코드 분석기도 같은 문제를 가지고 있습니다.

정적 코드 분석 도구의 원죄

정적 코드 분석 도구의 핵심 기술인 정적 분석 기술은 태생적인 문제가 있습니다. 위에서 언급한 4가지 상황 중 최악의 상황인 1번과 4번의 발생을 피할 수 없다는 점입니다. 이에 대해서 파수닷컴 PA개발 2팀장 정영범 박사님이 디지털 타임즈에 기고한 글을 인용합니다.

정적 분석 기술은 태생적으로 완벽할 수가 없다. 완벽한 정적 분석이 가능하다는 것은 그 유명한 정지 문제(Halting Problem)를 풀 수 있다는 것과 동치이다. 정지 문제는 풀 수 없다는 것이 이미 증명되었기에 완벽한 정적 분석이 불가능하다는 결론을 얻는다. 정적 분석이라는 것이 실행 중에 결정될 수 있는 정보를 모르는 상태에서 실행 의미를 예측하는 것이기에 이는 어쩔 수 없는 결과이다. 결혼 전에 보는 궁합과 실제 결혼 생활, 기상청의 날씨 예보와 실제 날씨, 대입 수능의 성적과 실제 대학에서의 수학 능력이 완벽하게 일치하지는 않는 것처럼.

좋은 정적 코드 분석 도구의 조건

이런 정적 코드 분석 도구의 태생적 약점 때문에 정적 코드 분석 도구의 선택 조건을 탐지한 결함 갯수로 설정하는 것은 위험합니다. 정적 코드 분석 도구는 어디까지나 True Positive(결함이 있는 코드를 결함으로 탐지), False Negative(결함이 아닌 코드를 결함으로 미탐지) 가 극대화되고 False Positive(결함이 없으나 결함으로 탐지), True Negative(결함이 있으나 결함을 못찾음) 가 최소화되어야 좋은 정적 코드 분석기라 할 수 있습니다.

정적 코드 분석 도구에서 찾은 결함 중 False Positive(업계 용어로는 “오탐”이라고 합니다. 이하 “오탐”으로 합니다.) 가 많으면 그 만큼 관리자와 개발자가 결함을 리뷰하는데 많은 시간을 사용하기 때문에 생산성이 낮아집니다. 물론 결함이 있는데도 정적 코드 분석기가 찾지 못하는 True Negative(업계 용어로는 “미탐”이라고 합니다. 이하 “미탐”으로 합니다.) 일 경우 개발자와 관리자가 당연히 결함을 인지하지 못할 것이며 따라서 실제 배포 후 문제가 발생할 수 있습니다.

코딩 규칙 선택

정적 코드 분석 도구를 오탐과 미탐이 적고 True Positive, False Negative가 많은 도구를 선정하고 구입하셨다면 다음 할 일은 팀 내에서 사용할 코딩 규칙을 설정하는 일입니다.

가장 중요한 규칙은 왠만해서는 모두 선택

제가 접해봤던 모든 정적 코드 분석 도구에서는 코딩 규칙마다 심각도 레벨이 있었습니다. 예를 들어 정적 분석 도구인 파수 Sparrow 의 경우 심각도 레벨 1부터 5까지 있고 SonarQube의 경우 Critical, Major, Minor 로 심각도 레벨을 구분하고 있습니다. 보통 가장 심각도 레벨이 높은 규칙을 위반하면 프로그램이 정상적으로 실행되지 않기 때문에  반드시 선택하는 것이 좋습니다. C/C++ 의 예를 들면 Buffer Overflow 가 발생할 위험이 있다거나, Null Dereference 가 발생한다거나, 메모리 누수가 발생하는 경우가 이에 해당됩니다. 덜 중요한 규칙은 필요하다 싶은 것만 선택하십시오.

목적에 따라 코딩 규칙 선택

프로젝트의 목적에 따라서 코딩 규칙을 설정해야 할 때도 있습니다. 예를 들어 자동차에 들어갈 임베디드 장비라 한다면 MISRA-C의 코딩 규칙을 적용해야 하며, 항공장비라면 DO-178B 컴플라이언스에 준하거나 JSF 코딩 규칙을 적용해야 겠죠. 보안이 중요하다면 시큐어코딩 규칙을 적용할 수도 있습니다.

일반 소프트웨어 업체는 위의 코딩 규칙 중에서 필요한 것만 선택해서 사용하셔야 합니다. 막연하게 MISRA-C와 같은 코딩 규칙을 모두 따르면 버그 없는 소프트웨어를 만들 수 있겠지라고 생각하실 수 있지만 실상은 그 반대가 되는 경우가 많습니다 . 예를 들어 MISRA-C 같은 코딩 규칙은 엄격한 안전성과 신뢰성을 요구하는 미션 크리티컬(Mission Critical) 소프트웨어를 개발하기 위해 제정되었습니다. 이러한 코딩 규칙은 주로 개발자의 자유도를 상당히 제한하기 때문에 오히려 생산성이 저하될 위험이 있습니다.

추가로, 코딩 규칙 중 품질과 직접적인 연관이 없는 코딩 스타일(빈 칸, 중괄호 위치 등등) 관련 규칙은 최소한으로 적용하는 것이 좋습니다. 이건 순전 개인적인 생각입니다만, 이건 제가 추후 글로 정리하도록 하겠습니다.

팀 내 적용

서서히 적용

만약 팀이 정적 코드 분석 도구를 한 번도 사용해본 적이 없다면, 도입 시 저항감이 있을 지도 모릅니다. 아니, 기본적으로 ‘저항’한다고 가정하는 것이 일을 진행하기 편할 것입니다. 특히 상위 부서에서 정하고 하위 부서에 강제적으로 도입하는 경우가 그렇습니다. 이 경우는 정적 코드 분석 도구를 담당하는 부서 입장에서는 좀 더 조심스럽게 접근 할 필요가 있습니다.

매우 중요한 규칙만 먼저 적용하세요. 정적 코드 분석을 수행하는 것은 새내기 개발자 어깨 너머에 백전노장 개발자가 서 있어서 새내기 개발자가 코딩할 때 뒤에서 계속해서 팁을 알려주는 것과 같습니다. 만약 백전노장 개발자가 소스코드 한 줄 한 줄 마다 하찮은 이슈로 끊임없이 잔소리 타령을 한다고 가정합시다. 새내기 개발자는 곧  좋은 조언이건 나쁜 조언이건 간에 모든 조언을 무시하기 시작할 것입니다.

잔소리가 지속되면 아얘 귀를 막습니다…

그러나 경험있는 개발자가 심각한 문제를 일으킬수 있는 한 두 개의 이슈에 초점을 맞춘다면, 새내기 개발자는 그가 준 조언을 더 기억하고 더 좋은 코드를 작성하기 시작할것이며, 실제로 이런 종류의 피드백에 감사하고 신뢰하게 될 것 입니다. 정적 코드 분석 도구도  마찬가지입니다. 개발자와 정적 코드 분석 도구를 신뢰하기 시작하면 그 때부터 조금씩 조금씩 다른 규칙도 적용하는 것이 좋습니다.

새로운 프로젝트부터 적용

새로 정적 코드 분석 도구를 도입하면 대부분은 현재 개발되었거나 과거 개발되었던 프로젝트를 분석해 볼 것입니다. 하지만 보통 과거 프로젝트는 코딩 표준을 따르지 않았거나, 신경쓰지 않고 개발한 경우가 많아서 수 많은 규칙 위반이 발생할 것입니다. 이러면 해당 결함을 리뷰할 담당자 혹은 개발자는 처음부터 숫자에 압도당할 경우가 많습니다.  그러다가 점점 더 정적 코드 분석 도구를 멀리하게 되지요.

정적 코드 분석 도구를 처음 도입하면 기존 프로젝트보다 현재 프로젝트를 우선적으로 분석하세요. 기존 프로젝트는 심각도가 높은 규칙만 검사해도 충분할 수 있습니다.

지속적으로 많은 위반이 발생하는 규칙은 재검토

규칙을 설정했는데도 지속적으로 많은 위반이 발생하면, 이는 곧 개발자들이 규칙대로 개발하고 있지 않는다는 뜻입니다. 이 경우에는 해당 규칙을 재검토하시길 바랍니다. 규칙이 개발 환경에 안 맞을 수도 있거든요.

다만 인증(FDA, MISRA 등)에 꼭 필요한 경우라면 개발자를 설득시켜서 반드시 규칙을 지키도록 유도해야 합니다.

프로세스화

이제 이렇게 힘들게 도입한 정적 코드 분석 도구를 개발 프로세스에 넣는 일 만 남았습니다. 정적 코드 분석 도구를 사용하는 방식은 크게 두 가지입니다.

  1. 개발자가 소스코드 Commit 전 사용
  2. 일정 주기로 소스코드 저장소에서 불러온 후 사용

어떤 방식이 더 좋은 지는 자유 : ) 개인적으로는 2번을 더 선호합니다.

마지막으로 정적 코드 분석 도구를 도입하겠다고 마음을 먹었으면 모든 프로세스에는 “반드시” 개발자와 함께 하십시오! 정적 코드 분석 도구는 개발팀의 협조 없이는 유명무실한 소프트웨어입니다.

Leave a Reply

Leave a Reply

Your email address will not be published. Required fields are marked *