Node.js 소스 코드에서 숨은 오타 찾기
개요
들어가기 앞서
다음의 문장을 속독으로 가볍게 읽어보자.
- 캠릿브지 대학의 연결구과에 따르면, 한 단어 안에서 글자가 어떤 순서로 배되열어 있지는는 중하요지 않고, 첫 번째와 마지막 글자가 올바른 위치에 있는 것이 중하요다고 한다. 나머지 글들자은 완전히 엉진망창의 순서로 되어 있라을지도 당신은 아무 문제 없이 이것을 읽을 수 있다. 왜하냐면, 인간의 두뇌는 모든 글자를 하하나나 읽는 것이 아니라 단어 하나를 전체로 인하식기 때이문다.
윗 글을 다시 한 번 글자 단위로 세세하게 들여다보면 그저 빠르게 슥 훑었을 때와는 분명 다른 느낌이 들 것이다.
문장 속 단어들을 이루는 문자의 구성과 수가 같다면 인간은, 특히나 해당 언어에 익숙한 사람일 수록 문장 전체 뜻을 이해하는데 별다른 어려움을 겪지 않는다는 게 요지이다.
그러니 오류를 찾지 못 했다고 하여 너무 자책할 필요는 없다. 오히려 읽는 데 버벅였다거나 지적을 많이 한 경우가 그 언어를 더 어색하게 느끼거나 난독 증세가 있다는 의미니 말이다.
그런데 왜 난데없이 기술 블로그에 이런 소리를 하고 있는 걸까?
소스 코드 역시 결국은 사람이 작성하는 지라 클래스나 메소드, 변수 명 등을 선언 할 때 적지 않은 오탈자가 발생할 여지가 있고 유심히 바라보지 않는다면 사람이 직접 이런 오류를 처리하기가 매우 힘들다는 게 문제이다. 오탈자가 계속해서 누적된다면 변수 혹은 객체의 속성 key등이 의미하는 바가 퇴색되어 추후 해당 기능/속성을 참조하거나 다른 개발자가 이를 활용할 때 혼란과 오해를 발생시킬 가능성이 있다.
Do you know Typo?
Jetbrains에서 만든 PyCharm이나 IntelliJ 혹은 이를 기반으로 한 Android Studio 환경에서의 개발 경험이 있는 사람이라면 Typo라는 말을 한 번 이상은 들어봤을 것이다. Typo는 위에서 언급한 소스 코드 내 오탈자들을 보편적인 혹은 개인적으로 작성한 사전(Dictionary) 목록의 내용과 부합하는지를 검사하고 경고 메시지를 보내는 역할을 하는 코드 포맷터의 일종이다. 이에 대해 이미 아는 사람이라면 eslint의 spellcheck 플러그인이 무슨 역할을 하는지 납득하기가 더 편할 것이다. 다만 본 포스트는 Node.js에 관한 것이니 Typo에 대한 자세한 설명은 생략하겠다.
맛보기
Node.js 개발 환경에서도 Typo와 비슷한 역할을 하는 친구가 있는데, 바로 eslint의 플러그인인 eslint-plugin-spellcheck이다. 전체 설치 및 적용 방법에 앞서 이게 실제 환경에서 어떤 식으로 적용되는지 가볍게 핥아보도록 하자.
다음은 사용자의 이름, 성, 나이를 생성자 매개변수로 받아 private
으로 저장하고 sayHello
라는 함수로 본인에 대해 소개하는 클래스의 선언문이다.
1 | export class User { |
위 스크립트를 찬찬히 살펴보자. 혹시 문제점이 보이는가?
2가지 있는데 이는 TSC의 문법적 오류가 아닌 앞서 언급했던 영어 오탈자에 해당하는 것이다. lint에 spellcheck 플러그인을 적용한 환경에서 위 문장을 다시 보면 다음과 같이 나온다.
요약하자면 다음과 같다.
- famliy 라는 단어를 찾을 수 없습니다.
- maet 라는 단어를 찾을 수 없습니다.
첫 번째는 famliyName이라는 멤버에서 famliy라는 단어가 잘못되었다는 의미이다. l과 i의 위치가 바뀌어 있는데, 원래 의도대로 family로 고쳐야 한다.
두 번째는 maet인데, meet이라고 적으려다가 실수한 케이스이다.
코드 품질 관리 작업을 사람이 직접 해야 한다고 생각해보자. 매일 하루 8시간씩 모니터앞에 앉아 내가 이기나 컴퓨터가 이기나 눈싸움하며 소스 코드의 글자 하나하나를 일일이 다 확인하는 거다. 퇴직 각 날카롭다.
다행히 이런 건 그 어떤 개발자도 환영하지 않는 요소이다. 이와 같은 문제에 대한 해결책은 조금만 검색해 보면 보통 항상 준비되어 있다.
여담이지만 이 역시 넓게 보면 작성한 코드를 빌드하고 모아서 테스트 하고 서버에 배포되는 수순을 자동화 한 CI/CD 프로세스, 나아가 DevOps 엔지니어링 공법도 이러니 저러니 해도 결국 이러한 개발진들의 귀차니즘을 해결하고자 나온 결과가 아닌가 싶다.
설치 및 적용
먼저 vsc 스크립팅 환경은 평소 사용하는 기본 값에 맞추었다. 각 요소에 대한 설명이 모두 들어가면 포스트가 너무 길어지므로 spellcheck 플러그인의 설치와 적용에 대해서만 적었다. 아래는 환경 정보이다.
- 사용 언어 : TypeScript
- 린터 & 코드 포맷터 : eslint + prettier
- 런타임 : Node v16
- 패키지 관리자 : yarn
다음의 명령어로 플러그인을 프로젝트 의존성 모듈로 설치한다.
1 | yarn add --dev eslint-plugin-spellcheck |
.eslintrc
에 spellcheck
플러그인을, 린터 규칙으로는 spellcheck/spell-checker
항목을 추가한다.
1 | module.exports = { |
이러면 기본적인 설정은 끝이 난다. 여담이지만 규칙 레벨을 error(2)로 빡빡하게 설정하는 분들도 종종 있는데, 맞춤법 검사 정도야 warn(1) 수준이면 충분할 것으로 본다.
규칙 옵션
여타 다른 eslint 플러그인들과 마찬가지로 스펠 체크 플러그인 역시 여러 규칙 설정 옵션들을 제공한다. 다음은 플러그인 소스 저장소 및 NPM 패키지 페이지에서 제공되는 규칙 옵션들이다.
1 | module.exports = { |
여기서 눈 여겨 볼 옵션들이 몇 가지 보인다.
적용 대상
일단 identifiers
옵션은 아주 특별한 상황이 아니면 기본 값인 true
로 두는 게 적합하다.
comments
와 strings
은 정말로 옵셔널한데, 이 부분은 개발자 본인의 취향에 맞춰 선택하면 되겠다. 보통 comments
는 false
로 (주석을 한글로 다는 경우가 많은데 한글은 당연하게도 맞춤법 검사 안 해준다.) strings
는 true
로 설정하는 경우가 많다.
옵션 명 | 타입 | 기본값 | 설명 | 추천 |
---|---|---|---|---|
comments | boolean | true | 주석에 맞춤법 검사 적용 여부 | false |
strings | boolean | true | 문자열에 맞춤법 검사 적용 여부 | true |
identifiers | boolean | true | 식별자(변수명, 클래스 명 등)에 맞춤법 검사 적용 여부 | true |
제외 대상
ignoreRequire
는 문자 그대로 require
문 안에 있는 문자열(모듈 명 혹은 경로 명)을 제외할 것인가에 대한 옵션이다. 기본값이 false
로 되어 있는데, 경험 상 true
로 해주는 편이 정신 건강에 이롭다.
skipWords
는 맞춤법 적용 대상에서 제외 할 항목들이다. 의외로 JS나 TS에서 자주 사용하는 용어들이 맞춤법 검사에 적용되는 경우가 많다. 당장 방금 언급 한 JS
, TS
라는 단어 자체도 검사기에 걸린다. 영어사전에 등재된 항목만 통과한다는 이야기다. 이는 각자 경험에 비추어 검사에서 제외해야 할 단어들을 한 곳에 저장 해 두고 관리하는 것을 추천한다.
skipIfMatch
와 skipWordsIfMatch
두 항목은 모두 정규 표현 식을 사용한다. 기본적으로 어떤 단어/문장 등을 검사 할 때 작성한 정규 표현 식을 만족하는 경우 제외하겠다는 의미인데, skipIfMatch
는 문장 전체에, skilWordsIfMatch
는 단어 별로 적용된다.
minLenth
는 검사를 수행할 단어의 최소 길이를 의미한다. 값을 3
으로 설정하면 1~2글자로 이루어진 단어는 맞춤법 검사에 걸리지 않는다.
옵션 명 | 타입 | 기본값 | 설명 | 추천 |
---|---|---|---|---|
ignoreRequire | boolean | false | require 문 안에 있는 문자열 검사 적용 제외 | true |
skipWords | Array |
[] | 검사에서 제외시킬 단어 목록 | |
skipIfMatch | Array |
[] | 검사에서 제외할 문자열의 정규 표현식 목록 | |
skipWordsIfMatch | Array |
[] | 검사에서 제외할 단어의 정규 표현식 목록 | |
minLenth | number | 1 | 검사를 적용할 최소 단어/문장 길이 | 3 |