top of page

Simon Willison, Ruff v0.16.0로 CI 실패를 겪다. 기본값이 바뀌었다

Simon Willison은 Ruff v0.16.0가 기본 린트 규칙을 59개에서 413개로 확대한 뒤 여러 CI 작업이 실패하는 상황을 겪었다. 버전이 고정되지 않은 Ruff 개발 의존성이 기존 Python 프로젝트에 새 릴리스를 조용히 가져온 것이다.

Astral은 2026년 7월 23일 이 버전을 출시했다. 이틀 뒤 Willison은 의도적으로 업그레이드하지 않았는데도 이 업데이트가 자신의 빌드에 적용된 과정을 설명했다. 이 실패 사례는 린터 릴리스를 의존성 관리에 대한 실질적인 경고로 바꿔 놓았다.

핵심 충돌은 더 엄격한 린팅과 더 약한 코드 사이의 문제가 아니다. 구성 없이도 안전성을 높이려는 Ruff의 방향과, 변경되지 않은 저장소에서 개발자가 기대하는 안정성의 충돌이다. CI가 매 실행마다 최신 개발 도구를 설치하는 곳이라면 어디서나 이 긴장은 중요하다.

Ruff v0.16.0가 “기본값”의 의미를 바꿨다

Ruff v0.16.0에서 가장 중요한 변화는 새 명령어가 아니다. 구성되지 않은 프로젝트가 오류로 간주해야 할 범위를 훨씬 넓게 정의했다는 점이다.

Ruff는 Rust로 작성된 Python 린터이자 포매터다. 린터는 프로그램을 실행하지 않고도 소스 코드의 실수, 의심스러운 패턴, 그리고 일부 스타일 문제를 분석한다.

이번 릴리스 전에는 프로젝트가 명시적인 린트 선택을 제공하지 않을 경우 Ruff가 59개 규칙을 활성화했다. Astral의 마이그레이션 가이드에 따르면 버전 0.16.0은 같은 조건에서 413개 규칙을 활성화한다.

활성 검사 항목이 354개 늘어난 셈이다. 이제 기본 Ruff 설치는 이전보다 거의 7배 많은 규칙을 평가한다는 뜻이기도 하다.

규칙 카탈로그 자체도 커졌다. Ruff의 기본값이 마지막으로 변경된 버전 0.1.0 당시에는 708개 규칙을 지원했다. Astral은 현재 컬렉션이 968개 규칙을 포함한다고 밝혔다.

기존 기본값은 주로 Pyflakes와 pycodestyle의 일부를 선택했다. 프로젝트는 Ruff가 통합한 많은 규칙군에 대해 즉시 세부 결정을 내리지 않고도 이를 도입할 수 있었다.

이 보수적인 기준선은 Ruff가 기존 저장소에 잘 녹아들도록 도왔다. 동시에 도구가 알고 있는 내용과 자동으로 보고하는 내용 사이의 격차를 점점 더 벌어지게 했다.

Astral은 버전 0.16.0에서 그 격차의 상당 부분을 줄였다. 새 기본값은 flake8-bugbear, pyupgrade, 그리고 Ruff 자체의 RUF 카테고리를 포함한 추가 규칙군에서 가져온다.

Flake8-bugbear는 발생 가능성이 높은 버그와 의문스러운 설계 패턴에 집중한다. Pyupgrade는 프로젝트가 지원하는 Python 버전에 맞춰 현대화할 수 있는 문법과 표준 라이브러리 패턴을 식별한다.

이제 기본 규칙 목록에는 문법 문제와 즉시 발생할 수 있는 런타임 오류를 드러낼 수 있는 검사가 포함된다. 이는 단순히 공백이나 명명에 대한 선호의 문제가 아니다.

이 차이는 Ruff CI 실패가 주목할 만한 이유를 설명한다. 일부 새 보고는 Ruff가 관련 탐지기를 자동으로 활성화하지 않았기 때문에 이전에는 통과했던 결함을 드러낸다.

다른 보고는 유지보수성, 현대화 또는 팀이 의도적으로 허용하는 패턴에 관한 것일 수 있다. 더 큰 기본 규칙 집합이 모든 저장소의 호환성 요구사항이나 설계 관례를 알 수는 없다.

따라서 Ruff v0.16.0는 동시에 두 가지를 바꾼다. 자동 결함 탐지를 늘리고, 7월 23일 이후 첫 업그레이드에서 더 많은 정책 결정을 요구한다.

