맥북 서버 탈출기

[맥북 서버 탈출기 1편] 내 앱 서버는 맥북 에어였다

TerryDev 2026. 10. 15. 14:16

이 글 요약

  • 개인 앱 2개의 백엔드를 맥북에서 운영하던 구조와, 그게 위험했던 이유 4가지
  • 이사를 결심하게 만든 "사라진 터널 설정 파일" 사건
  • 이사 목표, 그리고 AI 코딩 에이전트에게 일을 맡긴 방식

몇 달 동안 내 앱 서버는 책상 위 맥북 에어였다. 이번에 오라클 클라우드 무료 서버로 옮겼다.

이 시리즈는 그 이사 기록이다. 왜 옮겼는지, 어디로 옮길지 어떻게 정했는지, 운영 중인 앱을 몇 분 만에 옮긴 방법, 그리고 0원을 유지하면서 백업과 배포를 갖춘 과정까지 차례로 정리한다. 1편은 출발점, 맥북 서버 이야기다.


내 앱 서버는 맥북 에어였다

혼자 앱 두 개를 만들고 있다.

  • PowerUp: 점진적 과부하를 도와주는 운동 기록 앱 (Expo + Spring Boot)
  • LoveToday: 둘 다 써야 상대 글이 열리는 커플 교환일기 앱 (Expo + Spring Boot)

둘 다 실제 사용자가 있다. 그리고 둘 다 백엔드 서버는 내 맥북 에어였다. 구조는 이랬다.

[앱 사용자]
    │ https://powerup.도메인
    ▼
[Cloudflare] ── Tunnel ──▶ [맥북 에어]
                             ├─ launchd: PowerUp 백엔드 (:8080)
                             ├─ launchd: LoveToday 백엔드 (:8083)
                             └─ MySQL (:3307) ← 모든 사용자 데이터
  • launchd: macOS에서 프로그램을 상시 실행해 주는 관리자다. Spring Boot jar를 여기에 등록해 두면, 죽어도 다시 띄워 준다.
  • Cloudflare Tunnel: 내 컴퓨터가 Cloudflare 쪽으로 먼저 연결을 맺고, 그 통로로 외부 요청을 받아 오는 방식이다. 공유기 포트포워딩 없이 도메인을 연결할 수 있다.
  • MySQL: 맥에 설치된 하나에 두 앱의 데이터가 같이 들어 있었다.

서버비는 0원이었다. 코드를 고치면 바로 운영에 반영할 수 있었다. 꽤 똑똑한 구조라고 생각했다. 몇 달 동안 실제로 문제없이 돌아갔으니, 틀린 생각도 아니었다. 운이 좋았을 뿐.


맥 서버가 위험했던 이유 4가지

1. 덮개를 닫으면 서비스도 닫힌다

맥북은 노트북이다. 덮개를 닫거나, 배터리가 떨어지거나, macOS 업데이트로 재부팅되면 로그인도, 운동 기록 저장도, 일기 쓰기도 전부 멈춘다. 서비스의 가용성이 덮개의 각도에 달려 있었다.

2. 백업이 없다

사용자 데이터는 맥북 SSD 한 곳에만 있었다. 그 SSD가 원본이었고, 백업이었고, 유일한 희망이었다. 맥북은 자주 가방에 들어갔다.

3. 배포가 손으로 이뤄진다

배포는 맥에서 jar를 빌드한 뒤 launchctl unload/load로 재시작하는 방식이었다. 빌드가 깨진 채로 재시작하면 그대로 장애였고, 직전 버전으로 되돌리는 방법도 없었다. 테스트는 돌릴 때도 있었고 안 돌릴 때도 있었다. 주로 안 돌렸다.

4. 개발과 운영이 한 몸이다

같은 맥에서 개발 서버, iOS 시뮬레이터, 운영 서버가 같이 돌았다. 개발하다 메모리를 많이 쓰면 운영 서버가 느려졌다. 로컬 DB와 운영 DB가 같은 MySQL에 있었으니, 실수 한 번이면 운영 데이터를 건드릴 수 있었다.

항목 상태
가용성 덮개 상태에 따름
백업 없음
배포 수동
모니터링 사용자 제보

그리고 터널 설정 파일이 없었다

이사를 미루던 중에 결정적인 걸 발견했다. 터널 설정을 확인하려고 폴더를 열었는데, 로그 파일만 있었다.

$ ls ~/.cloudflared/
cloudflared.log  lovetoday.log  me.log  powerup.log

있어야 할 터널 설정 파일(powerup.yml)과 인증 파일이 없었다. 그런데 앱은 정상으로 돌고 있었다.

