정적 분석으로 자바스크립트 코드의 오류와 코드 스멜 찾기 ② - 정적 분석 도구로 수집한 코드 결함 사례와 정적 분석 도구 선택 Tip

정적 분석으로 자바스크립트 코드의 오류와 코드 스멜(Code Smell) 찾기 ② - 정적 분석 도구로 수집한 코드 결함 사례와 정적 분석 도구 선택 Tip

지난 아티클에서 정적 분석의 작동 방식과 Rollbar에서 발표한 실제 오류 사례 중 일부를 살펴보았고, 이제 깃허브에 있는 수천 개의 공용 자바스크립트 및 타입스크립트 프로젝트를 분석하여 정적 분석 도구로 수집한 코드 결함 사례와 정적 분석 도구를 선택할 때 고려해야 할 사항들을 살펴보겠습니다.

먼저 상위 10가지 코드 결함은 다음과 같습니다.

상위 10가지 코드 결함 [ 그림 1 ] 상위 10가지 코드 결함 유형별 코드 결함 [ 그림 2 ] 유형별 코드 결함

상위 코드 결함 중 대부분은 미사용 변수, 초기화되지 않은 로컬 변수 및 널 포인터와 연관이 있습니다.
각 경우에 대해 자세히 살펴보도록 하겠습니다.


미사용 변수(Unused Variables)
미사용 변수란 선언/정의만 하고 사용되지 않거나 사용 전에 재정의(할당)되는 변수를 말합니다. 개발자는 간과하는 경우가 많지만 이 미사용 변수는 추후 코드 베이스의 유지 관리를 어렵게 만드는 요인이 됩니다. 외관상 사소해 보이는 문제이지만 원하지 않는 결과로 이어질 수 있는데, 아래 [그림 3]을 보면 3행에서 'target' 변수에 할당된 값이 4행에서의 재할당으로 무시되어 url에 'userName' 매개 변수가 추가되지 않은 채로 치환됩니다.

미사용 변수의 예 [ 그림 3 ] 미사용 변수의 예

중복 변수와 함수(Duplicated Variables or Functions)
변수나 함수를 중복 정의하는 경우인데, 이것은 개발자가 자바스크립트 언어나 새 기능에 대해 잘 모르고 있다는 징후일 수도 있습니다. 자바스크립트는 중복 정의에 대해 에러를 내지 않고 마지막에 정의된 것만 유효하며 함수 오버로딩을 지원하지 않는데, 특히 오버로딩(overloading)을 지원하는 기존 언어에 익숙한 개발자의 경우에 혼동하는 경우가 많습니다.
이 결함으로 인해 실행 오류가 발생하지는 않지만 중복된 코드는 제거하는 것이 좋은 코딩 습관입니다. 중복 변수와 함수로 인해 어떤 것이 실제로 사용되는지 혼동을 가져와 유지 보수성 (maintainability)을 저하시키고 기술 부채가 증가하기 때문입니다.


초기화되지 않은 변수(Uninitialized Variables)
초기화되지 않은 변수를 사용하는 경우로서 'var' 변수의 스코프(scope)와 함수 호이스팅(hoisting)에 대한 이해 부족 때문에 종종 발생합니다.
아래 [그림 4]에서 'html5' 변수는 2행과 5행에서 선언되고 있습니다. 'var'로 선언된 변수는 함수 범위를 갖기 때문에 두 변수는 다르게 취급되는데 5행의 변수만 초기화되고 2행의 변수는 초기화되지 않았습니다. 따라서 2행의 변수를 반환하게 되면 호출자(caller)는 기대한 값을 받지 못해 예기치 않은 동작이 발생할 수 있습니다.

초기화되지 않은 변수의 예 [ 그림 4 ] 초기화되지 않은 변수의 예

