6 응용 계층 - HTTP의 응용
쿠키
- 쿠키 cookie 는 HTTP의 스테이트리스한 특성을 보완하기 위한 대표적 수단으로, 서버에서 생성되어 클라이언트 측에 저장되는 <이름, 값> 쌍 형태의 데이터입니다
- 서버는 쿠키를 생성하여 클라이언트에 전송하고, 클라이언트는 쿠키를 저장해 두었다가 추후 같은 서버에 요청을 보낼 때 요청 메시지에 쿠키를 포함하여 전송합니다.
- 서버가 클라이언트에게 쿠키를 전송할 때는 응답 메시지의 Set-Cookie 헤더가 활용되고, 클라이언트가 서버에게 쿠키를 건넬 때는 Cookie 헤더가 활용됩니다.

- 특정 서버로부터 쿠키를 전달받았다면 다음부터 해당 서버에 요청을 보낼 때 전달받은 쿠키를 자동으로 전송한다는 점입니다.
- 도메인과 경로, 유효기간, 보안 등과 관련한 쿠키 데이터의 대표적인 속성들을 알아보겠습니다.
- 쿠키는 domain과 path 속성을 통해 쿠키를 전송할 도메인과 경로를 제한할 수 있습니다. 예를 들어 다음과 같은 응답 메시지에서는 헤더를 통해 쿠키를 사용할 도메인과 경로를 ‘minchul.net’과 ‘/lectures’로 제한하고 있습니다.
- 또한 Expires로 명시된 시점이 지나거나 Max-Age로 명시된 유효기간이 지나면 해당 쿠키는 삭제되어 전달되지 않습니다. Expires는 [요일, DD-MM-YY HH:MM:SS GMT]의 형식으로 표기되는 쿠키 만료 시점을 의미하고, Max-Age는 초 단위 유효기간을 의미합니다.
- 쿠키의 보안 속성으로 Secure과 HttpOnly라는 속성도 있습니다.
- Secure은 HTTP의 더 안전한 방식인 HTTPS를 통해서만 쿠키를 송수신하도록 하는 속성입니다.
- HttpOnly는 자바스크립트를 통한 쿠키의 접근을 제한하고, 오직 HTTP 송수신을 통해서만(HTTP 헤더를 주고받는 방식으로만) 쿠키에 접근하도록 하는 방식입니다.
웹 스토리지: 로컬 스토리지와 세션 스토리지
- 쿠키 이외에도 클라이언트의 상태를 추측할 수 있는 <키, 값> 쌍 형태의 정보가 있습니다. 바로 웹 스토리지 (web storage )입니다.
- 웹 스토리지는 웹 브라우저 내의 저장 공간으로, 일반적으로 쿠키보다 더 큰 데이터를 저장할 수 있습니다.
- 쿠키는 서버로 자동 전송되지만, 웹 스토리지의 정보는 서버로 자동 전송되지 않습니다.
- 웹 스토리지에는 크게 로컬 스토리지(local storage )와 세션 스토리지(session storage )가 있는데요.
- 로컬 스토리지는 별도로 삭제하지 않는 한 영구적으로 저장이 가능한 정보이고,
- 세션 스토리지는 세션이 유지되는 동안(쉽게 말해, 브라우저가 열려 있는 동안) 유지되는 정보입니다.
캐시
- 캐시는 응답받은 자원의 사본을 임시 저장하여 불필요한 대역폭 낭비와 응답 지연을 방지하는 기술입니다.
- 우선 클라이언트가 날짜를 기반으로 원본 자원의 변경 여부를 묻는 헤더로는 If-Modified-Since 헤더가 대표적입니다.
- If- Modified-Since 헤더의 값으로는 다음과 같은 특정 시점(날짜와 시각) 이 명시되는데, 이 시점 이후로 원본 자원에 변경이 있었다면 그때만 변경된 자원을 메시지 본문으로 응답하도록 서버에게 요청하는 헤더입니다.

