Kamal을 활용한 Basecamp Fizzy 배포 및 아키텍처 분석

Episode #539 - Cool Things in Fizzy

작성자
jeff
발행일
2025년 12월 08일

핵심 요약

  • 1 Basecamp의 Fizzy 애플리케이션을 Kamal을 활용하여 프로덕션 환경에 배포하고, 메인 브랜치와 분리된 프로덕션 브랜치로 변경 사항을 관리하는 과정을 상세히 설명합니다.
  • 2 Kamal을 통한 배포 시 필요한 비밀 키(secret_key_base, vapid keys)를 Rails Credentials로 안전하게 생성 및 관리하는 방법을 제시합니다.
  • 3 Fizzy 코드베이스에서 발견된 멀티테넌시 구현, 엔트로피 기반 자동 연기 로직, Active Job 확장 등 Basecamp 고유의 아키텍처 패턴을 분석합니다.

도입

Basecamp에서 새롭게 공개한 오픈소스 제품인 Fizzy 애플리케이션의 배포 및 아키텍처 분석에 대한 내용을 다룹니다. 본 영상은 Fizzy를 프로덕션 환경에 배포하는 실질적인 과정을 시연하며, 특히 최소한의 코드 변경으로 유지보수 가능한 배포 전략을 구축하는 데 중점을 둡니다. 또한, 일반적인 Rails 컨벤션에서 벗어난 Fizzy 코드베이스의 독특한 아키텍처 패턴들을 심층적으로 탐구하여 Basecamp의 개발 철학과 구현 방식을 이해하는 데 기여합니다.

Fizzy 애플리케이션 배포 및 관리 전략

1. 배포 환경 설정 및 브랜치 전략

Fizzy 애플리케이션은 GitHub에서 소스 코드를 복제(clone)하여 시작합니다. deploy.yml 파일을 수정하여 웹 서버 IP 주소, SSH 사용자, SSL 설정(Cloudflare 프록시 사용 시 false 권장), 그리고 완전한 도메인 이름(FQDN)을 구성합니다. 이때, 메인(main) 브랜치에 직접 변경 사항을 적용하는 것은 향후 충돌 위험을 높이므로, git stash를 사용하여 변경 사항을 임시 저장하고 production과 같은 별도의 브랜치를 생성하여 개인적인 변경 사항을 관리하는 것이 중요합니다. 메인 브랜치는 원본 Basecamp 코드를 유지하고, 주기적으로 git pull을 통해 최신 상태를 유지한 후, git rebase를 사용하여 production 브랜치에 병합함으로써 변경 사항을 통합하고 유지보수성을 확보합니다.

2. Kamal을 활용한 배포 및 비밀 키 관리

Kamal을 이용한 배포를 위해 kamal init 명령어를 실행하여 kamal/secrets.yml 파일을 생성합니다. 애플리케이션 운영에 필수적인 secret_key_base, vapid_public_key, vapid_private_keybin/rails credentials:edit 명령어를 통해 Rails Credentials 파일에 안전하게 저장합니다. Rails.application.credentials.vapid.public_key와 같이 접근할 수 있도록 네임스페이스를 설정하고, Rails 콘솔에서 직접 키를 생성하여 적용합니다. 이 과정을 통해 민감한 정보가 코드 저장소에 노출되지 않도록 관리합니다. kamal setup 명령을 실행하면 Docker 설치를 포함하여 서버 환경 설정 및 애플리케이션 배포가 진행됩니다.

Fizzy 코드베이스의 주요 아키텍처 패턴

1. Gemfile 및 데이터베이스 구성

Gemfile을 살펴보면 Rails를 GitHub의 main 브랜치에서 직접 사용하며, SQLite3와 Trilogy(MySQL용)를 모두 포함하여 개발자가 데이터베이스 선택의 유연성을 가질 수 있도록 합니다. 배포 시에는 database.sqlite.yml 파일이 기본적으로 활용됩니다.

2. 멀티테넌시 구현

Fizzy는 Account 모델의 slug를 활용하여 독특한 멀티테넌시를 구현합니다. URL에서 slug를 추출하여 해당 계정을 찾고, 이를 요청 수명 주기 초기에 전역적으로 설정하는 미들웨어 방식을 사용합니다. 이는 서브도메인, 별도 데이터베이스 또는 복잡한 라우팅 로직 없이 멀티테넌시를 효율적으로 해결하는 방법입니다.

3. 엔트로피 기반 자동 연기(Auto-postpone) 로직

Account Settings에 설정된 entropy 값(3일, 7일, 30일, 90일, 1년, 그리고 재미있는 내부 농담인 11일)에 따라 Card 모델의 entropic 모듈에서 관련 로직을 처리합니다. 매시간 실행되는 백그라운드 작업을 통해 특정 조건의 카드를 “나중에(not now)” 컬럼으로 자동으로 이동시키는 기능을 제공합니다.

4. Active Job 확장

멀티테넌트 환경에서 백그라운드 작업 시 current_account 컨텍스트가 손실되는 문제를 해결하기 위해 Active Job을 확장합니다. 작업이 직렬화될 때 현재 계정의 글로벌 ID를 저장하고, 작업 실행 시 이를 조회하여 current_attribute로 설정함으로써 백그라운드 작업에서도 올바른 계정 컨텍스트를 유지합니다.

5. 모델 중심의 비즈니스 로직 및 컨트롤러 구조

Fizzy는 services 폴더 없이 모든 비즈니스 로직을 모델 폴더 내에 포함하는 ‘풍부한 도메인 모델(Rich Domain Model)’을 채택합니다. concerns 대신 특정 모델에 종속된 모듈은 해당 모델의 네임스페이스 폴더(예: Card 모델의 assignable 모듈은 card/assignable.rb)에 위치시킵니다. 컨트롤러는 표준 CRUD 액션 외에 특정 작업을 위한 네임스페이스 컨트롤러(예: 카드 닫기를 위한 ClosuresController)를 사용하여 역할을 명확히 분리합니다.

6. Rails 내부 확장

멀티테넌시 지원을 위해 Action Text, Active Storage, Active Storage Variants와 같은 Rails 내부 컴포넌트에도 account_id 컬럼을 추가하여 확장합니다. 이는 Rails의 내부 구조를 깔끔하게 확장하는 모범 사례를 보여줍니다.

결론

본 에피소드는 Basecamp의 Fizzy 애플리케이션을 Kamal을 통해 성공적으로 배포하는 과정을 시연하며, 특히 유지보수 가능한 배포를 위한 브랜치 전략과 Rails Credentials를 활용한 보안 비밀 키 관리의 중요성을 강조합니다. 또한, Fizzy 코드베이스에 구현된 미들웨어 기반 멀티테넌시, 엔트로피 로직, Active Job 확장, 그리고 모델 중심의 풍부한 도메인 모델과 같은 독특한 아키텍처 패턴들을 심층적으로 분석하여 Basecamp의 혁신적인 Ruby on Rails 개발 접근 방식을 조명합니다. 이러한 분석은 일반적인 Rails 개발에서 벗어나 보다 효율적이고 견고한 애플리케이션을 구축하기 위한 영감을 제공합니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!