Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

RubyCritic으로 Ruby 코드 품질 높이기: 시각적 분석과 지속적인 개선

RubyCritic은 Ruby 애플리케이션의 코드 스멜(code smell), 코드 구조, 테스트 용이성, 테스트 커버리지를 한눈에 파악할 수 있는 시각적 리포트를 제공하는 도구입니다.

이 도구는 현재도 활발하게 개발되고 있으며, 새로운 코드 분석 기능이 꾸준히 추가되고 있습니다. 따라서 RubyCritic의 릴리스 소식을 지속적으로 확인해 두는 것이 좋습니다.

이 글에서는 RubyCritic의 장점, 내부 의존성, 그리고 코드 리포트를 읽는 방법까지 살펴보겠습니다.

그럼 시작해 보겠습니다!

Ruby on Rails 애플리케이션에서 RubyCritic을 선택해야 하는 이유

프로젝트의 코드 개선 사항을 한곳에서 검토하고 싶다면 RubyCritic을 사용하는 것을 고려해 볼 만합니다. 개발 프로세스에 RubyCritic을 도입하면 개발팀이 기술 부채(technical debt)를 처리하는 데 소요되는 시간을 확실히 줄일 수 있습니다. 대부분의 기술 부채는 개발 단계에서 미리 파악될 수 있기 때문입니다.

RubyCritic이 프로젝트와 개발 프로세스에 제공하는 주요 이점은 다음과 같습니다.

  • 모든 정보를 한곳에서 통합 관리
  • 시각화된 리포트 제공
  • 간편한 설치
  • 별도 설정 없이 바로 사용 가능(제로 컨피그)
  • 자유로운 커스터마이징 지원
  • 확장성 — 자체 오픈소스 통합 구현 가능
  • 배지(badge) 생성기 🎉

RubyCritic이 어떻게 동작하는지 이해하기 위해, 리포트를 생성하는 데 사용되는 내부 의존성을 살펴보겠습니다.

RubyCritic의 내부 의존성

프로젝트에 RubyCritic을 추가하면 몇 가지 의존성도 함께 설치됩니다.

그중에서 핵심적인 역할을 하는 의존성은 Reek, Flay, Flog 세 가지 젬(gem)입니다. 이 의존성 덕분에 RubyCritic은 코드에 대한 유용한 정보를 보여줄 수 있습니다. 각 도구의 동작 원리를 이해하면 RubyCritic을 더욱 효과적으로 활용할 수 있습니다.

Reek: Ruby 코드 스멜 탐지

Reek은 Ruby 코드의 코드 스멜을 탐지하는 젬입니다. 코드 스멜은 '잘못된 코드'를 찾는 것이 아니라, '더 잘 작성될 수 있는 코드'가 있는지 분석하는 개념입니다.

Reek의 분석은 무언가를 다른 방식으로 구현할 수 있는지 여부를 식별합니다. 다만 어떻게 수정해야 하는지는 제시하지 않습니다. 대부분의 코드 스멜은 비즈니스 로직과 개발자의 언어 숙련도와 연관되어 있기 때문입니다.

예를 들어, if 문을 메타프로그래밍 기법으로 쉽게 재작성할 수 있습니다. 하지만 실제로 어떻게 수정할지는 프로젝트의 맥락에 따라 개발자가 판단해야 합니다. 이런 경우 최적의 해결책을 알려주는 라이브러리는 존재하지 않습니다.

Reek은 매우 다양한 종류의 스멜을 탐지합니다. 다음 항목들을 검사하여 잠재적인 스멜을 식별합니다.

  • 클래스(Classes)
  • 속성(Attributes)
  • 메서드(Methods)
  • 파라미터(Parameters)
  • 모듈(Modules)
  • 이터레이터(Iterators)
  • 다형성(polymorphism) 구현

스멜을 발견하면 이를 개선하여 코드의 가독성과 유지보수성을 높일 수 있습니다.

Reek은 다음과 같은 커스텀 설정도 지원합니다.

  • 탐지기(detector) 유형별 비활성화
  • 스캔에서 제외할 디렉터리 지정
  • 필터를 사용한 경고 무시

심지어 특정 코드를 스캔 대상에서 제외하도록 정의할 수도 있습니다. 아직 완성되지 않았거나 리팩토링이 예정된 코드, 또는 레거시 코드를 다룰 때 매우 유용한 기능입니다.

Reek의 동작 예시를 살펴보겠습니다. 아래 코드에서는 예외 객체가 단순히 e로 정의되어 있습니다.