➊ 서버가 요청받은 자원이 변경된 경우 서버는 상태 코드 200 (OK )과 함께 새로운 자원을 반환합니다.
➋ 서버가 요청받은 자원이 변경되지 않은 경우 서버는 메시지 본문 없이 상태 코드 304 (Not Modified )를 통해 클라이언트에게 ‘자원이 변경되지 않았음’을 알립니다.
➌ 서버가 요청받은 자원이 삭제된 경우 서버는 상태 코드 404 (Not Found )를 통해 요청한 ‘자원이 존재하지 않음’을 알립니다.
- 클라이언트가 서버에게 원본 자원의 변경 여부를 묻기 위해 날짜가 아닌 엔티티 태그를 기반으로 물어볼 수도 있습니다.
- 흔히 Etag라고도 줄여 부르는 엔티티 태그 Entity Tag 는 ‘자원의 버전’을 식별하기 위한 정보를 말합니다.
- 자원이 변경될 때마다 자원의 버전을 식별하는 Etag 값이 변경되고, 반대로 자원이 변경되지 않았다면 Etag 값도 변경되지 않습니다.
➊ 서버가 요청받은 자원이 변경된 경우 서버는 상태 코드 200 (OK )과 함께 새로운 자원을 반환합니다.
➋ 서버가 요청받은 자원이 변경되지 않은 경우 서버는 메시지 본문 없이 상태 코드 304 (Not Modified )를 통해 클라이언트에게 ‘자원이 변경되지 않았음’을 알립니다. 이 경우 클라이언트는 캐시된 자원을 사용할 수 있습니다.
➌ 서버가 요청받은 자원이 삭제된 경우 서버는 상태 코드 404 (Not Found )를 통해 요청한 ‘자원이 존재하지 않음’을 알립니다.
콘텐츠 협상
- 같은 자원에 대해 할 수 있는 여러 표현 중 클라이언트가 가장 적합한 자원의 표현을 제공하는 기술을 콘텐츠 협상 content negotiation 이라고 합니다.
- Accept - 선호하는 미디어 타입을 나타내는 헤더
- Accept-Language - 선호하는 언어를 나타내는 헤더
- Accept-Encoding - 선호하는 인코딩 방식을 나타내는 헤더
보안:SSL/TSL와 HTTPS
- HTTPS는 HTTP에 SSL 혹은 TLS라는 프로토콜의 동작이 추가된 프로토콜입니다.
- SSL Secure Sockets Layer 과 TLS Transport Layer Security 는 모두 인증과 암호화를 수행하는 프로토콜로, TLS는 SSL을 계승한 프로토콜입니다. 따라서 SSL과 TLS의 작동 과정은 세부적인 차이가 있을 수는 있지만 큰 틀에서 보면 유사합니다.
- TLS 1.3 기반 HTTPS 메시지는 크게 다음과 같은 단계를 거쳐 송수신됩니다.
➊ TCP 쓰리 웨이 핸드셰이크
➋ TLS 핸드셰이크
➌ 메시지 송수신 - HTTPS 메시지 송수신은 일반적인 HTTP 메시지 송수신에 ➋가 더해진 것에 불과합니다. ➋의 과정을 거쳐 (서로에 대한 인증과 더불어)메시지 암호화가 이루어지므로 ➋를 거쳐 ➌에서 주고받는 메시지는 암호화된 메시지입니다.
- 우리가 알아 두어야 하는 TLS 핸드셰이크의 핵심 내용은 크게 2가지입니다.
- 하나는 TLS 핸드셰이크를 통해 암호화 통신을 위한 키를 생성/교환할 수 있다는 점이고, 또 하나는 인증서 송수신과 검증이 이루어질 수 있다는 점입니다.
- 처음으로 클라이언트는 ClientHello 메시지를 보냅니다.
- 이 메시지는 암호화된 통신을 위해 서로 맞춰 봐야 할 정보들을 제시하는 메시지 입니다. 지원되는 TLS 버전, 사용 가능한 암호화 알고리즘과 해시 함수, 키를 만들기 위해 사용할 클라이언트의 난수 등이 포함되어 있습니다. 이
- 때 클라이언트는 ‘사용 가능한 암호화 알고리즘과 해시 함수’를 서버에 알리기 위해 ClientHello 메시지에 다음과 같은 형태의 정보를 포함하여 전송합 니다. 이를 암호 스위트 cipher suite 라고 합니다.

