본문 바로가기
서버, 인프라

7개 도메인을 무중단으로 HTTPS 이전한 이야기

by 요즘IT 2026. 6. 19.

[서버 침해 대응기 시리즈] 1인 개발자가 크립토재킹 당하고, 서버를 통째로 새로 만든 5일간의 기록

docker.sock도 막았고.

새 서버도 준비됐어요.

이제 서비스를 옮길 차례입니다.

근데 저는 도메인이 7개예요.

수학 놀이터, 청약맵, 주식모아, 책토리, 힐링숲...

이걸 다 새 서버로, 그것도 끊김 없이 옮겨야 합니다.

운영 중인 서비스거든요.

잘못 옮기면 사용자가 에러 페이지를 보게 돼요.

무중단이 왜 어렵냐면

생각해보면 이상하죠.

그냥 새 서버에 띄우고, 도메인만 새 서버로 바꾸면 되는 거 아닌가?

맞아요. 큰 틀은 그래요.

근데 함정이 있어요.

도메인 주소(DNS)를 바꾸면.

전 세계 사람들한테 동시에 적용되는 게 아니에요.

누구는 새 서버로 가고.

누구는 아직 옛 서버로 가요.

이게 며칠씩 섞여요.

전파(propagation)라고 부르는데.

쉽게 말하면.

이사 갔는데 우편물이 옛 집이랑 새 집에 며칠간 따로 오는 거랑 같아요.

그래서 옛 서버를 바로 끄면 안 됩니다.

옛 주소로 오는 사람들이 갈 곳을 잃거든요.

nginx가 교통정리를 합니다

먼저 새 서버에서 nginx를 세웠어요.

nginx는 한마디로 교통경찰입니다.

들어오는 요청을 보고.

"너는 수학 놀이터로."

"너는 청약맵으로."

이렇게 알맞은 서비스로 보내주는 역할이에요.

도메인이 7개니까.

각 도메인마다 "이 주소로 오면 이 서비스로 보내라"를 정해줍니다.

컨테이너 이름으로 보내는 게 깔끔하더라고요

여기서 작은 팁이 하나 있어요.

보통 nginx 설정할 때 이렇게 합니다.

proxy_pass http://localhost:3000;

포트 번호로 보내는 거죠.

근데 서비스가 많아지면 포트가 헷갈려요.

3000은 뭐였지? 5001은?

그래서 저는 컨테이너 이름으로 보냈어요.

proxy_pass http://math-playground:3000;

이러면 한눈에 보이거든요.

"아 이건 수학 놀이터구나."

같은 도커 네트워크에 묶어두면.

컨테이너끼리 이름으로 서로를 찾을 수 있어요.

전화번호 대신 이름으로 거는 거랑 비슷해요.

nginx reverse proxy multiple domains
nginx reverse proxy multiple domains

HTTPS는 certbot한테 맡깁니다

이제 자물쇠를 달아야죠.

요즘은 HTTPS가 기본이잖아요.

주소창에 자물쇠 안 뜨면 사용자가 불안해하고.

검색 노출에도 불리하고요.

HTTPS를 쓰려면 인증서가 필요한데.

이걸 무료로 발급해주는 게 Let's Encrypt예요.

그리고 certbot이 그 발급을 자동으로 해줍니다.

명령 한 줄이면.

certbot certonly --webroot -d math.nxex.kr

"이 도메인 인증서 발급해줘" 하면 끝이에요.

발급받고, nginx에 연결하면.

자물쇠가 딱 생깁니다.

진짜 무중단 비법은 순서예요

여기가 핵심이에요.

무중단으로 옮기는 비법은 사실 단순해요.

순서를 지키는 거예요.

  1. 새 서버에 서비스 다 띄움 (아직 도메인은 옛 서버 향함)
  2. 새 서버에서 인증서 미리 발급
  3. nginx 설정 다 해둠
  4. 그다음에야 도메인을 새 서버로 변경

이렇게 하면.

도메인을 바꾸는 순간.

새 서버는 이미 완벽하게 준비돼 있어요.

사용자는 끊김을 못 느껴요.

옛 서버로 가던 사람도, 새 서버로 가던 사람도.

둘 다 정상 작동하는 거죠.

거꾸로 하면 큰일 나요.

도메인부터 바꿔놓고 서버 준비하면.

그 사이에 들어온 사용자는 에러를 봅니다.

솔직히 한 번 삽질했어요

순서대로 잘 하고 있었는데.

certbot 자동 갱신 설정에서 좀 헤맸어요.

인증서는 90일마다 만료되거든요.

자동으로 갱신되게 해놔야 하는데.

certbot이 갱신은 해도.

nginx가 그 새 인증서를 다시 안 읽으면 소용없어요.

옛 인증서 들고 있다가 만료되는 거죠.

그래서 매일 새벽에 nginx를 한 번씩 리로드하게 했어요.

0 4 * * * docker exec nginx nginx -s reload

이러면 갱신된 인증서를 새로 읽어요.

이런 건 한 번 당해봐야 챙기게 되더라고요.

90일 뒤에 갑자기 전 사이트 자물쇠 풀리면.

진짜 식겁하거든요.

7개 다 옮기고 나니

하나씩 옮기는데.

도메인 바꾸고, 전파 기다리고, 자물쇠 확인하고.

이걸 7번 반복했어요.

솔직히 단순 작업이긴 한데.

운영 중인 서비스라 긴장은 됐어요.

근데 순서를 지키니까.

생각보다 깔끔하게 끝났습니다.

사용자 입장에선 아무 일도 없었던 것처럼요.

그게 무중단 이전의 목표죠.

"아무도 모르게 옮기기."

결국 핵심은 준비를 먼저

무중단의 비결은 화려한 기술이 아니에요.

"바꾸기 전에 다 준비해둔다."

이거 하나예요.

새 집 이사 갈 때.

전기, 수도, 인터넷 다 미리 연결해두고.

그다음에 짐 옮기는 거랑 같아요.

준비 없이 짐부터 옮기면.

며칠 불 꺼진 집에서 살아야 하잖아요.

서버도 똑같습니다.

다음 편 예고

서비스도 옮겼고.

HTTPS도 달았어요.

이제 마지막.

자동배포를 붙일 차례입니다.

push 한 번에 자동으로 빌드되고 배포되게요.

근데 여기서.

2편에서 세운 그 문지기(socket-proxy)랑.

제대로 한판 붙습니다.

403 Forbidden을 몇 번이나 봤는지 몰라요.

다음 편은 그 삽질의 기록이에요.

보안을 빡세게 막아놨더니, 내 배포가 막히는 아이러니.

제대로 풀어볼게요.