부주의한 널 체크(Incautious NULL Checking)
변수나 인자의 널을 체크하는 상황에서 TypeError 발생 가능성이 높습니다. 특히 예외적인 유스 케이스(코드의 else 분기문)에서 더 그런데 이는 개발자가 일반적으로 주된 유스 케이스(코드의 if 분기문) 또는 정상적인 인자 값만 테스트하기 때문입니다. 이와 같이 널 체크를 제대로 하지 않으면 다양한 유스 케이스를 갖는 사용자 경험을 방해하게 됩니다.
아래 [그림 5]을 보면 변수 'match'가 9행의 else 분기문에서 널 값을 갖게 되고 12행에서 역참조되어 TypeError가 발생합니다. 결과적으로 사용자의 특정 유스 케이스(에디터에서 마크를 하나도 추가하지 않은 상황)에서 에러가 발생하는 좋지 않은 영향을 미칩니다.

부주의한 널 체크의 예 [ 그림 5 ] 부주의한 널 체크의 예

지금까지 코드 결함 사례를 살펴봤는데, 특기할 점은 위의 예시와 통계가 저장소(repository)에 최종 커밋된 코드로부터 나왔다는 것입니다. 즉, 개발자 자신 혹은 동료의 코드 리뷰를 거쳤다는 것이고 사람에 의한 코드 리뷰로는 코드 결함 예방이 불완전함을 의미합니다. 정적 분석 도구는 감정이나 주변 여건에 영향을 받는 개발자와 달리 일관적이고 자동화된 방식으로 문제를 발견하고 수십만 라인 이상의 코드도 빠르게 분석하여 이 과정을 보완할 수 있습니다.
또, 데이터 흐름 분석을 지원하는 도구는 결함 원인을 정확하게 파악해 주기 때문에 개발자는 빠르고 쉽게 결함을 수정할 수 있습니다.
위 [그림 5]의 예제에 대해 정적 분석 도구는 다음과 같이 널 포인터 문제(널 객체가 이 지점에서 참조됩니다)와 그 원인(9행에 있는 할당문 때문입니다)을 출력해 줄 수 있습니다:

Variable ' match ' has a null value originated from assignment ' match = null ' at line 9. But its property is accessed at this point.

추가적으로 결함 수정 시간에 대한 정적 분석 도구의 통계를 확인해 보겠습니다.
결함 수정 시간은 결함이 처음 발견된 시점부터 해결(코드 수정, 제거, 선별)될 때까지의 시간을 평균한 것입니다.

평균 결함 수정 시간 [그림 6] 평균 결함 수정 시간

개발자들이 느리게 수정하는 결함을 보면 미사용 PropTypes, 재선언된 'var' 변수, if/else 분기문에서의 동일한 구현과 같은 결함이 있고 이런 종류의 결함은 상대적으로 개발자가 중요한 문제로 간주하지 않는다고 생각할 수 있습니다. 하지만 개발자 의도와 다르게 발생하는 명백한 실행 오류나 실수는 중요한 문제로 간주되고, 널 포인터, 부주의한 널 체크, 잘못된 Strict 모드, React에서의 잘못된 이벤트 처리 (React는 DOM과 다른 자체 이벤트 시스템을 가집니다), 조건문에서의 할당 연산자(비교 연산자를 잘못 쓴 경우) 같은 결함은 개발자가 빠르게 수정하는 것으로 파악됩니다.
이 결과를 보면 정적 분석 도구는 실행 오류 및 코드 품질에 영향을 미치는 유의미한 결함을 발견할 때만 개발자가 저항 없이 사용한다는 사실을 알 수 있습니다. 전체 자바스크립트 프로그램의 데이터 흐름을 이해하는 정적 분석 도구만이 이런 결함을 찾아냄으로써 개발팀의 생산성을 향상시키고 비용 대비 만족스러운 효과를 낼 수 있겠습니다.