이유는 단순했다. 며칠 전에 실행된 cloudflared 프로세스가 메모리에 남은 설정으로 계속 동작하고 있었다. 파일은 그사이 어디론가 사라졌다. 맥이 한 번만 재부팅돼도 앱은 끊기고, 다시 연결할 설정 파일조차 없는 상태였다. 아주 안정적인 시스템이었다. 재부팅만 안 하면.

정리하다 보니 하나가 더 나왔다. 앱 이름을 바꾸기 전에 만든 예전 터널이 옛 도메인 주소 9개를 품은 채, 관리자 권한(root)으로 계속 실행되고 있었다. 언젠가 정리하려고 했다. 그 언젠가는 오지 않았고, 그사이 터널은 성실하게 일했다. 나보다 성실했다.

미룰 이유가 없어졌다.


이사 목표

막연히 "클라우드로 옮기자"고 시작하면 끝이 없다. 조건부터 적었다.

목표 기준
비용 월 0원. 무료 한도를 넘는 자원은 아예 만들 수 없게 막는다
중단 시간 앱당 5분 이내. 운영 중인 앱이다
보안 외부에 여는 포트 최소화. 비밀값은 서버 파일 권한으로 관리
백업 서버 밖에 매일 암호화 백업. 복원 테스트까지
배포 명령어 하나. 실패하면 자동으로 이전 버전 복구
검사 push할 때마다 테스트 자동 실행 (CI)
코드 백엔드 코드는 그대로 두고 서버만 옮긴다

마지막 조건이 중요했다. Cloudflare Workers 같은 서버리스로 다시 짜는 안도 고민했다. 두 앱을 합치면 Java 코드가 1만 7천 줄이 넘는다. 이사를 하려다 재개발을 할 수는 없었다. 이 결정 과정은 2편에서 다룬다.

목표는 완벽했다. 이 목표를 세운 사람이 맥북으로 서버를 돌리던 사람이라는 점만 빼면.


이번엔 AI 에이전트에게 맡겼다

이번 이사는 Claude Code와 함께 했다. 터미널 명령을 실행하고 브라우저를 직접 조작하는 AI 코딩 에이전트다. "명령어를 알려 줘"가 아니라 작업은 에이전트가 하고, 나는 결정과 승인을 맡는 방식이었다.

에이전트가 한 일

  • 오라클 클라우드 콘솔과 Cloudflare 대시보드를 브라우저에서 직접 클릭하며 설정
  • 서버에 SSH로 접속해 Java, MySQL, 서비스 설정
  • DB를 옮긴 뒤 테이블별 행 개수를 맥과 서버에서 대조
  • 배포·백업·CI 스크립트 작성과 실제 실행 검증
  • 중간에 터진 문제(쿼터 정책 오류, 깨진 빌드 캐시)의 원인 추적

내가 한 일

  • 결제 버튼 클릭
  • 관리자 비밀번호 입력, GitHub 권한 승인
  • "진행할까요?"에 "네"라고 답하기

정리하면 그렇다. 덧붙이자면 결제 버튼은 에이전트가 누르려다 안전장치에 막혔다. 서버 세팅은 다 해 놓고, 카드 앞에서는 멈췄다. 능력이 부족한 게 아니라 권한이 없었다. 바람직한 동료였다.

인상적이었던 건 확인하는 습관이었다. "무료 한도가 바뀌었을걸?"이라고 하자 공식 문서를 찾고 계정의 실제 한도까지 확인했다. 실제로 바뀌어 있었다.

에이전트도 틀렸다. 오라클 계정을 종량제로 전환해야 한다고 했다. 이미 종량제였다. 확인하고 바로 정정했다. 그래서 최종 판단은 결국 사람이 해야 한다. 이번 작업에서 가장 확실하게 배운 것이다.


시리즈 목차

  1. 내 앱 서버는 맥북 에어였다 ← 지금 글
  2. 오라클 클라우드 vs Cloudflare: 어디에 올릴까
  3. 오라클 클라우드 무료 인스턴스 만들기 (2026, 캡처 포함)
  4. 오라클 인스턴스 생성 실패 해결 모음 (쿼터 정책의 함정)
  5. 포트 하나 안 열고 서비스하기: Cloudflare Tunnel
  6. 운영 중인 앱을 3분 만에 서버 이전하기
  7. 무료로 만드는 자동 백업: restic + Cloudflare R2
  8. 1인 개발자의 배포·CI 세팅과 0원 유지법

오늘의 교훈
설정 파일이 없는데 서비스가 돌아간다면, 그건 안정적인 게 아니라 아직 재부팅을 안 한 것이다.

다음 편에서는 어디로 옮길지 고민한 과정을 정리한다. 오라클 클라우드와 Cloudflare 중 하나를 고르려고 했는데, 알고 보니 고를 필요가 없었다.