- 서버는 ClientHello 메시지에 대한 응답으로 ServerHello 메시지를 전송합니다.
- ClientHello 메시지가 암호화 이전에 맞춰 봐야 할 정보들을 제시하는 메시지라면, ServerHello 메시지는 제시된 정보들을 선택하는 메시지입니다.
- 따라서 이 메시지에는 선택된 TLS 버전, 암호 스위트 등의 정보, 키를 만들기 위해 사용할 서버의 난수 등이 포함되어 있습니다.
- ClientHello 메시지와 ServerHello 메시지를 주고받으면 암호화된 통신을 위해 사전 협의해야 할 정보들이 결정되고, 결정된 정보를 토대로 서버와 클라이언트가 암호화에 사용할 키를 만들어 암호화에 사용할 수 있습니다
- 인증서 및 인증서 검증과 관련한 메시지로는 Certificate 메시지와 CertificateVerify 메시지가 있습니다.
- Certificate 메시지에는 인증서 서명 값 등 앞서 제시한 그림과 같은 인증서 내용들이 포함되어 있으며, CertificateVerify 메시지는 인증서의 내용이 올바른지 검증하기 위한 메시지입니다.
- 이렇게 서버와 클라이언트는 암호화에 사용할 키를 획득하고, 서로가 틀림없다는 사실까지 인증했습니다.
- 서버와 클라이언트는 마지막으로 TLS 핸드셰이크의 마지막을 의미하는 Finished 메시지를 주고받고, 이후부터는 TLS 핸드셰이크를 통해 얻어낸 키를 기반으로 암호화된 데이터를 주고받게 됩니다.
7 프록시와 안정적인 트래픽
오리진 서버와 중간 서버 : 포워드 프록시와 리버스 프록시

- 수많은 네트워크 장비와 중간 서버들 사이에서 클라이언트가 최종적으로 메시지를 주고받는 대상, 즉 앞선 설명에서 단순히 ‘서버’라고 지칭했던 대상은 조금 더 정확히 표현하면 ‘자원을 생성하고 클라이언트에게 권한이 있는 응답을 보낼 수 있는 HTTP 서버’를 의미하는데요. 이를 오리진 서버 origin server 라고 합니다.
- 즉, 서버와 클라이언트 사이에는 수많은 중간 서버가 있을 수 있습니다.
- 중간 서버에 대해 좀 더 이야기해 볼까요? 대표적인 HTTP 중간 서버의 유형에는 프록시와 게이트웨이가 있습니다.
- 프록시는 포워드 프록시, 게이트웨이는 리버스 프록시라고도 부릅니다.
- 프록시 proxy 란 클라이언트가 선택한 메시지 전달의 대리자로, 주로 캐시 저장, 클라이언트 암호화 및 접근 제한 등의 기능을 제공합니다.
- 클라이언트가 어떤 프록시를 언제, 어떻게 사용할지 선택하기 때문에 프록시는 일반적으로 오리진 서버보다 클라이언트와 더 가까이 위치해 있습니다

- 게이트웨이 gateway 는 오리진 서버(들)을 향하는 요청 메시지를 먼저 받아서 오리진 서버(들)에게 전달하는 문지기, 경비 역할을 수행합니다. 게이트웨이는 요청 메시지를 보내는 네트워크 외부의 클라이언트 시각에서 보면 마치 오리진 서버처럼 보입니다.
- 게이트웨이가 클라이언트의 요청을 받고, 클라이언트에게 응답을 보내니까요.
- 그래서 게이트웨이는 일반적으로 클라이언트보다 오리진 서버(들)에 더 가까이 위치해 있습니다.
- 게이트웨이에는 캐시를 저장할 수도 있고, 부하를 분산하는 로드 밸런서로도 동작할 수 있습니다.

aws에서란?
고가용성 : 로드 밸런싱과 스케일링
가용성
- 업타임 uptime 은 정상 적인 사용 시간을 의미하고, 다운타임 downtime 은 모종의 이유로 인해 정상적인 사용이 불가능한 시간을 의미합니다. 고가용성은 바로 이 수식의 값이 높은 성질을 말합니다.

