Robocop 플러그인 시스템의 진화
- 기존 문제점: Robocop은 Ruby 스타일 가이드를 구현한 도구로, 사용자 정의 스타일을 지원하기 위해
enforced_style
과supported_styles
같은 설정을 제공합니다. 그러나 기존의 플러그인 확장 방식은inject
와 같은 비공식적인 몽키 패치를 사용했으며, 이는 코드 재사용성 저해, 버그 발생률 증가, 유지보수 난이도 상승 등의 문제를 야기했습니다. - LintRoller 도입: 이러한 문제를 해결하기 위해
LintRoller
라는 중간 계층이 도입되었습니다.LintRoller
는 플러그인과 Robocop(또는 Standard Ruby) 같은 런너 사이의 통신을 담당하며, Rails와 애플리케이션 서버 사이의 Rack과 유사한 역할을 수행합니다. - 새로운 플러그인 개발 방식: 플러그인 개발자는
LintRoller::Plugin
을 상속받는 플러그인 클래스를 생성하고,about
및rules
메서드를 구현하여 플러그인 정보와 설정 파일 경로를 제공합니다. 또한,gemspec
의 메타데이터(default_lint_roller_plugin
)를 통해 Robocop이 플러그인 클래스를 인지하도록 합니다. - 사용자 설정 변경:
.rubocop.yml
파일에서 기존의require
대신plugins
키워드를 사용하여 플러그인을 로드하도록 변경되었습니다. 이는 사용자에게 더 명확하고 공식적인 플러그인 로딩 방식을 제공합니다.
Ruby LSP 및 Robocop LSP 통합
- LSP의 중요성 증가: Rails 7.1 이후 개발 컨테이너에서 Ruby LSP가 기본으로 활성화되는 등 LSP(Language Server Protocol)의 중요성이 커지고 있습니다. Ruby LSP는 Robocop의 기능을 활용하기 위해 독자적인 확장을 시도해왔습니다.
- 구현 재사용: Robocop은 이미 내장 LSP 기능을 가지고 있었으며, Ruby LSP는 이 Robocop LSP 런타임을 어댑터 패턴을 통해 재사용하도록 구현되었습니다. 이는 중복 구현을 방지하고, Robocop의 LSP 기능을 Ruby LSP 생태계에서 활용할 수 있게 합니다.
- 성능 및 재사용성: 이 통합을 통해 Ruby LSP가 한 번 파싱한 소스 코드를 Robocop이 다시 파싱할 필요 없이 재사용할 수 있게 되어 전체적인 성능 향상과 자원 효율성을 기대할 수 있습니다. 현재 이 기능은 실험 단계에 있습니다.
AST 및 파서의 변화: Parser Gem에서 Prism으로
- Parser Gem의 한계: Robocop은 오랫동안
parser_gem
을 Ruby 코드의 추상 구문 트리(AST) 파서로 사용해왔습니다. 그러나parser_gem
은 Ruby 3.4의 블록 파라미터와 같은 최신 문법을 지원하지 못하고, 유지보수가 사실상 중단된 상태입니다. - Prism으로의 전환: 이러한 문제로 인해 Robocop은
prism_translation_parser
를 통해Prism
을 새로운 기본 파서로 채택했습니다. Robocop 1.62부터 선택적으로Prism
을 사용할 수 있었으며, Robocop 1.75 이상에서는 Ruby 3.4+ 환경에서Prism
이 기본 파서로 동작합니다. - 유지보수성 및 미래 지향:
Prism
은 Ruby 자체에서 개발 및 유지보수되고 있어 최신 Ruby 문법을 빠르게 지원하며,parser_gem
에 비해 훨씬 안정적인 유지보수를 기대할 수 있습니다. 이는 Robocop의 장기적인 안정성과 발전 가능성을 높입니다. - AST/CST 논의: 파서 변경은 기존 커스텀 Cop 개발자들에게 AST 패턴 매칭 방식 변경 등 상당한 영향을 미칠 수 있습니다. AST와 CST(Concrete Syntax Tree) 중 어떤 것이 더 적합한지에 대한 논의가 있으며, 현재로서는 기존 AST 인터페이스를 유지하면서 내부적으로
Prism
을 활용하는 방식이 채택되었습니다. 이는 기존 생태계에 미치는 영향을 최소화하면서 점진적인 전환을 목표로 합니다.