개발자의 장난감, 홈서버에 나만의 CI/CD를 구축해 보자

Admin LeeJul 11, 202611 min read15 views

핵심 3줄 요약

  • 메모리와 자원이 부족한 홈서버 환경에서도 Gitea와 Woodpecker CI 조합은 놀라울 정도로 쾌적하게 동작하는 최적의 솔루션입니다.
  • 인터넷망에 의존하지 않는 로컬 서버망 내부에서 빠르고 제한 없는 나만의 무제한 빌드 및 배포 자동화 파이프라인을 완전히 소유할 수 있습니다.
  • 도커 컴포즈를 통해 우아하게 인프라를 관리할 수 있으며, 리버스 프록시를 통한 암호화 적용 및 정기적 백업 파이프라인 연동은 안전한 운영의 필수 조건입니다.

개발자의 장난감, 홈서버에 나만의 CI/CD를 구축해 보자

집 한구석이나 신발장 위에서 밤낮없이 조용히 쿨링팬을 돌리며 돌아가고 있는 여러분의 홈서버, 지금 어떤 용도로 활약하고 있나요? 아마 대부분의 분들이 영화를 스트리밍하기 위한 미디어 서버나 소중한 가족 사진을 보관하는 개인용 NAS 용도로 훌륭하게 사용하고 계실 거라 생각합니다. 하지만 뼛속까지 개발자의 DNA가 흐르는 우리들에게, 이 24시간 꺼지지 않는 훌륭한 컴퓨팅 자원을 그저 파일 저장소로만 놀려두는 것은 너무나도 아까운 일이죠.

그래서 오늘은 조금 더 개발자의 본능을 자극하는 깊이 있는 주제를 다루어 보려고 합니다. 바로 외부의 무겁고 값비싼 클라우드 플랫폼에 의존하지 않고, 오직 내 홈서버 내부에서 독립적으로 쌩쌩하게 돌아가는 셀프 호스팅 기반의 완벽한 CI/CD 파이프라인을 내 손으로 직접 구축하는 짜릿한 경험에 대한 이야기입니다.

물론 깃허브 액션이나 깃랩 CI처럼 이미 너무나도 잘 만들어진 훌륭한 무료 클라우드 서비스들이 차고 넘치는데, 굳이 퇴근하고 피곤한 몸을 이끌고 집에서까지 인프라 세팅을 해야 하냐고 반문하실 수도 있습니다. 하지만 개인적인 토이 프로젝트의 덩치가 커지고 이것저것 무거운 도커 이미지를 굽는 실험을 반복하다 보면, 어느 순간 무료 티어가 제공하는 한 달 빌드 시간 제한에 턱 하고 걸려서 답답했던 경험이 다들 한 번쯤은 있으실 겁니다.

게다가 절대 외부에 퍼블릭으로 공개하기 꺼려지는 극비(?)의 개인 프로젝트나, 우리 집 공유기 내부의 로컬 네트워크망 안에서만 안전하게 실행되어야 하는 특수한 자동화 스크립트들을 돌릴 때는 홈서버 내부에서 통제되는 나만의 자체 CI/CD 환경이 클라우드보다 압도적으로 편리하고 빠릅니다. 자, 그럼 가벼우면서도 상상 이상으로 강력한 퍼포먼스를 내주는 두 단짝, Gitea와 Woodpecker CI의 매력적인 세계로 함께 들어가 볼까요?

수많은 도구 중 왜 하필 Gitea와 Woodpecker CI 조합일까?

세상에는 정말 수많은 셀프 호스팅 도구들이 존재하지만, 제가 수년간의 삽질 끝에 이 두 가지의 조합에 정착하고 강력히 추천하는 데에는 아주 명확하고 기술적인 이유가 있습니다.

첫 번째 주인공인 Gitea는 그야말로 경량화의 예술을 보여주는 도구입니다. 엔터프라이즈 환경에서 많이 쓰는 깃랩은 기능이 어마어마하게 방대하고 훌륭하지만, 그만큼 최소 구동에만 수 기가바이트의 메모리를 잡아먹는 하마입니다. 리소스가 한정적인 구형 미니 PC나 라즈베리파이 같은 척박한 홈서버 생태계에서는 띄워놓는 것 자체로 서버가 숨을 헐떡이게 되죠. 반면 Gitea는 Go 언어로 극도로 최적화되어 작성되어 있어서, 놀라울 정도로 가벼우면서도 우리가 평소에 깃허브에서 숨 쉬듯이 사용하는 핵심 기능들, 즉 이슈 트래커, 풀 리퀘스트, 코드 리뷰 시스템 등을 거의 완벽하게 동일한 감각으로 지원합니다. UI 디자인 구조도 매우 친숙해서 따로 매뉴얼을 읽을 필요조차 없이 곧바로 실무에 투입할 수 있습니다.