이 릴리스는 또한 기본적으로 Markdown 파일 내부의 Python 코드 블록을 Ruff로 포맷한다. 지원되는 fenced block에는 python, py, python3, py3, pyi, pycon이 포함된다.

이 동작은 문서, 튜토리얼 또는 Quarto 노트북을 포함하는 저장소에 중요하다. 이제 포맷 검사에서 일반적인 .py 파일 밖의 변경 사항도 식별할 수 있다.

Ruff의 릴리스 노트는 새 억제 주석과 더 풍부한 진단 출력도 설명한다. 이러한 개선은 추가 발견 사항이 나타난 뒤 개발자가 이를 처리하는 데 도움이 된다.

범위 변경은 여전히 주요 마이그레이션 이벤트다. 지난주에는 예측 가능하게 동작하던 명령어가, 동일한 소스 코드에 대해 오늘은 0이 아닌 종료 코드를 반환할 수 있다.

Simon Willison의 CI 실패가 중요한 이유

Simon Willison의 경험은 개발 도구 업데이트가 저장소 자체를 바꾸지 않고도 저장소의 실질적인 정책을 바꿀 수 있음을 보여준다.

Willison은 Python, 데이터 도구, 생성형 AI 관련 프로젝트로 알려진 독립 개발자이자 작가다. 그는 경력 초기에 Django 웹 프레임워크를 공동 제작하기도 했다.

7월 25일 Willison은 자신의 “여러 CI 작업”이 실패하기 시작했다고 썼다. 그는 실패 원인을 새 Ruff 기본값과 버전이 고정되지 않은 "ruff" 개발 의존성으로 추적했다.

그의 Ruff 관련 기록은 이 릴리스에 대한 구체적인 사용자 관점을 제공한다. 저장소 코드는 반드시 퇴행한 것이 아니었지만, 그 아래의 검증 환경이 바뀌었다.

CI 작업, 즉 지속적 통합 작업은 개발자가 변경을 제안하거나 병합할 때마다 자동 검사를 실행한다. 팀은 코드가 받아들여도 안전한지 판단하기 위해 일관된 결과에 의존한다.

작업이 버전 제약 없이 ruff를 설치하면 패키지 해결기는 가장 최신의 사용 가능한 릴리스를 선택할 수 있다. 다음 빌드는 어떤 유지보수자도 명시적으로 검토하지 않은 동작을 강제할 수 있다.

Ruff는 대개 개발 의존성이므로 이 실패 방식은 가볍게 여겨지기 쉽다. 일반적으로 사용자에게 서비스를 제공하는 애플리케이션 안에 포함되어 배포되지는 않는다.

하지만 개발 의존성은 소프트웨어가 배포 파이프라인을 통과할 수 있는지를 좌우한다. 새 린터 종료 코드는 pull request를 막고, 릴리스를 중단시키며, 수 시간의 조사 작업을 유발할 수 있다.

이 사례는 런타임 의존성과 도구 사이의 오해하기 쉬운 구분도 드러낸다. 런타임 패키지는 배포된 소프트웨어의 동작에 영향을 주고, 도구는 개발자가 이를 배포할 수 있는지에 영향을 준다.

둘 다 운영상 변화를 일으킬 수 있다. 다만 시스템 내에서 작동하는 지점이 다를 뿐이다.

Willison의 경험이 특히 유용한 이유는 Ruff의 확장된 규칙이 출시된 대로 작동하고 있었기 때문이다. 실패가 발생하는 데 손상된 패키지, 침해된 레지스트리 또는 결함 있는 설치 프로그램은 필요하지 않았다.

도구는 성공적으로 설치됐다. 새 정책에 따라 프로젝트를 올바르게 검사했다. CI가 실패한 이유는 그 정책이 저장소가 암묵적으로 의존해 온 정책과 달랐기 때문이다.

이는 재현성 문제다. 재현 가능한 빌드나 검사는 같은 소스와 선언된 입력값으로부터 동등한 결과를 만들어야 한다.

“최신 Ruff”는 안정적인 입력값이 아니다. 이는 패키지 관리자가 언제 해결하는지에 따라 의미가 달라지는 이동하는 요청이다.

락파일과 정확한 버전 제약은 이 입력값을 명시적으로 만들 수 있다. 이후 의존성 업데이트 서비스는 통제된 업그레이드를 제안할 수 있어, 유지보수자가 버전 변경을 병합하기 전에 새 진단을 검토할 수 있다.

