Cloud Service Practice 11
NAT 게이트웨이: 프라이빗 서버의 안전한 외부 통신 길 만들기
프라이빗 서버는 외부에서 직접 들어오지 못해야 하는데, 동시에 업데이트나 외부 요청은 나가야 한다는 요구가 서로 모순처럼 보인다.
근거 · 교안 p83-p108
1장: 밖으로 ‘내보내기’와 안으로 ‘받아들이기’는 왜 다른가요?
솔라의 손이 허공에서 잠시 멈칫했다. 화이트보드에는 방금 그린 서버 아키텍처 다이어그램이 펼쳐져 있었다. ‘웹 서버’가 있는 퍼블릭 서브넷과 ‘데이터베이스 서버’가 있는 프라이빗 서브넷. 깔끔하게 분리된 두 개의 상자가 선으로 연결되어 있었다. 문제는 프라이빗 서브넷에서 시작되었다.
“언니, 이거 좀 이상해.”
노트북 화면을 보던 루나가 고개를 들었다. 솔라는 보드마카 펜 끝으로 ‘프라이빗 DB 서버’라고 적힌 상자를 톡톡 건드렸다.
“프라이빗 서버는 외부 인터넷에서 직접 접근할 수 없어야 하잖아. 그래서 프라이빗 서브넷에 넣은 거고. 그런데 이 서버도 보안 패치나 소프트웨어 업데이트는 해야 하니까, 외부 인터넷에 접속해서 파일을 다운로드해야 한단 말이야.”
솔라는 ‘프라이빗 DB 서버’ 상자에서 바깥쪽 ‘인터넷’ 구름 그림으로 나가는 화살표를 그렸다. 그리고는 잠시 망설이다가, 다시 인터넷에서 서버로 들어오는 화살표를 그렸다 지우기를 반복했다. 희미한 자국만 남았다.
“봐, 외부랑 통신을 하려면 길이 열려야 하잖아. 길이 열리면… 나갈 수도 있지만 들어올 수도 있는 거 아니야? 한쪽만 열린 길이라는 게 있나? ‘외부 접근은 막지만 외부 통신은 가능하다’는 말이 서로 모순되는 것 같아.”
솔라의 말대로였다. 길은 길이다. 차가 나갈 수 있는 도로라면, 반대편에서 차가 들어올 수도 있는 법이다. 솔라의 생각은 ‘통신’이라는 단어를 양방향 도로처럼 여기고 있었다. 한쪽이라도 움직이려면 양쪽 차선이 모두 필요하다는 생각이었다.
루나는 잠시 솔라의 다이어그램을 바라보다가, 자신의 휴대폰을 들어 솔라에게 보여주었다.
“솔라, 네가 나한테 전화를 걸 때를 생각해봐.”
“내가 언니한테 전화를 걸 때?”
“응. 네가 내 번호를 눌러서 전화를 걸면, 내 휴대폰이 울리지. 나는 화면에 ‘솔라’라고 뜨니까 안심하고 전화를 받아. 그리고 우리는 대화를 시작하지.”
“당연한 거 아니야?” 솔라가 반문했다.
“그럼 이번엔 반대로, 내가 모르는 번호로 전화가 온다고 생각해봐. 나는 그 번호가 누군지 몰라. 받을 수도 있지만, 스팸 전화일 것 같으면 그냥 받지 않고 끊어버릴 수도 있어. 내 선택이지.”
루나는 말을 이었다.
“네가 건 전화를 내가 받는 것과, 모르는 번호의 전화를 내가 받는 것은 시작부터 달라. 네 전화는 네가 ‘대화를 시작’했기 때문에 내가 응답하는 거고, 모르는 번호는 외부에서 일방적으로 ‘대화를 시작’하려고 시도하는 거야.”
솔라는 잠시 눈을 깜박였다. 전화. 너무나 당연한 일상이었지만, 그 안에 담긴 방향성에 대해서는 깊이 생각해본 적이 없었다. 내가 거는 것과 남이 거는 것.
“그게 서버랑 무슨 상관인데?”
“아주 큰 상관이 있지.” 루나가 화이트보드 쪽으로 다가왔다. “프라이빗 서버가 소프트웨어 업데이트를 위해 외부 인터넷에 접속하는 건, 네가 나한테 전화를 거는 것과 같아. 서버가 먼저 ‘저 업데이트 파일 좀 주세요’라고 말을 건 거야. 외부 서버는 그 요청을 받았으니, ‘여기 파일 있어’ 하고 응답을 보내주는 거지. 이건 이미 시작된 대화에 대한 ‘응답’이야.”
루나는 솔라가 그렸다 지운 희미한 화살표 자국을 손가락으로 가리켰다.
“하지만 아무 관련 없는 외부의 누군가가 갑자기 프라이빗 서버에 접속을 시도하는 건, 모르는 번호로 전화가 걸려오는 것과 같아. 서버는 ‘누구세요? 당신과는 대화를 시작한 적이 없는데요?’ 하면서 전화를 받지 않는 거지. 문을 열어주지 않는 거야.”
그제야 솔라의 얼굴에 맺혀 있던 의문이 조금씩 풀리기 시작했다. 그녀는 자신의 다이어그램을 새로운 눈으로 바라보았다. 나가는 화살표와 들어오는 화살표가 더 이상 하나의 ‘길’로 보이지 않았다.
“아…! 그러니까 통신은 통신인데, ‘누가 먼저 대화를 시작했느냐’가 핵심이구나. 외부로 나가려는 요청으로 시작된 통신은 허용된 대화니까 응답이 들어올 수 있는 거고, 외부에서 아무 맥락 없이 불쑥 들어오려는 통신은 아예 대화 자체를 시작하지 않는 거네.”
솔라는 보드마카 뚜껑을 열고 확신에 찬 손길로 화이트보드를 수정했다. 프라이빗 서버에서 인터넷으로 향하는 실선 화살표를 진하게 그렸다. 그리고 인터넷에서 프라이빗 서버로 향하는 길 위에는 작은 자물쇠 아이콘을 그려 넣었다. 대신, 실선 화살표의 응답을 나타내는 점선 화살표를 서버 쪽으로 그렸다. ‘요청’과 그에 따른 ‘응답’이라는 흐름이 명확해졌다.
모순처럼 보였던 두 가지 조건, ‘외부 통신’과 ‘외부 접근 차단’이 사실은 ‘대화의 시작점’이라는 하나의 규칙 아래 움직이고 있었다.
문제가 해결되었다고 생각한 순간, 솔라의 머릿속에 새로운 질문이 떠올랐다.
“알겠어. 원리는 알겠는데… 그럼 그걸 기술적으로 어떻게 구현하는 거야? 우리 집 현관문처럼, 내가 나갔다가 다시 들어오는 건 허용하지만, 밖에서 모르는 사람이 문을 두드리는 건 막아주는 특별한 장치가 필요하다는 거잖아. 네트워크 세상에서 그런 똑똑한 문지기 역할을 하는 게 대체 뭐지?”
2장: NAT 게이트웨이는 어떻게 ‘우리의 대변인’이 되나요?
화이트보드 위, 솔라가 그린 다이어그램은 그대로였다. 요청과 응답을 나타내는 화살표, 그리고 외부에서의 접근을 막는 자물쇠 아이콘까지. 원리는 이해했지만, 그 원리를 구현할 ‘똑똑한 문지기’의 정체는 여전히 물음표로 남아 있었다. 솔라가 펜을 만지작거리며 고민에 잠겨 있을 때, 루나가 다가와 보드마카를 들었다.
루나는 솔라의 다이어그램 위, 프라이빗 서브넷과 인터넷 구름 그림 사이에 네모난 상자를 하나 더 그렸다. 그리고는 그 안에 ‘문지기?’라고 적었다. 솔라의 머릿속에 맴돌던 추상적인 질문이 눈앞의 구체적인 도형으로 나타난 순간이었다. 이 ‘문지기’는 프라이빗 서버가 밖으로 나갈 때는 문을 열어주지만, 낯선 손님이 밖에서 문을 두드릴 때는 잠가버리는 역할을 해야 했다.
“이 문지기, 생각보다 더 똑똑해야 해.”
루나가 상자를 톡톡 치며 말했다.
“전화 비유를 조금 바꿔볼까? 우리 프라이빗 서브넷이 하나의 커다란 회사 건물이라고 상상해봐. 그 안에는 수많은 팀원(서버)들이 각자의 자리에서 일하고 있어. 이 팀원들은 외부 업체에 물건을 주문하거나 자료를 요청해야 할 때가 많지. 하지만 보안 규정상, 자기 자리의 내선 번호나 개인 주소를 외부에 절대로 노출하면 안 돼.”
“그렇겠지. 내부 정보니까.” 솔라가 고개를 끄덕였다.
“그래서 이 회사에는 공식 ‘대변인’이 딱 한 명 있어. 외부와 소통할 일이 있는 모든 팀원은 자신의 요청서를 이 대변인에게 전달해야만 해.”
“아, 그럼 대변인이 대신 요청을 보내주는 거구나. 외부 접근을 막는 방화벽 같은 역할이네. 허가된 요청만 내보내 주는.”
솔라의 생각은 ‘문지기’가 허가증을 검사하는 경비원과 비슷하다는 쪽으로 흘렀다. 외부로 나가는 통신이 규칙에 맞는지 확인하고 통과시켜주는 필터 같은 존재.
“단순히 전달만 하는 것 이상이야.”
루나는 ‘문지기?’ 상자 옆에 작은 메모장을 그리는 시늉을 했다.
“팀원 A가 ‘X 물품 10개 주문’이라는 요청서를 대변인에게 주면, 대변인은 먼저 자기 수첩에 ‘이 요청은 A가 보냄’이라고 기록해 둬. 그리고는 요청서를 새로운 봉투에 넣지. 중요한 건, 보내는 사람 주소 칸에 팀원 A의 자리가 아니라, 회사의 공식 대표 주소, 즉 대변인의 주소를 적는다는 거야.”
솔라의 눈이 동그래졌다.
“잠깐, 그럼 외부 업체 입장에서는 누가 주문했는지 전혀 모르는 거 아니야? 그냥 그 회사 ‘대변인’이 주문한 걸로만 알겠네.”
“바로 그거야.” 루나가 미소 지었다. “외부 업체는 오직 대변인과 소통하는 거지. 물건이 준비되면 업체는 당연히 봉투에 적힌 발신 주소, 즉 대변인의 주소로 물건을 보내. 팀원 A에게 직접 보낼 방법 자체가 없어.”
“아하! 그럼 소포는 대변인에게 도착하고… 대변인은 아까 적어둔 수첩을 보고 ‘아, 이건 A가 요청했던 물품이구나’ 하고 A에게 직접 가져다주는 거구나!”
그제야 퍼즐 조각이 맞춰졌다. 문지기의 역할은 단순한 통과/차단이 아니었다. 주소를 바꿔치기하는 교묘한 작업이 핵심이었다. 외부 세계로부터 내부 구성원들의 진짜 주소를 완벽하게 숨겨주는 것.
솔라는 다시 화이트보드의 다이어그램을 보았다. ‘문지기?’라고 쓰인 상자가 더 이상 단순한 경비 초소로 보이지 않았다.
“그러니까 이 문지기는… 우리 프라이빗 서버들이 외부로 통신을 요청할 때, 서버의 원래 주소, 그러니까 내부에서만 쓰는 사설 IP 주소를 감추는 거구나. 대신 자신의 주소, 외부와 소통 가능한 공인 IP 주소로 바꿔서 내보내는 거야. 그리고 외부에서 응답이 오면, 그 응답이 어떤 요청에 대한 것인지 기억했다가 원래 요청했던 프라이빗 서버에게 돌려주는 거고. 이건… 주소 번역가잖아!”
솔라의 목소리에 깨달음의 확신이 실렸다. ‘외부 접근 차단’의 비밀은 단순히 문을 잠그는 게 아니었다. 애초에 외부에서는 내부의 진짜 주소를 알 방법이 없었던 것이다.
루나는 고개를 끄덕이며 솔라가 ‘문지기?’라고 썼던 글자 위에 덧썼다.
NAT 게이트웨이 (Network Address Translation Gateway)
“맞아. 네트워크 세상에서는 이 대변인을 ‘NAT 게이트웨이’라고 불러. 그리고 방금 네가 설명한, 내부 주소를 외부용 대표 주소로 바꾸는 과정을 바로 ‘네트워크 주소 변환(NAT)’이라고 하지.”
이제 모든 게 명확해진 것 같았다. 프라이빗 서버는 NAT 게이트웨이라는 대변인을 통해 안전하게 외부와 소통할 수 있었다. 하지만 솔라는 다이어그램을 꼼꼼히 뜯어보다가 새로운 의문점을 발견했다.
“알겠어. 대변인이 필요하고, 무슨 일을 하는지도 이해했어. 그런데… 회사 건물 안에 있는 수많은 팀원들이 자기가 보낼 편지를 왜, 그리고 어떻게 꼭 이 대변인에게 가져가야 한다는 걸 알지? 그냥 자기가 알아서 우체통에 넣을 수도 있잖아. 모든 외부행 우편물은 반드시 대변인을 거쳐야 한다는 ‘사내 규정’ 같은 게 따로 있어야 하는 거 아니야?”
3장: ‘나갈 문’만 열고 ‘들어올 문’은 잠그는 라우팅 테이블
솔라는 화이트보드에 그려진 다이어그램을 노려봤다. 프라이빗 서버들이 ‘대변인’인 NAT 게이트웨이를 통하도록 강제할 방법. 그녀는 마커를 들어 프라이빗 서브넷 상자 옆에 새로운 네모를 그리고 ‘사내 규정집’이라고 적었다. 모든 서버가 외부로 통신할 때 반드시 NAT 게이트웨이를 거치도록 강제하는 규칙, 그것이 지금 솔라가 찾고 있는 마지막 퍼즐 조각이었다.
하지만 곧바로 새로운 불안감이 엄습했다. 그녀는 ‘규정집’ 상자 아래에 작은 글씨로 규칙 예시를 적었다. ‘규칙 1: 외부로 나갈 땐 대변인 경유.’ 그리고 그 옆에 붉은색 마커로 더 불안한 가능성을 추가했다. ‘규칙 2: 외부에서 들어올 땐 서버 A로 직접 전달?’ 만약 이 규정집이 들어오고 나가는 모든 길을 다루는 것이라면, 누군가 악의적인 길을 추가할 수도 있었다. 길을 안내하는 표지판이 있다면, 그 표지판이 적진으로 향하는 길을 가리킬 수도 있다는 모순. 문제는 해결된 게 아니라, 단지 다른 형태로 옮겨갔을 뿐이었다.
그때, 루나가 다가와 솔라가 그린 ‘사내 규정집’과 그 아래의 붉은 글씨를 지긋이 바라보았다. 그리고는 그 옆에 간결한 표를 그리기 시작했다. 두 개의 열로 이루어진 단순한 표였다. 왼쪽 열의 제목은 ‘목적지’, 오른쪽 열의 제목은 ‘경로’였다.
“규정집이라기보다는, 갈림길에 세워진 아주 단순한 이정표라고 생각하는 게 더 정확해.”
루나는 표의 첫 번째 줄에 내용을 채워 넣었다.
| 목적지 | 경로 |
|---|---|
| 내부 네트워크 (예: 10.0.0.0/16) | 로컬 (직접 통신) |
“프라이빗 서브넷 안에 있는 서버가 다른 내부 서버와 통신하려고 할 때, 이 이정표를 봐. 목적지가 내부 네트워크 주소 범위 안에 있지? 그럼 ‘경로’는 ‘로컬’이야. 그냥 내부에서 직접 찾아가라는 뜻이지. 회사 건물 안에서 옆 팀 동료에게 서류를 건네주는 것과 같아.”
솔라는 고개를 끄덕였다. 그건 당연해 보였다. 루나는 이어서 두 번째 줄을 추가했다. 이것이 결정적인 규칙이었다.
| 목적지 | 경로 |
|---|---|
| 내부 네트워크 (예: 10.0.0.0/16) | 로컬 (직접 통신) |
| 그 외 모든 곳 (0.0.0.0/0) | NAT 게이트웨이 |
“하지만 만약 목적지가 내부 네트워크가 아닌 곳, 즉 인터넷 어딘가라면? 이 두 번째 규칙이 적용돼. ‘그 외 모든 곳’으로 가려는 모든 통신은 무조건 ‘NAT 게이트웨이’라는 출구로 가야 한다는 뜻이야.”
솔라는 표를 뚫어지게 쳐다봤다. 순간, 머릿속에 안개가 걷히는 기분이었다. 그녀는 자신이 붉은색으로 썼던 ‘규칙 2: 외부에서 들어올 땐 서버 A로 직접 전달?’이라는 글자를 조용히 지웠다. 지우개로 문지르자 붉은색 흔적이 사라지고, 그 자리에 공백만 남았다. 애초에 그런 규칙을 써넣을 칸 자체가 존재하지 않았던 것이다.
“아…!”
탄성이 터져 나왔다.
“이 표에는 ‘외부에서 들어오는 길’에 대한 안내 항목이 아예 없군요! 그냥 ‘안으로 갈 거면 알아서 가고, 밖으로 나갈 거면 무조건 저쪽 문(NAT 게이트웨이)으로 가!’ 이게 전부네요.”
보안을 위해 ‘들어오는 것을 막는다’는 규칙을 찾는 데 집중했지만, 사실은 ‘들어올 수 있는 길 자체를 알려주지 않는 것’이 핵심이었다. 외부에서 시작된 소포가 프라이빗 서브넷에 도착해도, 이정표 어디에도 그 소포를 내부 서버의 자리까지 배달할 경로가 적혀있지 않은 것이다. 갈 곳을 잃은 소포는 배달 불능으로 반송될 뿐이다.
“정확해. 네트워크 세상에서는 이 이정표를 ‘라우팅 테이블(Routing Table)’이라고 불러. 그래서 ‘NAT 게이트웨이로 패킷을 전달하는 라우팅 설정이 필요하다’는 말은, 바로 이 나가는 길에 대한 단 하나의 규칙을 의미하는 거야. 들어오는 길과는 아무 상관없이.”
루나의 설명에 솔라는 비로소 모든 조각을 맞출 수 있었다.
- 대화의 시작점: 프라이빗 서버가 먼저 외부로 요청을 보낸다.
- 라우팅 테이블: 이 요청은 ‘외부로 나가는 길’이므로, 라우팅 테이블의 규칙에 따라 NAT 게이트웨이로 전달된다.
- NAT 게이트웨이 (대변인): 요청의 발신지 주소를 자신의 공인 IP 주소로 ‘주소 변환’하여 인터넷으로 보낸다. 이때 원래 요청한 서버를 기록해둔다.
- 응답: 인터넷의 목적지는 NAT 게이트웨이에게 응답을 보낸다.
- 귀환: NAT 게이트웨이는 기록을 보고 원래 요청했던 프라이빗 서버에게 응답을 정확히 전달한다.
이 과정 어디에도 외부에서 먼저 말을 걸어 프라이빗 서버까지 도달할 수 있는 길은 존재하지 않았다. ‘나갈 문’은 명확히 지정되어 있지만, ‘들어올 문’은 처음부터 만들어지지도 않은 것이다.
솔라는 확신에 찬 손길로 화이트보드에 어지럽게 흩어져 있던 자신의 생각들을 지우고, 최종적인 다이어그램을 그리기 시작했다. 프라이빗 서버에서 나온 화살표가 ‘라우팅 테이블’이라는 이정표를 거쳐 ‘NAT 게이트웨이’로 향했다. 그리고 NAT 게이트웨이를 통해 인터넷으로 나갔다가, 점선으로 된 응답 화살표가 다시 NAT 게이트웨이를 거쳐 서버로 돌아왔다. 외부 인터넷 구름 그림에서 프라이빗 서버로 직접 향하는 길에는, 이제 자물쇠 아이콘 대신 ‘경로 없음’이라고 명확하게 적었다.
“됐어.”
솔라는 완성된 다이어그램을 보며 만족스럽게 말했다.
“프라이빗 서버의 안전한 외부 통신 설계. 외부 접근은 원천적으로 차단하면서, 필요할 때만 외부로 나갈 수 있는 길을 여는 방법. 이제 누구에게든 설명할 수 있겠어.”
모순처럼 보였던 두 가지 요구사항은 더 이상 충돌하지 않았다. 오히려 ‘라우팅 테이블’과 ‘NAT 게이트웨이’라는 두 장치를 통해 서로를 보완하며 완벽한 보안 구조를 만들어내고 있었다. 솔라의 화이트보드 위, 복잡했던 물음표들은 이제 하나의 명쾌한 설계도로 완성되어 있었다.