이런 훌륭한 Gitea의 파트너로 낙점된 두 번째 주인공 Woodpecker CI 역시 가벼움에 있어서는 타의 추종을 불허합니다. 과거 꽤 인기를 끌었던 Drone CI의 오픈소스 포크 버전으로 뼈대를 다진 이 프로젝트는, 태생부터 Gitea와의 찰떡궁합을 목표로 진화해 왔습니다. 복잡하고 머리 아픈 환경 설정 없이, Gitea 설정 화면에서 OAuth2 애플리케이션으로 Woodpecker를 툭 하고 등록해 주기만 하면 두 시스템의 인증과 권한이 마법처럼 매끄럽게 연동됩니다.

또한 파이프라인의 동작을 정의하는 야멜 파일 역시 문법이 굉장히 직관적입니다. 무엇보다 빌드의 각 스텝이 완전히 독립된 임시 도커 컨테이너 내부에서 격리되어 샌드박스 형태로 실행되었다가 흔적도 없이 사라지기 때문에, 홈서버의 호스트 운영체제 환경에 잡다한 패키지가 깔리거나 쓰레기 파일이 남아서 더럽혀질 걱정을 원천적으로 차단해 줍니다.

도커 컴포즈로 조립하는 우아하고 깔끔한 인프라

복잡해 보이는 이 모든 자동화 시스템을 실제로 구축하는 과정은 여러분의 예상보다 훨씬 단순하고 우아합니다. 이미 홈서버에 여러 컨테이너를 띄워보신 분들이라면 너무나도 익숙하실, 잘 짜인 도커 컴포즈 파일 하나면 모든 준비가 끝나거든요. 리눅스 패키지 매니저로 호스트에 직접 이것저것 지저분하게 설치할 필요가 전혀 없습니다.

마치 규격이 딱 들어맞는 레고 블록을 조립하듯이 컴포즈 파일 안에 Gitea 웹 서버 컨테이너, 데이터를 든든하게 저장해 줄 PostgreSQL 데이터베이스 컨테이너, 전체 파이프라인을 지휘할 Woodpecker 컨트롤러 서버, 그리고 실제로 땀을 흘리며 코드를 빌드하고 테스트하는 작업을 수행할 Woodpecker 에이전트 컨테이너를 정의해 줍니다. 이들을 전용 도커 브릿지 네트워크로 예쁘게 묶어주고 환경 변수 몇 개만 설명서대로 맞춰준 뒤, 마법의 주문 한 줄을 입력하면 끝입니다.

이 구조의 진정한 묘미는 무한한 확장성에 있습니다. 기본적으로는 에이전트 하나만 띄워도 훌륭하지만, 만약 거실 서랍장에 굴러다니는 구형 안드로이드 스마트폰이나 화면이 깨진 고물 노트북이 있다면 어떨까요? 그곳에 리눅스를 올리고 Woodpecker 에이전트 컨테이너만 달랑 하나 띄워서 홈서버의 마스터와 연결해 보세요. 무거운 도커 이미지 빌드 작업은 거실의 고물 노트북이 전담해서 처리하는, 나만의 귀여운 분산 처리 클러스터 아키텍처를 돈 한 푼 안 들이고 구성하는 긱(Geek)스러운 즐거움을 맛볼 수 있습니다.

코드 작성부터 배포까지, 나만의 자동화 공장 돌리기

인프라가 든든하게 올라갔다면 이제 우리의 개발 삶을 윤택하게 만들어줄 짜릿한 자동화의 맛을 제대로 볼 차례입니다. 로컬 PC의 IDE에서 열심히 코드를 수정하고 Gitea 원격 저장소에 푸시를 날리는 그 찰나의 순간, Gitea의 웹훅이 빛의 속도로 Woodpecker 컨트롤러의 옆구리를 찌르며 파이프라인 톱니바퀴가 경쾌하게 돌아가기 시작합니다.