교훈은 Ruff를 넘어선다. 포매터, 타입 검사기, 테스트 실행기, 문서 빌더, 보안 스캐너 모두 릴리스 사이에 기본값을 수정할 수 있다.

애플리케이션 라이브러리는 고정했지만 개발 도구는 변동 상태로 둔 저장소는 부분적으로만 재현 가능하다. 프로덕션 동작은 고정돼도 프로덕션으로 가는 경로는 바뀔 수 있다.

이 문제는 자동화된 코딩 시스템에서 특히 중요하다. 에이전트는 종종 저장소 검사를 실행하고 그 출력을 해석한 뒤, 모든 게이트를 통과할 때까지 코드를 수정한다.

그 게이트 뒤의 도구가 예기치 않게 바뀌면 에이전트는 움직이는 목표를 마주한다. 왜 발견 사항이 나타났는지 이해하지 못한 채 불필요한 수정이나 억제를 생성할 수 있다.

검색 가능한 엔지니어링 지식 기반을 구축하는 팀은 구성 및 CI 이력과 함께 업그레이드 결정을 보존할 수 있다. 이 맥락은 미래의 유지보수자가 의도적인 정책과 우연한 드리프트를 구분하는 데 도움이 된다.

Simon Willison이 드러낸 Ruff의 새로운 트레이드오프

Ruff의 더 넓어진 기본값은 첫 실행에서의 적용 범위를 개선하지만, 구성을 생략한 것을 안정적인 계약으로 여긴 프로젝트에 마이그레이션 작업을 전가한다.

Astral의 입장은 명확하다. Ruff는 수백 개의 검사를 축적했지만 기본 선택은 그대로 유지되어, 구성하지 않은 사용자의 경우 중요한 진단이 비활성 상태로 남았다.

기존 선택은 Ruff v0.1.0까지 거슬러 올라간다. 이후 규칙 카탈로그는 708개에서 968개로 260개 늘었다.

59개 검사만 활성화한 상태를 유지한다는 것은 Ruff의 구성 없는 사용 경험이 그 역량 중 점점 더 작은 부분만을 대표한다는 뜻이었다. 새 사용자는 기본값이 실제보다 더 포괄적이라고 생각할 수 있었다.

이번 릴리스는 이 불일치를 해결한다. 개발자는 수백 개의 규칙 코드를 먼저 공부하지 않아도 문법 오류, 런타임 위험, 현대화 기회, 의심스러운 구문을 발견할 수 있다.

이는 소규모 프로젝트에 가치가 있다. 유지보수자가 세부 린팅 정책을 수립하기 전 합리적인 적용 범위를 원하는 새 저장소에도 도움이 된다.

반대되는 기대 역시 충분히 합리적이다. 특히 문서에서 도구를 구성 없이 사용할 수 있다고 소개할 때 기본값은 흔히 제품 동작으로 간주된다.

lint.select를 생략한 개발자는 Ruff가 유지하는 기준선을 선택한다고 믿을 수 있다. 버전 0.16.0 이전에는 그 기준선이 업그레이드 전반에 걸쳐 안정적으로 유지될 것이라는 기대에도 의존하고 있었다.

Astral은 그대로 두는 것에도 비용이 따랐기 때문에 기준선을 바꿨다. 설치된 바이너리가 이미 탐지할 수 있는 오류를 포함한 프로젝트가 Ruff를 통과할 수 있었다.

따라서 이 트레이드오프는 안전성과 편의성의 대립이 아니다. 더 폭넓은 자동 보호와 업그레이드 예측 가능성의 대립이다.

더 좁은 기본값은 업그레이드 중의 놀라움을 줄이지만 새 사용자에게 더 많은 발견 사항을 숨긴다. 더 넓은 기본값은 더 많은 결함을 드러내지만 기존 파이프라인을 방해할 수 있다.

Ruff v0.16.0는 다음 실행을 위한 더 강한 보호를 선택한다. 이전 계약을 원하는 프로젝트는 이제 그 선호를 명시적으로 기록해야 한다.

Astral은 직접적인 호환성 구성을 제공한다:

구성이 독립형 ruff.toml에 있을 경우 정확한 표는 달라질 수 있다. 중요한 결정은 파일명이 아니라 명시적인 규칙 선택이다.

