고정IP가 월10만원입니다. 유동IP로 홈서버
오라클 클라우드 항상무료티어 1 cpu 1gb ram 인스턴스의 한계를 드디어 경험했습니다
현재까지 백엔드 API 프로그램 3개, 리버스프록시 2개, caddy웹서버 1개 이렇게 사용중인데
cpu 사용량은 평소 1%미만 mem 사용량은 170/950mb 로 안정적입니다(뭐 접속자가 거의 없습니다)
근데 go 컴파일을 거기서 하는데 메모리 950mb 다 먹고 swap 2gb 걸어둔걸 1gb 넘게 쓰고
cpu는 메모리에서 swap 퍼나르는데 90%이상 소모되더군요
노트북 PC에서 똑같은 go 코드를 컴파일 하면 몇초내로 되는데 오라클 인스턴스에서는 5분 가까이 걸리더군요
그때는 당연히 백엔드 API 요청도 엄청 느려졌겠죠
도커 사용해서 노트북PC에도 오라클 클라우드 인스턴스와 똑같은 환경 만들어서(특히 glibc 버전)
노트북에서 빌드해서 실행파일(go는 실행파일 1개가 전부입니다)을 클라우드 인스턴스에 올려주면 되지만..
그리고 오라클 인스턴스가 미서부 산호세에 있다보니 사용자가 최종 결과를 받아보는데 대략 500ms 정도는 걸립니다
이 정도면 일반 프로그램으로서는 큰 문제가 아닌데 반응성이 좋아야 하는 웹앱에서는 엄청 느린겁니다
특히 API요청을 여러번 다중으로 해야 되면 이게 사실 사용불가죠
목표는 100~200ms 더좋게는 100ms 이하로 해야 됩니다
이런 이유로 결국 홈서버 구축을 시작했습니다
N100 미니PC 베어본 139000원짜리 2개 샀고, 500GB MVNe SSD 2개, 16GB RAM 2개 총 44만원 정도 들었네요
문제는 가정용 인터넷회선 500Mbps (실제 다운로드 500, 업로드 300 정도)가 유동IP인데 DDNS는 IP가 바뀌는 순간 수분에서 수십분간 서비스가 먹통이 됩니다. 아무리 토이 프로젝트라고 해도 이건 아니죠
그래서 cloudflare의 서울지역의 pages, cdn에서 프론트엔드 sveltekit 정적 웹파일을 웹호스팅하고
여기 dns로 프론트엔드와 백엔드(홈서버)를 동일 도메인/서브도메인으로 관리해서
www.mypwa.com / api.mypwa.com 이런식으로
oauth2 - jwt - httponly cookie 인증도 가능하게 하고
결정적으로 Cloudflare 프록시 (Orange Cloud - 주황색 구름) 이걸 사용하면
백엔드 서버의 IP를 숨길 수 있고 DDos도 막아주고 기본적인 WAF도 되기 때문에 보안에 매우 큰 도움이 됩니다
사실 홈서버IP를 막바로 외부로 노출시키는 순간 해커들의 맛집이 될겁니다. 이걸 cloudflare가 걸러주는 역할 매우 중요합니다
정적웹파일서빙 pages와 cdn 서비스는 매우 강력한 캐싱으로 전송상 대역폭을 상당히 아껴주기도 하구요
가장 중요한건 이 기능이 백엔드 유동IP를 사실상 지연이 거의 없는(몇초) 고정IP화를 할 수 있다는 겁니다
집에 인터넷 공유기의 ddns가 유동IP가 바뀌는 즉시 홈서버(N100)의 go 프로그램에게 바뀐 IP를 알려주고
그 go 프로그램이 cloudflare DNS서버의 api.mypwa.com 의 A 레코드(IP 주소)를 새로운 N100의 공인 IP로 업데이트 하면
cloudflare DNS서버가 권위 있는 DNS 서버 (Authoritative DNS Server)이기 때문에 다른 DNS서버들로 전파기간 동안의 지연(수분~수십분) 없이 즉시(몇초)안에
프론트엔드의 웹페이지/PWA의 api.mypwa.com/get/price 같은 API호출은 새로운 IP주소를 사용해서 지연이 없습니다
몇초간의 지연에 대해서는 프론트엔드 js코드로 호출 실패시 재시도 로직 (Retry Logic) 만들어서 0.5초 뒤 1초 뒤 2초 뒤 이렇게 3.5초 정도간 3번 정도 더 시도해 보도록 하면 됩니다
이렇게 하면 10만원짜리 ISP의 고정IP보다는 덜 robust해도 토이 프로젝트에 쓰기에는 적당할 겁니다
물론 가정용 인터넷으로 서버 돌리다가 ISP에서 전화오면 뭐.. 그 정도로 붐빌 정도면 오피스넷으로 바꾸는게 맞겠죠
유동IP의 고정IP화를 고민하면서 여러가지 생각을 해봤는데 wireguard vpn tunnel을 사용하는 것도 뭐 결국
ddns 파급 지연 문제에서 걸리는거고 또 vpn을 사용하면 거부당하는 접근도 있기 때문에 이런 제한 때문에 포기했고
N100 미니PC 1대는 nginx 캐싱 리버스프록시서버 + API서버로 쓰고 또 1대는 redis 캐싱 + supabase 데이터서버로 쓸겁니다
문제는 cloudflare를 dns, proxy로 쓰더라도 백엔드서버 기준 인바운드는 매끄럽게 고정IP화 되어서 안정적이지만
아웃바운드는 결국 유동IP의 변동되는 IP가 백엔드 서버의 origin으로 잡히기 때문에
api.mypwa.com 처럼 도메인은 고정되어 있더라도 IP가 자꾸 바뀌는 경우 외부API서버에서 거부를 하는 경우가 있습니다
구글 API 들이나 웹서비스 API들은 대부분 도메인만 고정되면 IP가 바뀌더라도 허용하는 경우가 있는데
금융관련, 국가인증관련은 IP가 자꾸 바뀌는걸 허용하지 않는 경우도 있습니다
이런 경우를 위해 vpn이나 스팸, 크롤링 자주하는 IP 집단, 데이터센터 IP등이 아닌 선량하고 고정된 IP를 가진 아웃바운드 프록시서버가 필요합니다. 금융이나 국가인증관련 외부API호출을 대신하고 결과값을 받아서 N100홈서버에 전달해줄 go 프로그램을 가동하는 서버죠
원래 이것도 무료 오라클 인스턴스에서 처리하려고 했는데 안타깝게도 오라클 클라우드 가입할때 테넌트가 확정되면 지역(region)을 변경할 수 없게 되어 있습니다. 지금은 미서부 산호세라서 한국 서비스할때 지연이 발생합니다. 가족 이름으로 계정 한개 더 만들려고 하다가 멀티계정생성 하는 것이 의심된다고 거부 당해서 그만 두었구요
그래서 컴퓨팅 자원이나 대역폭/전송 허용량 등을 고려해서 16000원짜리 클라우드 서버 dedicated 1 cpu 2gb ram 인스턴스 하나 쓸려고 합니다. 이건 금융,국가인증 외부API 호출 필요할때 홈서버를 대리하는 역할만 할 겁니다.
그리고 만약에 cloudflare의 프록시 (Orange Cloud)의 유동IP 변동시 고정IP화 하는 부분이 매끄럽지 못하거나 3.5초 이상의 멈춤이 발생할 경우에는 또 하나의 대비책으로 이 클라우드 서버 인스턴스에 백엔드 유동IP가 변동된 새로운 IP값을 저장하고 프론트엔드가 처음 시작할때 항상 이 클라우드 서버의 go gin API 로 current_ip 가져와서 웹브라우저 로컬저장소에 저장해 놓고 이 ip를 통해서 백엔드에서 API호출을 할 수 있도록 할겁니다
(이렇게 되면 백엔드 IP가 노출되기 때문에 보안이 크게 무너지기 때문에 이렇게까지 안되도록 해야겠죠)
이틀정도 공부하고 고민한 것 정리해 봤네요
원래 이렇게 하는거 맞나요?
잘 될지는 모르겠는데 해봐야죠