애플리케이션 성능 최적화는 단순히 코드 개선을 넘어 하드웨어의 특성과 데이터 흐름을 이해하는 것에서 시작됩니다. 특히 CPU 캐시(L1, L2, L3)의 중요성은 간과되기 쉬우나, RAM이나 SSD보다 훨씬 빠른 데이터 접근 속도를 제공하므로 이를 효과적으로 활용하는 것이 핵심입니다. 강연자는 간단한 연산의 경우 CPU에서 직접 계산하는 것이 캐시에 저장하는 것보다 빠를 수 있음을 지적하며, 캐싱이 항상 최적의 해답은 아니므로 애플리케이션의 특성과 하드웨어 환경에 맞는 벤치마킹을 통해 최적의 전략을 수립해야 한다고 강조합니다.
강연에서는 Raspberry Pi 3 모델을 기반으로 하는 웹샵 애플리케이션을 예시로 들어, 초기 벤치마크(약 30,000밀리초)를 기준으로 다양한 최적화 기법을 적용하고 그 효과를 측정합니다. 주요 최적화 기법은 다음과 같습니다:
select
메서드 활용: Active Record 쿼리 시 필요한 컬럼만 명시적으로 선택하여 로드함으로써 메모리 사용량을 줄이고 캐시 효율을 높입니다. 예를 들어, 카테고리의 불필요한 설명을 로드하지 않음으로써 약 3%의 성능 향상을 달성했습니다.- 데이터 타입 최적화: 데이터베이스 컬럼의 데이터 타입을 실제 데이터 범위에 맞게 조정하여 저장 공간을 절약하고 캐시 효율을 극대화합니다. 예를 들어, 0-5 범위의 별점에는
integer
대신tinyint
를 사용하여 저장 공간을 50-90% 절약할 수 있으며, 이는 L1/L2 캐시 적중률 향상으로 이어져 전반적인 속도 개선에 기여합니다. - 인덱스 추가: 데이터베이스 쿼리 속도를 향상시키기 위해 적절한 인덱스를 추가하는 것은 필수적입니다. 강연자는 복합 인덱스 사용 시 왼쪽 컬럼만으로도 인덱스 활용이 가능하므로 중복 인덱스를 제거하여 공간을 효율적으로 사용할 수 있는 팁을 제공하며, 이를 통해 약 6%의 성능 향상을 얻었습니다.
- 프래그먼트 캐싱 및 러시안 돌 캐싱: 뷰의 특정 부분을 캐시하여 렌더링 시간을 단축하는 강력한 기법입니다.
updated_at
속성을 캐시 키로 활용하고, 연관된 부모 레코드 변경 시 자식 레코드의updated_at
을 자동으로 업데이트하는touch
옵션을 사용하여 캐시 무효화를 효율적으로 관리합니다. 이 기법은 약 60%에 달하는 가장 큰 성능 개선 효과를 가져왔습니다. - HTTP 캐싱 (ETag, Last-Modified): 컨트롤러 수준에서 HTTP 헤더(ETag, Last-Modified)를 사용하여 클라이언트(브라우저)가 이미 가지고 있는 페이지가 변경되지 않았을 경우, 서버가 HTML을 다시 렌더링하지 않고 304 Not Modified 응답을 보내도록 합니다. 이는 서버의 부하를 줄이고 클라이언트로의 전송량을 감소시켜 응답 속도를 향상시킵니다.
strong ETag
와Last-Modified
를 함께 사용하는 것이 권장되며, 이를 통해 약 2%의 추가적인 성능 향상을 달성했습니다. - 정적 페이지 생성 (Autobahn): 자주 접근되는 페이지(예: 제품 상세 페이지)의 정적 HTML 복사본을 파일 시스템에 저장하고 Nginx와 같은 웹 서버를 통해 직접 서비스하여 Rails 애플리케이션을 거치지 않도록 합니다. 이는 가장 빠른 페이지 제공 방식 중 하나입니다. Brolti와 같은 최신 압축 기술을 적용하여 전송 효율을 높이고, 유효 기간이 있는 제품의 경우 매일 정적 파일을 재생성하는 Cron 작업을 설정하여 최신 정보를 유지합니다. 이 전략을 통해 동일 하드웨어에서 10배 이상의 트래픽을 처리할 수 있는 능력을 확보했습니다.
이러한 종합적인 최적화 노력을 통해 초기 30,000밀리초였던 응답 시간을 약 3,500밀리초(약 10%) 수준으로 단축하는 데 성공했습니다.