- 고가용성을 유지하는 것의 핵심은 ‘애초에 문제가 발생하지 않도록 하는 것’이라기보다 ‘문제가 발생하더라도 계속 기능할 수 있도록 설계하는 것’에 가깝습니다.
- 문제가 발생하더라도 기능할 수 있는 능력을 결함 감내 fault tolerance 라고 합니다.
- 즉, 다운타임을 낮추고 가용성을 높이기 위해서는 서비스나 인프라가 결함을 감내할 수 있도록 설계하는 것이 중요합니다.
- 이를 위한 대표적인 기술이 바로 다중화입니다.
- 서버를 다중화하면 특정 서버에 문제가 발생하더라도 다른 예비 서버가 이를 대신해 동작할 수 있기 때문입니다.
로드 밸런싱
- 하나 이상의 서버가 트래픽을 어떻게 고르게 분산하여 수신할지를 고려해야 합니다.
- 트래픽의 고른 분배를 위해 사용되는 기술이 바로 로드 밸런싱 load balancing 입니다. 로드 밸런싱은 로드 밸런서 load balancer 에 의해 수행되는데, 로드 밸런서는 다중화된 서버와 클라이언트 사이에 위치하며 클라이언트의 요청(들)을 각 서버에 균등하게 분배하는 역할을 합니다.
- 로드 밸런서는 ‘L4 스위치’, ‘L7 스위치’라 불리는 네트워크 장비로도 수행할 수 있지만, 로드 밸런싱 기능을 제공하는 소프트웨어를 설치하면 일반 호스트도 로드 밸런서로 사용할 수 있습니다.
- 대표적인 로드 밸런싱 소프트웨어로는 HAProxy, Envoy 등이 있으며, 대표적인 웹 서버 소프트웨어인 Nginx에도 로드 밸런싱 기능이 내장되어 있습니다.
- 로드 밸런싱에 있어 중요하게 고려해야 할 점이 하나 있습니다. 단순히 ‘다중화된 모든 서버에 균일한 부하를 부여하는’ 전략은 모든 서버의 성능이 동일하다는 전제가 있을 때만 유효하다는 것입니다
스케일링 : 스케일 업 스케일 아웃 오토스케일링

- 하나는 기존 부품을 더 나은 사양으로 교체하는 방법이고, 또 하나는 기존 부품을 여러 개로 두는 방법입니다.
- 전자를 스케일 업 scale-up 이라고 하고, 후자를 스케일 아웃 scale-out 이라고 합니다.
- 스케일 업을 수직적 확장 vertical scaling , 스케일 아웃을 수평적 확장 horizontal scaling 이라고도 부릅니다.
- 스케일 업의 가장 큰 장점은 설치와 구성의 단순 함입니다.
- 대신 스케일 업은 스케일 아웃에 비해 유연하지는 않습니다.
- 하나의 스케일 업 장비의 성능에 한계가 있을 경우, 스케일 아웃을 하지 않는 이상 계속해서 더 비싸고 성능 좋은 장비를 구비하는 수밖에 없기 때문입니다.
- 반면, 스케일 아웃의 중요한 장점은 유연한 확장 및 축소가 가능하다는 점입니다.
- 스케일 업에 비해 설치와 구성이 단순하지는 않을 수 있지만, 설치 및 구성 방법만 알면 장비의 확장과 축소가 매우 쉬워질 것입 니다.
- 무엇보다 스케일 아웃으로 확장할 경우, 스케일 업으로 확장했을 때보다 결함을 감내하기가 더 용이 합니다.
- 스케일 업으로 확장했더라도 해당 장비가 하나밖에 존재하지 않는다면 해당 장비에 부하가 집중되거나 병목이 생길 우려가 있습니다.
- 해당 장비가 하드웨어적 문제로 고장이라도 난다면 큰일이 생길 수 있죠.
- 반면, 스케일 아웃으로 확장하면 부하가 분산되도록 설계하기가 용이하기 때문에 병목이 생길 우려가 적어지므로 더욱 안정적인 운용이 가능합니다.
nginx로 알아보는 로드밸런싱
➊ http : 웹 서버 관련 설정
➋ access log : 웹 서버가 수신한 개별 요청 관련 로그는 ‘/var/log/nginx/access.log’에 남김
➌ error log : 웹 서버와 관련한 오류 발생 시 오류 관련 로그는 ‘/var/log/nginx/error.log’에 남김
➍ conf.d : ‘/etc/nginx/conf.d/’ 경로에 놓인 <파일명>.conf의 내용은 모두 웹 서버 관련 설정으로 간주함

