린트 (소프트웨어)
1. 개요
린트는 소프트웨어 코드의 잠재적인 오류, 스타일 문제, 그리고 의심스러운 구조를 탐지하는 데 사용되는 도구이다. 1978년 벨 연구소의 스티븐 C. 존슨에 의해 처음 개발되었으며, 유닉스 운영 체제를 32비트 머신으로 이식하는 과정에서 C 언어의 Yacc 문법을 디버깅하면서 소프트웨어 이식성 문제를 해결하기 위해 "린트"라는 용어를 사용했다. 린트는 구문 오류, 선언되지 않은 변수 사용, 형식 불일치 등을 탐지하며, C, C++, JavaScript, Python 등 다양한 프로그래밍 언어에서 활용된다. 린팅(linting)은 코드 검사 및 분석을 의미하며, 린터를 통해 저품질 코드를 검출하고 버그를 예방하는 데 목적을 둔다.
-
정적 프로그램 분석 도구 -
JSLint
JSLint는 자바스크립트 코드의 잠재적 오류를 검사하는 도구이며, 2021년부터 FSF/OSI 승인 언라이선스를 사용한다. -
정적 프로그램 분석 도구 -
클랭
Clang은 LLVM 프로젝트의 컴파일러 프론트엔드로서, C, C++, Objective-C, Objective-C++ 등의 언어를 지원하며, 오픈 소스 라이선스로 배포되고, GCC와의 호환성, 메모리 효율성, 빠른 컴파일 속도를 목표로 설계되어 다양한 운영체제 및 환경에서 사용되며 여러 파생 컴파일러의 기반이 된다. -
유닉스 소프트웨어 -
GNU 코어 유틸리티
GNU 코어 유틸리티는 유닉스 계열 운영체제에서 파일, 셸, 텍스트 조작을 위한 기본적인 명령어 모음으로, GNU 파일 유틸리티에서 시작하여 3개의 패키지가 통합되어 발전했으며 셸 스크립트 및 시스템 관리에 필수적인 도구를 제공한다. -
유닉스 소프트웨어 -
한/글
한/글은 1980년대 후반부터 개발된 대한민국의 대표적인 워드프로세서로, 다양한 운영체제 지원, 정부 전자 문서 시스템에서의 역할, 꾸준한 기능 발전과 사용자 편의성 및 국제 표준을 고려한 업데이트를 통해 발전해왔다. -
프로그래밍 도구 -
SWIG
SWIG는 C/C++ 코드를 다른 프로그래밍 언어에서 사용할 수 있도록 인터페이스를 자동으로 생성해주는 도구로서, 복잡한 데이터 형식 처리, 메모리 관리 등을 지원하며, LLDB, GNU Radio, TensorFlow 등 다양한 프로젝트에서 활용된다. -
프로그래밍 도구 -
소스 코드 편집기
소스 코드 편집기는 구문 강조, 자동 완성, 들여쓰기 등의 기능으로 코드 편집을 용이하게 하고 개발 도구 실행 환경을 제공하며, 텍스트 편집 대신 AST를 조작하는 구조 편집기도 존재한다.
2. 역사
벨 연구소의 스티븐 C. 존슨은 1978년 유닉스를 32비트 머신으로 이식하는 과정에서 린트(lint)라는 용어를 만들었다. 이후 린트는 여러 C 및 C++ 컴파일러를 위해 개발되었으며, 오늘날의 컴파일러는 린트와 유사한 기능을 갖추고 있다. 1985년에 소개된 킴펠의 PC-Lint는 C++ 소스 코드를 분석하는 데 사용되며 현재까지 판매되고 있다.
2.1. 기원
벨 연구소의 컴퓨터 과학자 스티픈 C. 존슨은 1978년에 유닉스를 32비트 머신으로 이식하면서 C를 위해 작성한 Yacc 문법을 디버깅하던 중 린트(lint)라는 용어를 창안했다. 이 용어는 옷에서 떨어져 나오는 미세한 섬유 덩어리를 뜻하는 린트에서 따온 것으로, 그가 작성한 명령어가 마치 옷감 건조기의 린트 트랩처럼 온전한 옷감은 그대로 두고 불필요한 섬유만을 잡아내는 역할을 했기 때문이다. 1979년, 린트는 벨 연구소 외부에서 처음으로 사용되었으며, 이는 유닉스의 일곱 번째 버전(V7)이었다.
2.2. 발전
벨 연구소의 컴퓨터 과학자 스티븐 C. 존슨은 1978년 yacc 문법을 C로 디버깅하는 과정에서 유닉스를 32비트 머신으로 포팅하면서 이식성 문제에 직면하여 "린트"라는 용어를 생각해냈다. 이 용어는 옷에서 떨어져 나오는 미세한 섬유 덩어리를 뜻하는 단어 린트에서 따온 것으로, 그가 작성한 명령어가 마치 옷감 건조기의 린트 트랩처럼 온전한 옷감은 그대로 두고 불필요한 섬유만을 잡아내는 역할을 했기 때문이다. 1979년, 린트 프로그래밍은 벨 연구소 외부에서 처음으로 사용되었으며, 이는 유닉스의 일곱 번째 버전(V7)이었다.
수년에 걸쳐 다양한 버전의 린트가 여러 C 및 C++컴파일러를 위해 개발되었으며, 오늘날의 컴파일러는 린트와 유사한 기능을 갖추고 있지만, 린트와 유사한 도구 역시 그 기능을 발전시켜왔다. 예를 들어, 1985년에 소개되어 C++ 소스 코드를 분석하는 데 사용된 킴펠의 PC-Lint는 현재까지 판매되고 있다.
3. 린트의 기능 및 활용
린트는 최적화 컴파일러에서도 수행할 수 있는 분석을 포함하며, 현대의 컴파일러는 린트의 역사적인 기능 중 다수를 포함하고 있다. 그럼에도 불구하고, 린트와 유사한 도구들은 더 광범위하고 의심스러운 구문을 탐지하도록 발전했다.
린트는 동적으로 타입이 지정된 언어인 자바스크립트 및 파이썬과 같은 언어에 특히 유용하다. 이러한 언어는 실행 중에 엄격한 규칙을 적용하지 않기 때문에, 린터는 일반적인 오류뿐만 아니라 찾기 어려운 오류를 찾는 디버거로도 사용될 수 있다. 린트는 주로 소스 코드의 정적 분석을 수행한다.
또한, 린트와 유사한 도구는 주어진 언어 소스 코드에 대한 문법 및 스타일 가이드를 적용하기 위해 개발되었다. ESLint와 같은 일부 도구는 규칙을 자동 수정할 수 있도록 허용한다. 즉, 규칙 정의와 함께 해당 규칙이 더 이상 트리거되지 않도록 하는 변환 정의를 제공한다. 스타일에 대한 규칙은 자동 수정과 함께 제공될 가능성이 높다. 린터가 서식에 대한 규칙만 트리거하는 파일에서 "모두 수정" 모드로 실행되면, 린터는 포매터처럼 작동한다.
3.1. 탐지하는 문제
린트는 구문 오류, 선언되지 않은 변수 사용, 사용 중단된 함수 호출, 형식 불일치, 잠재적 버그, 의심스러운 코드 구조 등을 탐지한다. 특히 자바스크립트나 파이썬과 같은 동적으로 타입이 지정된 언어에서 유용하며, 간단한 디버거 역할도 수행할 수 있다.
C 언어에서 반환 값이 없는 함수는 미정의 동작을 유발할 수 있어 린트에서 경고가 발생한다. 예를 들어, 다음 코드는 `sum`이 100 이상일 때만 값을 반환하고, 그렇지 않으면 반환 값이 없어 린트 경고가 발생한다.
int foo(int count) {
int sum = 0;
int i;
for (i = 1; i <= count; ++i) {
sum += i;
}
if (sum >= 100) {
return sum;
}
}
하지만 최근 컴파일러의 기능 강화로, 이러한 종류의 오류도 컴파일 단계에서 탐지할 수 있게 되었다. 예를 들어 Microsoft Visual C++에서는 C4715 경고가, GCC 및 Clang에서는 `-Wreturn-type` 옵션을 통해 경고를 발생시킨다. C 언어 및 C++는 미정의 동작이 많아 컴파일러나 린트의 경고에 의존해야 하는 경우가 많다.
3.2. 활용
린트는 C, C++뿐만 아니라 자바스크립트, 파이썬, HTML, TypeScript 등 다양한 언어에서 활용된다. Another HTML-lint는 HTML 구문 검사에 사용되는 린트 도구의 한 예이다. Android Studio에서는 Java 및 Kotlin 코드 분석에 린트를 사용할 수 있다.
컴파일러가 존재하는 언어의 경우, 정적 코드 분석에 컴파일러와 린터를 함께 사용하면 어휘/구문 검사와 의미론적 검사를 모두 수행할 수 있다. 코드 편집기에서 실시간으로 동작하는 린터를 이용하면 코드를 작성하는 동안 지속적으로 린팅을 수행할 수 있다. 예를 들어 Visual Studio Code에서 TypeScript 코드를 작성할 때, 어휘/구문 검사를 담당하는 `tsserver`와 린팅을 담당하는 ESLint를 함께 사용하여 코드 작성 중 실시간 정적 코드 분석이 이루어지도록 할 수 있다. 최신 통합 개발 환경에는 보통 정적 코드 분석 도구가 기본적으로 내장되어 있어, 문제가 있는 부분을 코드 편집기에서 강조 표시하거나 분석 결과 목록을 보여주는 기능을 표준적으로 제공한다.
3.3. 목적
린트의 주된 목적은 저품질 코드를 검출하여 버그를 예방하는 것이다. 언어 구문에 일치하더라도 실행 시 오류나 의도하지 않은 동작을 일으키거나, 유지보수성 및 이식성을 저하시키는 등 잠재적 문제를 야기할 수 있는 코드에 대해 린트는 오류를 발생시킨다. 린터는 일반적인 컴파일러 경고보다 더 세밀한 분석 결과를 제공하며, '오류를 자주 일으키는 패턴' 또는 '오류를 피하는 베스트 프랙티스 패턴'을 사용하여 품질이 낮은 코드를 찾아낸다. 이렇게 검출된 코드를 개선하면 버그 발생 가능성을 줄여 예방할 수 있다.
1978년 존슨은 오류 감지를 위한 별도 프로그램을 만든 이유를 다음과 같이 설명했다. 분석 프로그램과 별개로 "두 개의 프로그램을 갖는다는 일반적인 개념은 좋은 것이다"[이는 두 프로그램이 서로 다른 것에 집중하기 때문에 프로그래머가] "프로그래밍 과정의 한 단계에서 오로지 알고리즘, 자료 구조, 프로그램의 정확성에 집중하고, 나중에 린트의 도움을 받아 보편성과 이식성이라는 바람직한 속성을 추가할 수 있도록 한다."
4. 린트와 유사 도구
최적화 컴파일러는 더 빠른 코드를 생성하기 위한 분석을 수행하며, 현대의 컴파일러는 린트의 역사적인 기능을 많이 포함한다. 그럼에도 린트와 유사한 도구들은 "구문 오류 경고, 선언되지 않은 변수 사용, 사용 중단된 함수 호출, 간격 및 서식 규칙, 범위 오용, switch 문의 암시적 폴스루, 라이선스 헤더 누락, 위험한 언어 기능" 등 더 광범위하고 의심스러운 구문을 탐지하도록 발전했다.
린트와 유사한 도구는 동적으로 타입이 지정된 언어인 자바스크립트 및 파이썬과 같은 언어에 특히 유용하다. 이러한 언어의 인터프리터는 실행 중 엄격한 규칙을 적용하지 않기 때문에, 린터는 일반적인 오류와 하인버그와 같은 찾기 어려운 오류를 찾는 디버거로도 사용된다. 린트와 유사한 도구는 주로 소스 코드의 정적 분석을 수행한다.
ESLint와 같은 일부 도구는 규칙을 자동 수정할 수 있다. 즉, 규칙 정의는 해당 규칙이 더 이상 트리거되지 않도록 하는 변환 정의와 함께 제공될 수 있다. 스타일에 대한 규칙은 자동 수정과 함께 제공될 가능성이 높다. 린터가 서식에 대한 규칙만 트리거하는 파일에서 "모두 수정" 모드로 실행되면, 린터는 포매터처럼 작동한다.
C 언어에 한정되지 않고, 각종 프로그래밍 언어로 작성된 코드에 대해 구문 검사나 정적 분석을 수행하는 프로그램도 린트라고 불린다. HTML 구문 검사를 수행하는 Another HTML-lint가 그 예시이다. Android Studio에서는 Java 및 Kotlin 코드 정적 분석 도구로 린트를 사용할 수 있다.
코드를 검사·분석하는 동작을 lint/linting, 린트를 수행하는 프로그램을 linter라고 부르기도 한다. Clang 기반의 C++ linter로는 Clang-Tidy가 있다.
컴파일러가 존재하는 언어의 경우, 정적 코드 분석에 컴파일러와 linter를 병용함으로써 어휘/구문 검사와 의미론적 검사를 실현할 수 있다. 코드 에디터상에서 실시간으로 동작하는 linter를 이용하면 코딩하면서 상시 linting을 수행할 수 있다. 예를 들어 Visual Studio Code 상에서 TypeScript 코드를 작성하는 경우, 어휘/구문 검사를 담당하는 tsserver와 linting을 담당하는 ESLint를 사용하여 코딩 중에 상시 정적 코드 분석이 실행되는 상태를 실현할 수 있다. 최신 통합 개발 환경에는 일반적으로 정적 코드 분석 도구가 내장되어, 문제가 있는 부분을 코드 에디터상에서 강조 표시하거나 분석 결과 목록을 표시하는 기능을 표준적으로 사용할 수 있다.
linting의 주된 목적은 저품질 코드 검출에 의한 버그 예방이다. 언어 구문에 일치하지만 실행 시 에러나 의도하지 않은 동작, 유지 보수성 저하 등의 잠재적 문제를 일으킬 수 있는 코드는 린트 에러가 발생할 수 있다. linter 경고는 일반적인 컴파일러 경고보다 더 세밀한 분석 결과이다. linter는 「에러를 종종 일으키는 패턴」 혹은 「에러를 피하는 베스트 프랙티스 패턴」을 사용하여 품질이 낮은 코드를 검출하고, 이를 개선함으로써 버그 삽입 가능성을 낮춘다.