이 설정은 이전 기본 규칙군을 복원한다. 팀이 버전 0.15에 무기한 고정되지 않고도 숨을 돌릴 여지를 제공한다.

하지만 이전 동작을 복원하는 일은 모든 새 검사를 자동으로 거부하는 것이 아니라 마이그레이션 단계가 되어야 한다. 일부 실패는 즉시 수정할 가치가 있는 버그를 식별할 수 있다.

신중한 업그레이드는 전체 진단 출력을 캡처하는 것에서 시작한다. 이후 유지보수자는 규칙 코드, 심각도, 수정 안전성, 호환성 영향별로 발견 사항을 그룹화할 수 있다.

확실한 문법 또는 런타임 문제를 드러내는 규칙은 우선순위를 받아야 한다. 기계적인 현대화 관련 발견 사항은 가능하면 집중된 커밋에서 별도로 검토할 수 있다.

정책 지향 검사는 팀의 판단을 요구한다. 어떤 패턴은 생성된 파일, 프레임워크 관례, 호환성 모듈 또는 쉽게 변경할 수 없는 공개 API에 대해 유효할 수 있다.

Ruff는 이런 경우에 파일별 무시와 대상 지정 억제를 지원한다. 버전 0.16.0은 기존 noqa 동작에 더해 ruff: ignoreruff: file-ignore 주석을 추가한다.

대상 지정 억제는 대체로 광범위한 제외보다 감사하기 쉽다. 규칙이 맞지 않는 위치를 기록하고 미래의 유지보수자를 위한 사유를 포함할 수 있다.

그럼에도 기존 위반이 한꺼번에 수백 건 나타나면 억제는 복잡해질 수 있다. 유지보수자가 의도적인 정리를 계획할 때까지는 프로젝트 전체의 규칙 선택이 더 정직할 수 있다.

올바른 대응은 저장소의 성숙도에 따라 달라진다. 새 프로젝트는 더 넓은 기준선을 즉시 받아들일 수 있지만, 대규모 레거시 코드베이스는 단계적 도입이 필요할 수 있다.

이것이 기본값 변경이 유난히 큰 비중을 갖는 이유다. 서로 완전히 다른 역사와 제약을 지닌 프로젝트에 하나의 제품 수준 판단을 적용하기 때문이다.

새로운 기본값은 마이그레이션의 일부일 뿐이다

첫 번째 진단 경고 물결을 해결한 팀도 Markdown 서식, 기계가 읽을 수 있는 출력, 억제 동작을 검토해야 한다.

Ruff v0.16.0은 Markdown 내 Python 코드 블록을 포매터의 일반 적용 범위에 포함한다. 이로 인해 README, 문서 페이지, 노트북형 게시 파일이 변경될 수 있다.

포매터는 펜스 코드 블록에 붙는 일반적인 Python 정보 문자열을 인식한다. pyi는 스텁 코드로, pycon은 대화형 Python 세션으로 처리한다.

Quarto 사용자는 {python}과 같은 형식으로 표시된 블록도 포맷할 수 있다. .qmd 파일을 사용하는 프로젝트는 Ruff가 이를 포함하기 전에 확장자 매핑이 필요할 수 있다.

이 기능은 문서 예제를 소스 포매터와 일치시킨다. 따라서 복사해 쓴 예제가 오래되었거나 일관성 없는 서식을 사용할 가능성이 줄어든다.

반면 이전에는 ruff format --check가 일반적인 소스 파일만 검사했다면, 이제 예상치 못한 CI 실패가 발생할 수도 있다. 문서 담당자는 처음으로 Ruff 정책을 마주할 수 있다.

필요하다면 프로젝트는 extend-exclude로 Markdown을 제외할 수 있다. 선택한 영역 주변에 포맷 억제 주석을 사용할 수도 있다.

이 결정은 코드 샘플이 실행 가능한 안내인지, 아니면 정교하게 구성된 설명 자료인지에 따라 달라져야 한다. 자동 포맷은 후자보다 전자에 더 일관되게 도움이 된다.

진단 표시 방식도 바뀌었다. 이제 Ruff는 일반 checkformat --check 출력 안에서 제안된 diff를 보여 준다.

이전에는 개발자가 별도로 diff를 요청할 수 있었다. 새 전체 출력은 진단과 제안 변경 사항을 함께 유지하므로, 실패한 검사를 더 쉽게 해석할 수 있다.

