네트워크(3) – HTTP 응용, 보안 & 로드밸런싱 정리

1. 응용 계층 – HTTP의 응용

1.1 쿠키

HTTP는 기본적으로 스테이트리스 프로토콜입니다. 즉, 각 HTTP 요청은 독립적인 메시지로 취급됩니다. 그렇다면 “3일간 보지 않기”와 같은 기능은 어떻게 구현될까요? 바로 쿠키를 활용합니다.

  • 쿠키의 정의: 서버에서 생성하여 클라이언트(주로 브라우저)에 저장되는 _이름-값 쌍 형태의 데이터_입니다.
  • 부가 속성: 이름과 값 외에도 만료 기간(Expires, Max-Age), 도메인(Domain), 경로(Path), 보안 관련 속성(Secure, HttpOnly) 등이 있습니다.
  • 동작 원리:
    • 서버는 응답 메시지에 Set-Cookie 헤더를 포함하여 클라이언트에 쿠키를 전송합니다.
    • 클라이언트는 저장된 쿠키를 이후 요청 시 Cookie 헤더에 담아 서버로 전송합니다.
    • 여러 쿠키는 세미콜론(;)으로 구분되어 전송됩니다.
  • 보안 속성:
    • Secure: HTTPS를 통해서만 쿠키를 송수신.
    • HttpOnly: 자바스크립트를 통한 접근을 제한, 오직 HTTP 요청/응답을 통해서만 접근.

또한, 웹 스토리지를 통해 쿠키보다 더 큰 용량의 데이터를 저장할 수 있습니다.

  • 로컬 스토리지: 별도 삭제가 없으면 영구 저장.
  • 세션 스토리지: 브라우저가 열려있는 동안만 저장.

2. 캐시

HTTP 캐시(웹 캐시)는 서버의 부하를 줄이고 응답 속도를 높이기 위해 자원의 사본을 임시 저장하는 기술입니다.

  • 기본 개념: 클라이언트가 큰 용량의 데이터(예: 10MB 이미지)를 서버로부터 한 번 받아 캐시에 저장해두고, 이후 동일 요청 시 저장된 사본을 재사용합니다.
  • 유효기간:
    • 응답 메시지의 Expires 헤더: 만료 날짜를 명시.
    • Cache-Control 헤더의 Max-Age 값: 초 단위 유효 기간.
  • 캐시 신선도: 캐시된 데이터가 원본과 얼마나 일치하는지를 판단하는 기준입니다.
    • 유효기간 만료 후 처리:
    • 원본 데이터가 변경되지 않았다면 캐시의 유효기간을 연장하여 재사용할 수 있음.
    • 원본이 변경되었다면 새로운 데이터를 받아와야 합니다.
  • 원본 데이터 변경 여부 확인:
    • If-Modified-Since: 클라이언트가 날짜를 기반으로 서버에 요청하여, 이후 변경이 있으면 200(OK)과 함께 새 자원, 없으면 304(Not Modified) 응답.
    • If-None-Match: Etag 값을 기반으로 요청하여, 자원의 버전이 변경되었을 때만 새 데이터를 응답.
    • Etag: 자원의 버전을 식별하는 태그. 자원 변경 시 Etag 값도 변경.

서버는 요청에 따라 200, 304, 혹은 404(Not Found) 상태 코드로 응답합니다.


3. 콘텐츠 협상

HTTP 메시지를 통해 주고받는 것은 _자원의 표현_입니다. 동일한 자원도 다양한 표현(예: 한국어, 영어, HTML, XML 등)으로 제공될 수 있습니다.

  • 콘텐츠 협상(content negotiation): 클라이언트가 선호하는 표현을 헤더를 통해 서버에 전달하면, 서버는 그에 맞는 표현을 응답합니다.
  • 주요 콘텐츠 협상 헤더:
    • Accept: 선호하는 미디어 타입
    • Accept-Language: 선호하는 언어
    • Accept-Encoding: 선호하는 인코딩 방식
  • 우선순위 지정:
    • q 값(quality value): 0부터 1까지의 값으로 선호도를 나타내며, 값이 클수록 우선순위가 높습니다.

예시 요청 메시지:

GET /index.html HTTP/1.1
Host: example.com
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Accept: text/html,application/xml;q=0.9,text/plain;q=0.6,*/+;q=0.5

이 메시지는 클라이언트가 언어 및 미디어 타입에 대해 복수의 선호도를 표현하는 예입니다.


4. 보안: SSL/TLS와 HTTPS

