JavaScript/TypeScript 진영 많은 개발자들이 eslint
를 이용합니다. eslint 는 강력한 규칙들과 확장 가능한 아키텍처를 가지고 있으며 이 덕분에 현재 자바스크립트 진영에서 필수급으로 여겨지는 라이브러리들 중 하나입니다.
개발을 하다 보면 많은 eslint 오류를 마주치는데요, 이런 오류를 마주쳤을 때 개발자들이 공통적으로 하는 실수가 있습니다.
// eslint-disable-next-line
하지만 개인적으로는 eslint-disable
은 정말정말 바보같은 기능이고, 이용하지 말아야 한다고 생각합니다.
린터는 정적 코드 분석 도구입니다. 코드를 읽은 다음, 미리 지정된 규칙에 맞지 않을 경우 코드상에 오류를 표시해줍니다.
여기서 미리 지정된 규칙이란, 팀원들과 합의된 "if문은 항상 중괄호로 감싸자" 와 같은 컨벤션일 수도 있고, 위 사진과 같이 버그를 발생시킬 수 있는 안티패턴에 대한 경고일 수도 있습니다.
린터를 이용하면 코드를 수행해보거나 코드 리뷰를 받거나 유저가 버그를 만나기 전에, 에디터에서 바로 문제를 확인하고 해결해야 한다는 걸 인지할 수 있습니다. 프로그래밍에서 모든 문제는 놔두면 점점 커지기 때문에, 에디터에서 바로 문제를 확인하고 바로 고칠 수 있다는 장점이 있습니다.
이렇게 eslint 는 지켜야 하는 규칙들을 알려주고 규칙을 지키지 않았을 때 다양한 방식으로 "너 여기 틀렸어!" 라고 소리쳐주는 좋은 도구입니다. 그리고 이런 eslint 가 들고 있는 규칙들은 린트를 이용하는 개발자들이 직접 설정한 것들입니다.
이 글의 핵심과도 같은 내용이기에 강조합니다. eslint 는 누가 강요하지도 않았고, 원래부터 있지도 않은 - 개발자들이 더 나은 코드를 구현하고자 스스로의 의지로 직접 설정한 것입니다.
eslint 는 특정 라인 / 파일에 대해 규칙을 disable하는 기능을 제공합니다.
// eslint-disable-next-line
이라는 주석을 달면 다음 줄에 대해 린트 오류가 울리지 않습니다. 또한 파일 첫 줄에 /* eslint-disable */
이라는 주석을 달면 해당 파일에 대해 통째로 eslint 가 꺼집니다. 특정 규칙에 대해서만 설정할 수도 있습니다. // eslint-disable-next-line react-hooks/exhaustive-deps
라고 주석을 달면 react-hooks/exhaustive-deps 라는 규칙만 검사하지 않습니다.
어떤 상황에 eslint-disable을 활용할 수 있을까요? 결론부터 말하자면, 모든 경우에 eslint-disable 은 좋은 선택지가 아닙니다.
no-nested-ternary
규칙은 a ? a : b ? b : c
와 같은 코드를 썼을 때 오류를 발생시킵니다. 하지만 이를 보며 "왜? 난 삼항연산자 좋은데?" 라고 생각할 수도 있습니다. 실제로 삼항연산자는 강력한 기능입니다.
앞에서, eslint 는 개발자가 스스로의 의지로 설정한 것이라고 했습니다. 하지만 가령 보일러플레이트 코드가 eslint 규칙들을 포함하고 있었다거나, airbnb
규칙이 유명하다길래 설치해서 적용해봤다거나 하는 상황이라면 오류 내용에 공감이 되지 않을 수 있습니다. 이럴 때 개발자들은 귀찮아하며 규칙을 disable하곤 합니다. 하지만 이는 왜 있는지도 모를 함정에 스스로를 빠트린 다음 다시 함정에서 탈출하는 것입니다.
두 가지 해결 방법이 있습니다.
@typescript-eslint/no-non-null-assertion
의 경우 깃헙 레포에서 해당 규칙이 존재하는 이유에 대해 설명합니다: no-non-null-assertion.md. 설명을 읽고, 필요성에 공감하게 될 수도 있습니다.@typescript-eslint/no-non-null-assertion
이나 react-hooks/exhaustive-deps
처럼 진짜 필요한 규칙을 꺼버리게 될 수도 있으니 주의해야 합니다.eslint 가 알려주는 내용에 개발자가 공감한다면 좋은 코드를 편하게 짤 수 있는 훌륭한 가이드이지만, 그렇지 않다면 코딩에 방해가 되는 거추장스러운 모래주머니일 뿐입니다. 공감되지 않는 규칙을 굳이 설정해두고 굳이 발목잡혀서 굳이 스트레스받을 필요는 없습니다.
import-sorts
와 같이 import 문의 순서만 변경하면 해결되는 간단한 규칙들도 있는 반면, 앞에서 봤던 exhaustive-deps
와 같이 해결하기 위해 의존성 배열을 수정하면 로직이 꼬여버리는 복잡한 규칙들도 있습니다. 이런 경우에 린트 규칙을 끄기 위해 규칙을 disable하기도 합니다.
이런 경우는 주로 구조를 잘못 잡았거나 코드에 미숙할 때 발생합니다. 역시 두 가지 정도의 해결 방법이 있습니다.
린터 경고는 매우 요란해서 해당 줄뿐 아니라 파일 시스템을 타고 폴더 구조까지 모두 노랗게/빨갛게 물들입니다.
특히 이와 같은 경우에 eslint-disable 처리하는 건 정말 위험한데, 린터가 경고하는 코드는 요란하기 때문에 개발자가 주목할 수라도 있는 반면 주석이 달려 있는 코드는 조용하기 때문에 놓치기 쉽습니다.
그리고 이렇게 조용히 터진 버그는 나중에 어떤 결과를 초래할지 모르는 일입니다. 회사나 유저에게 막대한 피해를 입힐 수도 있습니다.
이 경우 역시 disable 처리하는 것보단 그대로 두는 게 좋습니다. 노랗게 경고가 올라오는 상황이라면, 나중에 여유가 있을 때 해당 코드를 발견하고 고칠 수 있습니다. 하지만 // eslint-disable
이라는 주석만 달려 있는 상황이라면 잘못된 코드가 있다는 걸 인지하기 어렵습니다.
내용을 조금 추가하자면, 사실 발견했을 때 바로 고치는 게 결국 시간도 가장 절약하고 고통도 가장 적게 받는 길입니다. 당장 1분 안에 제출해야 하는 채용과제나 외주 프로젝트를 수행하고 있는 게 아니라면요.
린터는 훌륭한 도구입니다. 자동으로 컨벤션을 잡아주고, 코드를 정리해주고, 버그를 만나지 않게 도와줍니다.
하지만 간혹 린터를 별 생각 없이 이용하다 보면 불필요한 규칙 때문에 스스로 고통받는 상황이 오기도 합니다. 스스로를 함정에 빠트리는 꼴입니다.
린트 규칙은 필요하다면 설정하고, 불필요하다면 꺼야 합니다. 린트 규칙을 능동적으로 설정해야 합니다. 그리고 거의 모든 상황에서 eslint-disable
은 문제를 덮어버리는 나쁜 해결책일 것입니다.
글을 작성하는 데 많은 영감을 받았던 Dan Abramov 의 Writing Resilient Components 글을 언급하며 마칩니다 :)
공감이 되네요. eslint의 몇가지 설정에 대해서 공감이 되지 않을 때에는 주위에 eslint 옵션에 대해서 다같이 on/off 에 대한 혹은 특정 옵션의 선호도를 많이 물어보곤 했던게 기억이 납니다. 생각보다 사람들마다 생각이 달랐고 몇몇은 공감이 되어서 받아들이기도 했고 몇몇은 모래주머니가 맞구나 했던 기억이 납니다. 혼자서만 고민을 하면 결국 돌고돌아 자기확신만 강해지던데 이런 얘기들을 주제로 함께 다같이 이야기해보는 것도 좋을 것 같아요. 이 글을 보신 분들은 한번 동료분들과 이런 주제 얘기를 해보는 것도 좋을 것 같아요! 좋은 글 감사합니다 :)