CI 제공업체의 경우 format --check는 이제 GitHub 및 GitLab 어노테이션에 사용되는 출력 형식을 지원한다. 포맷 문제를 코드 리뷰의 영향을 받는 줄에 직접 표시할 수 있다.

기계 소비자는 더 면밀한 주의가 필요하다. Ruff의 JSON 출력에 있는 여러 필드는 이제 자리표시자 위치 대신 null이 될 수 있다.

영향을 받는 필드에는 filename, location, end_location, 그리고 수정 편집 내의 해당 위치 정보가 포함된다. 모든 위치가 객체나 문자열이라고 가정하는 소비자는 실패할 수 있다.

대부분의 사용자에게는 작은 호환성 변경이다. 하지만 Ruff 출력을 대시보드, 리뷰 봇 또는 맞춤형 품질 시스템으로 파싱하는 팀에는 더 중요하다.

따라서 업데이트 후 파이프라인은 세 계층에서 실패할 수 있다. Ruff가 새 위반 사항을 발견할 수 있고, 포맷 대상이 새 파일 형식으로 확장될 수 있으며, 출력 파서가 null 허용 필드를 거부할 수도 있다.

모든 실패를 “더 많은 린트 규칙”으로 취급하면 실제 원인을 놓칠 위험이 있다. 유지관리자는 애플리케이션 코드를 수정하기 전에 어느 계층이 바뀌었는지 식별해야 한다.

새 억제 형식도 정책 검토가 필요하다. 줄 끝의 ruff: ignore[F401]은 해당 진단에 대한 표적형 noqa처럼 동작한다.

앞선 주석은 다음 논리적 줄의 발견 사항을 억제할 수 있다. 이는 보고된 문제가 관련 토큰 옆에 깔끔하게 들어가지 않는 여러 줄 함수 헤더에 유용하다.

파일 전체 억제는 ruff: file-ignore를 통해 사용할 수 있다. 여기에 이유를 포함하면, 설명 없는 일괄 제외보다 리뷰어에게 더 많은 정보를 제공한다.

--add-ignore 옵션은 억제를 자동으로 삽입할 수 있다. 이 편의 기능이 근본 진단이 실제 결함을 나타내는지 검토하는 일을 대체해서는 안 된다.

자동화는 주석을 추가해 CI를 빠르게 통과시킬 수 있다. 그러나 프로젝트가 수년간 그 예외를 유지해야 하는지까지 결정할 수는 없다.

Ruff는 안전하다고 간주되는 수정과 unsafe-fix 옵션이 필요한 수정을 구분한다. 안전한 분류라 하더라도 생성 코드, 공개 API, 비정상적인 런타임 동작의 맥락에서 검토해야 한다.

Python의 동적 동작은 정적 분석이 보장할 수 있는 범위를 제한한다. Ruff의 자체 수정 안내는 안전한 수정이 코드를 손상시키는 사례를 사용자에게 보고해 달라고 요청한다.

이 한계가 린팅의 필요성을 약화시키지는 않는다. 오히려 탐지, 자동 수정, 사람의 승인을 구분해야 할 필요성을 강화한다.

고정되지 않은 개발 도구가 이제 압박 지점이다

즉각적인 압박은 규칙 선택을 암묵적으로 둔 채 Ruff를 동적으로 설치하는 리포지터리에 가해진다.

명시적인 select 목록과 완전히 고정된 Ruff 버전에는 두 가지 안정적인 제어 장치가 있다. 하나는 도구 구현을 고정하고, 다른 하나는 프로젝트가 선택한 린트 정책을 고정한다.

명시적 규칙이 있는 유동 버전은 부분적인 안정성을 제공한다. 새 Ruff 릴리스는 여전히 개별 규칙 동작, 파싱, 출력, 포맷 또는 구성 의미를 변경할 수 있다.

명시적 규칙이 없는 고정 버전 역시 부분적인 안정성을 제공한다. 유지관리자가 Ruff를 업데이트할 때까지 CI는 일관되게 유지되지만, 그때 기본값 마이그레이션이 한꺼번에 도착한다.

명시적 규칙도 없는 고정되지 않은 버전에는 어느 제어 장치도 없다. 이 조합이 Simon Willison의 Ruff CI 실패를 초래한 조건을 만들었다.

고정한다고 해서 도구를 무기한 동결한다는 뜻은 아니다. 업그레이드를 발견하는 일과 이를 채택하는 일을 분리하는 것이다.