현재 대부분의 웹 서비스는 HTTP에 SSL/TLS를 결합한 HTTPS를 사용합니다.

  • HTTPS의 개념: HTTP에 SSL(또는 TLS)의 기능이 추가된 프로토콜로, 브라우저에 자물쇠 아이콘으로 표시됩니다.
  • SSL과 TLS:
    • SSL (Secure Sockets Layer)TLS (Transport Layer Security): 암호화 및 인증을 수행하는 프로토콜이며, TLS는 SSL의 후속 프로토콜입니다.
    • 현재 주로 사용되는 버전은 TLS 1.2와 TLS 1.3입니다.

TLS 1.3 핸드셰이크 과정

HTTPS 통신은 아래와 같은 단계로 진행됩니다.

  1. TCP 쓰리 웨이 핸드셰이크: 기본 TCP 연결 설정.
  2. TLS 핸드셰이크: 인증과 암호화에 필요한 키 생성 및 교환, 인증서 검증 등이 이루어집니다.

핵심 메시지:

ClientHello: 클라이언트가 지원하는 TLS 버전, 암호 스위트, 클라이언트 난수 등 정보 전달.
ServerHello: 서버가 선택한 TLS 버전, 암호 스위트, 서버 난수 등 정보 전달.
CertificateCertificateVerify: 서버의 신뢰성을 보장하기 위해 CA(인증 기관)에서 발급한 인증서를 전송하고 검증.
Finished: 마지막 메시지 교환 후, 이후 통신은 핸드셰이크 과정에서 얻은 키를 기반으로 암호화되어 전송됩니다.

  1. 메시지 송수신: 암호화된 데이터를 주고받음.

핸드셰이크의 핵심은 암호화 통신을 위한 키의 생성/교환서버의 인증입니다.


5. 프록시와 안정적인 트래픽

현실의 네트워크에서는 클라이언트와 단일 서버가 같은 네트워크 내에 존재하지 않고, 여러 중간 장비와 서버가 존재합니다. 이때 오리진 서버(origin server)는 자원을 생성하고 클라이언트에게 응답을 제공하는 최상위 서버를 의미합니다.

5.1 오리진 서버와 중간 서버

  • 프록시(proxy):

클라이언트의 요청을 대신 전달하는 대리자 역할.
주로 캐싱, 클라이언트 암호화, 접근 제한 등의 기능을 제공.
클라이언트와 가까운 위치에서 동작하며 “심부름꾼”의 역할을 수행합니다.

  • 게이트웨이(gateway) / 리버스 프록시(reverse proxy):

오리진 서버로 향하는 요청을 대신 받아 전달하는 역할.
클라이언트 입장에서는 오리진 서버처럼 보이며, 캐시 저장이나 부하 분산(로드 밸런싱)의 역할도 수행합니다.
클라이언트보다 오리진 서버에 더 가까운 위치에서 동작합니다.


6. 고가용성: 로드 밸런싱과 스케일링

시스템의 가용성(availability)은 전체 사용 시간 중 정상적으로 작동하는 비율을 의미하며, 높은 가용성(예: 99.999% 또는 ‘파이브 나인스’)을 목표로 합니다.
가용성은 다음 수식을 통해 계산됩니다.

가용성 = 업타임 / (업타임 + 다운타임)

여기서

  • 업타임(uptime): 시스템이나 서비스가 정상적으로 운영되어, 사용자가 문제 없이 접근할 수 있는 시간을 의미합니다. 예를 들어, 웹 서비스가 정상적으로 요청을 처리하는 시간 전체가 업타임입니다.
  • 다운타임(downtime): 장애나 유지보수 등으로 인해 서비스가 중단된 시간을 의미합니다. 이 시간 동안 사용자는 서비스를 이용할 수 없게 됩니다.

시스템의 가용성을 극대화하기 위해서는 업타임을 최대화하고, 다운타임을 최소화하는 전략을 수립하는 것이 매우 중요합니다.


6.1 고가용성을 위한 설계 개념

