린터

Linter

도구

코드를 실행하지 않고 훑어, 문법은 맞지만 사고로 이어지기 쉬운 자리를 저장하는 순간에 짚어 주는 도구입니다.

등장 배경

문법이 틀린 코드는 돌아가지 않으니 금방 드러납니다. 문제는 문법은 맞는데 의도와 어긋난 코드입니다. 비교하려고 쓴 자리에 값을 넣어 버린 한 글자, 선언만 해 놓고 아무도 쓰지 않는 변수, 실패했을 때 무슨 일이 벌어질지 아무도 적어 두지 않은 호출 같은 것들입니다. 기계는 이런 코드를 아무 불평 없이 실행합니다.

그래서 이 일은 오랫동안 사람의 눈이 맡았습니다. 코드 리뷰에서 동료가 읽다가 발견하는 식입니다. 코드 리뷰는 합치기 전에 다른 사람이 변경 내용을 읽어 보는 절차인데, 여기에는 두 가지 손해가 따라붙었습니다. 하나는 시점입니다. 태오가 화요일에 쓴 코드를 목요일에 누가 읽고 지적하면, 태오는 이틀 전의 맥락을 다시 꺼내야 합니다. 다른 하나는 내용입니다. 설계를 이야기해야 할 자리에서 "여기 변수 안 쓰네요" 같은 말이 절반을 차지하면 정작 중요한 이야기를 할 시간이 남지 않습니다.

같은 지적이 사람마다 다르게 나온다는 문제도 있었습니다. 어떤 리뷰어는 짚고 어떤 리뷰어는 넘어가니 기준이 코드베이스 안에서 갈렸습니다. 린터는 이 판정을 기계에 맡기려고 만든 도구입니다. 기준을 파일로 적어 두고 모두가 같은 기준을 받게 한 것입니다.

해결하는 문제

린터가 잡는 것은 크게 네 갈래입니다.

  1. 쓰이지 않는 것. 선언해 놓고 쓰지 않는 변수, 아무 데서도 부르지 않는 함수, 가져다 놓기만 한 외부 코드입니다. 그 자체로 고장은 아니지만 읽는 사람을 헷갈리게 하고, 지워야 할 코드가 남아 있다는 신호인 경우가 많습니다.
  2. 실수하기 쉬운 문법. 두 값을 비교해야 하는 자리에 대입을 써 버린 경우가 대표적입니다. 언어에 따라 이 코드는 오류 없이 돌아가면서 항상 참이 되어, 조건문 하나가 통째로 무력해집니다.
  3. 위험한 습관. 실패할 수 있는 호출의 결과를 확인하지 않고 지나가거나, 오류를 잡아 놓고 아무것도 하지 않고 삼켜 버리는 코드입니다. 문제가 생겨도 조용히 넘어가기 때문에 나중에 원인을 찾기 가장 어려운 종류입니다.
  4. 팀이 정한 규칙. 날짜를 다룰 때 쓰기로 한 함수만 쓰게 한다거나, 특정 폴더에서는 다른 폴더의 파일을 직접 가져오지 못하게 막는 식입니다. 언어의 문제가 아니라 이 팀에서만 통하는 약속이라, 규칙을 직접 적어 넣습니다.

쓰는 방법은 세 자리에 걸어 두는 것입니다. 편집기에 붙여 두면 코드를 쓰는 동안 문제가 되는 줄에 바로 표시가 뜹니다. 합치기 전에 올리는 풀 리퀘스트에 걸어 두면 리뷰어가 읽기 전에 결과가 붙습니다. 마지막으로 지속적 통합에 걸어 두면 규칙을 어긴 코드가 아예 합쳐지지 않습니다. 지속적 통합은 변경을 자주 합치면서 매번 자동으로 검사를 돌리는 방식입니다.

규칙마다 오류와 경고를 나눠 다는 것이 보통입니다. 오류는 통과를 막고 경고는 알려만 줍니다. 새 규칙을 켤 때는 먼저 경고로 두고 기존 코드를 정리한 뒤 오류로 올리는 순서를 밟습니다. 한 번에 오류로 켜면 무관한 파일 수백 개가 같이 빨개져서, 정작 지금 고치는 코드가 묻힙니다.

대안