e가 예외를 의미한다는 것을 쉽게 짐작할 수 있지만, 만약 다른 예외들도 함께 있다면 어떻게 될까요? 변수명을 명확하게 지정하는 것이 좋은 코드를 유지하는 가장 확실한 방법입니다.

Reek은 e를 UncommunicativeVariableName(의미 전달이 어려운 변수명)으로 식별하고 경고를 표시합니다.


Flay: Ruby 코드 중복 검사

Flay는 Ruby 코드의 구조적 유사성을 식별하는 도구로, 다음과 같은 기능을 제공합니다.

  • 프로젝트 내 코드 중복 탐지
  • 모든 코드 수준에서의 차이점 검사
  • 코드 품질을 측정하는 점수 생성 (점수가 낮을수록 코드 품질이 좋음)

Flay가 코드에서 유사성을 보고했다면, 리팩토링이 필요하다는 강력한 신호입니다. 이를 무시해서는 안 됩니다! 중복 코드는 버그로 이어지는 통로입니다. 한 곳만 수정하고 다른 곳을 놓치면 새로운 버그가 계속 발생하게 됩니다.

Flay 자체 소스 코드에 Flay를 실행하면 어떻게 동작하는지 확인할 수 있습니다.


Flay는 다음 두 코드 조각 사이의 유사성을 식별합니다.


코드의 표기 방식은 완전히 같지 않지만, 기능은 동일하므로 중복을 피하기 위해 리팩토링할 수 있습니다. 이것이 바로 Flay의 매력입니다!

Flog: Ruby 코드 복잡도 검사

Flog는 코드가 얼마나 테스트하기 어려운지를 검사합니다. 코드 한 줄마다 복잡도 점수를 부여하고, 메서드와 클래스 단위로 점수를 합산합니다.

점수가 높을수록 복잡도가 큰 구현이라는 의미이며, 그만큼 리팩토링이 필요하다는 신호입니다.

Flog의 실제 동작을 살펴보겠습니다. 사소한 변경 하나만으로도 점수가 달라질 수 있습니다.



첫 번째 코드에는 or 검사가 포함되어 있어 점수가 0.4점 증가한 것을 확인할 수 있습니다.



그 외 RubyCritic 의존성

RubyCritic은 다음과 같은 런타임 의존성도 함께 사용합니다.

  • byebug — Ruby 애플리케이션 디버깅을 한 단계 끌어올리는 도구입니다. 프로그램을 한 줄씩 실행하고, 중단점을 설정하며, 런타임에 값을 평가하고 추적할 수 있습니다. 아직도 puts로 디버깅하고 있다면 Byebug의 기능과 명령어를 익혀볼 때입니다.
  • rubocop — Ruby 코드 린터(linter)로, Ruby 커뮤니티에서 사용하는 스타일 가이드를 준수하거나 자체 코드 스타일을 적용하는 데 도움을 줍니다. 팀 내 코딩 표준을 정립하고 공백·탭 문제로 인한 불필요한 논쟁을 피하는 데 매우 유용합니다.
  • SimpleCov — Ruby 애플리케이션의 코드 커버리지를 확인하는 도구입니다. 테스트와 함께 실행되도록 설정할 수 있으며, 코드 커버리지 지표를 제공하여 어떤 부분에 주의해야 하고 더 나은 테스트 케이스를 위해 어디에 시간을 투자해야 하는지 파악할 수 있게 해줍니다.

RubyCritic의 전체 의존성 목록도 직접 살펴보시길 권합니다.

Ruby on Rails 앱에서 RubyCritic 활용하기

RubyCritic은 별도의 복잡한 설정 없이 빠르게 시작할 수 있도록 훌륭한 문서를 제공합니다. 따라서 이번 섹션에서는 리포트를 분석하는 데 유용한 기능들을 중심으로 살펴보겠습니다.

RubyCritic은 'Code', 'Smells', 'Coverage' 세 가지 리포트를 제공합니다. 각각의 기능을 차례대로 살펴보겠습니다.

RubyCritic의 Overview 화면

'Overview' 페이지에서는 도넛 차트로 프로젝트의 전체 점수와 등급(A가 최고 등급, F가 최저 등급)을 확인할 수 있습니다. 'Summary' 섹션에서는 파일 수, 체인(churn, 커밋 변경 횟수), 발견된 스멜 수 등 각 등급의 세부 정보를 보여줍니다.

RubyCritic으로 Ruby 코드 품질 높이기: 시각적 분석과 지속적인 개선

'Churn vs Complexity' 섹션에서는 복잡도가 가장 높은 클래스를 바로 식별할 수 있으며, 해당 클래스가 아마도 가장 먼저 주목해야 할 대상일 것입니다.

