Skip to main content

Command Palette

Search for a command to run...

[gcp] 외부 Ip 없는 안전한 서버 구축기

Zero-Trust 기반의 GCP 인프라 설계 전략

Updated
2 min read

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)라는 전용 통로를 구축했습니다.

  1. VPC 피어링(Peering): 우리 VPC와 구글 SQL VPC 사이에 거대한 전용 고속도로를 뚫습니다.

  2. 내부 IP 할당: 우리 VPC의 남는 IP 대역을 DB용으로 정해두면, 구글 DB가 그 주소를 달고 우리 내부망인 것처럼 행동합니다

  3. 결과: 우리 서버는 인터넷을 거치지 않고, 구글 클라우드 내부 망을 통해 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으로 넣을 수 있겠죠?☺️

More from this blog

[Elasticsearch] Elasticsearch 기본용어와 CRUD 명령어

-elastic ▶ 들어가며 이번 글에서는 Elasticsearch를 공부하면서 가장 먼저 익혀야 하는 기본 용어를 정리하고,직접 코드를 쳐가며 CRUD(Create / Read / Update / Delete) 명령어에 익숙해지는 시간을 가져보려고 한다. Elasticsearch는 처음 보면 생소한 용어가 많아서 막막할 수 있는데,사실 구조적으로는 우리가 익숙한 MySQL과 닮은 부분이 굉장히 많다. 둘 다 데이터베이스라는 큰 틀 안에서 데...

Feb 17, 20264 min read

Jpa N+1 문제, 우리는 이렇게 잡았다 — 1:1 문의 Api 실전 최적화기

코드 리뷰 한 줄에서 시작된 쿼리 최적화 여정 1. 시작 — "일단 돌아가게 만들자" Finders 프로젝트에서 1:1 문의(Inquiry) API를 맡았다. 현상소에 문의를 남기고, 답변을 받고, 목록을 조회하는 — 평범한 CRUD다. "JPA 쓰면 쿼리 안 짜도 되는 거 아니야?" 솔직히 처음엔 그렇게 생각했다. JpaRepository에 findAll, findById 쓰면 끝이니까. // 첫 번째 버전의 목록 조회 (QueryDS...

Feb 11, 20268 min read

[모니터링] Sentry 도입부터 Discord 에러 알림까지 — 서버 감시 시스템 구축기

"서버 죽었는데 아무도 몰랐다"에서 "에러나면 1분 안에 안다"까지 1. 모니터링을 시작한 계기 프론트엔드: "API 안 되는데요?"백엔드: "엥? 언제부터요?"프론트엔드: "...2시간 전부터요?"백엔드: 😱 어느 날 서버가 죽어있었는데 아무도 몰랐다. 그날 이후, 모니터링 시스템 구축을 결심했다. (Issue #102) 2. 모니터링 도구 비교: 뭘 쓸까? 처음에는 여러 도구를 비교했다. 도구무료 티어장점단점 Sent...

Feb 11, 20268 min read

[CI/CD] 수동 태그에서 자동 릴리즈까지 — Git Flow와 Auto Release

🚀 우리 auto-release.yml 바로 보러가기 → 이 글에서 설명하는 워크플로우의 전체 코드를 바로 확인할 수 있다! main에 머지만 하면 버전 태그부터 릴리즈 노트까지 알아서 생긴다 1. 우리의 Git 전략: Git Flow (경량 버전) Finders 프로젝트는 Git Flow 전략을 사용하고 있다. 다만 hotfix나 release 브랜치 없이, 조금 가볍게 운영한다. main ← 운영 서버 (prod) 배포 브...

Feb 11, 20265 min read

[ci/cd] 대학생 팀의 배포 파이프라인 진화기

PR 하나면 끝나는 무중단 배포까지, 삽질의 기록 1. 시작은 단순했다 "서버에 올려야 하는데... 어떻게 하지?" Finders 프로젝트를 시작했을 때, 배포라는 걸 해본 적이 없었다. 그래서 처음에는 이렇게 했다. 1. SSH로 서버 접속 2. git pull 3. ./gradlew build 4. java -jar app.jar 당연히 문제가 생겼다. 빌드하는 동안 서버가 꺼져있음 (프론트: "API 왜 안 돼요?" 🔥) 빌...

Feb 11, 20267 min read
F

Finders Tech Blog

16 posts