린터 없이 같은 문제를 다루는 방법이 몇 가지 있고, 각각 다루는 범위가 다릅니다.

  1. 언어의 타입 시스템. 타입스크립트처럼 값의 종류를 미리 적게 하는 언어는 숫자가 들어와야 할 자리에 글자가 들어오는 종류의 사고를 애초에 막습니다. 린터가 관습을 보는 것과 달리 이쪽은 값의 흐름을 봅니다. 다만 타입이 맞아도 안 쓰는 변수나 삼켜 버린 오류는 그대로 남습니다.
  2. 정적 분석. 파일 하나를 넘어 함수와 파일 사이를 타고 다니며 더 넓은 문제를 찾습니다. 잡아내는 범위가 넓은 대신 돌리는 시간이 길고 사실이 아닌 지적도 함께 늘어납니다. 저장할 때마다 돌리기는 어렵고 하루 한 번이나 합치기 전에 돌립니다.
  3. 팀 규칙 문서. 하지 말아야 할 것을 문서로 적어 둡니다. 새로 온 사람이 읽을 것이 생기지만, 문서는 지켜지는지를 확인해 주지 않습니다.
  4. 사람의 리뷰. 판단이 필요한 문제는 결국 사람만 잡습니다. 이 함수를 여기에 두는 것이 맞는지, 이름이 하는 일을 제대로 가리키는지는 규칙으로 적을 수 없습니다.

넷은 서로를 대신하지 않고 층을 이룹니다. 기계가 규칙으로 적을 수 있는 것을 먼저 걷어 내면, 사람의 리뷰에는 사람만 판단할 수 있는 것이 남습니다.

실무 용례

"린트에서 막혔어요. 안 쓰는 변수 하나 남겨 뒀네요."

규칙 위반으로 검사가 실패했고 원인은 이미 안다는 보고입니다.

"이 규칙은 우리 팀에 안 맞는 것 같은데 꺼도 될까요?"

규칙 하나를 두고 팀 전체의 기준을 바꾸자는 제안이라 혼자 결정하지 않는다는 뜻입니다.

"그건 린터가 잡아 줄 테니 리뷰에서는 구조만 봅시다."

기계가 볼 수 있는 것에 리뷰 시간을 쓰지 말자는 말입니다.

페이지덱에서 린터가 화제에 오르는 때는 대개 규칙을 새로 켜거나 끌 때입니다. 태오가 같은 실수를 세 번째 발견하고 그것을 막는 규칙을 찾아 제안하면, 팀은 그 규칙이 기존 코드에서 몇 군데를 걸리게 하는지부터 세어 봅니다. 열 군데면 그 자리에서 고치고 오류로 켜지만, 삼백 군데면 우선 경고로 켜 두고 코드 스멜이 있는 파일을 손볼 때마다 함께 정리합니다.

반대로 규칙을 끄자는 제안도 나옵니다. 걸릴 때마다 예외 표시를 달고 지나가는 규칙은 아무것도 막지 못하면서 잡음만 만듭니다.

흔한 오해

린트를 통과했으니 코드가 괜찮다고 읽는 경우가 가장 많습니다. 검사를 통과했다는 초록 표시가 품질 판정처럼 보이니 그렇게 읽기 쉽습니다. 하지만 린터가 보는 것은 규칙 목록에 적힌 항목뿐입니다. 화면에 잘못된 금액을 띄우는 코드, 다른 사람의 데이터를 보여 주는 코드도 규칙만 지키면 조용히 통과합니다. 통과를 품질로 읽기 시작하면 팀은 테스트와 리뷰에 쏟던 힘을 줄이고, 정작 기계가 못 보는 종류의 사고가 늘어납니다.

규칙은 많을수록 좋다고 보는 것도 흔한 오해입니다. 경고가 늘면 그만큼 많이 잡아 준다고 느끼기 때문입니다. 실제로는 반대로 흘러갑니다. 경고가 천 개를 넘는 순간 아무도 목록을 열지 않고, 그 안에 섞여 있던 진짜 문제까지 같이 묻힙니다. 규칙은 켤 때가 아니라 위반을 0으로 만들고 오류로 올릴 때 비로소 일을 시작합니다.

자주 헷갈리는 용어

용어무엇을 보는가린터와의 차이
포매터줄바꿈, 들여쓰기, 따옴표 같은 겉모양모양만 보고 의미는 건드리지 않습니다. 그래서 고칠지 묻지 않고 그냥 고칩니다. 린터는 의미가 걸린 문제를 다루므로 대부분 사람이 판단해야 합니다
정적 분석파일과 함수를 가로지르는 값의 흐름보는 범위가 넓고 돌리는 시간이 깁니다. 린터는 대체로 파일 하나 안에서 판단해 저장하는 순간 결과가 나옵니다

같이 보면 좋은 페이지

  • 코드 품질

    린터가 어떤 활동과 원칙 사이에 놓인 도구인지 전체 지형을 봅니다

  • 포매터

    거의 항상 같이 걸어 두는 도구라 둘의 역할 분담을 함께 알아 두면 좋습니다

마지막 업데이트 2026-09-16