정적 분석 도구 선택 Tip
지금까지 정적 분석 도구가 자바스크립트의 코드 결함을 얼마나 효과적이고 효율적으로 탐지할 수 있는지 살펴보았습니다. 전체 자바스크립트 프로그램을 이해할 수 있도록 설계된 정적 분석 도구가 할 수 있는 일은 다음과 같습니다.

  • 단순 코드 분석 도구가 찾을 수 없는 코드 결함의 탐지
  • 개발 초기 단계에서부터 실행 오류 및 코드 품질 저하를 예방
  • 자바스크립트 개발자/테스터의 잘못된 코딩 관행을 바로잡아 프로그래밍 스킬 향상을 도움
  • 개발자가 놓칠 수 있는 코드 결함을 탐지합니다. 본 아티클의 예는 최종 코드 리뷰를 마친 코드로부터 발췌한 것입니다. 코드 리뷰(peer review)는 매우 유용하나 사람이 대량의 전체 프로그램을 쉽게 이해할 수는 없기 때문에 기계적인 일관성과 빠른 속도를 지닌 자동 분석 도구로 보완되어야 함

다음 체크 리스트에서 자바스크립트 정적 분석 도구의 채택 및 도입에 대한 권장 사항을 제시하였습니다.

데이터 흐름 분석 정적 분석 도구는 자바스크립트 모듈 내 함수 사이나 모듈 사이의 데이터 흐름을 인식해야 합니다. 자바스크립트 코드 베이스가 커지고 모듈이 세분화되면서 이런 분석 기능이 더욱 중요해지고 있습니다.
낮은 오탐지율 정적 분석 도구가 발견한 결함이 오탐(결함이 아닌 코드를 결함으로 감지, false alarm)으로 판명될 경우 해당 도구에 대한 개발자의 신뢰가 저하됩니다. 따라서 정적 분석 도구는 실제 발생 가능한 결함을 예방하면서도 오탐지율을 낮게 유지해야 합니다.
최신 기술 지원 자바스크립트 생태계는 매우 빠르게 변하고 있으며 적극적으로 최신 기술을 수용하는 경향을 보입니다. 정적 분석 도구는 최신 자바스크립트 사양과 타입스크립트, Flow, JSX, React, Vue.js 같이 근래 많이 사용되는 기술을 지원해야 다양한 개발 프로젝트에서 활용할 수 있습니다.
개발 워크플로우와 통합 정적 분석 도구는 개발자의 잘못을 찾아내어 비난하기 위한 도구로 자칫 인식될 수 있습니다. 또, 개발이 많이 진척된 단계에서 처음 적용하면 수정해야 할 결함이 많이 나오고 기능 회귀(regression)에 대한 부담이 커집니다. 따라서 에디터 플러그인이나 명령행 도구(command-line tools) 같이 개발자가 일상적인 개발에 쉽게 적용하여 도움을 받는 도구로 활용할 수 있는 방법이 제공되어야 합니다.

결론적으로, 자바스크립트를 위한 정적 분석 도구를 개발/테스트 프로세스나 제품 검수 기준에 도입함으로써 웹 애플리케이션에 대한 신뢰성 보장을 기대할 수 있습니다. 자바스크립트 사용의 확대와 함께 웹 개발 및 프로젝트 관리 팀의 생산성 향상과 품질 비용 절감에 대한 요구가 커지면서 정적 분석 도구의 필요성도 더욱 커질 것입니다.
정적 분석 도구를 활용해 더 즐거운 자바스크립트 개발을 시작하시길 바랍니다!


에스코어는 시스템 소프트웨어 기술력과 컨설팅 역량을 바탕으로, 고객의 성공적인 Digital Transformation을 위한 IT 전략 수립, 신기술 기반 소프트웨어 R&D 및 플랫폼 개발/운영 서비스를 One-Stop으로 통합 제공합니다.

▶   해당 콘텐츠는 저작권법에 의하여 보호받는 저작물로 기고자에 저작권이 있습니다.
▶   해당 콘텐츠는 사전 동의없이 2차 가공 및 영리적인 이용을 금하고 있습니다.


공유하기
김강호 프로
김강호 프로 IT테크놀로지 전문가
에스코어

김강호 프로는 타이젠 웹 SDK의 개발 리더를 역임했고 현재 자바스크립트 정적 분석 솔루션인 DeepScanTM의 제품 관리자를 맡고 있습니다. DeepScan 서비스(https://deepscan.io)를 통해 개발자와 관계를 맺고 싶어 합니다.