이 자동화 공장의 컨베이어 벨트 위에서는 어떤 멋진 일들이 벌어질 수 있을까요?

  1. 무자비한 코드 검증과 린팅: 내가 새벽 감성으로 짠 코드가 팀의 엄격한 포맷 컨벤션을 위반하지는 않았는지, 로직에 치명적인 버그가 숨어있지 않은지 미리 작성해 둔 수십 개의 유닛 테스트 코드들이 병렬로 실행되며 깐깐하게 검증을 수행합니다.
  2. 도커 이미지 무한 구워내기: 테스트를 완벽하게 통과한 자랑스러운 코드들은 그 즉시 애플리케이션이 실행될 수 있는 도커 이미지로 예쁘게 포장되어 빌드됩니다. 그리고 구름 너머의 도커 허브로 가는 대신, 홈서버 구석에 몰래 구축해 둔 나만의 프라이빗 레지스트리 창고에 차곡차곡 안전하게 푸시되어 쌓입니다.
  3. 손 안 대고 코 푸는 자동 배포: 새롭게 구워진 따끈따끈한 이미지는 배포 스크립트를 타고 넘어가, 현재 홈서버에서 서비스 중인 낡은 컨테이너를 부드럽게 종료시키고 새로운 버전의 애플리케이션 컨테이너를 곧바로 띄워 올립니다. 이 모든 과정이 무중단에 가깝게 롤링 업데이트로 처리될 수도 있습니다.

우리가 한 일이라고는 그저 터미널에서 엔터키를 쳐서 코드를 푸시하고, 방으로 걸어가서 따뜻한 커피 한 모금을 마신 것뿐입니다. 그 짧은 몇 분의 시간 동안 이 모든 복잡하고 지루한 배포 과정이 백그라운드에서 오차 없이 자동으로 완벽하게 이루어집니다. 더 이상 떨리는 손으로 서버에 SSH로 접속해서 옛날 폴더를 백업하고, 풀을 받고, 데몬을 수동으로 재시작하며 식은땀을 흘리던 원시적인 노동 방식과는 영원히 작별하는 것이죠.

홈서버 운영의 딜레마, 보안과 백업은 선택 아닌 필수

하지만 이렇게 아름답고 편리한 나만의 시스템을 운영할 때, 절대로 한순간도 긴장의 끈을 놓아서는 안 되는 아주 중요한 대전제가 두 가지 있습니다. 시스템이 집 안에 있다고 해서 결코 위험으로부터 100% 안전한 것은 아니며, 보안과 백업의 부재는 언젠가 반드시 처참한 재앙으로 돌아오기 때문입니다.

만약 외부 카페나 회사에서도 코드에 접근하기 위해 Gitea와 Woodpecker의 웹 대시보드를 공유기 밖 인터넷에 노출시킬 계획이라면, Nginx Proxy Manager나 Traefik 같은 리버스 프록시를 문지기로 세워 반드시 철저한 HTTPS 암호화 통신을 강제해야 합니다. 비밀번호가 평문으로 네트워크를 떠돌아다니는 끔찍한 일은 막아야 하니까요. 또한 봇들의 무차별적인 비밀번호 대입 공격을 막기 위해 Fail2ban 같은 방패막이를 구축하는 것도 매우 훌륭한 실무적 접근입니다.

그리고 이 모든 것보다 더 중요한 최우선 과제는 바로 집착에 가까운 백업입니다. 하드디스크는 우리의 생각보다 훨씬 연약한 부품이며, 어느 날 갑자기 끼릭거리는 소음과 함께 여러분의 수년간의 피땀 어린 소스 코드와 커밋 히스토리를 안고 산화해 버릴 수 있습니다. Gitea의 데이터베이스 덤프 파일과 리포지토리의 실제 데이터 볼륨은 반드시 물리적으로 분리된 외부 스토리지나 저렴한 클라우드 오브젝트 스토리지로 매일 새벽 암호화되어 전송되도록 설정해야 합니다. 앞서 정성 들여 구축한 바로 그 Woodpecker 파이프라인을 영리하게 활용해서, 매일 밤 정해진 시간에 크론잡처럼 백업 스크립트가 알아서 실행되도록 파이프라인을 하나 더 만들어 둔다면 정말 우아하고 완벽한 홈서버 생태계가 완성될 것입니다.

로컬 환경에 구축하는 CI/CD의 진정한 철학적 가치는, 단순히 명령어 타이핑을 치는 물리적 시간 몇 초를 아껴주는 데 있는 것이 아닙니다. 배포 과정에서 필연적으로 발생하는 휴먼 에러의 가능성을 시스템적으로 원천 차단하고, 개발자인 우리가 온전히 비즈니스 로직을 치열하게 고민하고 아키텍처를 설계하는 본연의 창조적인 업무에만 100% 몰입할 수 있도록 아주 쾌적하고 든든한 울타리를 만들어준다는 점에 있습니다. 돌아오는 주말, 넷플릭스 정주행은 잠시 미뤄두고 여러분의 방구석 서버에 이 작고 강력한 마법의 자동화 공장을 꼭 한번 건설해 보시기를 진심으로 권해드립니다!

This post was drafted with the help of AI tools and personally reviewed and edited.

Share:

Thanks for reading!

If you found this post useful, check out more articles on the homepage.

Read More Posts