시스템이 장애 상황에서도 지속적으로 동작할 수 있도록 하기 위해 아래와 같은 핵심 개념들을 설계에 반드시 포함해야 합니다.

  • 결함 감내 (Fault Tolerance)
    • 정의: 시스템 내부의 일부 구성 요소에 장애가 발생해도 전체 서비스가 중단되지 않도록 하는 능력입니다.
    • 추가 설명: 결함 감내를 구현하기 위해서는 하드웨어, 소프트웨어, 네트워크 등의 다양한 요소에서 예외 상황을 고려하고, 자동으로 장애를 우회하거나 복구할 수 있는 메커니즘을 포함시켜야 합니다.
  • 다중화 (Multiplexing)
    • 정의: 동일한 역할을 수행할 수 있는 여러 서버 또는 장비를 병렬로 운영하여, 특정 서버에 장애가 발생해도 다른 서버가 그 역할을 대신하도록 하는 방식입니다.
    • 추가 설명: 예를 들어, 웹 서버를 3대 이상으로 구성하여 한 서버에 문제가 생겨도 나머지 서버가 요청을 처리함으로써 전체 시스템의 다운타임을 줄일 수 있습니다.
  • 페일오버 (Failover)
    • 정의: 장애가 발생한 주 서버 대신 예비 서버가 자동으로 서비스에 투입되어 지속적인 서비스 제공을 보장하는 기능입니다.
    • 추가 설명: 페일오버는 보통 다중화와 결합되어 작동합니다. 예비 서버가 실시간 또는 짧은 지연 시간 내에 활성 서버의 역할을 인계받음으로써, 사용자는 거의 느끼지 못할 정도의 서비스 중단만 경험합니다.

이러한 설계 개념들은 시스템의 업타임을 극대화하고, 다운타임을 최소화하여 전체 가용성을 높이는 데 핵심적인 역할을 합니다.


6.2 로드 밸런싱

과도한 트래픽이 특정 서버에 집중되면 해당 서버의 성능 저하 및 장애로 이어질 수 있으므로, 로드 밸런싱(load balancing)은 전체 시스템의 안정성을 유지하는 데 필수적인 기술입니다.

  • 로드 밸런서
    • 정의: 클라이언트의 요청을 다중화된 서버들에 고르게 분산시켜 부하를 균등하게 나누어주는 장비나 소프트웨어입니다.
    • 추가 설명: 로드 밸런서는 네트워크 상의 중간 계층에 위치하여, 서버의 상태와 부하를 지속적으로 모니터링하고, 실시간으로 최적의 분배 전략을 적용합니다.
  • 부하 분산 알고리즘

로드 밸런싱의 효과를 극대화하기 위해 다양한 알고리즘이 사용됩니다.
라운드 로빈 (Round Robin): 순차적으로 서버에 요청을 분배하는 방식으로, 구현이 간단하지만 서버의 성능 차이를 고려하지 않습니다.
최소 연결 (Least Connection): 현재 연결 수가 가장 적은 서버에 우선적으로 요청을 배분하여, 실시간 부하 분산에 효과적입니다.
랜덤 (Random): 요청을 임의의 서버에 배분하는 방식으로, 경우에 따라 부하 분산이 고르게 이루어질 수 있습니다.
IP 해시 (IP Hash): 클라이언트의 IP 주소를 기반으로 특정 서버를 선택하는 방식으로, 세션 유지가 필요한 서비스에 적합합니다.

  • 가중치 (Weight)
    • 정의: 서버마다 서로 다른 성능을 고려하여, 성능이 우수한 서버에 더 많은 트래픽을 할당하는 방법입니다.
    • 추가 설명: 예를 들어, 4대의 서버 중 2대가 다른 서버보다 두 배의 성능을 가진 경우, 성능이 높은 서버에 높은 가중치를 부여하여 그에 따라 더 많은 요청을 처리할 수 있도록 합니다.

이처럼 로드 밸런싱은 시스템의 부하를 효과적으로 분산시키고, 특정 서버에 집중되는 과부하를 방지하여 전체 가용성을 유지하는 중요한 역할을 합니다.


6.3 스케일링

시스템 확장을 위한 전략은 두 가지 주요 방식으로 구분됩니다. 이는 서비스 성장에 따라 자원을 유연하게 조절하는 데 핵심적인 역할을 합니다.

  • 스케일 업 (수직적 확장, Vertical Scaling)
    • 정의: 기존 서버나 하드웨어 부품을 더 높은 성능의 장비로 교체하여 처리 능력을 향상시키는 방식입니다.
    • 장점: 설치와 구성이 단순하며, 기존 인프라에 바로 적용할 수 있습니다.
    • 단점: 하드웨어의 물리적 한계로 인해 확장성이 제한되며, 고성능 장비의 비용이 상대적으로 높습니다.
  • 스케일 아웃 (수평적 확장, Horizontal Scaling)
    • 정의: 여러 대의 서버를 추가하여 전체 시스템의 처리 능력을 확장하는 방식입니다.
    • 장점: 시스템의 유연성을 극대화할 수 있으며, 단일 서버 장애 시에도 전체 시스템에 미치는 영향을 최소화할 수 있습니다.
    • 단점: 서버 간의 데이터 일관성 유지 및 분산 환경 구성에 따른 복잡성이 증가할 수 있습니다.
  • 오토스케일링 (Autoscaling)
    • 정의: 트래픽 변화나 부하 상황에 따라 시스템 자원을 동적으로 자동 확장하거나 축소하는 기능입니다.
    • 추가 설명: 특히 클라우드 환경에서 자주 사용되며, 필요할 때 리소스를 추가하고, 부하가 줄어들면 자원을 줄여 비용 효율성을 극대화할 수 있습니다.

