Client & Server
클라이언트와 서버
1. 기본 개념
1.1 Client
서버에 특정 기능이나 정보를 요청하고, 서버가 제공하는 서비스를 사용하기 위한 컴퓨터나 프로그램.
즉, 클라이언트는 서비스를 요청하는 주체입니다. 보통 사용자 또는 애플리케이션을 대표하며, 데이터를 요청하거나 처리된 결과를 받습니다.
1.2. Server
네트워크를 통해 다른 컴퓨터(클라이언트)에게 자료나 서비스를 제공하는 컴퓨터 또는 프로그램을 의미.
서버는 클라이언트의 요청을 받아 데이터를 처리하고 응답을 반환하는 주체. 데이터를 저장하거나 특정 기능(인증, 파일 등)을 제공합니다.
서버의 종류:
데이터베이스 서버: 데이터 저장 관리
웹 서버: HTTP 프로토콜을 통해 웹 클라이언트로부터 받은 요청에 대한 응답 전송(정적)
파일 서버: 파일을 저장하고 공유하는 역할 수행
메일 서버: 전자우편 송수신 및 관리
애플리케이션 서버: 특정 비즈니스 로직이나 애플리케이션 기능을 처리하고 결과를 제공(동적)
1.3. Client-Server Model
클라이언트는 요청(Request)를 보내고, 서버는 응답(Response)을 반환하는 구조.
장점:
중앙집중식 관리: 서버에서 데이터와 서비스를 관리해서 업데이트나 보안관리 용이
효율성: 다수의 클라이언트가 같은 자원을 서버에서 중앙집중 방식으로 활용
확장성: 여러 대를 연동(로드 밸런싱, 클러스터링)하여 성능 향상
단점:
서버 부담
단일 장애점(SPOF)
클라이언트 종속성: 서버에 의존하여 서버에서 문제가 발생할 시에 영향이 큼
2. 통신 방식
2.1. 통신 구조 개념
요청-응답: 클라이언트가 서버에 요청을 보내고, 서버는 HTML 등의 리소스를 응답으로 반환
연결형/비연결형:
TCP: 연결형 프로토콜. 3 way handshake를 통한 신뢰성 확보
UDP: 비연결형 프로토콜. 신뢰성보다는 속도를 우선시.
상태 유무
Stateless: 서버가 클라이언트의 상태 정보를 별도로 저장하지 않는 형태
Stateful: 클라이언트와 서버가 연결된 동안 일정한 상태를 유지. 이전 통신 context를 기반
2.2. 대표적인 통신 방법
HTTP/HTTPS
HTTP: 애플리케이션 레벨 프로토콜로, 요청-응답 방식으로 통신하며 TCP를 기반으로 동작.
HTTPS: HTTP에 SSL/TLS 암호화 계층을 얹어 보안성을 강화한 프로토콜
특징:
Request-Response
Stateless
확장 용이: REST API, GraphQL, gRPC 등 다양한 방식으로 확장 가능
WebSocket
HTTP를 통해 초기 연결을 맺은 뒤, 양방향 통신을 위한 전이중 채널을 형성하는 프로토콜
서버와 클라이언트가 실시간으로 메시지를 주고받을 수 있으며, 채팅, 실시간 알림, 주식 시세 등 실시간성이 필요한 서비스에서 사용
특징:
양방향
지속 연결(Stateful)
실시간 데이터: 별도의 polling없이도 서버에서 즉시 데이터를 push
Server-Sent Events(SSE)
단방향 실시간 통신 방식. 클라이언트가 서버에 연결을 맺으면 서버에서 클라이언트로 이벤트(데이터)를 지속적으로 전송 가능
Websocket과 달리, 서버에서 클라이언트로만 전송. 클라이언트에서 서버 요청은 HTTP 요청을 사용해야됨.
특징:
단방향: 서버 -> 클라이언트로만 메인 스트림 존재
자동 재연결: 연결이 끊어지면 브라우저가 자동 재접속 시도.
텍스트 기반: JSON, Plain text 등으로 쉽게 전송.
Long Polling
WebSocket이나 SSE가 나오기 전, 실시간 통신을 모방하기 위해 사용되던 기법
클라이언트가 서버에 요청을 보내면, 서버는 새로운 데이터가 생길 때까지 응답을 지연시키다가 응답을 반환. 응답을 받은 클라이언트는 다시 새로운 요청을 보내어 실시간 처럼 동작.
구현이 비교적 간단하지만, 많은 연결을 장시간 유지해야 하므로 서버 리소스를 많이 소모.
gRPC
구글에서 개발한 고성능 원격 프로시저 호출 방식. HTTP/2를 기반으로 Protocol Buffer(바이너리 형식)를 사용해 데이터를 주고 받음
다수의 언어와 플랫폼을 지원하며 양방향 스트리밍도 가능. 마이크로 서비스간 동신 등에 자주 활용
2.3. 사용처
단순 웹페이지/파일 제공: HTTP(S)
채팅 등 실시간 기능: WebSocket, SSE, gRPC 스트리밍 등 양방향/단방향 실시간 프로토콜 고려
API 통신(REST, GraphQL 등): HTTP(S) 기반의 요청 응답 사용
마이크로서비스 간 고성능 통신: gRPC, 메시지 큐 등 사용
3. 동작 원리
3.1. IP주소 얻기
클라이언트와 서버는 서로 상호작용하며, 약속된 프로토콜을 통해 데이터를 주고 받습니다. IP주소와 포트를 사용하여 서로를 식별하게 됩니다.
약속된 프로토콜: Http/Https, TCP/IP, UDP
URL 입력: 유저는 도메인url을 클라이언트 웹브라우저에 입력합니다.
hosts 파일 확인: hosts 파일은 사용자가 수동으로 관리합니다. DNS 캐시 포이즈닝으로 공격자가 DNS서버에 잘못된 응답을 전송하거나 DNS 서버의 응답을 변조하여 오염된 데이터를 캐시에 저장하게끔 하는 공격이 발생할 수 있기떄문에 가장 먼저 확인합니다.
브라우저 캐시 확인: 브라우저는 브라우저 캐시(DNS 캐시)를 확인합니다.
OS 캐시 확인: 브라우저가 DNS조회를 위해 OS가 제공하는 네트워크 API를 시스템 콜을 수행하여 OS 캐시를 확인합니다. OS캐시는 TTL이 존재하며, 메모리에 저장됩니다.
로컬 DNS 리졸버로 질의: 로컬 DNS 리졸버(isp, 인터넷 서비스 제공자에서 제공하는 DNS 서버)에 도메인 이름을 질의. 로컬 DNS 리졸버는 이전 요청에 대한 결과를 TTL 동안 캐싱하고 있습니다. 캐시 미스가 발생하면 로컬 DNS 리졸버가 재귀적으로 질의를 수행합니다.
루트 DNS 서버로 요청: 루트 DNS는 13개의 클러스터로 분산되어 있으며, 최상위 레벨 TLD를 관리합니다. 루트서버는 도메인의 IP주소를 반환하지 않고, .com/.net 등 다음 TLD 서버의 위치를 반환합니다. (.com의 네임서버의 주소)
TLD 네임서버로 요청: 로컬 리졸버는 루트 DNS 서버의 응답을 통해, TLD 네임서버에 질의합니다. TLD 네임서버는 권한 네임서버(Authroitative Name Server)의 위치를 반환합니다. (example.com의 권한 네임서버의 주소)
권한 네임서버로 요청: 도메인에 대한 최종 정보를 보유한 서버입니다. 권한 네임서버에서 IP주소를 요청하게 되며, 응답으로 IP주소를 처음에 반복적 질의를 했던 로컬 DNS 리졸버에 반환합니다. 권한 네임서버는 A레코드(IPv4 주소), AAAA레코드(IPv6 주소), CNAME레코드(리다이렉션 주소)를 저장하고 있습니다. 리다이렉션 주소를 반환받으면 해당 주소를 브라우저에 반환하고, Hosts 파일 확인부터 다시 실행.
로컬 DNS 리졸버의 응답: 최종적으로 권한 네임서버로부터 받은 IP를 브라우저에 반환합니다.
3.2. 서버와의 연결 설정-TCP
클라이언트는 반환된 IP주소와 서버의 지정된 포트(https:433, http:80 기본값)으로 연결을 시도합니다.
3 way-handshake 1단계: 클라이언트가 랜덤ISN을 생성해서 서버측에 보냅니다.
2단계: 서버측에서는 받은 Syn값에 1을 더한 Ack와, 서버의 ISN을 생성해서 Syn값으로 보냅니다.
3단계: 클라이언트측에서는 서버의 Syn과 클라이언트의 Ack를 받게됩니다. 이때 다시 서버의 syn+1을 Ack값으로 서버에 보내게됩니다. 서버측은 소켓 테이블에 클라이언트 정보를 등록합니다. 소켓은 클라이언트와 서버 간 데이터를 주고받기 위해 필요한 논리적인 개념이고, 실제로는 요청에서 클라이언트 정보를 받아서 소켓 테이블을 확인합니다. 소켓은 운영체제의 커널에서 생성되고 관리됩니다. 서버는 소켓이 열려있지 않은 요청이 들어오면 무시하거나 새로운 연결로 처리하고, 4 way handshake가 발생하면 소켓 테이블에서 정보를 삭제합니다.
3.3. 서버와의 연결 설정-SSL/TLS
TLS Handshake 1단계: 클라이언트 Hello를 보냅니다. 클라이언트가 사용할 수 있는 암호화 알고리즘, TLS 버전, 랜덤값, 세션 ID가 포함됩니다.
2단계: 서버는 클라이언트에게 Server Hello와 인증서(CA 인증기관에서 발급되고 서버의 공개 키를 포함)를 전송합니다. 서버의 공개 키, 인증서를 발급한 CA 서명, 인증서 유효기간 등의 정보를 포함. 또한 대칭키를 생성하기 위한 키 교환 방법을 선택. (RSA / ECDHE)
3단계: 클라이언트는 인증서를 통해 서버의 신원을 확인. 신뢰할 수 있는 CA인지 확인, 인증서 유효기간 확인, CA의 서명을 검증합니다.
4단계: 클라이언트는 pre-master-secret을 생성합니다.
RSA 방식: 클라이언트는 서버의 공개 키를 사용하여 pre-master-secret을 암호화하고 서버에 전달.
ECDHE 방식: 클라이언트는 임시 키 쌍을 생성하고, 자신의 공개 키를 서버로 전송. 서버의 공개키와 클라이언트의 개인 키를 조합하여 pre-master-secret을 계산.
5단계: 서버는 pre-master-secret을 복호화.
RSA 방식: 서버의 개인 키를 사용하여 복호화
ECDHE 방식: 클라이언트의 공개 키와 서버의 개인 키를 조합하여 pre-master-secret 계산.
6단계: 양측에서 pre-master-secret을 통해 대칭키로 사용될 세션 키를 생성. 이후 요청과 응답을 세션키를 활용하여 암호화, 복호화
3.4. 데이터 패킷의 라우팅
출발지 IP와 MAC 주소, 도착지 IP와 MAC 주소의 역할:
IP 주소는 네트워크의 위치를 식별하며, 패킷이 어느 네트워크로 가야 하는지 결정하는 데 사용됩니다.
MAC 주소는 같은 네트워크(LAN) 내에서 물리적 기기를 식별하며, 패킷이 어떤 기기로 가야 하는지 결정하는 데 사용됩니다.
사설 IP → 공인 IP 변환 (NAT):
라우터(또는 게이트웨이)는 사설 네트워크의 IP와 포트 번호를 공인 IP와 새로운 포트 번호로 변환하며, 변환 정보는 NAT 테이블에 기록됩니다.
응답이 돌아올 때, 라우터는 NAT 테이블을 참조하여 패킷을 올바른 사설 IP로 전달합니다.
라우터에서 다음 홉 찾기:
라우터는 라우팅 테이블을 참조하여, 도착지 IP가 속한 네트워크 대역을 찾습니다.
해당 네트워크로 가는 경로가 라우팅 테이블에 있으면, Next Hop(다음 라우터)으로 패킷을 전달합니다.
Default Route 사용:
라우팅 테이블에서 도착지 IP에 해당하는 네트워크 대역을 찾을 수 없으면, Default Route를 따라 상위 라우터로 패킷을 전달합니다.
상위 라우터의 역할:
상위 라우터는 하위 라우터들이 담당하는 네트워크 대역(IP 범위)을 알고 있습니다.
도착지 IP가 속한 범위를 확인한 뒤, 해당 범위를 담당하는 하위 라우터로 패킷을 전달합니다.
Last updated