개발을 하다 보면 이런 패턴을 한 번쯤은 접해봤을 겁니다. 메서드의 마지막 인자로 options 해시를 받아서 추가 파라미터를 처리하는 방식이죠: def hello_message(name_parts = {}) first_name = name_parts.fetch(:first_name) last_name = name_parts.fetch(:last_name) Hello, #{first_name} #{last_name} end 문제는 해시에서 파라미터를 일일이 꺼내야 한다는 점입니다. 정작 중요한 로직에 도달하기 전에
성능은 곧 기능입니다. 그리고 많은 성능 문제는 개발 단계에서 발견하고 해결할 수 있습니다. 하지만 프로덕션 환경에서만 나타나는 성능 저하라면 어떨까요? 모든 코드 줄마다 로그 메시지를 추가해야 할까요? 그건 오히려 애플리케이션을 더 느리게 만들 뿐입니다. 아니면 이러면 고쳐지려나? 하는 식의 자잘한 커밋을 수없이 쏟아붓으며 무엇이 효과가 있는지 지켜봐야 할까요? 사실 코드를 망가뜨리지 않고도 충분히 분석할 수 있습니다. 바로 rbtrace를 사용하는 것입니다. 실행 중인 Ruby 애플리케이션 추적하기 rbtrace를 사용하
새로 만든 작은 기능을 커밋하기 직전, 전체 통합 테스트를 돌립니다. 화면에 점들이 찍혀 나가기를 바라보며 기다리고 또 기다리던 어느 순간… ......FF.... :-( 테스트가 모두 끝나기까지는 아직 몇 분이나 남았습니다. 하지만 지금 실행을 중단하면 어떤 테스트가 실패했는지 전혀 알 수 없습니다. 과연 실패한 테스트를 보려면 전체 실행이 끝날 때까지 기다리는 수밖에 없을까요? Ctrl-T가 구원자입니다! 맥(Mac)을 사용하고 있다면 테스트 실패를 미리 확인할 수 있는 방법이 있습니다. 테스트가 실행되는 동안 Ct
Rails에서는 ID만 있으면 데이터베이스에서 여러 레코드를 손쉽게 가져올 수 있습니다. Person.where(id: [1, 2, 3]).map(&:id) # => [1, 2, 3] 그런데 만약 레코드를 다른 순서로 받아오고 싶다면 어떻게 해야 할까요? 예를 들어 검색 엔진이 관련도가 높은 순서대로 ID를 반환한다고 가정해 봅시다. 그렇다면 그 순서를 그대로 유지한 채 레코드를 가져오려면 어떻게 해야 할까요? 단순히 where를 다시 사용해 볼 수도 있습니다. Person.where(id: [2, 1, 3]).
최근에 Ruby를 업데이트하고 여러 프로젝트를 업그레이드하면서, 이전까지 몰랐던 RubyGems의 꽤 유용한 기능들을 발견하게 됐습니다. 알아두면 반복적인 번거로움을 크게 줄여주는 팁들이니 하나씩 살펴보겠습니다. 실행 파일이 구버전을 가리킬 때 저는 예전에 rvm으로 Ruby 버전을 관리했습니다. 하지만 마지막으로 개발 환경을 세팅할 때는 rvm 없이 써보기로 했습니다. Bundler가 있으면 Gemset이 필요 없고, Homebrew로도 Ruby를 최신 상태로 유지할 수 있기 때문입니다. 이 방식은 잘 작동합니다. Ruby를
잘못된 테스트로 가득한 코드를 다뤄본 적이 있다면 그 고통을 잘 알 것입니다. 버그 하나를 고칠 때마다 새로운 버그 다섯 개가 생기고, 코드가 제대로 동작하더라도 그것이 설계 의도에 따른 결과인지, 아니면 우연히 맞아떨어진 것인지 확신할 수 없기 때문입니다. 반대로, 아주 작은 기능 하나를 배포하기 위해 무려 200개에 달하는 테스트를 작성해야 하는 경우도 있습니다. 100% 테스트 커버리지를 채우려고 이미 잘 동작하는 코드를 계속 다시 설계해야 하고, 테스트를 가장 꼼꼼히 작성한 코드가 오히려 더 읽기 어려워진다는 느낌이 듭니다
Rails 앱이 느리게 동작하나요? 간단한 뷰 하나를 불러오는 데 몇 초씩 걸린다면, 파고들 가치가 있는 문제입니다. 원인은 데이터베이스 호출이 너무 많거나, 실행 속도가 느린 메서드일 수 있습니다. 아니면 누군가 코드에 넣어두고 잊어버린 성능 저하 루프일 가능성도 있죠. 앱의 병목 지점을 찾는 데 도움이 되는 도구는 매우 다양합니다. 몇 주 전에는 rbtrace에 대해 소개했는데요. New Relic의 rpm 젬 역시 앱 속도 개선에 큰 도움이 되었습니다. 하지만 제가 가장 선호하는 성능 문제 탐색 도구는 훨씬 더 강력합니
Rails 앱을 개발하다 보면 수많은 젬(gem)을 사용하게 됩니다. 어떤 젬들은 마치 마법처럼 느껴지기도 하는데요. 그렇다면 그 마법은 대체 어떻게 일어나는 걸까요? 사실 대부분의 젬이 하는 일은 여러분이 할 수 없는 것이 아닙니다. 그저 루비(Ruby) 코드일 뿐입니다. 물론 때로는 꽤 복잡한 루비 코드이긴 하지만요. 하지만 그 코드를 직접 탐색해 보면, 마법의 근원이 어디에 있는지 조금씩 이해하게 됩니다. 소스 코드 찾기 젬이 어떻게 동작하는지 이해하려면 먼저 그 코드를 찾아야 합니다. 특정 메서드에 대해 더 알고 싶다면 소스
레일스 역량 차트(Rails Competency Chart)라는 것을 보신 적 있나요? CodeFellows의 브룩 리지오(Brook Riggio)가 만든 이 차트는 현대적인 레일스 개발자가 알아야 할 모든 개념을 한눈에 보여줍니다. 직접 확인해 보세요: 벅차게 느껴지시나요? 마치 수백 개의 촉수를 휘저으며 달려드는 괴물처럼 보입니다. 레일스 학습이 부담스럽게 느껴지는 것도 당연합니다. SQL이나 배포(Deployment)처럼 그 자체로 하나의 커리어 경로가 될 수 있는 분야도 있고, 애플리케이션 아키텍처에는 몇 년을 투자
Ruby로 API를 래핑할 때는 반드시 설정(configuration) 방법이 필요합니다. 래퍼에 사용자 이름과 시크릿 키가 필요할 수도 있고, 호스트 주소만 필요할 수도 있죠. 이를 처리하는 방법은 여러 가지가 있습니다. 그렇다면 어떤 방식을 선택해야 할까요? 간단한 전역 설정 방식 서비스가 항상 곁에 있는 것처럼 동작하기를 원할 수 있습니다. 앱의 어디에서든 바로 사용할 수 있다면 얼마나 좋겠습니까. 그렇지 않으면 API를 사용하는 한 줄마다 설정하는 데 세 줄을 추가로 써야 하니까요! 상수나 클래스 속성을 사용해 설정을
Rails의 핵심 개념은 자신 있게 이해하고 있습니다. 동작하는 코드를 작성하는 것도 문제없죠. 게다가 요즘은 코드 품질, 리팩토링, 훌륭한 테스트 작성, 객체지향 설계에 대해서도 더 깊이 배워가고 있는 중입니다. 어느새 이제 감을 잡았다는 느낌이 들기 시작합니다. 전문가로 가는 길 위에 서 있다는 확신이 생기죠. 뒤돌아보면 얼마나 많은 발전을 이뤘는지 보이고, 그 성장에 꽤 만족스러운 마음이 듭니다. 그런데 왜 이렇게 느리다고 느껴질까요? 테스트, 유지보수성, 설계까지 신경 쓰기 시작하면서, 무언가를 출시하는 데 예전보다 훨씬 많
Ruby on Rails를 배우기 위한 책, 영상, 팟캐스트, 온라인 강의는 셀 수 없이 많습니다. 모든 자료를 다 살펴볼 시간은 절대 없겠죠! 그렇다면 프로그래밍을 처음 시작하는 입문자에게 가장 좋은 학습 방법은 무엇일까요? 어떤 리소스부터, 어떤 순서로 시작해야 할까요? 책과 웹사이트 프로그래밍이 완전히 처음이라면 크리스 파인(Chris Pine)의 『Learn to Program』부터 시작하는 것이 가장 좋습니다. 이 책은 꼭 알아야 할 핵심 프로그래밍 개념을 소개하는 입문서입니다. 특히 모든 예제가 Ruby로 작성되어 있
Rails의 스코프(scope)를 사용하면 원하는 레코드를 아주 손쉽게 조회할 수 있습니다. app/models/review.rb class Review < ActiveRecord::Base belongs_to :restaurant scope :positive, -> { where(rating > 3.0) } end irb(main):001:0> Restaurant.first.reviews.positive.count Restaurant Load (0.4ms) SELECT `restaurant
질문이 대기 중(pending), 승인(approved), 신고(flagged) 세 가지 상태 중 하나만 가질 수 있다고 상상해 보세요. 아니면 전화번호가 집, 사무실, 휴대폰, 팩스 중 하나로 분류되는 경우도 있겠죠(1982년이라면 말이지만요). 어떤 모델들은 이런 종류의 데이터를 필요로 합니다. 몇 가지 값 중 하나만 가질 수 있는 속성이며, 그 값의 집합은 거의 변하지 않는 것이죠. 순수 Ruby였다면 그냥 심볼(symbol)을 쓰면 되는 상황입니다. PhoneNumberType이나 QuestionStatus 같은 별도 모델을
제가 예전에 작성한 글의 댓글에서 Thom Parkin이 훌륭한 지적을 남겼습니다. 좋은 조언입니다. 하지만 아주 중요한 마지막 포인트 하나를 놓치셨네요. 여기가 오픈 소스라는 점을 생각해 보세요. 문서가 부족한 기능이나 함수의 세부 사항을 파악하게 됐다면, 직접 문서를 업데이트하고 풀 리퀘스트를 제출해야 합니다. 그러면 커뮤니티 전체가 혜택을 받고, 참여한 보람으로 코더 명성까지 얻을 수 있습니다! Thom이 이 이야기를 꺼내 줘서 정말 다행입니다. 너무나 중요한 부분이니까요. 문서를 고치는 일은 여러분이 사용하고 좋아
Rails 앱을 배포하는 방법을 찾아보다 보면 Apache, Unicorn, Puma, Phusion Passenger, Nginx, Rainbows 등 수많은 이름을 마주하게 됩니다. 이 도구들은 모두 Rails 배포라는 범주에 속해 보이지만, 그 사이에는 중요한 차이가 있습니다. 어떤 것은 웹 서버이고, 어떤 것은 앱 서버입니다. 두 개념의 차이와 각각이 시스템에서 담당하는 역할을 이해하면, 배포 과정이 훨씬 명확하게 다가옵니다. 다만 두 범주의 경계가 항상 뚜렷하지는 않습니다. 웹 서버란 무엇이고, 앱 서버와는 어떻게 다를
Ruby 컨퍼런스는 정말 매력적입니다. 수많은 사람들이 방대한 지식을 나누기 때문에 거의 모든 발표에서 얻어가는 것이 있습니다. 게다가 현장에 직접 가지 못하더라도, 새로운 컨퍼런스가 열릴 때마다 새로운 발표 영상이 쏟아져 나옵니다. 하지만 문제가 하나 있습니다. 영상은 시간이 든다는 점입니다. 1.5배속으로 재생해도 발표 하나당 20~30분은 그대로 걸립니다. 그리고 이렇게 집중해서 시청할 시간은 생각만큼 자주 확보하기 어렵습니다. 반면 팟캐스트는 이미 일상 깊숙이 자리 잡고 있는 콘텐츠입니다. 출근길이 시작되면 거의 항상 O
Rails는 왜 그토록 빠르게 인기를 얻었을까요? 단순함이 한몫했습니다. 특히 Java, XML, 엔터프라이즈 개발 세계에서 온 사람들에게는 더욱 그랬죠. 마케팅도 놀라울 정도로 잘 되었습니다. 하지만 그게 전부는 아닙니다. 스타트업 세계에서 Rails가 성공한 데에는 하나의 단순한 사실이 자리하고 있습니다. 바로 기업들이 겪는 문제는 그리 독특하지 않다는 것입니다. Rails는 유연성을 잃지 않으면서도 CRUD 사이트를 만드는 데 탁월했습니다. 그리고 수많은 기업에게 필요한 것은 사실상 그게 전부입니다. 특히 초기 단계에서는 더욱
스코프(Scope)는 데이터베이스에서 원하는 객체를 손쉽게 가져오는 훌륭한 도구입니다. app/models/review.rbclass Review < ActiveRecord::Base scope :most_recent, -> (limit) { order(created_at desc).limit(limit) } end 스코프는 다음과 같이 호출해서 사용합니다. app/controllers/homepage_controller.rb@recent_reviews = Review.most_recent(5) 그런데 잘 보면
이상하고 도무지 해결되지 않는 버그를 만났을 때, 로깅을 개선하는 것이 가장 확실한 첫걸음일 수 있습니다. 훌륭한 로깅은 한 부류의 버그 전체를 탐지하고 수정하는 가장 쉬운 방법입니다. 충분한 정보를 로그로 남기면 요청(request) 처리 과정에서 데이터가 어떻게 변화하는지 확인할 수 있고, 다른 서비스로 보내는 호출을 추적하며 그 응답까지 조사할 수 있습니다. 실제로 저는 디버거로도 잡지 못했던 인생 최고의 난항이었던 버그를 로깅 덕분에 해결한 적이 있습니다. 하지만 로그를 너무 많이 남기면 로그 파일은 순식간에 읽을 수도,