의존성 업데이트 pull request는 눈에 보이는 리뷰 경계를 만든다. 기존 main 브랜치는 재현 가능한 상태로 유지하면서, CI는 새 발견 사항을 보여 줄 수 있다.

그런 다음 유지관리자는 여러 대응 중에서 선택할 수 있다:

  • 새 기본값이 식별한 명확한 결함을 수정한다.

  • 분리된 커밋에서 안전한 기계적 변경을 수용한다.

  • 리포지터리별 패턴에 대해 의도적인 예외를 구성한다.

  • 이전 선택으로 복원하고 단계적 규칙 채택 일정을 잡는다.

  • null 허용 JSON 위치 정보를 처리하지 못하는 파서를 업데이트한다.

  • 수동 서식을 보존해야 하는 문서 파일을 제외한다.

이러한 조치를 무분별하게 섞어서는 안 된다. 하나의 대규모 자동 수정 커밋은 수천 건의 서식 편집 사이에 동작 변경을 숨길 수 있다.

규칙 계열별로 작업을 묶으면 더 명확한 리뷰가 가능하다. 또한 한 규칙이 프로젝트가 지원하는 Python 버전과 충돌할 경우 되돌리기도 쉬워진다.

pyupgrade 규칙이 활성화되어 있다면 대상 버전 구성이 중요하다. 현대적인 문법은 하나의 인터프리터 기준선에서는 올바르지만 다른 기준선에서는 사용할 수 없을 수 있다.

팀은 Ruff에 구성된 Python 대상이 실제 배포 환경과 일치하는지 확인해야 한다. 그렇지 않으면 현대화 권고가 프로덕션 지원 범위를 앞질러 갈 수 있다.

생성 코드 역시 별도 처리가 필요하다. 생성된 파일을 다시 포맷하거나 린팅하면, 다음에 생성기가 실행될 때 사라질 변경이 생기는 경우가 많다.

생성 경로를 제외하는 편이 억제 주석으로 채우는 것보다 더 정확할 수 있다. 품질을 적용하기에 적절한 위치는 대개 생성기의 소스나 템플릿이다.

모노리포지터리는 또 다른 복잡성을 안고 있다. 서로 다른 패키지가 각기 다른 Python 버전을 지원하거나 별개의 린트 정책을 유지할 수 있다.

루트 수준 기본값은 운영을 단순화할 수 있지만, 관련 없는 구성요소에 하나의 마이그레이션 일정을 강요할 수도 있다. 패키지별 구성이 소유 관계를 더 잘 반영할 수 있다.

가장 핵심적인 의문은 413개 규칙이 폭넓게 수용 가능한 기준선인지다. Astral은 선택 근거를 문서화했지만, 실제 도입 과정에서 오탐률과 호환성 부담이 검증될 것이다.

Willison의 실패는 초기 신호 하나일 뿐, 대표적인 조사 결과는 아니다. 이는 혼란이 가능하다는 점을 보여 줄 뿐, 대부분의 Ruff 사용자가 이를 경험한다는 뜻은 아니다.

이미 명시적인 select 또는 extend-select를 사용하는 프로젝트는 다르게 대응할 수 있다. 실제 규칙 집합은 해당 구성이 새 기준선과 어떻게 상호작용하는지에 따라 달라진다.

Astral은 이 변경이 구성된 사용자에게도 유용한 규칙을 드러낼 수 있다고 말한다. 각 팀은 구성만으로 릴리스가 무관해진다고 가정하지 말고, 해석된 선택 결과를 확인해야 한다.

과도하게 대응할 위험도 있다. Ruff만 고정하고 다른 모든 개발 도구는 유동 상태로 두는 것은 더 큰 문제의 눈에 보이는 사례 하나만 해결한다.

팀은 포매터, 타입 체커, 테스트 도구, pre-commit hook, 문서 빌더를 목록화해야 한다. 이들 어느 것이든 깨끗한 빌드를 실패로 바꿀 수 있다.

지속 가능한 정책은 단순하다. 코드의 출시 가능 여부를 결정하는 환경을 버전 관리하라. 이 정책에는 개발자가 전통적으로 선택 사항으로 분류해 온 도구도 포함된다.

Simon Willison과 Ruff 사용자가 다음으로 주시할 점

다음 세 가지 신호는 Ruff의 더 넓어진 기준선이 수용되는 정책이 될지, 아니면 반복되는 CI 마찰의 원인이 될지를 보여 줄 것이다.

