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

잘 알려지지 않았지만 강력한 루비 젬(Ruby Gem) 7가지

Rails 프로젝트에서 활용할 수 있는 최고의 루비 젬(Ruby Gem)은 무엇일까요?

이 글에서 그 답을 확인할 수 있습니다!

흔히 소개되는 유명한 젬이 아니라, 실제로 매우 유용하지만 아직 잘 알려지지 않은 젬 7가지를 소개해 드리겠습니다.

그 전에 한 가지 주의사항을 먼저 말씀드립니다.

젬 남용에 대한 경고

개발자 중에는 조금이라도 쓸모 있어 보이면 무조건 젬을 추가하는 경우를 종종 볼 수 있습니다.

그 젬이 정말 자신의 문제를 해결해 주는지, 최선의 선택인지, 꾸준히 유지보수되고 문서화가 잘 되어 있는지 고민하지 않고 말입니다.

이것은 실수입니다.

왜일까요?

프로젝트가 의존하는 요소가 많아질수록, 환경이 변할 때 무언가 깨질 가능성도 커지기 때문입니다.

그리고 변화는 언제나 일어납니다.

새로운 Rails 버전, 새로운 루비 버전, 새로운 기능 등 끊임없이 바뀌죠.

다만 이렇게 말씀드린 이유는

젬을 사용하면 많은 작업을 줄일 수 있고, 코드를 깔끔하게 유지하며, 보안 문제까지 예방할 수 있습니다. 현명하게 사용하세요!

자, 이제 목록을 살펴보겠습니다.

1. traceroute — 죽은 라우트를 찾아 코드를 깔끔하게 유지하기

Rails 애플리케이션이 커질수록 라우트도 계속 늘어나게 됩니다.

코드를 수정하다 보면 일부 라우트가 더 이상 사용되지 않는 상태가 되기 마련입니다.

필요 없어졌는데도 config/routes.rb에 그대로 남아 관리를 어렵게 만들죠.

어떤 라우트를 삭제해야 할지 어떻게 알 수 있을까요?

traceroute라는 젬이 도움이 됩니다.

이 젬은 라우트를 로드한 뒤, 실제로 정의된 컨트롤러 액션과 비교합니다.

다만 현재 두 가지 한계가 있습니다:

  1. Rails 6와 호환되지 않음
  2. 암시적(implicit) 컨트롤러 액션을 감지하지 못함

필자는 Rails 6 지원을 추가하는 풀 리퀘스트를 보냈고, 동시에 이런 제약이 없는 자체 버전도 만들었습니다.

2. strong_migrations — 마이그레이션을 안전하게 만들기

Rails 마이그레이션은 잘못 사용하면 큰 문제를 일으킬 수 있습니다.

예를 들면:

컬럼을 삭제하는 작업은 문제를 일으킬 수 있습니다. Rails는 컬럼 정보를 캐싱하는데, 마이그레이션을 실행해도 이 캐시가 초기화되지 않기 때문입니다.

또 다른 예:

PostgreSQL을 사용 중인 상태에서 인덱스를 추가하면, 작업이 완료될 때까지 테이블 전체가 잠깁니다.

사용자에게 좋지 않겠죠.

잠긴 테이블에 접근해야 하는 요청에는 애플리케이션이 응답할 수 없습니다.

좋은 소식은?

이런 사항들을 전부 외울 필요가 없다는 점입니다.

strong_migrations 젬을 사용하면, 위험한 마이그레이션이 프로덕션에 배포되기 전에 미리 경고를 받을 수 있습니다.

3. isolator — 안전하지 않은 트랜잭션 방지하기

Rails의 트랜잭션은 원래 "전부 아니면 전무(all or nothing)" 방식으로 동작해야 합니다.

형태는 다음과 같습니다:

Book.transaction do
  # ...
end

하지만 파일에 쓰기를 하거나 API를 호출하는 것처럼 트랜잭션 통제 밖의 작업을 수행하면, 이 "전부 아니면 전무"의 보장은 더 이상 유효하지 않습니다.

짐작하시겠지만, 이로 인해 여러 가지 문제가 발생합니다.

해결책은?

거창한 기술은 아닙니다. 트랜잭션의 "외부 세계"에 영향을 주는 부수 효과(side effect)를 피하는 것입니다.

isolator 젬이 이 작업을 도와줍니다.

모든 트랜잭션을 감사하여 안전한지 확인해 줍니다.

설치만 하면 되고, 문제가 있는 transaction을 감지하면 예외를 발생시킵니다.

직접 사용해 보세요!

4. test-prof + ruby-prof — 느린 테스트를 찾아 속도 개선하기

느린 테스트는 누구에게나 고통스럽습니다.

다행히 테스트가 왜 느린지 찾아내고 해결할 수 있는 도구가 있습니다!

그중 하나가 test-profruby-prof의 조합입니다.

사용 방법은 다음과 같습니다:

TEST_RUBY_PROF=1 rake

출력 결과:

