클라이언트
클라이언트는 다른 프로그램에 일을 맡기고 그 결과를 받아 쓰는 쪽입니다. 먼저 말을 거는 쪽이 클라이언트입니다. 기다리고 있다가 답하는 쪽은 서버입니다. 웹 브라우저도, 다른 서버를 불러 쓰는 서버도 그 순간에는 클라이언트입니다.
쉽고 빠른 이해
클라이언트는 다른 프로그램에 일을 맡기고 결과를 받아 쓰는 쪽입니다. 주소창에 주소를 넣으면 웹 서버에 문서를 달라고 부탁하는 웹 브라우저가 그런 쪽입니다.
맡기는 쪽과 맡는 쪽을 가르면 데이터와 계산을 한곳에 모아 둘 수 있습니다. 쓰는 쪽이 여럿이어도 같은 값을 봅니다. 가르지 않으면 쓰는 쪽마다 같은 데이터를 자기 안에 따로 들고 있어야 합니다.
도는 모양은 셋입니다.
- 클라이언트가 무엇을 해 달라는 요청을 만들어 보냅니다
- 서버가 그 요청을 처리하고 응답을 돌려줍니다
- 클라이언트가 받은 응답을 화면에 그리거나 다음 계산에 씁니다
대가가 있습니다. 두 프로그램이 네트워크로 떨어져 있어서 답이 늦게 오거나 아예 안 올 수 있습니다. 기다림과 실패를 감당하는 코드가 클라이언트 쪽에 늘 따라붙습니다.
상세
걸려 온 전화를 받아 묻는 말에 답해 주는 사람이 있습니다. 그 사람도 자기가 모르는 것은 수화기를 들어 다른 데로 겁니다. 한 통에서 건 쪽과 받은 쪽을 가르는 것은 그 사람이 누구냐가 아니라 누가 먼저 걸었느냐입니다.
클라이언트는 다른 프로그램이 내놓은 기능을 요청해서 쓰는 쪽입니다. 어디로 무엇을 보내면 무엇이 돌아오는지를 미리 적어 둔 약속을 인터페이스라고 합니다. 클라이언트는 인터페이스에 적힌 대로 요청을 만들어 보냅니다.
요청을 받아 처리하고 답하는 쪽은 서버라고 합니다. 서버는 먼저 말을 걸지 않습니다. 누가 부를지 모르는 채로 기다리다가 요청이 오면 그때 일을 합니다. 이렇게 역할을 둘로 가른 구성을 클라이언트-서버 구조라고 합니다.
역할을 가르는 까닭은 데이터와 계산을 한곳에 모아 두려는 것입니다. 모아 두면 쓰는 쪽이 여럿이어도 같은 값을 봅니다. 가르지 않으면 쓰는 쪽마다 데이터를 자기 안에 들고 있어야 합니다. 한쪽이 고친 것을 다른 쪽은 모릅니다.
요청과 응답 한 왕복
클라이언트가 일을 한 번 맡기는 동안 오가는 것은 요청과 응답 두 가지입니다.
클라이언트가 보내는 것을 요청이라고 합니다. 무엇을 해 달라는 내용과 그 일에 필요한 값이 요청에 담깁니다. 서버가 돌려주는 것은 응답입니다. 일의 결과와 그 일이 잘 됐는지 아닌지가 응답에 담깁니다.
sequenceDiagram
participant 클라이언트
participant 서버
클라이언트->>서버: 요청 · 무엇을 해 달라
Note over 서버: 요청을 처리한다
서버-->>클라이언트: 응답 · 결과와 성패
그림에서 화살표는 언제나 클라이언트에서 시작합니다. 서버는 받은 요청에 대해서만 답합니다. 그래서 클라이언트가 부르지 않으면 서버 쪽에서는 아무 일도 일어나지 않습니다.
한 프로그램이 겸하는 두 역할
클라이언트와 서버는 프로그램의 종류가 아니라 한 번의 주고받음에서 맡는 역할입니다. 그래서 같은 프로그램이 상대에 따라 양쪽이 다 됩니다.
웹 서버가 그런 예입니다. 브라우저가 문서를 달라고 하면 웹 서버는 답하는 쪽입니다. 그런데 그 문서를 만들려고 데이터베이스에 질의를 보낼 때, 웹 서버는 먼저 말을 거는 쪽이 됩니다.
flowchart TD
B["웹 브라우저"]
W["웹 서버"]
D["데이터베이스"]
B -->|요청| W
W -->|요청| D
D -.->|응답| W
W -.->|응답| B
가운데에 있는 웹 서버는 브라우저가 보낸 요청을 받습니다. 그 웹 서버는 데이터베이스에 요청을 보냅니다. 응답은 각각 반대 방향으로 돌아옵니다.
브라우저에게 웹 서버는 서버입니다. 데이터베이스에게 웹 서버는 클라이언트입니다. 어느 쪽인지를 가르는 것은 프로그램의 정체가 아니라 그 한 번의 주고받음에서 누가 먼저 말을 걸었느냐입니다.
같은 이름으로 불리는 세 가지
실무에서 이 낱말은 크기가 다른 세 가지에 붙습니다. 셋 다 「요청해서 쓰는 쪽」이라는 뜻은 같습니다. 무엇을 그렇게 부르느냐만 다릅니다.
| 부르는 대상 | 그렇게 부르는 예 |
|---|---|
| 요청을 보내는 쪽 | 웹 서버에 요청을 보내온 브라우저 · curl |
| 사용자 기기에서 도는 프로그램 | 게임 클라이언트 · 메일 클라이언트 |
| 서버 호출을 감싸 둔 코드 | 데이터베이스 드라이버 · 클라이언트 라이브러리 |
첫째가 이 낱말의 뿌리입니다. 나머지 둘은 그 역할을 맡은 프로그램과 그 역할을 대신해 주는 코드에 같은 이름을 붙인 것입니다.
클라이언트 쪽 코드에 따라붙는 세 가지
서버를 부르는 줄 하나 말고 클라이언트 쪽 코드가 더 들고 있는 것은 기다림과 실패와 연결, 셋입니다.
기다림을 다뤄야 합니다. 답이 언제 올지 모르므로 얼마까지 기다릴지를 미리 정해 둡니다. 이 한도를 타임아웃이라고 합니다. 한도가 없으면 답이 안 오는 요청 하나가 그것을 기다리는 코드를 영영 붙잡아 둡니다.
실패도 다뤄야 합니다. 요청이 중간에 사라지면 클라이언트는 서버가 그 일을 했는지 아닌지 모릅니다. 그래서 같은 요청을 다시 보냅니다. 이것을 재시도라고 합니다.
다시 보내려면 조건이 하나 있습니다. 같은 요청이 두 번 도착해도 결과가 달라지지 않아야 합니다. 이 성질을 멱등성이라고 합니다.
연결도 아껴 씁니다. 요청마다 연결을 새로 맺으면 그때마다 연결을 여는 준비 과정이 붙습니다. 클라이언트는 맺어 둔 연결을 모아 두고 다시 꺼내 씁니다. 그 모아 둔 곳이 커넥션 풀입니다.
서버가 클라이언트를 믿지 않는 까닭
클라이언트는 대개 서버를 만든 쪽의 손이 닿지 않는 데서 돕니다. 사용자의 브라우저 안이거나 남의 회사 서버 안입니다. 그래서 서버는 클라이언트가 보낸 값을 받은 대로 쓰지 않습니다.
클라이언트에 넣어 둔 검사는 사용자를 돕는 장치이지 방어벽이 아닙니다. 입력 칸에서 글자 수를 막아 두어도, 요청은 그 화면을 거치지 않고 손으로 만들어 보낼 수 있습니다. 그래서 같은 검사를 서버에서 한 번 더 합니다.
비밀도 같습니다. 클라이언트 안에 넣어 둔 값은 그 프로그램을 쥔 사람이 꺼내 볼 수 있습니다. 서버만 알아야 하는 열쇠는 클라이언트에 두지 않습니다.
대신 서버가 액세스 토큰을 발급해 들려 보냅니다. 이 토큰은 쓸 수 있는 범위와 기한이 정해져 있습니다. 새어 나가도 그 범위와 기한 밖으로는 못 씁니다.
관련 항목
클라이언트와 짝을 이루어 요청을 받는 상대
서버 · 웹 서버 · 오리진 서버 · 애플리케이션 서버 · 업스트림 서버 · 자원 서버
클라이언트와 서버 사이에 서는 중개자
프록시 · 리버스 프록시 · 게이트웨이 · 로드 밸런서 · 터널 · 중개자
클라이언트 노릇을 하는 프로그램
브라우저 · 사용자 에이전트 · 모바일 앱 · 명령줄 도구 · curl · 게임 클라이언트 · 메일 클라이언트
클라이언트가 서버에 닿을 때 지나는 길과 프로토콜
네트워크 · HTTP · gRPC · WebSocket · TCP · DNS · 원격 프로시저 호출
클라이언트 호출을 대신 짜 주는 부품
클라이언트 라이브러리 · SDK · 스텁 · 채널 · 커넥션 풀 · HTTP 클라이언트
클라이언트가 서버에게 자기를 증명하는 수단
액세스 토큰 · 리프레시 토큰 · API 키 · 인증서 · 세션 · 쿠키
클라이언트 쪽에서 코드를 돌리는 방식
프론트엔드 · 클라이언트 사이드 렌더링 · 서버 사이드 렌더링 · 씬 클라이언트 · 오프라인 우선
클라이언트가 서버 장애를 견디는 수단
타임아웃 · 재시도 · 지수 백오프 · 서킷 브레이커 · 폴백 · 멱등성
클라이언트에서 자주 나는 오류·장애
커넥션 누수 · 썬더링 허드 · 재시도 폭풍 · 낡은 데이터 · CORS 오류
클라이언트가 서버와 주고받는 메시지
클라이언트와 서버가 미리 맞춰 두는 약속
다른 이름: client · 클라이언트 프로그램 · 요청자