처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.04.19 19

루비 Path 메서드는 왜 느렸을까 — byroot가 풀어낸 경로 처리 최적화 이야기

Hacker News 원문 보기
루비 Path 메서드는 왜 느렸을까 — byroot가 풀어낸 경로 처리 최적화 이야기

작은 메서드가 만든 큰 병목

루비로 웹 서비스를 오래 운영해본 분들은 아마 한 번쯤 경험하셨을 거예요. 프로파일링을 돌려보니 File.expand_path, Pathname#join, File.dirname 같은 경로 처리 메서드들이 의외로 CPU 시간을 많이 먹고 있다는 사실 말이에요. 루비 코어 기여자로 유명한 byroot(Jean Boussier, Shopify에서 Ruby 성능 최적화를 주도하는 분이에요)가 최근에 이 부분을 어떻게 최적화했는지 블로그에 정리했는데, 우리가 평소 대수롭지 않게 쓰는 API가 내부적으로 얼마나 일을 많이 하는지 보여주는 좋은 사례라 한번 풀어볼게요.

왜 경로 처리가 병목이 되나

Rails 앱이 부팅되거나 require가 일어날 때, 루비는 로드 경로($LOAD_PATH)를 뒤지면서 파일을 찾아요. 이 과정에서 상대 경로를 절대 경로로 바꾸고, ...을 정리하고, 심볼릭 링크를 따라가는 작업이 수없이 반복돼요. 규모가 큰 앱은 부팅 시점에 이런 호출이 수만 번씩 일어나기도 해요. 메서드 하나가 0.01ms여도 3만 번이면 300ms가 되니까, 부팅 시간이나 요청 레이턴시에 직접 영향을 줘요.

기존 구현의 문제는 크게 두 가지였어요. 하나는 불필요한 문자열 할당이에요. 루비에서 문자열을 이어 붙이거나 자르면 새 객체가 생기는데, 경로 처리는 '부모 디렉토리 추출 → 결합 → 정규화' 같은 단계를 거치면서 중간 문자열을 여러 개 만들었어요. 이 객체들은 GC가 나중에 치워야 하니까 메모리 압박도 늘어나고요. 다른 하나는 C 레벨과 루비 레벨을 왔다갔다 하는 비용이에요. Pathname은 순수 루비로 구현된 클래스라서 내부에서 File.expand_path 같은 C 함수를 호출할 때마다 VM 스택을 오가요.

byroot가 적용한 기법들

블로그에서 소개된 최적화는 몇 가지 축으로 나뉘어요. 첫째, 인라인 문자열 처리예요. 예를 들어 File.dirname('/a/b/c.rb')를 하면 기존에는 내부적으로 문자열을 분리하고 다시 합쳤는데, 이걸 끝에서부터 슬래시 위치만 찾아 그 앞 구간을 잘라내는 방식으로 바꿨어요. 이게 뭐냐면, '/'의 인덱스를 memrchr 같은 저수준 함수로 찾으면 전체를 훑지 않아도 되고 중간 객체도 안 만들어지거든요.

둘째는 짧은 경로에 대한 패스트 패스예요. 실제 애플리케이션에서 다루는 경로는 대부분 수십 바이트 수준이에요. 그래서 일정 길이 이하면 스택 버퍼에 담아 처리하고, 그보다 길 때만 힙 할당을 해요. C 개발 경험 있는 분이면 익숙한 패턴인데, 작은 사이즈를 위한 최적화가 평균 케이스에서 크게 먹히는 경우죠.

셋째는 Pathname 메서드의 C 이식이에요. 자주 쓰이는 Pathname#join, Pathname#relative_path_from 같은 메서드를 C 확장으로 다시 써서 메서드 디스패치 오버헤드를 줄였어요. 루비는 메서드 호출 자체가 비싸기 때문에(캐시 미스, 인라인 캐시 등), 뜨거운 경로에 있는 메서드를 C로 내리면 효과가 큽니다.

성능 수치

블로그에 나온 벤치마크를 보면 주요 메서드에서 2배에서 많게는 5배 이상 빨라졌어요. 특히 Pathname#join 같은 건 기존 구현이 워낙 순수 루비였기에 개선 폭이 컸고요. 실제 Rails 앱 부팅 시간에 100~300ms 수준의 단축 효과가 있다는 리포트도 있어요. 이게 개발 서버에서는 사소해 보일 수 있는데, CI가 수천 번 돌거나 테스트가 수백 번 부팅되는 환경에서는 꽤 의미 있는 숫자예요.

업계 맥락에서 보면

Shopify는 수년째 루비 성능에 투자해왔어요. YJIT(Yet another Just-In-Time compiler)이 루비 3.2부터 기본 탑재된 것도 Shopify 엔지니어들이 주도한 결과고, 이번 경로 최적화도 같은 맥락이에요. '동적 언어는 느리다'는 통념을 인프라 레벨에서 정면으로 깨부수는 흐름이라고 볼 수 있어요. 파이썬 쪽에서도 Meta가 Cinder를 만들고, Faster CPython 프로젝트로 3.11, 3.12가 연속 속도 개선된 것과 비슷한 분위기죠.

흥미로운 건 최적화의 방향이에요. 과거에는 JIT 같은 큰 망치로 전체를 때렸다면, 요즘은 핫한 표준 라이브러리 메서드를 하나하나 프로파일링해서 갈아끼우는 접근이 동시에 가고 있어요. JIT은 사용자 코드의 루프를 빠르게 해주지만, 코어 API 자체가 무거우면 한계가 있거든요. 두 방향이 합쳐질 때 체감 속도가 확 올라와요.

한국 개발자에게

한국에서도 우아한형제들, 쏘카, 당근 일부 팀이 여전히 Ruby on Rails로 서비스를 운영 중이고, 스타트업 중에는 프로토타이핑을 Rails로 빠르게 하는 곳이 많아요. 루비 최신 버전을 따라가는 게 왜 중요한지 이번 사례가 잘 보여줍니다. 특히 CI 시간이 길어서 고민인 팀이라면 루비 버전업만으로도 무료 개선을 얻을 수 있어요. 반대로 오래된 루비에 머물러 있으면, 경쟁사가 동일 인프라 비용으로 더 많은 일을 처리하게 되는 거죠.

또 한 가지, 이 블로그 글 자체가 프로파일링-병목 식별-저수준 최적화의 교과서 같은 흐름을 보여줘요. 자기 서비스에서 stracerbspy 같은 도구로 핫스팟을 찾아본 적이 없다면, 주말에 한 번 돌려보시길 권합니다. 의외의 메서드가 CPU를 먹고 있는 걸 발견할 수 있어요.

마무리

핵심 한 줄로 정리하면, 동적 언어의 '편한 API'는 공짜가 아니고, 코어 기여자들이 그 비용을 C 레벨에서 꾸준히 깎아내고 있다는 거예요. 여러분은 어떤 언어/런타임의 어떤 메서드가 의외로 느렸던 경험이 있으신가요? 프로덕션에서 발견한 '범인 메서드'가 있다면 공유해주시면 재미있을 것 같아요.


🔗 출처: Hacker News

이 뉴스가 유용했나요?

이 기술을 직접 배워보세요

파이썬으로 자동화를 시작해보세요

파이썬 기초부터 자동화까지 실전 강의.

파이썬 강의 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.