첫 번째 신호는 버전 0.16.0 이후 몇 주 동안의 Astral 패치 릴리스 활동이다. 기본 규칙에 대한 빠른 조정은 실제 리포지터리에서 상당한 호환성 문제가 발견되었음을 시사한다.

규칙별 수정이 확장된 기준선을 무효화하지는 않는다. 이는 훨씬 더 큰 선택 집합이 프로덕션 워크로드에서 조정될 필요가 있음을 보여 줄 것이다.

반대로 되돌리기 활동이 제한적이라면, 대부분의 새 진단이 조치 가능하다는 Astral의 주장이 힘을 얻는다. 또한 더 많은 프로젝트가 이전 집합으로 복원하는 대신 기본값을 수용하도록 유도할 것이다.

두 번째 신호는 공개 Python 리포지터리 전반의 구성 동작이다. 유지관리자는 공식 설문이 없어도 커밋을 통해 자신의 판단을 드러낼 것이다.

명시적으로 이전 기본값을 선택하는 흐름은 팀이 즉각적인 적용 범위보다 마이그레이션 제어를 중시한다는 뜻일 수 있다. 광범위한 수정과 기본값 유지가 나타난다면 성공적인 도입을 가리킬 것이다.

가장 유익한 리포지터리는 그 이유를 문서화할 것이다. 단순 ignore 목록은 무엇이 바뀌었는지 보여 주지만, 마이그레이션 노트는 팀이 각 규칙 계열을 수용하거나 거부한 이유를 설명한다.

세 번째 신호는 패키지 템플릿과 CI 예제가 Ruff를 고정하기 시작하는지 여부다. 새 프로젝트 생성기는 사후 경고보다 습관 형성에 더 효과적인 경우가 많다.

템플릿이 버전 제약과 자동 업데이트 워크플로를 채택한다면, Willison의 경험은 이 단일 릴리스를 넘어 실무에 영향을 미친 셈이 된다.

예제가 계속 제약 없는 ruff를 설치한다면, 향후 기본값이나 포매터 변경도 같은 놀라움을 반복할 수 있다. 구체적인 규칙 수는 달라지겠지만 재현성 문제는 남는다.

개발자는 행동하기 전에 이러한 신호를 기다릴 필요가 없다. 브랜치에서 새 버전을 실행하고 출력을 보존한 뒤, 어떤 발견 사항이 코드 개선에 도움이 되는지 결정할 수 있다.

유용한 테스트 명령은 다음과 같다:

버전을 지정하면 실험을 재현할 수 있다. ruff format --check .를 별도로 실행하면 린트 실패와 Markdown 또는 소스 포맷 변경을 구분하는 데 도움이 된다.

처음부터 전역 ignore를 추가하지 말라. 먼저 어떤 규칙이 확실한 버그를 찾았는지, 어떤 규칙이 현대화를 제안하는지, 어떤 규칙이 논쟁의 여지가 있는 정책을 담고 있는지 식별해야 한다.

그런 다음 구성과 버전 관리에 결정을 기록하라. 어떤 품질 계약이 그것을 만들었는지 아무도 모른다면, 녹색 CI 배지의 가치는 떨어진다.

Ruff v0.16.0은 활성 기본값의 장점과 비용을 보여 준다. 이 도구는 구성 없이 더 많은 것을 잡아내지만, 구성을 생략한다고 해서 동작이 변하지 않는 것은 더 이상 아니다.

Simon Willison의 경험은 이 추상적인 절충안을 즉각적인 엔지니어링 질문으로 바꾼다. 여러분의 리포지터리는 릴리스를 통제하는 도구와 정책을 선언하고 있는가?

브랜치에서 고정된 버전을 실행하고, 새 규칙 계열을 하나씩 검토한 뒤, 기준선을 명시적으로 만들어라. 다음 깨끗한 빌드는 CI가 우연히 Ruff를 설치한 날짜가 아니라 검토된 결정을 반영해야 한다.

 
 

무료로 시작하세요

개인 지식 관리 기능을 갖춘 로컬 우선 AI 어시스턴트

더 나은 AI 경험을 위해

현재 remio는 Windows 10+ (x64)M-Chip Macs만 지원합니다.

​머릿속에 검색창을 추가하세요

remio에게 물어보기만 하면 됩니다

모든 것을 기억하세요

정리는 필요 없습니다

bottom of page