이 그래프를 제대로 이해하려면 코드 체인(code churn) 개념을 짚고 넘어갈 필요가 있습니다. 자주 변경되는 코드는 로직이나 비즈니스 도메인 등 어딘가에 문제가 있다는 경고 신호일 수 있습니다. 어느 쪽이든 'Churn vs Complexity'를 살펴보면 프로젝트 전반의 고충 지점(pain point)을 파악하는 데 큰 도움이 됩니다.

Code 리포트

'Code' 리포트는 클래스별 점수를 보여주며, 체인(churn), 복잡도(complexity), 중복(duplication), 스멜(smells)에 대한 지표도 함께 표시됩니다.

이 목록은 열(column) 기준으로 정렬할 수 있어, 가장 높은 수치를 기록한 항목부터 확인하고 우선순위가 높은 문제를 먼저 해결할 수 있습니다.

RubyCritic으로 Ruby 코드 품질 높이기: 시각적 분석과 지속적인 개선

또한 이 목록에는 클래스 이름으로 빠르게 검색할 수 있는 필터 기능도 있습니다.

클래스 이름을 클릭하면 해당 클래스의 코드와 함께 다음과 같은 상세 지표 페이지가 열립니다.

  • 코드 라인 수
  • 메서드 개수
  • 계산된 체인(churn)
  • 메서드별 복잡도
  • 복잡도 점수 (클래스당 총합)
  • 발견된 중복 코드 수
  • 스멜 개수

문제가 발견된 코드 라인은 하이라이트로 표시됩니다(Reek 젬이 제공하는 정보 기반).

Flog가 문제를 식별했다면 점수가 표시되고, Flay 리포트에서 중복 코드가 감지되었는지 여부도 함께 확인할 수 있습니다.

RubyCritic으로 Ruby 코드 품질 높이기: 시각적 분석과 지속적인 개선

Smells 리포트

'Smells' 페이지에서는 스멜 유형, 스멜이 발견된 정확한 위치, 수정 상태를 확인할 수 있습니다.

앞서 언급했듯이 스멜은 Reek에 의해 탐지되며, 이 페이지에서도 정렬과 필터링이 가능합니다.

클래스 이름을 클릭하면 코드 상세 정보가 담긴 페이지로 이동합니다. 또한 스멜 유형별로 클래스를 묶어서 볼 수도 있습니다(이 기능은 스멜 개수만 표시하는 'Code' 페이지에는 없는 기능입니다).

RubyCritic으로 Ruby 코드 품질 높이기: 시각적 분석과 지속적인 개선

Coverage 리포트

마지막으로 'Coverage' 리포트에서는 클래스 분류와 각 클래스의 커버리지 백분율을 확인할 수 있습니다. 다만 'Code' 및 'Smells' 리포트의 목록과 달리, 'Coverage'의 목록은 정렬과 필터링이 지원되지 않습니다.

코드 커버리지 백분율만 확인할 수 있으며, 추가 정보는 제공되지 않습니다.

RubyCritic으로 Ruby 코드 품질 높이기: 시각적 분석과 지속적인 개선

SimpleCov 리포트를 통합하면 이 페이지의 가치와 활용도를 더욱 높일 수 있습니다. 하지만 어느 쪽이든, 프로젝트의 테스트 커버리지를 간단히 점검할 리포트가 필요하다면 'Coverage' 리포트가 충분히 유용합니다.

마무리

이번 글에서는 Ruby 애플리케이션에서 RubyCritic이 주는 이점을 간략히 살펴본 후, 내부 의존성인 Reek, Flay, Flog를 자세히 알아보았습니다. 이어서 RubyCritic의 리포트를 읽고 분석하는 방법도 정리했습니다.

다음 단계로는 RubyCritic을 CI/CD 파이프라인에 통합하는 방법을 고민해 보시기 바랍니다.

즐거운 코드 리팩토링 되세요!

P.S. Ruby Magic의 글을 발행 즉시 받아보고 싶으시다면 Ruby Magic 뉴스레터를 구독하고 어떤 글도 놓치지 마세요!

RubyCritic으로 Ruby 코드 품질 높이기: 시각적 분석과 지속적인 개선

Brena Monteiro

게스트 저자 Brena Monteiro는 신입 개발자 멘토링에 열정을 가진 테크 리드(Tech Lead)로, 고성능 팀을 구성하고 이끈 경험이 풍부합니다. 확장 가능한 API와 클라우드 서비스 간 통합 구축 경험을 보유하고 있으며, 진화형 아키텍처(evolutionary architecture)에 관심이 많고 XR(Extended Reality) 앱렌티스로도 활동하고 있습니다.

Brena Monteiro의 모든 글 보기