-
ruff check와 ruff format은 왜 둘 다 필요할까Programming 2026. 9. 19. 22:16728x90반응형

코드의 형식과 규칙을 서로 다른 관점에서 확인하는 AI 생성 개념 이미지입니다. Ruff에서는 코드 규칙 검사와 포맷 검사를 별도로 실행해 어떤 종류의 수정이 필요한지 구분하세요.
저장할 때 코드 모양이 깔끔해졌는데 CI에서는 Ruff 오류가 남습니다. 반대로
ruff check가 통과했는데ruff format --check는 실패하기도 합니다. 두 명령이 같은 파일을 봐도 질문이 다르기 때문입니다. 하나는 선택한 코드 규칙의 위반을 찾고, 다른 하나는 정해진 배치와 표기 방식으로 정리할 부분이 있는지 봅니다.이 글은 2026년 9월 13일 공식 문서를 기준으로 두 작업을 나누는 방법을 설명합니다. 예시 코드는 진단 차이를 보여 주기 위해 작성했으며 실제 Ruff 실행 결과를 옮긴 것이 아닙니다. 기존 프로젝트를 일괄 수정하거나 자동 실행 설정을 추가하는 작업도 하지 않았습니다.
포맷이 맞는 코드에도 오류가 있을 수 있습니다
ruff check는 linter의 진입점입니다. 활성화한 규칙에 따라 사용하지 않는 import나 정의되지 않은 이름 등 코드의 문제를 찾습니다. 검사 규칙은 설정과 옵션에 따라 달라지므로, “Ruff 통과”라는 말에는 어떤 규칙으로 무엇을 검사했는지가 따라야 합니다. Ruff 규칙 검사ruff format은 formatter입니다. 공백, 줄바꿈, 따옴표 등 코드의 표현을 일정한 스타일로 정리합니다. 기본 실행은 파일을 수정하고,--check를 붙이면 수정하지 않고 포맷 변경 필요 여부를 검사합니다. 포맷이 맞다는 결과는 함수가 의도대로 계산한다는 결과가 아닙니다. Ruff 포맷 명령예를 들어 줄바꿈과 들여쓰기가 완벽해도 존재하지 않는 변수를 반환할 수 있습니다. 반대로 논리적으로 문제가 없는 짧은 함수도 프로젝트의 포맷과 다른 간격으로 작성될 수 있습니다. 이런 차이를 나누면 CI 실패를 보고 어디부터 고쳐야 할지 빨리 결정할 수 있습니다.
두 명령 모두 테스트를 대신하지는 않습니다. 올바른 이름을 썼지만 계산식을 잘못 작성한 함수는 선택한 lint 규칙과 포맷 검사를 모두 통과할 수 있습니다. 그 동작은 별도의 입력과 기대 결과로 확인해야 합니다.
예시 파일에서 세 종류의 문제를 찾아봅니다
다음은 설명용
example.py입니다. 사용하지 않는 표준 라이브러리 import, 정리되지 않은 공백, 함수 매개변수와 다른 이름을 의도적으로 넣었습니다.import math def add_fee(amount): fee=3 return amout+feemath는 이 파일에서 사용하지 않습니다. Ruff의F401은 사용하지 않는 import를 검사하는 규칙입니다.amout는 정의되지 않았고, 이 사례에서는 매개변수amount의 오타라는 의도를 가정했습니다.F821은 정의되지 않은 이름의 사용을 검사합니다. F401, F821반면
fee=3과amout+fee의 간격은 포맷 관점의 문제입니다. formatter가 간격을 정리하더라도amout를 반드시amount로 고쳐 주는 것은 아닙니다. 어떤 값이 의도된 것인지 결정하는 일까지 포맷의 역할로 기대하지 않습니다.이 예시를 주변 설정의 영향 없이 살펴보려면 다음처럼 소스를 수정하지 않는 검사를 나눌 수 있습니다.
ruff check --isolated --select F401,F821 --no-fix example.py ruff format --isolated --check example.py--isolated는 설정 파일을 무시하는 옵션입니다. 여기서는 두 규칙과 포맷의 차이를 설명하기 위해 사용합니다. 실제 프로젝트 CI에서도 무조건 붙이라는 뜻은 아닙니다. 프로젝트가 합의한 규칙을 확인할 때는 그 설정이 적용되어야 합니다. 설정과 명령 옵션예상할 관계는 분명합니다. 첫 명령은 import와 이름 사용을, 둘째 명령은 포맷 필요 여부를 확인하는 용도입니다. 실제 출력 문구와 진단 범위는 도구 버전과 설정에서 확인하며, 이 글에는 실행하지 않은 터미널 결과를 넣지 않았습니다.
자동 수정으로 해결되는 것과 직접 결정할 것을 나눕니다
예시 파일을 수정해도 되는 작업 환경이라면 먼저 변경 전 상태를 확인합니다. 다른 사람이 수정한 내용이 섞여 있지 않은지, 이번 작업 범위가 이 파일인지 보는 단계입니다. 그다음 수정 가능한 lint 항목부터 적용할 수 있습니다.
ruff check --isolated --select F401,F821 --fix example.py이 예시의 사용하지 않는
mathimport는 제거할 수 있는 대상입니다. 그러나 반환식의 의도까지 자동으로 결정됐다고 생각해서는 안 됩니다. “수정한 항목 있음”과 “남은 진단 없음”은 다른 결과입니다. Ruff의--fix가 일부 문제를 고쳤어도 남은 문제가 있으면 이어서 확인해야 합니다. 자동 수정의 범위작성 의도가 입력 금액에 3을 더하는 것이라면
amout를amount로 고친 뒤 포맷을 적용합니다. 직접 판단한 의미 수정과 도구가 한 배치 수정을 Git diff에서 구분해 읽습니다.ruff format --isolated example.py git diff -- example.py아래는 그 의도에 맞춘 수정안입니다. formatter의 실제 출력 캡처가 아니라 최종 코드의 의미를 보여 주는 예시입니다.
def add_fee(amount): fee = 3 return amount + fee이 함수가 업무 규칙에 맞는지는 별도 확인이 필요합니다. 음수 금액을 허용하는지, 고정 수수료가 맞는지, 숫자가 아닌 입력은 어떻게 다룰지까지 lint가 정해 주지는 않습니다. 예제의 오타를 고쳤다는 사실과 실제 기능이 완성됐다는 사실을 구분합니다.
safe fix라도 변경 내용은 읽습니다
Ruff는 수정의 안전성을 safe와 unsafe로 구분합니다. 기본적으로 safe fix를 적용하며, unsafe fix는 동작이나 주석 등에 영향을 줄 수 있어 별도 선택이 필요합니다. 이 분류는 유용하지만 프로젝트의 모든 사용 맥락을 검증하는 테스트 결과는 아닙니다. 수정 안전성 분류
특히 사용하지 않는 import처럼 보여도 공개 인터페이스를 다시 내보내는 용도일 수 있습니다. F401 문서는 재내보내기 의도를 명시하는 방법과
__init__.py에서의 수정 주의를 따로 설명합니다. 예시의 단순한math제거를 모든 import 삭제에 그대로 일반화하지 않습니다. F401의 재내보내기·수정 조건기존 프로젝트에서는 자동 수정 안전성 분류를 바꾸는 설정이 있는지도 확인합니다. 진단을 빨리 없애기 위해 unsafe 옵션을 한꺼번에 켜기보다, 어떤 변경이 필요한지와 관련 테스트가 있는지를 먼저 보는 편이 좋습니다.
완료 판단에는 수정 후 diff와 다시 실행한 검사 결과가 함께 필요합니다. 도구가 파일을 바꿨다는 사실만 기록하면 의미가 달라진 부분을 놓칠 수 있습니다.
import 정렬도 formatter가 모두 맡지는 않습니다
Ruff formatter는 import 정렬을 수행하지 않습니다. import 순서를 정리하려면 관련 lint 규칙인
I계열 등을 선택해 처리하는 흐름을 검토합니다. lint 수정 다음에 format을 적용하는 순서가 공식 문서에 제시돼 있습니다. import 정렬의 담당 명령따라서 “포맷했으니 import 순서도 맞을 것”이라고 판단하지 않습니다. 반대로 formatter와 충돌하는 스타일 규칙이나 설정을 켜 두면 두 도구가 같은 코드를 서로 다른 방향으로 요구할 수 있습니다. 그런 경고가 있다면 formatter 문서의 호환되지 않는 규칙·설정 목록과 현재 설정을 대조합니다.
이 문제를 해결한다고 모든 규칙을 끄거나 무조건 모든 규칙을 켤 필요는 없습니다. 프로젝트가 유지할 규칙을 고르고, 형식 정리를 누가 맡는지 정하면 됩니다. 규칙 변경 자체와 그에 따른 대량 코드 수정을 분리하면 리뷰도 쉬워집니다.
CI에서는 검사를 위해 소스를 바꾸지 않습니다
로컬에서는 수정과 검사를 반복할 수 있지만, CI의 검증 단계에서는 제출된 코드가 기준을 만족하는지 확인하는 편이 명확합니다. 대상과 설정을 프로젝트에 맞춘 뒤 다음 두 종류의 검사를 각각 실행합니다.
ruff check --no-fix --no-fix-only . ruff format --check .위 명령은 파일 자동 수정 없이 진단과 포맷 필요 여부를 확인하려는 예시입니다. 프로젝트의 규칙·제외 설정은 적용됩니다. CI 실행기가 첫 실패 뒤 다음 단계를 생략할 수 있으므로, 두 검사 결과를 모두 수집할지와 어느 실패로 작업을 멈출지는 CI 구성에서 정합니다.
ruff format --check의 종료 코드 1은 포맷할 파일이 있다는 뜻이고, 2는 잘못된 옵션·설정이나 내부 오류 같은 비정상 종료를 뜻합니다. 둘을 같은 “코드 포맷 오류”로 뭉뚱그리면 설정 문제를 코드 수정으로 해결하려 할 수 있습니다. formatter 종료 코드로컬에서는 통과하고 CI에서만 다르면 Ruff 버전, 실행 디렉터리, 적용 설정, 검사 파일 범위를 비교합니다. 같은 도구 이름만으로 같은 검사를 했다고 판단하지 않습니다. 예시의
--isolated검사와 프로젝트 설정을 쓰는 CI 결과가 다른 것도 그 구분 안에 들어갑니다.두 검사가 통과한 뒤에도 남는 확인
최종 흐름은 진단을 읽고, 허용한 수정만 적용하고, 포맷한 뒤 diff와 테스트를 확인하는 순서입니다. 그다음 lint와 포맷 검사를 다시 실행해 남은 문제가 없는지 봅니다. 타입 관계나 실제 동작을 다루는 검사는 필요한 범위에서 별도로 유지합니다.
Ruff의 두 명령은 코드 규칙과 코드 배치라는 서로 다른 질문에 답합니다. 실패한 명령, 규칙 또는 파일, 변경한 내용, 다시 확인한 결과를 구분해 남기면 통과 표시가 무엇을 의미하는지도 분명해집니다.
728x90반응형'Programming' 카테고리의 다른 글
curl은 되는데 브라우저만 CORS 오류가 나는 이유 (0) 2026.09.20 UPDATE 전후 값을 한 번에 받고 싶다면: PostgreSQL 18 RETURNING (0) 2026.09.20 Cloudflare Workflows 실행 기록, 왜 예전보다 빨리 없어질까 (0) 2026.09.19 Cloudflare D1이 갑자기 오류를 내는 날: 무료 한도와 스캔 행 수 (1) 2026.09.19 npm 로그인은 되는데 배포가 막혔다면: 복구 코드 사용 뒤 확인할 것 (0) 2026.09.19