1인 개발 초반 서버 구성: 맥미니 두 대와 외부 서비스 나눠 쓰기

8GB 맥미니 한 대로 시작했다가 배포용 M2와 개발용 M4로 나누고, 포트를 모두 닫은 뒤 개인 프로젝트는 집 서버에, 공개 서비스는 Cloudflare와 Supabase에 두게 된 과정을 정리했다.

맥미니 한 대로 시작하기

개발을 한다면 일관성 있는 개발 환경을 위해 개발 서버 구성을 생각하게 된다. 마침 집에 남는 맥미니 M2 모델이 있어서 이걸로 가볍게 시작하기로 했다. macOS에서 서버 사용을 위해 인터넷에서 필요한 설정을 찾아 이것저것 간단하게 설정하고 바로 사용할 수 있었다. 만약 남는 게 윈도우 PC였다면 리눅스를 깔아서 사용해도 좋다.

손바닥 위에 올린 맥미니. 서버로 쓰기에 부담 없는 크기다

뭔가 애매한 스펙

M2 맥미니는 램이 8GB였고, 생각보다 금방 막혔다. 메모리가 문제였다. DB 하나에 도커 컨테이너 두세 개만 띄워도, 그중 연산 서버까지 있으면 개발을 병행할 때 빠듯해진다. 에디터, 브라우저, 빌드까지 같이 돌아가니 여유가 남지 않았다. 그래서 M2는 배포 전담으로 두고, 실사용 중인 램 16GB의 M4 맥미니를 개발 전담으로 들였다.

외부 접속은?

외부에서 개발 서버에 붙기 위해 가장 쉽게 떠올릴 수 있는 방법은 공유기 포트포워딩으로 SSH를 여는 방법일 것이다. 보안 설정은 두 가지만 했다. 기본 포트를 바꾸고, 비밀번호 로그인을 막아 키 인증만 허용했다. 당장 쓰기엔 문제가 없었지만 계속 마음에 걸렸다. 혼자 개발하면서 서버 보안까지 빈틈없이 챙기는 건 현실적으로 어렵고, 설정을 아무리 해 둬도 집 IP가 외부에 노출되어 있다는 사실은 그대로 남는다. 유동 IP여서 가끔 바뀌면 원격 제어로 접속해서 IP를 확인하는 일도 귀찮았다. 애초에 좋은 방법은 아니었으니, 설정을 더 쌓기보다 애초에 포트를 열지 않는 구조로 바꾸기로 했다.

스펙도, 접속 경로도 문제가 생기니 슬슬 구조 변경이 필요함을 느끼게 되었다.

Tailscale과 Cloudflare Tunnel

Tailscale과 Cloudflare Tunnel 비교 이미지

결론부터 말하면, 지금은 공유기 포트를 모두 닫고, 외부 접속에 Tailscale과 Cloudflare Tunnel을 함께 쓴다. (처음에는 Cloudflare Tunnel만 사용했지만 immich를 설치하면서 Tailscale과 병행하게 되었다.)

Tailscale은 내 기기들끼리 사설 네트워크를 만들어 준다. 내 계정으로 로그인한 기기에서만 서버에 닿기 때문에, 관리자 페이지나 SSH처럼 나만 쓰면 되는 것에 맞았다. 1인 개발 서버를 운영하는 입장에서는 딱 적당하지만, 배포 서버로도 사용하려면 이것만으로 다 되는 것은 아니다.

어쨌든 배포 서버는 데이터라든지 일부 기능을 외부로 제공해야 하는 수요가 생길 수밖에 없다. Cloudflare Tunnel은 서버에서 Cloudflare 쪽으로 바깥 방향 연결을 맺고, 도메인으로 들어온 요청을 그 터널로 넘겨 준다. 서버 IP를 드러내지 않고도 외부에 웹앱을 공개할 수 있어서, 외부로 노출시키기 적당하다. 사실, Cloudflare Zero Trust를 붙이면 SSH도 인증을 거쳐 들어오도록 구성할 수 있어서 이것도 꽤 쓸 만했다.

Tailscale Cloudflare Tunnel
쓰는 곳 관리자 페이지, SSH 외부에 공유할 앱
강점 보안성 범용성, 사용성

써 보니 범용성과 사용성은 Cloudflare Tunnel이 앞섰고, 보안은 외부에서 아예 보이지 않는 Tailscale이 유리했다. 둘 중 하나를 선택한다면, 배포와 개발을 모두 가지고 가고 싶다면 Cloudflare Tunnel이 좋고, SSH 등 private한 기능만 빼고 싶다면 Tailscale이 적당했다.

집 서버는 private하게, 공개 서비스는 밖으로

컴퓨터를 사자니 너무 비싸고, 있는 자원을 쓰자니 부족하고… 그래서 외부 서비스를 사용하기 시작했다. 보통이라면 외부 배포 서비스를 먼저 사용할 텐데, 나는 반대였다. 접속 경로를 정리하고, 자원을 효율적으로 활용하기 위해 서버에 무엇을 올릴지도 다시 나누게 됐다. 기준은 외부에 노출되어도 되는가였다.

외부에 노출되면 안 되는 개인 프로젝트는 M2에서 돌린다. 연산 작업도 M2가 맡고, DB도 내부 접속만 허용한다. 외부로 나가는 경로를 최소한으로 줄여서 M2는 철저히 private하게 쓴다.

반대로 공개용 프로젝트는 모두 외부 서비스에 올린다. 프론트엔드와 웹앱은 Vercel이나 Cloudflare Pages, Workers로 배포하고, DB는 Supabase를 쓴다. 지금 운영 중인 정산 앱 ezSplit의 웹버전도 Cloudflare Workers에서 돌아간다. 이렇게 하니 집 서버가 트래픽을 버틸지 걱정할 필요가 없고, 공개 서비스 때문에 M2를 외부에 열어 둘 이유도 사라졌다.

비용도 부담이 없다. Cloudflare와 Supabase 모두 무료 티어가 넉넉해서 초기 단계에서는 차고 넘친다.

당분간은 이 구성으로

정리하면 M4에서 개발하고, 개인 프로젝트와 연산, 내부 DB는 포트를 닫은 M2에서 돌리고, 공개 서비스는 Cloudflare와 Supabase 같은 외부 서비스에 맡기는 구조다. 서비스가 커지면 그때 이전을 고민하겠지만, 어느 정도 트래픽이 생기고 수익이 생기기까지는 당분간 이 구성으로도 충분할 것이라 생각된다.

#서버#맥미니#Tailscale#Cloudflare Tunnel#Supabase