7. Nginx로 알아보는 로드 밸런싱

Nginx는 웹 서버뿐 아니라 포워드 프록시리버스 프록시의 역할을 수행할 수 있습니다.

특히, Nginx를 활용한 로드 밸런싱 설정은 실제 환경에서 많이 사용됩니다.

7.1 기본 설정 파일 구조

Nginx 설치 후 생성되는 주요 파일 및 디렉터리:

  • /etc/nginx/nginx.conf: 가장 기본적인 설정 파일.
  • /etc/nginx/conf.d/: 추가 설정 파일들이 위치하는 디렉터리.
  • 로그 파일 위치: /var/log/nginx/access.log (접속 로그), /var/log/nginx/error.log (오류 로그).

7.2 예제 설정

다음은 Nginx를 통한 로드 밸런싱 설정 예제입니다.

upstream backend {
    server 10.10.10.2:80 weight=1;
    server 10.10.10.3:80 weight=2;
    server 10.10.10.4:80 backup;
}
server {
    listen 80;
    server_name localhost;
    location / {
        proxy_pass http://backend;
    }
}
  • upstream backend: 로드 밸런싱 대상 서버 그룹을 정의
    • 10.10.10.2: 기본 가중치 1
    • 10.10.10.3: 가중치 2, 더 많은 트래픽 분배
    • 10.10.10.4: backup 서버, 다른 서버에 문제가 있을 때 동작
  • server 블록: Nginx가 80번 포트에서 요청을 받고, / 경로에 대해 backend 그룹으로 프록시 전달함.

추가로, 로드 밸런싱 알고리즘을 명시하지 않으면 기본적으로 라운드 로빈 방식으로 동작합니다. 필요에 따라 least_conn, random, ip_hash 등의 알고리즘을 지정할 수도 있습니다.


8. 웹 서버와 웹 애플리케이션 서버

웹 서비스에서는 웹 서버웹 애플리케이션 서버(WAS)가 함께 사용되는 경우가 많습니다.

  • 웹 서버: 주로 정적 콘텐츠(HTML, 이미지, 동영상 등)를 응답합니다.
  • 웹 애플리케이션 서버: 데이터베이스 조회나 동적 처리가 필요한 동적 콘텐츠를 응답합니다.

예를 들어, 정적인 HTML 파일은 웹 서버(Nginx, Apache, IIS 등)에서 처리하고, 동적인 요청은 WAS(예: 톰캣, JBOSS, WebSphere 등)를 통해 처리하여 부하 분산 및 확장을 용이하게 할 수 있습니다.

또한, 웹 애플리케이션 서버는 미들웨어(middleware)의 역할을 하여, 운영체제와 응용 프로그램 사이를 중개하는 역할을 수행합니다. 자바 기반의 스프링 부트(Spring Boot)를 실행하면, 내부적으로 톰캣이 함께 실행되는 것을 확인할 수 있습니다.


9. 소켓 프로그래밍

네트워크 통신을 이해할 때 흔히 택배에 비유하는데, 소켓(socket)은 택배 우체통과 같습니다.

  • 소켓의 역할:
    • 두 프로세스 간의 데이터 송수신의 종착점(엔드포인트, endpoint) 역할.
    • 프로세스는 소켓을 통해 데이터를 쓰고(송신), 소켓으로부터 데이터를 읽어(수신) 통신합니다.
  • 유사점:
    • 파일 입출력과 유사하게 소켓은 파일 디스크립터를 통해 식별되고, 읽기/쓰기가 가능합니다.
    • 많은 운영체제에서 소켓을 파일처럼 취급하며, IPC(Inter-Process Communication)의 수단으로도 사용됩니다.
  • 시스템 콜*:
    • 네트워크 송수신을 위해 여러 소켓 관련 시스템 콜이 호출됩니다.
    • 예를 들어, Nginx와 같은 웹 서버는 GET 요청을 처리할 때 소켓 입출력 관련 시스템 콜을 다수 호출합니다.
    • 웹 프레임워크(스프링, 장고, 루비 온 레일스 등) 역시 내부적으로 소켓 통신을 사용합니다.

참고

_이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접 – 한빛미디어_

위로 스크롤