%self      total     self      wait      child     calls   name
 43.21      2.001     2.001     0.000     0.000        1   Kernel#sleep
  2.97      0.184     0.138     0.000     0.046     1640   Array#permutation
  1.39      0.064     0.064     0.000     0.000      144   PG::Connection#async_exec

여기서는 sleep 호출이 명확히 보이지만, 실제로는 API 호출, 대용량 파일 읽기, 느린 SQL 쿼리 등일 수도 있습니다.

또한 이벤트 프로파일러를 활용할 수도 있습니다.

이렇게 말입니다:

EVENT_PROF='sql.active_record' EVENT_PROF_EXAMPLES=1 rake

이 명령은 어떤 테스트가 가장 느린 쿼리를 실행하는지 찾는 데 도움이 됩니다.

참고로 Rails 6부터는 병렬 테스트(parallel testing)가 추가되었으며, 기존 프로젝트를 업그레이드하는 경우 test/test_helpers.rb에서 직접 활성화해야 합니다.

5. database_consistency — 데이터 일관성 높이기

밸리데이션(유효성 검사)은 훌륭한 기능입니다.

하지만 어떤 프레임워크로 웹 애플리케이션을 만들든 마찬가지입니다.

데이터베이스에 직접 데이터를 가져오거나, raw SQL로 레코드를 생성하거나, ORM에서 밸리데이션을 건너뛰는 메서드를 사용하면 얼마든지 밸리데이션을 우회할 수 있습니다.

즉,

밸리데이션은 사용자의 실수로부터는 보호해 주지만, 개발자의 실수로부터는 보호해 주지 못합니다.

이러한 개발자 실수는 데이터 불일치로 이어질 수 있습니다.

좋은 소식은?

대부분의 최신 SQL 데이터베이스는 "제약 조건(constraints)"을 지원합니다. 밸리데이션과 비슷한 규칙 집합이지만, 데이터베이스 수준에서 적용됩니다.

따라서 데이터 일관성을 높이려면 이 제약 조건을 구현해야 합니다.

database_consistency 젬이 이 작업을 도와줍니다.

사용 방법은?

먼저 설치합니다. 특별할 것 없습니다.

다음으로, 검사하려는 프로젝트 내에서 터미널에 bundle exec database_consistency를 실행합니다.

그러면 다음과 같은 리포트가 생성됩니다:

fail Comment title column should be required in the database
fail Comment author column should be required in the database

다음 단계는?

누락된 데이터베이스 제약 조건을 추가하면 됩니다. 위 예시의 경우 change_column_null 마이그레이션으로 not-null 제약을 걸어주면 됩니다.

6. attractor — 리팩토링 시간! 코드에서 가장 문제가 되는 부분은 어디일까?

코드를 개선하고 싶은데 어디서부터 시작해야 할지 모르겠나요?

메트릭(측정 지표)을 확인해 보세요!

순환 복잡도(cyclomatic complexity)나 체인(churn) 같은 다양한 코드 메트릭이 있습니다. 체인은 코드가 시간에 따라 변경되는 빈도를 측정합니다.

어떻게 측정할까요?

git 변경 이력을 활용합니다.

결과는?

가장 자주 변경되는 파일들의 목록입니다.

작업 시간의 90%를 User 모델 수정에 쓰고 있다면... 아마 거대한 파일에 긴 메서드들이 가득한 코드일 겁니다. 리팩토링의 최고 후보죠!

이렇게 끊임없이 변경되는 파일을 찾는 데 도움이 되는 젬이 attractor입니다.

실행 방법:

attractor report -p app

HTML 리포트와 함께 체인이 높은 파일 목록을 생성해 주므로, 리팩토링 노력을 어디에 집중할지 판단할 수 있습니다.

정말 유용한 도구입니다!

7. coverband — 프로덕션에서 실제 사용되는 코드와 그렇지 않은 코드 찾기

마지막으로 코드 개선에 도움이 되는 또 다른 도구를 소개합니다.

coverband입니다.

이 젬을 프로덕션에서 실행하면(오버헤드가 낮습니다), 실제로 실행 중인 코드에 대한 커버리지 리포트를 받을 수 있습니다.

사용되지 않는 뷰(view)까지 추적할 수 있습니다!

잘 알려지지 않았지만 강력한 루비 젬(Ruby Gem) 7가지

이 정보는 코드를 삭제하고 프로젝트를 정리할 때 의사 결정에 큰 도움이 됩니다.

사용하지 않는 코드가 쌓이게 두지 마세요!

마치며

이번 글에서는 테스트 속도를 개선하고, 코드 품질을 높이며, 안정성을 강화하는 데 활용할 수 있는 강력하면서도 잘 알려지지 않은 루비 젬 7가지를 살펴보았습니다.

젬 남용에 대한 작은 경고를 기억하되, 새로운 젬을 시도하는 데에는 주저하지 마세요.

루비 실력을 향상시키고 싶으시다면, 필자의 루비 책 『Ruby Deep Dive』를 참고해 보세요. 🙂

읽어주셔서 감사합니다!