[gcp] 외부 Ip 없는 안전한 서버 구축기
Zero-Trust 기반의 GCP 인프라 설계 전략
Finders 프로젝트의 백엔드 인프라를 설계하며, Zero-Trust 아키텍처를 구축한 과정을 공유합니다.
단순히 서버를 띄우는 것을 넘어, 외부 노출을 최소화하고 권한을 체계적으로 관리하는 법을 고민했습니다..
1. 왜 VPC와 Subnet을 설계해야 하는가?
인프라의 가장 밑단인 VPC(Virtual Private Cloud)는 구글 클라우드에서 만드는 우리만의 사유지입니다. 이는 외부와 완전히 격리되어 있으며, 우리는 이 내부를 보안 등급에 따라 Subnet이라는 논리적 구역으로 쪼개 관리합니다.
App Subnet (Private): 백엔드 서버(GCE)가 있는 공간입니다. 외부 IP가 없어 인터넷에서 직접 접근할 수 없습니다.
DB Subnet (Private/Logical): 데이터 관련 자원을 위해 비워둔 예비 공간입니다.
💡 외부 IP(Public IP)를 모두 제거함으로써, 외부의 Brute-force 공격이나 포트 스캐닝 가능성을 물리적으로 차단했습니다!

2. 서버와 DB의 통신: 비공개 서비스 액세스(PSA)의 원리
설계 과정에서 깨달은 점은 Cloud SQL은우리 VPC 안에 직접 설치되는 것이 아니라, 구글이 관리하는 별도의 ‘구글 서비스 VPC’에 존재한다는 점이었습니다. 그런데 어떻게 우리는 내부 IP로 DB에 접속할 수 있는 걸까요?
VPC 피어링과 PSA (Private Service Access)
격리된 두 동네(우리 VPC와 구글 VPC)가 통신하기 위해 비공개 서비스 엑세스(PSA)라는 전용 통로를 구축했습니다.
VPC 피어링(Peering): 우리 VPC와 구글 SQL VPC 사이에 거대한 전용 고속도로를 뚫습니다.
내부 IP 할당: 우리 VPC의 남는 IP 대역을 DB용으로 정해두면, 구글 DB가 그 주소를 달고 우리 내부망인 것처럼 행동합니다
결과: 우리 서버는 인터넷을 거치지 않고, 구글 클라우드 내부 망을 통해 DB 주소로 직접 패킷을 보냅니다.
3. 외부와의 소통은 어떻게 할까?
외부 IP가 없는데 사용자는 어떻게 접속하고, 서버는 어떻게 외부 API를 호출할까요? 여기서 입구(Inbound)와 출구(Outbound)의 분리가 일어납니다.
📥 입구: Cloudflare Tunnel (Inbound)
사용자의 요청은 서버로 직접 오지 않습니다. Cloudflare Tunnel이라는 가상의 보안 터널을 통해 들어옵니다. 서버는 밖으로 문을 열어두지 않아도, 이 터널을 통해 안전하게 요청만 전달받습니다.
📥 출구: Cloud NAT (Outbound)
서버가 샌드온(Sendon) 같은 외부 API에 요청을 보내야 할 때, Cloud NAT이 신분증 역할을 해줍니다.
IP Masquerading: 서버의 비공개 IP를 감추고, Cloud NAT의 고정된 외부 IP를 달고 밖으로 나갑니다.
Whitelisting: 서버가 10대든 100대든, 샌드온에는 Cloud NAT의 IP만 등록하면 모든 서버가 통신할 수 있습니다.
4. 마치며: 비어있는 서브넷과 Redis
결과적으로 제가 직접 만든 DB Subnet은 현재 비어있는 상태입니다. 향후 Redis 캐시 서버를 구축하거나 별도의 Proxy 서버를 둘 때, 이 구역을 이용할 수 있습니다.
현재 Redis 캐시 서버는 앱 서버 내에서 Docker 컨테이너로 운영 중이며, 논리적으로는 App Subnet에 위치합니다. 이를 별도 인스턴스로 분리한다면, DB Subnet으로 넣을 수 있겠죠?☺️