이 설정대로 작동할 경우 ‘10.10.10.1:80’의 ‘/’ 경로로 전달받는 트래픽은 ‘backend’ 서버 그룹(10.10.10.2, 10.10.10.3, 10.10.10.4 )으로 전달되며, ‘10.10.10.3’은 ‘10.10.10.2’에 비해 두배 많은 트래픽을 전달받고, 두 서버에 문제가 발생할 경우 ‘10.10.10.4’가 동작합니다.
업스트림과 다운스트림과 인바운드/아웃바운드

- 오리진 서버를 최상위에 위치한 서버라고 간주했을 때, 업스트림(upstream )이란 상위 서버로 데이터를 보내는 방향을 의미합니다.
- 업스트림 트래픽은 클라이언 트에서 오리진 서버로 향하는 트래픽인 셈입니다.
- 반대로, 다운스트림(downstream )은 상위 서버에서 클라 이언트로 데이터를 보내는 방향을 의미합니다.
- 오리진 서버가 응답 메시지를 생성해 클라이언트로 보낼 경우, 메시지가 향하는 방향이 다운스트림인 셈입니다.
- 인바운드(inbound ) 트래픽은 단순히 네트워크 외부에서 내부로 들어오는 트래픽을 의미합니다.
- 주로 외부 사용자가 내부 네트워크의 서버나 서비스에 접근하려는 요청을 가리키는데요.
- 예를 들어 외부 인터넷 사용자들이 회사 웹사이트에 접속하는 트래픽은 회사 입장에서 인바운드 트래픽에 해당합니다.
- 반대로, 아웃바운드 (outbound) 트래픽은 내부 네트워크에서 외부로 나가는 트래픽을 의미합니다.
- 내부 시스템이나 사용자들이 외부 서버나 서비스에 요청을 보내는 경우를 가리킵니다.
- 예를 들어 회사 직원이 외부 웹사이트를 방문할 때생성되는 트래픽은 회사 입장에서 아웃바운드 트래픽에 해당합니다.
웹서버와 웹어플리케이션서버

- 서버는 기본적으로 정적인 정보를 응답합니다.
- 정적인 정보란 송수신 과정에서 수정과 처리가 필요하지 않은 정보를 말합니다.
- 쉽게 말해서 언제, 어디서, 누가 봐도 변하지 않을 정보를 의미한 다고 보면 됩니다.
- 가령 HTML 파일, 이미지 파일, 동영상 파일 등을 생각해 보면 이러한 파일은 언제, 어디서, 누가 보아도 변하지 않습니다.
- 동적인 정보의 생성 응답을 위해 활용되는 것이 웹 애플리케이션 서버(WAS, Web Application Server )입니다.
- 웹 애플리케이션 서버에는 대표적으로 아파치 톰캣, JBOSS, WebSphere 등이 있습니다.
- 웹 서비스에는 웹 서버와 웹 애플리케이션 서버가 함께 사용되는 경우가 많습니다.
- 다음 그림처럼웹 서비스가 수신하는 요청 중 정적인 정보는 웹 서버가 응답하고, 동적인 정보는 웹 애플리케이션 서버가 응답하도록 설계하면 과도한 부하를 분산할 수도 있고, 여러 웹 애플리케이션을 연동하여 확장하는 데에도 유리합니다.
- 다음 그림처럼웹 서비스가 수신하는 요청 중 정적인 정보는 웹 서버가 응답하고, 동적인 정보는 웹 애플리케이션 서버가 응답하도록 설계하면 과도한 부하를 분산할 수도 있고, 여러 웹 애플리케이션을 연동하여 확장하는 데에도 유리합니다.
'개발' 카테고리의 다른 글
| [noteplan] 커스텀 theme 설정 (0) | 2025.12.05 |
|---|---|
| [netlify] blob 설정 - api key, site id 확인 방법 (0) | 2025.10.14 |
| [supabase][postgresql] Row Level Security 이란 (0) | 2025.09.04 |
| [supabase] Supabase Publishable Key vs Secret Key 정리 (1) | 2025.08.29 |
| [netlify] Cafe24에서 구입한 도메인을 Netlify에 연결하는 가이드 (0) | 2025.08.26 |