# Ruff v0.16.0 — 기본 규칙이 59개에서 413개로 대폭 확대

> Clean Markdown view of GeekNews topic #31852. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=31852](https://news.hada.io/topic?id=31852)
- GeekNews Markdown: [https://news.hada.io/topic/31852.md](https://news.hada.io/topic/31852.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-07-27T09:51:32+09:00
- Updated: 2026-07-27T09:51:32+09:00
- Original source: [astral.sh](https://astral.sh/blog/ruff-v0.16.0)
- Points: 1
- Comments: 1

## Topic Body

- Rust로 작성된 Python 린터·포매터 **Ruff v0.16.0**은 기본 활성화 규칙을 59개에서 413개로 늘려, 별도 설정 없이 구문 오류와 즉시 발생하는 런타임 오류를 더 폭넓게 탐지함
- Markdown에서 `python`, `py`, `pyi`, `pycon` 등으로 표시된 **Python 코드 블록 포매팅**을 지원하며 Quarto 노트북에도 적용 가능함
- **`ruff: ignore`와 `ruff: file-ignore`** 가 추가돼 논리적 코드 행이나 파일 전체의 진단을 억제할 수 있고, `--add-ignore`로 주석을 자동 삽입할 수 있음
- `check`와 `format --check`는 수정 내용을 기본 진단 아래 **diff로 표시**하며, 포매터 검사도 JSON과 GitHub·GitLab CI 주석용 출력 형식을 지원함
- 대부분은 큰 변경 없이 업그레이드할 수 있지만, 늘어난 기본 규칙과 일부 값이 `null`이 될 수 있는 **JSON 출력 변경**이 기존 설정과 자동화 도구에 미치는 영향을 확인해야 함

---

### 기본 규칙 413개로 확대
- [Ruff v0.16.0](https://github.com/astral-sh/ruff)은 Rust로 작성된 고속 Python 린터·포매터로, PyPI 또는 `uv tool install ruff@latest`로 설치할 수 있음
- Ruff의 전체 규칙은 v0.1.0 당시 708개에서 968개로 늘었지만, 기본 활성화 규칙은 그동안 59개로 유지돼 왔음
- v0.16은 기본 규칙을 **413개**로 확대해 구문 오류와 즉시 발생하는 런타임 오류를 포함한 심각한 문제를 별도 설정 없이 탐지함
  - flake8-bugbear의 `B`, pyupgrade의 `UP`, Ruff 자체 `RUF` 범주 규칙 등이 포함됨
  - 전체 목록은 [Default Rules](https://docs.astral.sh/ruff/default-rules/) 문서에서 확인할 수 있음
- `select`나 `extend-select`를 이미 사용하는 프로젝트도 새 기본 규칙을 통해 이전에 알지 못했던 유용한 규칙을 확인할 수 있음
- 이전 기본 규칙으로 되돌리려면 다음과 같이 설정함

```toml
[lint]
select = ["E4", "E7", "E9", "F"]
```

- 이번 변경은 장기 과제인 **규칙 재분류**와 연결되며, 관련 작업도 계속 이어질 예정임

### Markdown 코드 블록 포매팅
- `ruff format`이 Markdown 파일에 포함된 **Python 펜스 코드 블록**을 포매팅함
- 지원하는 정보 문자열은 `python`, `py`, `python3`, `py3`, `pyi`, `pycon`임
  - `pyi`는 스텁 파일 형식으로 처리함
  - `pycon`은 REPL 세션 형식으로 처리함
  - 나머지는 일반 Python 파일처럼 포매팅함
- `{python}`처럼 언어 이름이 중괄호로 둘러싸여 있어도 인식하므로 **Quarto 노트북**에도 사용할 수 있음
  - `.qmd` 확장자를 쓴다면 `extension` 매핑 설정이 필요할 수 있음
- 코드 블록 내부에서는 `fmt: off`와 `fmt: on`으로 일부 포매팅을 억제할 수 있음
- Markdown 문서 영역 전체는 `&lt;!-- fmt: off --&gt;`와 `&lt;!-- fmt: on --&gt;` HTML 주석으로 제외할 수 있음
- 모든 Markdown 파일을 제외하려면 `extend-exclude`에 `*.md` 같은 glob을 지정함
- 세부 동작은 [Markdown 코드 포매팅 문서](https://docs.astral.sh/ruff/formatter/#markdown-code-formatting)에서 확인할 수 있음

### 새로운 진단 억제 주석
- v0.15의 `ruff: disable`·`ruff: enable` 범위 억제에 이어, v0.16은 **`ruff: ignore`와 `ruff: file-ignore`** 를 추가함
- `ruff: ignore`는 `noqa`처럼 같은 행의 진단을 억제하거나, 독립된 주석으로 작성해 다음 논리적 행 전체에 적용할 수 있음
  - 여러 줄로 작성된 함수 헤더에서는 `def`부터 콜론까지가 하나의 논리적 행으로 취급됨
- `ruff: file-ignore`는 `ruff: noqa`처럼 파일 전체에서 지정된 진단을 억제함
- 각 억제 주석에는 규칙 코드 뒤에 **적용 이유**를 작성할 수 있음
- `--add-ignore` CLI 옵션은 필요한 `ruff: ignore` 주석을 자동으로 추가함
- 미리보기 모드에서는 `F401` 같은 코드 대신 `unused-import` 같은 **규칙 이름**도 사용할 수 있음
- 전체 주석 명세는 [Ruff linter 문서](https://docs.astral.sh/ruff/linter/#comments)에 정리돼 있음

### 수정 diff와 출력 형식
- `check`와 `format`은 기존에도 `--diff`를 지원했지만 일반 진단과 별도로 동작해, 수정 이유를 보여주는 진단과 함께 표시되지 않았음
- v0.16의 기본 `full` 출력은 가능한 린터·포매터 수정 사항을 **진단 아래 diff로 표시**함
- `format --check`도 린터가 지원하는 전체 출력 형식을 사용할 수 있음
  - 기계 판독용 JSON을 생성할 수 있음
  - GitHub와 GitLab이 CI에서 주석으로 렌더링하는 형식을 출력할 수 있음
- 지원 형식은 CLI 도움말과 [출력 형식 문서](https://docs.astral.sh/ruff/settings/#output-format)에서 확인할 수 있음

### 호환성과 안정화
- v0.16의 파괴적 변경은 소수여서 대부분은 코드나 설정을 크게 바꾸지 않고 업데이트할 수 있음
- JSON 출력의 `filename`, `location`, `end_location`, `fix.edits[].location`, `fix.edits[].end_location`은 빈 문자열이나 1행 1열을 기본값으로 쓰는 대신 **`null`이 될 수 있음**
  - 현재 영향을 받는 진단은 매우 적지만 향후 규칙에서는 더 흔해질 수 있음
- 12개 규칙이 미리보기에서 안정 상태로 전환됨
  - Airflow 3 함수 시그니처 호환성 `AIR303`, 저작권 고지 `CPY001`, float 변환 `FURB164`, 정렬된 min/max `FURB192`
  - 컬렉션 리터럴 문자열 결합 `ISC004`, 예외 처리기 밖의 예외 로깅 `LOG004`, 잘못된 bool 반환형 `PLE0304`
  - 과도한 위치 인자 `PLR0917`, StopIteration 반환 `PLR1708`, Union 내 `None` 위치 `RUF036`
  - 클래스 딕셔너리의 annotation 접근 `RUF063`, `__all__` 중복 항목 `RUF068`
- 일부 기존 규칙의 **안정화된 동작**도 기본 적용됨
  - `BLE001`은 `critical`, `error`, `exception` 이외의 `logging` 메서드로 예외를 기록해도 억제됨
  - `FA102`는 `collections.abc` 등 추가 PEP 585 호환 API를 검사함
  - `INT001`·`INT002`·`INT003`은 `gettext`를 `builtins._`에 할당하는 등 일반적인 사용 방식도 검사함
  - `S310`은 로컬 문자열 리터럴 바인딩을 해석해 오탐을 줄임
  - `S508`·`S509`는 최신 PySNMP의 권장 API를 지원함
  - `UP019`는 `typing.Text`뿐 아니라 `typing_extensions.Text`도 인식함
- 전체 변경 사항은 [GitHub 릴리스](https://github.com/astral-sh/ruff/releases/tag/0.16.0)에서 확인할 수 있음

## Comments



### Comment 62440

- Author: neo
- Created: 2026-07-27T09:51:33+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=49056112) 
- 약 **3천 줄 규모의 Python 프로젝트**를 v0.15.x에서 새 버전으로 올렸는데 오래 걸리지 않았고, 이전 버전이 놓치던 문제를 다수 찾아내 코드 품질도 좋아졌음  
  제안에 따른 수동 수정: [https://github.com/nickjj/plutus/commit/9af66d31f98bef841588...](<https://github.com/nickjj/plutus/commit/9af66d31f98bef841588effe7e1288395d6f7bce>)  
  줄 길이 규칙 재활성화: [https://github.com/nickjj/plutus/commit/21789f89bbcee37913c1...](<https://github.com/nickjj/plutus/commit/21789f89bbcee37913c13a98abf789a3f3b56341>)  
  미사용 변수에 `_` 접두사 강제: [https://github.com/nickjj/plutus/commit/a272c77b932e1c78558a...](<https://github.com/nickjj/plutus/commit/a272c77b932e1c78558a790bbff2a11517fc9d81>)  
  Ruff 자동 수정: [https://github.com/nickjj/plutus/commit/6fe69cf88385ebdf9b8c...](<https://github.com/nickjj/plutus/commit/6fe69cf88385ebdf9b8c2c63c3566e76ef8093f4>)

- Astral이 OpenAI에 인수된 뒤에도 **Ruff, ty, uv**가 활발히 개발돼서 반가움
  - ty를 기대했지만 **basedpyright보다 크게 뒤처져** 결국 사용을 중단했음. 검사 항목 부족보다 오탐이 치명적이었고, 대규모 코드베이스에 매우 유용한 기준선(baselining) 기능도 없었음  
    uv와 Ruff는 훌륭하며 ty도 언젠가는 그 수준에 도달하길 바람

- 서로 자의적인 규칙을 구현하고 무엇이 좋은 Python 코드인지조차 합의하지 못하는 **문법 경찰 도구**에 이토록 열광하는 모습이 놀라움  
  여러 줄 딕셔너리를 한 줄로 합치면서 주석의 의도를 망치고, 공백 두 개와 큰따옴표 같은 사소한 형식만 바로잡는 식임. 실제 문제는 줄 끝 공백이나 import 정렬이 아니라 해석하기 어려운 10줄짜리 리스트 컴프리헨션인데 이런 도구들은 잡지 못함  
  직장에서는 pylint, flake8, black, Ruff를 사용하면서 변경마다 수백 개의 커밋이 생겼고, 그 에너지를 다른 곳에 쓰는 편이 나았을 것임
  - 이런 도구의 목적은 **실제 문제에 집중**하게 하는 것임. 린트 결정을 자동화하면 PR에서 형식을 두고 논쟁하느라 사고력을 낭비하지 않아도 됨  
    자동 실행 결과를 그대로 받아들이면 린트 논의에서 빠질 수 있지만, 이런 도구가 없는 조직에서는 형식을 고민하고 토론하는 데 실제 시간을 써야 했음
  - 린터가 시간을 낭비한다는 반감이 합리적인 수준을 넘어선 듯함. 현장에서는 오히려 시간을 절약한다는 근거가 충분하며, 결국 핵심은 **린터가 마음에 들지 않는 변경도 가끔 한다**는 정도임  
    팀 개발에서는 개인적 선호를 강하게 밀어붙이기보다 주변 의견을 듣고, 협업과 장인정신의 우선순위를 다시 살펴볼 필요가 있음
  - Ruff는 줄 끝 주석을 인식해 각 항목을 별도 줄에 유지하고 **후행 쉼표와 공백**만 추가함. 후행 쉼표가 있으면 줄을 합치지도 않으며, 제시된 결과는 Black에서 나온 듯함  
    줄 주석이 있는데 줄을 합치는 동작은 부적절해 보임. 큰따옴표는 Python에서 단순한 스타일 선택이며, 작은따옴표 안에 큰따옴표가 있으면 Ruff도 그대로 둠
  - 이런 도구는 오히려 **팀의 에너지를 절약**해 줌. 도구가 없으면 개발자마다 형식, 코드 품질, 가독성에 대한 기준이 달라 끝없이 토론하게 되므로 Ruff에 맡기는 편이 나음
  - 마지막 항목 뒤에 **쉼표를 빠뜨렸기 때문**에 한 줄로 합쳐진 것임. 적어도 Black에서는 후행 쉼표를 유지하면 항목들이 압축되지 않지만, 의도한 형식을 자주 깨뜨려 더는 내 코드에 연결하지 않고 있음

- Go에도 Ruff 같은 도구가 있으면 좋겠음. 여러 언어에서 훌륭한 도구가 나오지만 Go 생태계는 분산돼 있고, **Ruff, Oxc, Biome, Mago**만큼 완성도 높게 느껴지는 도구가 없음
  - Go에는 더 나은 **Go Analysis Framework**가 있음: [https://pkg.go.dev/golang.org/x/tools/go/analysis](<https://pkg.go.dev/golang.org/x/tools/go/analysis>)  
    비교적 새로워 덜 알려졌지만 go fix와 go vet의 기반이며, Go 팀은 모듈 작성자가 go fix 실행 시 자동으로 작동할 사용자 정의 분석 패스를 쉽게 정의하도록 작업 중인 것으로 보임  
    `analysis.Analyzer` 구조체로 AST, 타입, SSA 정보에 접근하고 분석기 간 정보를 조합할 수 있으며, 바이너리로 컴파일해 go fix에 전달하면 도구 체인이 복잡한 캐싱까지 처리함. Go 팀이 직접 만들고 도구 체인에 포함했으므로 golangci-lint 같은 도구도 장기적으로 이 프레임워크로 통합될 가능성이 큼  
    AI 에이전트에게 Go Analysis 분석기를 작성하고 go fix로 구동하라고 시켜볼 수 있으며, 내 프로젝트에서도 부정확한 Markdown 지침 대신 여러 규칙을 결정론적으로 자동 강제하는 데 활용 중임
  - 얼마 전까지만 해도 분위기는 정반대여서 Python 커뮤니티가 도구 부족으로 고생하며 모두 **Python용 `gofmt`** 를 원했음. Ruff는 포매터가 아닌 린터지만 최근 Python 생태계의 발전 방향은 반가움
  - Go 생태계가 분산됐다는 말은 잘 이해되지 않음. Go에는 **공식 포매팅과 린팅 도구**가 있고, 초보자가 작성해도 일정한 형태가 되도록 언어 자체가 의도적으로 제한돼 있음  
    공식 도구가 특정 스타일을 강제하지 않는 Python이나 TypeScript와 달리 Go에서는 Ruff나 Biome을 처음 쓸 때와 같은 극적인 효과가 나오기 어려움
  - Go는 거대한 IDE 없이도 사용할 수 있는 최고의 언어 도구 생태계 중 하나이며 **golangci-lint**도 상당히 포괄적임. Go 배포판 자체가 이미 많은 부분을 해결해 줌
  - **golangci-lint**는 오래전부터 존재했고 널리 사용되고 있음

- 기본으로 **413개 규칙**을 활성화하면 대부분의 프로젝트가 설정을 건드리지 않고도 유용한 린트를 받을 수 있어 좋은 변화임
  - 기존 프로젝트에서 갑자기 **413개 잠재적 경고**가 쏟아지는 것이 유용한지는 의문이며, 신규 프로젝트에 더 적합해 보임  
    요즘은 에이전트에게 모든 린트 경고를 정해진 기준에 따라 수정하라고 맡기고 몇 시간 두면 해결할 수 있겠지만, Ruff가 제공하는 세밀한 진단 자체는 환영함

- Ruff에도 적용할 기본값 집합을 결정하는 Nix의 **stateVersion** 같은 기능이 필요함. 여러 저장소에서 Ruff를 업데이트하면 새 기본 규칙이 추가될 때마다 즉시 끄거나 위반 사항을 수정해야 해 결과를 예측하기 어려움  
  활성화할 규칙을 모두 허용 목록에 적을 수도 있지만, 설정은 단순하게 유지하고 모두가 몇 시간 투자할 수 있을 때 상태 버전만 올리는 편이 나음
  - 프로젝트마다 `pyproject.toml`에 원하는 **Ruff 버전을 고정**하는 방식이 더 적절함. 각 프로젝트가 준비됐을 때 버전을 올리면 되므로 여러 프로젝트를 동시에 조율할 필요가 없고, 하나가 뒤처져도 나머지가 막히지 않음
  - 원문에 따르면 Ruff의 **기본 규칙 집합**은 2년이 넘도록 바뀌지 않았으며, 마지막 변경은 v0.1.0이었음  
    [https://github.com/astral-sh/ruff/releases/tag/v0.1.0](<https://github.com/astral-sh/ruff/releases/tag/v0.1.0>)

- 에이전트 코딩 시대에는 **강력한 린팅**이 어느 때보다 중요하며, 더 많은 언어에서 forbidigo 같은 도구를 보고 싶음
  - 프로젝트들을 업그레이드하고 있지만 복잡한 마음도 듦. 직접 코드를 작성할 때는 직관에 따라 규칙을 건너뛰거나 무시할 시점을 판단했지만, pylint 규칙을 대부분 활성화한 프로젝트에서는 오히려 pylint를 만족시키기 위한 편법 때문에 코드가 읽기 어려워졌음  
    코딩 에이전트도 사소한 문제를 고치는 데 많은 토큰을 쓰거나, 테스트가 실패하면 아예 비활성화하기도 함. AI 결과의 전반적인 정확성은 신뢰하게 됐지만 **코드 품질에 대한 판단력**은 여전히 믿기 어려움

- 규칙이 **413개**나 되는데도 새 코드베이스에 합류할 때마다 import 정렬을 놓고 똑같은 세 가지 논쟁을 반복하게 됨

- 이제 **무설정 사용**이 권장되는 듯해 반가움. 새 `.ruff.toml`에는 `line-length = 300`만 두면 됨
