이 글은 사이드 프로젝트의 인프라 전환 기록을 바탕으로 정리했습니다. 실제 호스트 주소, 계정·버킷 이름, 자격 증명은 공개하지 않았습니다.
서비스를 홈 서버에서 실행한다는 말은 간단하지만, 어디까지 홈으로 옮길 것인가는 전혀 다른 문제다. 애플리케이션, 공개 HTTPS 진입점, 데이터베이스, 파일 저장소를 모두 한 번에 옮기면 구조는 단순해 보인다. 대신 장애 범위와 롤백 범위가 동시에 커진다.
이 사이드 프로젝트에서는 백엔드 애플리케이션을 홈 서버에서 실행하되, 사용자의 첫 요청을 받는 공개 진입점과 데이터 원본은 클라우드에 남겼다. 이 글에서는 모든 구성을 한 번에 옮기지 않고 단계별로 전환한 이유를 정리한다.
먼저 지킬 조건 정하기
전환 전에 바꾸지 않기로 한 것부터 정했다.
- 공개 도메인의 TLS 종료와 SPA 제공은 기존 클라우드 엣지에서 계속 담당한다.
- PostgreSQL은 기존 클라우드 서버에 남긴다. 홈 서버는 사설 네트워크를 통해서만 접속한다.
- 두 백엔드는 같은 불변 이미지 태그와 같은 스키마를 사용한다.
- 홈 서버에 문제가 생기면 클라우드의 기존 백엔드로 트래픽을 즉시 되돌릴 수 있어야 한다.
- 데이터베이스를 파일 시스템으로 공유하지 않는다. 애플리케이션과 백업 작업 모두 PostgreSQL의 표준 연결과 백업 도구를 사용한다.
이 조건은 “홈 서버가 꺼졌을 때도 서비스가 계속되는가?”라는 질문에 답하기 위한 것이다. 단일 장애점을 완전히 없애는 설계는 아니었다. 클라우드 데이터베이스와 엣지는 여전히 장애점으로 남는다. 대신 홈 서버라는 새 변수를 추가하면서, 기존 서비스의 복구 경로는 보존하려 했다.
flowchart LR U["사용자"] --> E["클라우드 엣지\nTLS · SPA"] E -->|"우선 경로"| H["홈 서버 백엔드"] H -->|"사설 네트워크"| D["클라우드 PostgreSQL"] H --> S["Private object storage"] E -. "상태 확인 실패 시" .-> F["클라우드 예비 백엔드"] F --> D F --> S
세 가지 이전 방법 비교하기
| 방향 | 장점 | 감수해야 할 비용 | 판단 |
|---|---|---|---|
| 클라우드에 현재 구조 유지 | 운영 경로가 가장 단순하다 | 홈 서버 자원을 활용하지 못하고, 전환·복구 절차를 검증할 기회도 없다 | 보류 |
| 모든 구성요소를 홈 서버로 이전 | 구성요소가 한곳에 모여 이해하기 쉽다 | 공개 네트워크, 인증서, DB 백업·복구, 파일 저장소의 장애를 모두 홈 환경에서 책임져야 한다 | 이번 범위에서 제외 |
| 홈 서버를 백엔드 주 경로로 두고 엣지·DB는 클라우드에 유지 | 새 실행 환경을 검증하면서 기존 복구 경로를 남길 수 있다 | 두 실행 환경의 이미지·설정·관측을 계속 맞춰야 한다 | 선택 |
여기서 중요한 것은 홈 서버가 “클라우드보다 항상 낫다”는 결론이 아니다. 이 프로젝트에서는 공개 진입점과 데이터 원본을 동시에 이전하는 위험이, 홈 서버에서 애플리케이션을 먼저 검증하는 이점보다 컸다. 따라서 전환 단위를 백엔드 실행 위치로 제한했다.
읽기 전용으로 먼저 실행하기
처음부터 홈 서버가 운영 DB에 쓰기 권한을 갖게 하면, 설정 오류가 곧바로 데이터 변경으로 이어진다. 그래서 사전 구동 환경을 운영 환경과 분리했다.
- 데이터베이스 덤프를 격리된 PostgreSQL 인스턴스에 복원하고, 행 수·외래 키·시퀀스·마이그레이션 버전과 애플리케이션 기동을 확인한다.
- 홈 서버는 전용 Compose 프로젝트와 읽기 전용 DB 계정으로 시작한다.
- 기능 플래그로 메일·OAuth처럼 외부에 영향을 주는 기능을 끄고, 조회·상태 확인·모니터링 데이터만 먼저 확인한다.
- 양쪽 인스턴스가 같은 대시보드에서 분리되어 보이는지 확인한 뒤, 제한된 테스트 데이터로 쓰기·삭제를 별도 절차에서 검증한다.
- 사전 구동 검증을 통과한 동일 이미지 태그만 운영 환경으로 승격한다.
pg_dump로 만든 논리 백업은 다른 서버나 다른 PostgreSQL 인스턴스에 복원해 검증하기에 적합하다. 다만 백업 파일을 만들었다는 사실만으로 복구 가능성이 증명되지는 않는다. 복원한 뒤 스키마와 데이터 상태, 그리고 애플리케이션의 실제 기동까지 확인해야 한다. PostgreSQL의 SQL dump 문서도 백업 방식과 복원 도구의 관계를 함께 설명한다.
필요한 네트워크와 권한만 열기
홈 서버가 DB에 접근해야 한다고 해서 DB 포트를 인터넷에 열 필요는 없다. 이 프로젝트에서는 서비스가 loopback에만 바인딩된 상태를 유지하고, 사설 네트워크 경로로만 필요한 TCP 연결을 노출하는 방식을 택했다. 전환 대상은 애플리케이션 경로뿐이므로, 공개 DNS나 DB의 외부 포트를 새로 늘리지 않았다.
파일 저장소도 두 실행 환경이 하나의 장기 자격 증명을 공유하지 않도록 분리했다. 각 워크로드에는 필요한 객체 경로만 접근하도록 최소 권한을 부여하고, 관리 권한과 애플리케이션 권한을 구분했다. 이는 홈 서버라는 위치의 문제가 아니라, 워크로드별 권한 경계의 문제다. AWS도 사람과 워크로드의 자격 증명을 분리하고 최소 권한을 적용할 것을 권장한다. AWS IAM 보안 모범 사례를 기준으로 정책을 검토했다.
실제 요청이 홈 서버로 가는지 확인하기
배포 워크플로가 성공해도 공개 요청이 새 백엔드로 실제 흐르는지는 별도 문제다. 그래서 전환 뒤에는 다음을 하나의 묶음으로 확인했다.
- 홈 서버와 클라우드 예비 백엔드 모두 상태 확인 요청에 응답하는가
- 공개 API health와 SPA가 정상 응답하는가
- 비인증 API가 의도한 상태 코드를 반환하는가
- 로그인과 조회 같은 최소 사용자 흐름이 동작하는가
- 홈 서버의 요청 수는 증가하고, 같은 요청에서 예비 백엔드의 요청 수는 증가하지 않는가
- 메트릭 전송 실패가 없고 애플리케이션과 서버 메트릭이 모두 수집되는가
특히 마지막에서 두 번째 항목이 중요했다. 외부 HTTP 200은 엣지까지의 도달성만 보여준다. 어떤 백엔드가 실제 요청을 처리했는지는 인스턴스 라벨이 붙은 메트릭이나 애플리케이션 로그가 있어야 확인할 수 있다.
문제가 생기면 쉽게 되돌리기
홈 서버의 상태 확인, DB 연결, OAuth, 파일 저장소, 응답 속도 중 하나라도 기준을 통과하지 못하면 먼저 사용자 요청부터 복구해야 한다. 이 구조에서 가장 빠른 복구 방법은 데이터베이스를 되돌리는 것이 아니라, 공개 진입점이 요청을 보내는 대상을 기존 클라우드 백엔드로 바꾸는 것이다.
flowchart TD
A["홈 서버 전환 후 검증"] --> B{"상태 확인 · 사용자 흐름 · 모니터링 통과?"}
B -->|"예"| C["홈 서버를 주 경로로 유지"]
B -->|"아니오"| D["엣지 upstream을 fallback으로 복원"]
D --> E["공개 health와 로그인·조회 재검증"]
E --> F["홈 서버 원인 분석은 트래픽 복구 후 진행"]
이 복구가 가능한 이유는 클라우드 예비 백엔드와 데이터베이스를 전환 과정에서 삭제하거나 덮어쓰지 않았기 때문이다. “새 환경을 정상으로 만들기”와 “기존 환경을 없애기”를 같은 작업으로 묶지 않는 것이 핵심이었다.
아직 남은 문제
이 설계에서는 홈 서버와 클라우드 환경을 함께 관리해야 한다. 이미지 태그, 실행 설정, 모니터링 라벨, 백업 상태가 서로 다르면 클라우드의 예비 백엔드는 필요할 때 제대로 동작하지 않는다. DB도 클라우드에 남아 있으므로 클라우드 서버 장애 문제는 아직 해결되지 않는다.
그럼에도 이번 전환에서 얻은 것은 단순한 실행 위치 변경이 아니다. 읽기 전용 사전 실행, 실제 요청 경로 확인, 요청 대상을 바꾸는 빠른 복구 절차가 생겼다. 이후 데이터베이스 고가용성이나 별도 백업 전략을 검토하더라도, 더 큰 변경을 한 번에 감수하지 않고 같은 방식으로 범위를 좁혀 갈 수 있다.