재 현
Client와 Server 간의 통신 - IP 패킷부터 HTTP까지 본문
IP 패킷: 통신의 기초
IP 패킷은 정보를 전송하기 위한 기본 단위입니다. 각 IP 패킷에는 출발지와 목적지 IP 주소가 포함되어 있습니다. 하지만 IP 패킷은 몇 가지 단점을 가지고 있습니다. 그 중에서도 가장 주요한 단점은 비연결성과 비신뢰성입니다.
비연결성은 IP 패킷이 일단 전송되면 해당 패킷이 제대로 도착했는지 또는 순서대로 도착했는지 확인하지 않는다는 의미입니다. 이는 데이터 손실의 가능성을 의미하며, 데이터를 보낸 후 어떠한 관리나 확인 과정 없이 데이터를 그냥 보내는 것을 의미합니다.
비신뢰성은 중간에서 패킷이 손실될 수 있거나 순서가 바뀔 수 있다는 것을 의미합니다. 이러한 이유로 IP 패킷은 신뢰성을 보장하지 않습니다.
TCP (Transmission Control Protocol): 신뢰성을 보장하는 프로토콜
TCP는 IP 패킷의 단점을 보완하기 위해 개발된 프로토콜입니다. TCP는 다음과 같은 특징을 가지고 있습니다.
- 연결을 보장: TCP는 클라이언트와 서버 간의 안전한 연결을 수립하고, 데이터를 신뢰성 있게 전송합니다. 이로써 데이터의 손실을 최소화하고, 데이터가 목적지에 정확하게 도착하며, 순서대로 도착함을 보장합니다.
- Port: TCP는 포트 번호를 사용하여 어떤 서버의 어떤 애플리케이션에 데이터를 전달할지 지정합니다. 이는 IP 주소가 아파트 번호라면 포트는 몇동 몇호에 해당하는 것입니다.
- DNS (Domain Name System): IP 주소는 기억하기 어렵고 변경될 수 있으므로, 도메인 이름을 사용하여 서버를 식별하기 위해 DNS가 사용됩니다. 예를 들어, **GOOGLE.COM**은 구글 서버의 IP 주소를 가리킵니다.
URI (Uniform Resource Identifier): 리소스 식별
URI에는 URL(Uniform Resource Locator)와 URN(Uniform Resource Name) 두 가지 유형이 있습니다. 일반적으로 URL을 사용하는데, 이것은 다음과 같은 형식을 가지고 있습니다.
예를 들어, **https://www.example.com:8080/members?id=123**와 같은 URL은 프로토콜, 도메인, 포트, 리소스 경로, 쿼리 파라미터로 구성됩니다.
HTTP (Hypertext Transfer Protocol): 웹 통신의 핵심
HTTP는 웹 통신을 위한 프로토콜로, 다음과 같은 특징을 가지고 있습니다.
- 클라이언트-서버 구조: HTTP는 클라이언트와 서버 간의 통신을 위한 프로토콜로, 클라이언트는 사용자 인터페이스(UI)를 제공하고, 서버는 비즈니스 로직을 담당합니다. 클라이언트는 요청(Request)을 보내고, 서버는 응답(Response)을 반환하여 소통합니다.
- 무상태(Stateless): HTTP는 상태를 기억하지 않는 프로토콜로, 이전 요청과 다음 요청 간의 상태를 알지 못합니다. 예를 들어, 로그인 세션과 같은 상태 정보를 서버가 기억하지 않습니다. 이러한 특성은 서버의 확장성을 향상시키지만, 일부 작업에서는 상태 정보가 필요할 수 있습니다.
- 비연결성: HTTP는 요청-응답 사이에 연결을 유지하지 않습니다. 각 요청은 독립적으로 처리되며, 요청 시마다 연결을 수립하고 해제하는 "3-way handshake" 비용이 듭니다. 최근에는 연결을 지속적으로 유지하는 옵션도 있습니다.
- HTTP 메시지: HTTP 요청과 응답은 메시지 형식을 가지고 있습니다. 이 메시지는 시작 라인, 헤더, 공백, 바디로 구성되어 있으며, 클라이언트와 서버 간의 통신에 필요한 모든 정보를 포함합니다.
HTTP 메서드: 리소스 조작
HTTP 메서드는 클라이언트가 서버에게 어떤 동작을 수행하길 원하는지를 나타냅니다. 주요 HTTP 메서드와 그 역할은 다음과 같습니다.
- GET: 리소스를 조회합니다. 쿼리 파라미터를 사용하여 데이터를 요청하며, 주로 읽기 작업에 사용됩니다.
- POST: 요청을 보내고, 서버가 리소스를 생성합니다. 주로 새로운 데이터를 서버에 제출할 때 사용하며, 서버가 리소스 관리를 담당합니다.
- PUT: 리소스를 대체합니다. 해당 리소스가 없으면 새로 생성하고, 이미 존재하면 완전히 대체합니다. 클라이언트가 리소스 관리를 담당합니다.
- PATCH: 리소스를 부분적으로 변경합니다. 일부 데이터만 수정하는 데 사용됩니다.
- DELETE: 리소스를 삭제합니다.
HTTP 속성: 안전성, 멱등성, 캐시
HTTP는 다음과 같은 속성을 가지고 있습니다.
- 안전(Safe): GET 메서드는 리소스를 변경하지 않는다는 특성을 가집니다. 따라서 GET 요청은 안전합니다.
- 멱등(Idempotent): 동일한 요청을 여러 번 전송하더라도 데이터가 변경되지 않는다는 특성을 가집니다. GET, PUT, DELETE 메서드는 멱등성을 가지며, 이것은 네트워크 문제나 중복 요청 시에도 안전하게 사용될 수 있음을 의미합니다.
- 캐시 가능(Cacheable): HTTP 응답은 캐시될 수 있으며, 이를 통해 네트워크 부하를 줄일 수 있습니다.
HTTP 상태 코드: 요청 결과 표시
HTTP 응답은 상태 코드를 포함하며, 이 코드는 요청의 결과를 나타냅니다. 주요 HTTP 상태 코드는 다음과 같습니다.
- 2xx (Success):
- 200: 성공
- 201: 요청 성공하여 새로운 리소스 생성됨
- 3xx (Redirection):
- 리다이렉션을 나타내며, 요청을 다른 위치로 이동하라는 것을 의미합니다. 예를 들어, 301은 영구적인 리다이렉션을 나타내고, 302는 일시적인 리다이렉션을 나타냅니다.
- 4xx (Client Error):
- 400: 잘못된 요청
- 401: 인증되지 않음
- 403: 요청은 이해되었지만 승인되지 않음
- 404: 리소스가 서버에 없음
- 5xx (Server Error):
- 서버 오류를 나타내며, 주로 서버 문제로 인한 것입니다. 일반적으로 사용자가 직접 처리하기 어려운 경우에 사용됩니다.
쿠키
HTTP 프로토콜은 무상태(Stateless)한 프로토콜로, 클라이언트가 서버와 통신을 마치면 서버는 클라이언트와의 연결을 끊는 특징을 가지고 있습니다. 이로 인해 클라이언트가 다시 서버에 요청을 보낼 때, 서버는 이전 요청과 아무런 상관이 없다고 간주합니다. 그렇다면 클라이언트와 서버 간의 상태를 어떻게 유지하고 정보를 전달할 수 있을까요?
- 클라이언트가 모든 정보를 요청: 그러나 이 방법은 정보가 많을 경우에 매우 비효율적이며, 불필요한 데이터를 반복해서 전송해야 하므로 네트워크 트래픽을 증가시키는 단점이 있습니다.
- 쿠키(Cookie): 이러한 문제에 대한 해결책으로 등장한 것이 바로 쿠키입니다. 클라이언트는 쿠키 저장소를 가지고 있으며, 서버로부터 받은 쿠키를 이 저장소에 저장합니다. 이후 클라이언트가 다시 서버에 요청을 보낼 때, 저장된 쿠키를 함께 전송합니다. 쿠키는 로그인 세션 관리, 광고 정보 전달, 사용자 추적 등 다양한 목적으로 사용됩니다. 그러나 항상 서버에 전송되므로 네트워크 트래픽을 추가로 발생시키는 단점이 있습니다.
- 정보를 서버에 전송하지 않는 방법: 네트워크 트래픽을 줄이기 위해 클라이언트 측에서 정보를 서버에 전송하지 않는 방법도 있습니다. 이를 위해 로컬 스토리지(Local Storage)나 세션 스토리지(Session Storage)를 활용할 수 있습니다.
- 로컬 스토리지: 로컬 스토리지는 클라이언트 브라우저에 데이터를 저장하는데 사용됩니다. 데이터는 브라우저를 종료해도 유지되며, 만료 기간을 설정할 수 있습니다.
- 세션 스토리지: 세션 스토리지는 로컬 스토리지와 유사하지만 브라우저 세션이 유지되는 동안에만 데이터가 유지됩니다. 브라우저를 종료하면 데이터가 삭제됩니다.
- 쿠키의 속성 쿠키를 사용할 때는 다양한 속성을 설정할 수 있습니다. 이러한 속성은 쿠키의 생명주기와 동작을 제어하는 데 사용됩니다.
- Expires: 쿠키의 만료 날짜를 설정합니다.
- Max-Age: 쿠키의 유효 기간을 초 단위로 설정합니다.
- 세션 쿠키(Session Cookie): 브라우저 세션 동안만 유지되는 쿠키로, 브라우저를 닫으면 삭제됩니다.
- 영속 쿠키(Persistent Cookie): 설정한 만료 날짜 또는 유효 기간에 따라 유지되는 쿠키입니다.
요약하면, HTTP 프로토콜의 무상태성을 극복하기 위해 쿠키와 로컬 스토리지 등 다양한 방법을 활용할 수 있습니다. 이를 통해 클라이언트와 서버 간의 정보 유지와 상태 관리를 효과적으로 할 수 있으며, 네트워크 트래픽을 최소화할 수 있습니다. 쿠키의 속성 설정을 통해 적절한 데이터 관리를 수행할 수 있습니다.
캐시
우선, 캐시를 사용하지 않을 때 어떤 문제가 발생하는지 알아보겠습니다. 웹 페이지를 로딩할 때마다 매번 서버에서 데이터를 다운로드해야 합니다. 이는 네트워크 비용이 높을 뿐만 아니라 웹 페이지의 로딩 속도를 늦추는 원인이 됩니다.
캐시를 적용하여 성능 향상
- 한정된 시간 동안 캐시 사용
캐시를 적용할 때, 우선 데이터에 유효 시간을 설정합니다. 이는 데이터가 캐시에 저장된 상태로 얼마나 오래 유지될지를 결정합니다. 이렇게 하면 브라우저는 해당 시간 동안 로딩 속도가 빠르며, 네트워크 비용을 줄일 수 있습니다.
- 캐시 유효 시간이 초과하면 서버에서 데이터 갱신
캐시 유효 시간이 지난 경우, 즉 데이터가 오래된 경우 서버로부터 데이터를 다시 조회하고 갱신합니다. 이 때 두 가지 경우를 고려해야 합니다.
- 데이터가 변경된 경우
데이터가 서버에서 변경되었을 경우, 서버는 클라이언트에게 변경된 데이터를 제공합니다. 이를 위해 "Last-Modified" 헤더를 사용하며, 클라이언트는 이 헤더를 통해 서버와 데이터의 수정 여부를 확인합니다. 변경이 있었다면 새로운 데이터를 다운로드 받게 됩니다.
- 데이터가 변경되지 않은 경우
데이터가 변경되지 않은 경우, 즉 유효한 캐시 데이터와 서버 데이터가 동일한 경우, 클라이언트는 서버로부터 데이터를 받지 않고 캐시된 데이터를 사용합니다. 이를 위해 "304 Not Modified" 상태 코드를 서버로부터 받게 되며, 데이터 전송을 최소화할 수 있습니다.
검증 헤더와 조건부 요청
- "Last-Modified" 헤더와 조건부 요청
서버는 데이터의 마지막 수정 일자를 "Last-Modified" 헤더로 제공합니다. 클라이언트는 다음 요청 시에 이 헤더를 함께 보내어 데이터가 수정되었는지 여부를 확인합니다. 데이터가 수정되지 않았다면 네트워크 비용을 아낄 수 있습니다
- "ETag" (Entity Tag) 헤더
서버는 캐시용 데이터에 고유한 버전 이름인 "ETag"를 부여합니다. 데이터가 변경될 때마다 이 이름을 바꾸며, 클라이언트는 이 헤더를 통해 데이터가 변경되었는지 여부를 확인합니다. "ETag"가 동일하다면 데이터를 재다운로드하지 않고 캐시된 데이터를 사용합니다.
- 캐시 제어 로직은 주로 서버에서 관리됩니다. 클라이언트는 단순히 서버에 필요한 정보를 제공하며, 서버는 데이터의 캐시 제어를 담당합니다. 이렇게 함으로써 데이터의 일관성과 성능을 유지할 수 있습니다.
프록시 캐시
웹 페이지의 캐시를 더 효율적으로 관리하기 위해 프록시 캐시 서버를 사용할 수 있습니다. 이 서버는 웹 브라우저와 원 서버 사이에 위치하며, 캐시 데이터를 중계하여 네트워크 비용을 절감하고 빠른 로딩을 도와줍니다.
캐시 무효화
데이터의 캐시 무효화는 중요한 측면입니다. 몇 가지 옵션을 살펴보겠습니다.
- No Cache: 데이터는 캐시해도 되지만, 항상 원 서버에 검증을 요청하고 사용합니다. 네트워크 단절 시 옛날 데이터를 사용하지 않습니다.
- No-Store: 데이터를 저장하지 않으며, 메모리에서만 사용하고 빨리 삭제합니다.
- Must-Revalidate: 원 서버에 검증을 필수로 요청합니다. 네트워크 단절 시 504 오류가 발생합니다.
'Computer Science' 카테고리의 다른 글
프로세스 vs 쓰레드: 멀티 쓰레드의 이해와 고려사항 (0) | 2023.09.08 |
---|