게이트웨이
고친 사람 github-actions[bot]
게이트웨이는 두 구역의 경계에 서서 한쪽에서 받은 것을 다른 쪽으로 넘겨 줍니다. 웹에서는 서버인 것처럼 요청을 받아 뒤쪽 서버로 전달하는 중개자가 게이트웨이입니다. 네트워크에서는 내 망 밖으로 나가는 길목의 장비를 가리킵니다. 이 편은 웹 요청을 넘기는 게이트웨이를 중심으로 다룹니다.
쉽고 빠른 이해
게이트웨이는 클라이언트 앞에서 서버 노릇을 하고, 받은 요청을 뒤쪽 서버에 넘겨 줍니다. 브라우저는 앞에 선 게이트웨이하고만 이야기하고 뒤에 서버가 몇 대인지 모릅니다.
뒤쪽 서버를 바깥에 드러내지 않으려고 이렇게 합니다. 요청을 여러 대에 나누거나 오래된 시스템을 감쌀 때도 앞에 하나를 세워 두면 클라이언트 쪽은 바뀌는 것이 없습니다.
- 클라이언트의 요청을 게이트웨이가 받습니다
- 게이트웨이가 요청을 고쳐 뒤쪽 서버로 보냅니다
- 뒤쪽 서버의 응답을 받아 클라이언트에게 자기 응답처럼 돌려줍니다
대가는 거쳐 가는 곳이 하나 늘어난다는 것입니다. 느려질 수 있고, 게이트웨이가 멈추면 뒤가 멀쩡해도 요청이 안 들어갑니다.
상세
회사 대표번호로 전화를 걸면 안내 직원이 받습니다. 직원은 내용을 듣고 담당 부서에 물어본 뒤 답을 전해 줍니다. 전화를 건 사람은 담당자의 번호를 몰라도 됩니다.
HTTP 중개자 세 가지
HTTP(HyperText Transfer Protocol)는 웹에서 요청과 응답을 주고받는 규칙입니다. 요청을 보내는 쪽을 클라이언트라 합니다. 브라우저나 다른 서버를 부르는 애플리케이션이 클라이언트입니다.
요청하는 자원을 가지고 응답을 만드는 원래 서버는 오리진 서버입니다. 게이트웨이가 있으면 오리진 서버는 그 뒤에 섭니다. 「쉽고 빠른 이해」에서 말한 뒤쪽 서버가 바로 이 서버입니다.
요청이 오리진 서버까지 곧바로 가지 않을 때가 많습니다. 그 사이에 끼어 요청과 응답을 넘겨 주는 프로그램이 중개자입니다.
흔한 중개자는 세 가지입니다. 게이트웨이는 그중 하나입니다.
| 중개자 | 누가 고르나 | 클라이언트가 보는 것 | 메시지를 고치나 |
|---|---|---|---|
| 프록시 | 클라이언트가 설정해서 고릅니다 | 프록시를 거친다는 것을 압니다 | 고칠 수 있습니다 |
| 게이트웨이 | 서버를 운영하는 쪽이 세웁니다 | 게이트웨이를 서버로 압니다 | 고쳐서 넘깁니다 |
| 터널 | 클라이언트가 연결만 이어 달라고 부탁하면 생깁니다 | 두 끝이 곧장 이어진 것처럼 봅니다 | 고치지 않고 바이트만 잇습니다 |
셋을 가르는 것은 「누구 편에 서 있나」입니다. 프록시는 클라이언트가 고른 대리인입니다. 게이트웨이는 서버를 운영하는 쪽이 앞에 세운 창구입니다.
편이 다르니 맡는 방향도 반대입니다. 프록시는 클라이언트 쪽에 서서 밖으로 나가는 요청을 대신 보냅니다. 게이트웨이는 서버 쪽에 서서 들어오는 요청을 대신 받습니다. 그래서 게이트웨이의 다른 이름이 리버스 프록시, 곧 거꾸로 선 프록시입니다. nginx 같은 웹 서버가 이 일을 흔히 맡습니다.
바깥쪽 연결과 안쪽 연결
게이트웨이는 연결 두 개 사이에 섭니다. 클라이언트와 맺은 연결은 바깥쪽 연결, 오리진 서버 쪽으로 새로 맺는 연결은 안쪽 연결입니다.
클라이언트가 보기에는 바깥쪽 연결 너머의 게이트웨이가 곧 오리진 서버입니다. 요청을 받는 것도 응답을 돌려주는 것도 게이트웨이이기 때문입니다. 안쪽 연결에서는 받은 요청을 고쳐 오리진 서버 하나나 여럿으로 전달합니다.
sequenceDiagram
participant 클라이언트
participant 게이트웨이
participant 오리진 as 오리진 서버
클라이언트->>게이트웨이: 요청
Note over 클라이언트,게이트웨이: 바깥쪽 연결 · 게이트웨이가 서버로 보인다
게이트웨이->>오리진: 고친 요청을 안쪽으로 전달
오리진-->>게이트웨이: 응답
게이트웨이-->>클라이언트: 자기 응답으로 돌려준다
그림에서 클라이언트는 게이트웨이까지만 연결합니다. 오리진 서버의 주소는 클라이언트에게 끝까지 드러나지 않습니다.
요청을 넘기며 하는 번역
게이트웨이는 받은 요청을 손대지 않고 흘려보내지 않습니다. 오리진 서버가 알아듣는 모양으로 고쳐서 보냅니다. 바깥에서 들어온 요청 하나를 예로 봅니다.
GET /shop/items HTTP/1.1
Host: example.com
클라이언트는 example.com 의 /shop/items 를 달라고 했습니다. 게이트웨이는 /shop 으로 시작하는 요청을
안쪽의 쇼핑 서버(오리진 서버)가 맡는다고 알고 있습니다. 그래서 안쪽으로는 이렇게 보냅니다.
GET /items HTTP/1.1
Host: 10.0.0.5:8080
Via: 1.1 gateway
X-Forwarded-For: 203.0.113.7
세 가지가 바뀌었습니다. 경로 앞의 /shop 을 떼었습니다. 받는 서버를 오리진 서버의 주소로 바꿨습니다. 그리고
헤더 두 줄을 더했습니다.
Via 헤더는 이 요청이 중개자를 거쳐 왔다는 흔적입니다. X-Forwarded-For 헤더는 요청을 처음 보낸 클라이언트의 주소를 담습니다. 오리진 서버가 보기에 연결을 맺은 상대는 게이트웨이뿐입니다. 이 헤더가 없으면 클라이언트의 주소를 알 길이 없습니다.
번역은 헤더에서 그치지 않을 수도 있습니다. 뒤에 선 프로그램이 HTTP 를 모르면 게이트웨이가 요청을 그 프로그램의 방식으로 바꿔 보냅니다. CGI(Common Gateway Interface)가 그 예입니다. 웹 서버가 요청의 경로와 헤더를 환경 변수에 담아 프로그램을 실행하고, 프로그램이 출력한 내용을 응답으로 돌려줍니다.
게이트웨이를 세우는 까닭
게이트웨이가 흔히 맡는 일은 셋입니다.
| 목적 | 게이트웨이가 하는 일 | 게이트웨이가 없으면 |
|---|---|---|
| 감싸기 | 오래됐거나 믿기 어려운 서비스를 뒤에 숨기고 앞에서 요청을 거릅니다 | 그 서비스가 바깥 요청을 직접 받습니다 |
| 가속 | 자주 나가는 응답을 저장해 두었다가 바로 돌려줍니다 | 같은 요청마다 오리진 서버가 다시 일합니다 |
| 나누기 | 요청을 여러 대의 서버에 나눠 보냅니다 | 클라이언트가 서버 주소를 하나하나 알아야 합니다 |
두 번째 줄의 저장해 두기는 캐싱입니다. 세 번째 줄의 나눠 보내기는 부하 분산입니다.
셋 모두 클라이언트 쪽에서는 아무것도 바뀌지 않는다는 점이 같습니다. 오리진 서버를 바꾸거나 늘려도 클라이언트는 같은 주소로 요청합니다.
오리진 서버가 답하지 못할 때
게이트웨이는 클라이언트에게 응답을 돌려줄 책임을 집니다. 오리진 서버가 제대로 답하지 않아도 무언가를 돌려줘야 합니다. 이때 쓰는 상태 코드가 이름에 게이트웨이를 달고 있습니다.
flowchart TD
A["게이트웨이가 요청을 안쪽으로 보냄"] --> B{"제시간에 응답이 왔나"}
B -->|안 왔다| C["504 Gateway Timeout"]
B -->|왔다| D{"올바른 응답인가"}
D -->|아니다| E["502 Bad Gateway"]
D -->|그렇다| F["클라이언트에게 응답을 넘긴다"]
HTTP 502 는 오리진 서버에서 잘못된 응답을 받았다는 뜻입니다. 오리진 서버가 연결을 끊었거나 알아볼 수 없는 응답을 보냈을 때 나옵니다. HTTP 504 는 오리진 서버의 응답을 제시간에 받지 못했다는 뜻입니다.
두 코드를 받았다면 고장 난 곳은 대개 게이트웨이가 아니라 그 뒤입니다. 게이트웨이는 그 사실을 전하는 쪽입니다. 백엔드 개발자가 배포 직후 502 를 보면 애플리케이션 서버가 떴는지부터 확인하는 까닭입니다.
거쳐 가는 곳이 늘어나는 대가
게이트웨이를 세우면 요청이 지나는 곳이 하나 늘어납니다. 연결을 하나 더 맺고 요청을 한 번 더 고치므로 응답이 그만큼 늦어집니다.
게이트웨이가 멈추면 오리진 서버가 전부 멀쩡해도 요청이 들어가지 못합니다. 모든 요청이 한 곳을 지나기 때문입니다. 이렇게 하나가 멈추면 전체가 멈추는 곳이 단일 장애점입니다. 그래서 게이트웨이도 여러 대를 세워 두곤 합니다.
오리진 서버가 보는 정보도 달라집니다. 연결 상대가 늘 게이트웨이입니다. 그래서 클라이언트의 주소나 원래 요청한 호스트 이름은 헤더로 따로 전해 받아야 합니다.
그런데 클라이언트도 X-Forwarded-For 헤더를 직접 적어 보낼 수 있습니다. 게이트웨이가 그 값을 지우지 않고
넘기면 오리진 서버는 클라이언트가 꾸며 적은 가짜 주소를 믿게 됩니다. 이 헤더를 믿어도 되는지는 게이트웨이가
클라이언트가 보낸 같은 헤더를 걸러 주는지에 달려 있습니다.
같은 이름을 쓰는 다른 게이트웨이
네트워크에서도 게이트웨이라는 말을 씁니다. 인터넷 초기에는 망과 망을 잇는 장비를 게이트웨이라고 불렀습니다. 지금은 대개 라우터라는 이름을 씁니다.
그 옛 이름은 컴퓨터의 네트워크 설정에 남아 있습니다. 기본 게이트웨이는 내가 속한 같은 망 밖으로 나가는 데이터를 넘길 라우터의 주소입니다. 같은 망 안의 상대에게는 직접 보냅니다. 그 밖의 상대에게 가는 것은 전부 이 주소로 보냅니다.
API(Application Programming Interface)는 프로그램이 다른 프로그램을 부르는 약속입니다. 백엔드 서버가 바깥에 열어 둔 주소와 요청 모양이 곧 그 서버의 API 입니다.
API 게이트웨이는 웹 게이트웨이에 일을 더 얹은 것입니다. 요청을 넘기기 전에 요청한 사람이 누구인지 확인합니다. 너무 잦은 요청은 막습니다. 경로에 따라 여러 서비스로 나눠 보내기도 합니다.
결제에서 말하는 결제 게이트웨이도 뿌리가 같습니다. 쇼핑몰과 카드사 사이에 서서 결제 요청을 받아 넘기고 결과를 돌려주는 서비스입니다. 넷 모두 「경계에 서서 한쪽의 요청을 다른 쪽으로 넘긴다」는 뜻을 나눠 갖습니다.
관련 항목
게이트웨이와 나란히 분류되는 HTTP 중개자
중개자 · 프록시 · 리버스 프록시 · 포워드 프록시 · 터널 · 투명 프록시
게이트웨이가 앞에 서서 요청을 넘겨 주는 상대
오리진 서버 · 클라이언트 · 사용자 에이전트 · 애플리케이션 서버 · 업스트림 서버
게이트웨이가 요청을 넘기며 맡는 기능
부하 분산 · 캐싱 · TLS 종료 · 인증 · 레이트 리미팅 · URL 재작성
게이트웨이를 거쳐 온 요청에 붙는 헤더
Via · X-Forwarded-For · Forwarded · Host · X-Forwarded-Proto
게이트웨이가 안쪽 실패를 알리는 상태 코드
HTTP 502 · HTTP 503 · HTTP 504 · 타임아웃
게이트웨이 역할을 맡는 소프트웨어
nginx · HAProxy · Envoy · Apache HTTP Server · Traefik
게이트웨이라는 이름을 나눠 쓰는 개념
API 게이트웨이 · 기본 게이트웨이 · 라우터 · 결제 게이트웨이 · NAT 게이트웨이 · CGI
게이트웨이를 세울 때 따라오는 위험
게이트웨이를 정의하는 표준
다른 이름: gateway · HTTP 게이트웨이