URL
Uniform Resource Locator
리소스가 무엇이고, 어디에 있고, 어떻게 접근할 수 있는지 알려주는 위치 정보
리소스
http
URL 스킴
웹 클라이언트가 리소스에 어떻게 접근하는지 알려준다.
www.joes-hardware.com
서버의 위치
리소스가 어디에 호스팅되어 있는지를 알려준다.
/seasonal/index-fail.html
리소스의 경로
서버에 존재하는 로컬 리소스들 중에서, 요청받은 리소스가 무엇인지 알려준다.
이를 통해 일관된 방식으로 많은 리소스에 접근할 수 있다.
URL 은 클라이언트에게 필요한 모든 것을 제공한다.
클라이언트가 원하는 리소스가 어디에 위치하고, 어떻게 가져오는지 정의한다.
<스킴>://<사용자 이름>:<비밀번호>@<호스트>:<포트>/<경로>;<파라미터>?<질의>#<프래그먼트>
가장 중요한 3요소는 스킴, 호스트, 경로이다.
스킴
호스트
포트
http://www.joes-hardware.com:80/index.html
http://161.58.228.45:80/index.html
모두 동일한 리소스를 가리킨다. (위 - 호스트명, 아래 - IP 주소)
리소스가 서버의 어디에 있는지 알려준다.
HTTP URL 에서 /
문자를 기준으로 경로 조각으로 나뉜다.
쿼리 파라미터
?
문자 뒤에 위치한다.
포맷에 제약사항은 없다.
&
로 나뉜 이름=값
쌍 형태로 주고 받는다.리소스 내의 조각을 가리키는 정보를 제공한다.
#
문자 뒤에 위치한다.
클라이언트는 서버에 프래그먼트를 전달하지 않는다.
절대 URL
상대 URL
리소스 접근에 필요한 부분적인 정보를 갖는다.
base URL 을 사용해 필요한 모든 정보를 얻는다.
base URL (기저 URL)
- base URL 을 바탕으로, 상대 URL에서 기술하지 않은 정보를 알아낸다.
- 해당 예에선, 스킴과 호스트를 알아냈다.
문서 집합의 위치가 변경되더라도, 새로운 base URL에 의해 알맞는 경로 정보를 얻을 수 있다.
URL을 입력한 다음이나, 입력 도중에 자동으로 URL을 확장하는, 브라우저가 제공하는 기능
크게 2가지로 나뉜다.
호스트명 확장
naver
입력 시, www
, .com
을 자동으로 호스트명에 붙인다.히스토리 확장
어떤 인터넷 프로토콜을 사용하던, 정보가 유실될 위험없이 URL을 전송해야 한다.
따라서 출력이 되지 않거나, 보이지 않는 문자들은 URL에 사용할 수 없다.
또한, 알파벳 외의 문자도 URL에 포함할 수 있도록 이스케이프 기능을 추가하였다.
이스케이프 : 특수기능을 갖는 특수문자를 일반문자처럼 취급하게 하는 것
안전하지 않은 문자 -> 안전한 문자로 인코딩
ex) 안전하지 않은 문자 ~
, 안전한 문자 %7E
(%16진수두자리)
브라우저와 같이 사용자로부터 최초로 URL을 입력받는 애플리케이션이 어떤 문자를 인코딩할지 결정하는 것이 바람직하다.
http
http://<호스트>:<포트>/<경로>?<질의>#<프래그먼트>
일반 URL 포맷을 지키는 하이퍼텍스트 전송 프로토콜
기본 포트값은 80
https
https://<호스트>:<포트>/<경로>?<질의>#<프래그먼트>
http 스킴과 거의 유사하다.
HTTP 커넥션의 양 끝단에서 암호화를 위한 보안 소켓 계층 (SSL) 을 사용한다.
기본 포트값은 443
URL은 실제 이름이 아닌 주소다.
리소스가 옮겨지면 해당 URL을 사용할 수 없다.
URN
그러나 표준을 바꾸는 것은 엄청난 작업을 요하므로, URL 방식이 당장 대체되진 않을 것이다.
HTTP 프로토콜이 배달원이라면, HTTP 메시지는 소포이다.
HTTP 메시지는 HTTP 애플리케이션 간에 주고받는 데이터 블록들
서버중심으로 생각한다.
- 메시지가 서버로 향하면 인바운드
- 메시지가 서버에서 나가면 아웃바운드
모든 메시지는 다운스트림으로 흐른다.
메시지는 시작줄 (start-line), 헤더블록, 본문으로 이루어진다.
시작줄과 헤더는 줄 단위로 분리된 문자열이다.
엔티티 본문은 선택적인 데이터 덩어리이다.
요청 메시지 형식
<메서드> <요청 URL> <버전>
<헤더블록>
<엔티티 본문>
메서드
- 클라이언트 측에서 서버가 리소스에 대해 수행해주길 바라는 동작
요청 URL
- 요청 대상이 되는 리소스를 지칭하는 URL
- 생략된 호스트/포트 정보는 서버 자신을 가리키는 것으로 간주
버전
- 사용중인 HTTP의 버전
- 해당 애플리케이션이 지원하는 가장 높은 HTTP 버전을 가리킨다.
<버전> <상태코드> <사유 구절>
<헤더블록>
<엔티티 본문>
상태코드
- 서버가 요청을 처리하는 중에 발생한 일을 설명하는 세자리 숫자
사유 구절
- 숫자로 된 상태 코드를 사람이 이해할 수 있게 설명해주는 짧은 문구
- 사람에게 읽히기 위한 목적으로만 존재
- 동작에 영향 X
Request-line (요청줄)
<메서드> <요청 URL> <버전>
부분Status-line (응답줄)
<버전> <상태코드> <사유구절>
부분안전한 메서드
GET, HEAD 메서드는 안전하다.
해당 요청의 결과는 서버에 어떤 작용도 하지 않는다.
GET
클라이언트에게 트랜잭션을 이해할 수 있는 쉬운 방법을 제공
1xx
정보성 상태 코드
100 Continue
2xx
성공 상태 코드
클라이언트의 요청을 서버가 성공적으로 처리했을 때 상태 코드
200 OK
201 Created
202 Accepted
203 Non-Authoritative Information
204 No Content
205 Reset Content
206 Partial Content
3xx
리다이렉션 상태 코드
클라이언트가 요청한 리소스에 대해 다른 위치를 안내하거나,
리소스 내용 대신 다른 대안 응답을 제공한다.
300 Multiple Choices
301 Moved Permanatly
302 Found
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect
새로운 위치(
Location
헤더 값) 로 리다이렉트 된 요청
If-Modified-Since
헤더는 로컬복사본의 수정 시각 정보를 갖는다.- 만약 요청한 리소스의 수정 시각이, 로컬 복사본의 수정 시각과 동일하면
- 즉, 변한것이 없다면
- 리소스를 다시 응답하지 않고
- 로컬 복사본을 사용하도록 리다이렉트 요청
4xx
클라이언트 에러 상태 코드
클라이언트가 서버가 다룰 수 없는 요청을 보냈을 경우의 상태 코드
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
5xx
서버 에러 상태 코드
클라이언트가 올바른 요청을 보냈지만, 서버 자체에서 에러가 발생했을 경우의 상태 코드
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
Start-line 다음에는 HTTP 헤더가 온다.
요청, 응답 메시지에 추가 정보를 더한다.
이름과 값이 하나의 쌍을 이룬다.
Content-length: 19
Content-length
헤더
- 하나의 헤더는
이름
:
(공백)
필드 값
CRLF
으로 이뤄진다.- 공백은 없어도 된다.
헤더 분류
일반 헤더
요청 헤더
응답 헤더
Entity 헤더
클라이언트와 서버 모두 사용한다.
메시지에 대한 기본적인 정보를 제공한다.
일반 정보 헤더
Date
: 메시지가 언제 만들어졌는지에 대한 날짜와 시간 제공
MIME-Version
: 발송자가 사용한 MIME 버전을 알려준다.
Transfer-Encoding
: 메시지에 어떤 인코딩이 적용되었는지 알려준다.
일반 캐시 헤더
Cache-Control
: 캐시 지시자를 전달한다.요청 메시지를 위한 헤더
요청을 보낸 클라이언트의 정보를 제공
서버는 클라이언트 정보를 바탕으로 더 나은 응답을 제공할 수 있다.
요청 정보 헤더
Host
: 요청 대상이 되는 서버의 호스트명과 포트를 알려준다.
User-Agent
: 요청을 보낸 애플리케이션의 이름을 알려준다.
Accept
관련 헤더
클라이언트의 선호도와 능력을 알려주는 헤더
Accept
: 클라이언트가 받을 수 있는 미디어 종류를 말해준다.
Accept-Charset
: 클라이언트가 받을 수 있는 문자집합을 말해준다.
Accept-Encoding
: 클라이언트가 받을 수 있는 인코딩을 말해준다.
Accept-Language
: 클라이언트가 받을 수 있는 언어를 말해준다.
조건부 요청 헤더
서버에 요청한 리소스가 클라이언트가 갖고 있는 로컬복사본과 다를 때만 전송해달라고 할 수 있다.
이처럼 서버에게 요청에 응답하기 전에 조건이 참인지 확인하게 하는 헤더
If-Modified-Since
: 주어진 날짜 이후에 리소스가 변경되지 않았다면 요청 제한
If-None-Match
: 문서의 엔티티 태그가 주어진 엔티티 태그와 일치하지 않는 경우에만 문서를 가져온다.
요청 보안 헤더
클라이언트가 어느 정도의 리소스에 접근하기 전에 자신을 인증하게 하는 헤더
Authorization
: 클라이언트가 서버에게 제공하는 인증 그 자체에 대한 정보
Cookie
: 클라이언트가 서버에게 전달하는 토큰
응답 메시지를 위한 헤더
응답을 보낸 서버의 정보를 제공
응답에 대한 특별한 설명 제공
클라이언트는 해당 정보를 바탕으로 응답을 잘 다루고 더 나은 요청을 할 수 있다.
응답 정보 헤더
Age
: 응답이 얼마나 오래되었는지 알려준다.
Server
: 서버 애플리케이션의 이름과 버전을 알려준다.
Retry-After
: 현재 리소스가 사용 불가능한 상태일 때, 언제 가능해지는지 날짜 혹은 시각
HTTP 메시지의 엔티티에 대해 설명하는 헤더
요청, 응답 모두 엔티티를 포함할 수 있다.
엔티티 정보 헤더
Location
: 클라이언트에게 엔티티가 실제로 어디에 위치하고 있는지 알려준다.콘텐츠 헤더
엔티티 콘텐츠에 대한 구체적인 정보를 제공한다.
Content-Encoding
: 본문에 적용된 인코딩 정보 제공
Content-Language
: 본문을 이해하는데 가장 적절한 자연어
Content-Length
: 본문의 길이나 크기
Content-Type
: 본문이 어떤 종류의 객체인지 정보 제공
엔티티 캐싱 헤더
캐시된 리소스가 유효한지 추정하기 위한 헤더
ETag
: 엔티티에 대한 엔티티 태그
Expires
: 엔티티 캐시의 만료 시각
Last-Modified
: 가장 최근 엔티티가 변경된 시각
HTTP 메시지의 마지막 부분으로 선택적이다.
이미지, 비디오, HTML 문서 등의 디지털 데이터이다.
모든 HTTP 통신은 TCP/IP 를 통해 이루어진다.
클라이언트와 서버는 TCP/IP 커넥션을 맺을 수 있다.
브라우저가 TCP 커넥션을 통해 서버에 요청을 보내는 과정
- HTTP, HTTPS 의 프로토콜 스택
- HTTPS 는 HTTP에 보안 기능을 더했다.
HTTP 가 메시지 데이터 전송을 하려면
현재 연결된 TCP 커넥션을 통해 데이터를 순서대로 전송
전송하려는 데이터들을 세그먼트 단위로 쪼갠다.
세그먼트를 IP 패킷에 담아 인터넷을 통해 데이터 전달
데이터 스트림 덩어리 = HTTP 가 전송하려는 메시지 데이터
TCP 는 포트번호를 통해 여러개의 커넥션을 가질 수 있다.
IP 주소는 해당 컴퓨터에 연결하기 위해 사용
포트번호는 해당 애플리케이션에 연결하기 위해 사용
발신지 IP 주소
, 발신지 포트
, 수신지 IP 주소
, 수신지 포트
로 유일한 커넥션을 생성한다.
HTTP 트랜잭션의 처리과정
처리 시간
은 다른 과정들에 비해 상당히 짧다.
대부분의 HTTP 지연은 TCP 네트워크 지연 때문에 발생한다.
도메인의 IP 주소가 캐싱되지 않았다면 DNS 이름 분석 시 시간 소요
커넥션을 연결하는데 시간 소요
맺어진 커넥션을 통해 HTTP 메시지를 주고 받는데 시간 소요
앞서 살펴봤듯이 TCP 성능은 HTTP 에 영향을 준다.
TCP 커넥션 핸드셰이크 지연
확인응답 지연 알고리즘
TCP 느린 시작
네이글 알고리즘
- SYN : 커넥션 생성 요청
- ACK : 커넥션 생성 요청이 받아들여짐을 의미하는 신호
(c)
와 같이 클라이언트는 ACK 와 요청 메시지를 같이 보낼 수 있다.
TCP 커넥션을 맺기 위해서는 연속적인 IP 패킷 교환이 필요하다.
크기가 작은 메시지들은 IP 패킷 하나에 담을 수 있다.
인터넷은 패킷 전송을 완벽히 보장하지 않는다.
TCP 는 완벽한 데이터 전송을 보장하는 프로토콜이다.
각 TCP 세그먼트는 순번과 무결성 체크섬을 가진다.
TCP 세그먼트 수신자는 세그먼트를 온전히 받으면 확인응답 패킷을 송신자에게 반환한다.
확인응답은 크기가 작아 같은 방향으로 송출되는 데이터에 편승시킨다.
확인응답이 데이터 패킷에 편승되는 경우를 늘리기 위해 확인응답 지연 알고리즘
을 사용한다.
특정 시간동안 확인응답을 버퍼에 저장
편승시키기 위한 송출 데이터를 탐색
특정 시간내에 송출 데이터를 찾지 못하면 그냥 단독으로 보낸다.
HTTP 동작 방식은 단순해서 확인응답의 편승 기회가 많지 않다.
확인응답 지연 알고리즘
으로 인한 지연이 자주 발생한다.TCP 커넥션은 데이터가 성공적으로 전송될 때마다 속도 제한을 높인다.
시간이 지날수록 성능이 올라간다. (튜닝)
생성 초기에는 속도 제한을 크게 줘 부하와 혼잡을 방지한다.
TCP 세그먼트 내의 데이터 스트림은 어떤 크기든지 전송 가능하다.
네이글 알고리즘
은 TCP 세그먼트가 최대크기가 되지 않으면 전송하지 않는다.
TCP 세그먼트가 최대크기가 될 때까지 데이터를 버퍼에 저장한다.
다른 모든 패킷이 확인응답을 받았을 경우에만 최대크기보다 작은 패킷을 전송한다.
확인응답 지연 알고리즘
과 같이 사용시, 성능이 많이 감소한다.
네이글 알고리즘
은 확인응답 도착전까지 데이터 전송을 멈춘다.
확인응답 지연 알고리즘
은 확인 응답 전송을 지연시킨다.
Connection
헤더의 값으로
- HTTP 헤더 필드명을 가지면, 해당 헤더를 다음 커넥션에 전달하지 않는다.
Close
값을 가지면, 이 트랜잭션이 끝나면 커넥션이 끊길 것임을 의미한다.
순차적인 트랜잭션 처리
병렬 커넥션
지속 커넥션
파이프라인 커넥션
브라우저가 3개의 이미지가 있는 웹페이지를 보여주기 위한 4개의 트랜잭션
웹 페이지의 컴포넌트들은 각각의 HTTP 커넥션에서 처리한다.
클라이언트가 여러개의 커넥션을 맺어 여러개의 HTTP 트랜잭션을 병렬 처리한다.
한 개의 커넥션이 인터넷의 모든 대역폭을 사용하는 경우가 아니면, 나머지 객체를 내려받는 데에 남은 대역폭을 사용함으로 처리시간을 줄일 수 있다.
일반적으로 빠르나, 여러개의 커넥션을 생성하면서 생기는 부하때문에 순차적인 방식보다 느릴 수도 있다.
복잡한 웹 페이지는 수백개의 객체를 포함한다.
각 트랜잭션마다 새로운 커넥션을 맺고 끊기 때문에 시간과 대역폭이 소요된다.
클라이언트는 일반적으로 같은 사이트에 여러개의 커넥션을 맺는다.
HTTP/1.1 부터는 처리가 완료된 후에도 TCP 커넥션을 유지하여 앞으로 있을 HTTP 요청에 재사용할 수 있다.
비지속 커넥션 : 처리가 끝나면 커넥션을 끊는다.
지속 커넥션 : 클라이언트나 서버가 커넥션을 끊기 전엔, 커넥션을 유지한다.
지속 커넥션은 적은 수의 병렬 커넥션과 함께 사용된다.
지속 커넥션이 끊어지지 않고, 계속 쌓이는 경우를 주의해야 한다.
Connection : close
헤더를 통해 커넥션을 끊을 수 있다.
그러나 Connection : close
헤더가 없더라도, 애플리케이션은 언제든지 커넥션을 끊을 수 있다.
지속 커넥션의 모든 메시지는 자신의 길이 정보를 정확히 가지고 있어야 한다.
지속 커넥션을 통해 요청을 파이프라이닝 한다.
지속 커넥션 : TCP 커넥션 생성 시 지연을 제거한다.
파이프라이닝 커넥션 : 전송 대기 시간을 단축한다.
POST 와 같이 비멱등 요청은 파이프라인으로 보내면 안된다.
TCP 커넥션은 양방향이다.
커넥션의 입력 채널을 끊으면 위험하다.
클라이언트가 이미 끊긴 입력 채널에 데이터를 전송하면, 서버의 운영체제는 connection reset by peer
리셋 메시지를 보낸다.
클라이언트는 리셋 메시지를 받아, 버퍼에 저장된 아직 읽지 못한 응답 데이터들을 전부 제거한다.
웹 서버는 HTTP 요청을 처리하고 응답을 제공한다.
HTTP 프로토콜 구현
웹 리소스를 관리
TCP 커넥션 관리
클라이언트가 웹 서버에 TCP 커넥션을 요청하면
웹 서버는 커넥션을 맺거나
커넥션을 거절할 수 있다.
클라이언트의 IP 주소를 클라이언트 호스트명으로 변환한다.
네트워크 커넥션에서 데이터를 읽어들인다.
요청 메시지를 쉽게 다룰 수 있도록 자료구조로 만들어 저장한다.
각 조각에 대한 포인터와 룩업 테이블 형태로 저장
커넥션의 입/출력을 처리한다.
커넥션 입/출력처리 아키텍처 종류
단일 스레드 웹 서버
한 번에 하나씩 요청 처리
요청 처리 도중 모든 다른 커넥션은 무시된다.
멀티 프로세스 & 멀티 스레드 웹 서버
여러 요청을 동시에 처리
너무 많은 스레드는 메모리와 시스템 리소스를 소비하므로, 보통 최대 개수의 제한을 둔다.
웹 서버는 요청으로부터 메서드, 리소스, 헤더, 본문을 파싱하여 처리한다.
이 책에서 계속해서 다룰 예정인 주제
웹 서버는 리소스 서버이다.
웹 서버는 HTML 페이지나 이미지같은 미리 만들어진 정적 콘텐츠를 제공한다.
WAS 가 만든 동적 콘텐츠도 제공한다.
콘텐츠를 제공하는 루트 폴더인 docroot
와 요청 URI를 합쳐 리소스를 제공한다.
docroot
경로 :/usr/local/httpd/files
요청 URI
:/specials/saw-blade.gif
하나의 웹 서버위에서 두 개의 사이트가 완전히 분리된 콘텐츠를 제공
요청 URI 가 파일이 아닌 디렉토리를 가리키는 경우에도 적절한 리소스를 반환한다.
/
요청 ➔ index.html
반환요청 URI 에 맞게 동적 리소스에 매핑한다.
클라이언트 IP 주소에 근거하여 각각의 리소스에 대한 접근을 제어한다.
리소스에 적절한 동작을 수행한 뒤 응답 메시지를 만든다.
만약 본문이 있다면
본문의 MIME 타입
을 서술하는 Content-Type
헤더
본문의 길이를 서술하는 Content-Length
헤더가 추가적으로 필요하다.
응답 본문 (리소스) 의 MIME 타입
을 결정한다.
일반적으로 확장자를 기반으로 타입을 연계한다.
리소스와 성공 메시지 대신 리다이렉션 응답을 만들기도 한다.
리소스가 옮겨진 경우
URL에 추가적인 문맥 정보를 포함하기 위해
요청을 분산시키기 위해
요청 URI 끝에 /
을 빠뜨린 경우 슬래시를 추가하기 위해
프락시 서버는 클라이언트와 서버 사이에 위치한 중개자다.
프락시 서버는 클라이언트와 서버 양쪽의 동작을 모두 수행할 수 있어야 한다.
공용 프락시
공용으로 사용되는 공유 프락시
대부분의 프락시
중앙 집중형 프락시를 관리하는 것이 쉽고 비용효율이 높다.
개인 프락시
하나의 클라이언트가 독점적으로 사용하는 프락시
브라우저의 기능 확장등을 위해 사용한다.
프락시는 같은 프로토콜을 사용하는 애플리케이션을 연결한다.
게이트웨이는 서로 다른 프로토콜을 사용하는 애플리케이션들을 연결한다.
프락시 서버는 중간에서 모든 HTTP 트래픽을 들여다보고 건드릴 수 있기 때문에, 부가적인 가치를 주는 유용한 웹 서비스를 구현하기 위해 사용된다.
어린이 사용자가 성인 콘텐츠에 접근하지 못하도록 필터링 프락시를 사용
- 각기 다른 조직에서 관리되는 많은 웹서버들에 대한 접근 제어를, 중앙 프락시 서버에서 한번에 설정한다.
- 클라이언트 1 : 제약없이 서버 A 뉴스페이지에 접근 허가
- 클라이언트 2 : 제약없이 인터넷 접근 허가
- 클라이언트 3 : 서버 B 에 접근 전 비밀번호 요구
중간에 바이러스를 제거하는 등, 보안을 강화하기 위해 사용
- 인기 있는 문서의 로컬 사본을 갖고 있다가, 해당 문서에 대한 요청이 오면 빠르게 제공
- 이를 통해 비싼 인터넷 커뮤니케이션을 줄인다.
- 서버 앞에 놓여 있는 프락시
- 로드 밸런싱 및 서버 보안을 위해 사용
- 데이터의 표현 방식을 프락시 서버가 중간에서 자연스럽게 변환시킨다.
- 한국어를 스페인어로 바꾸거나
- 작은 화면에 맞는 콘텐츠로 변환
- 신원을 식별할 수 있는 특성들을 제거해 개인정보를 보호한다.
User-agent
,From
,Referer
,Cookie
헤더 제거
출구 프락시
로컬 네트워크와 인터넷 사이의 트래픽을 제어한다.
방화벽, 필터링 역할등을 수행
접근 프락시
클라이언트의 모든 요청을 종합적으로 처리하기 위해 ISP 접근 지점에 위치
ISP : 인터넷 서비스 공급자
캐시 프락시 역할등을 수행
대리 프락시 (리버스 프락시)
웹 서버 바로 앞에서, 웹 서버로 향하는 모든 요청을 처리한다.
웹 서버의 호스트명과 아이피 주소를 사용한다.
네트워크 교환 프락시
브라우저와 같은 웹 클라이언트가 HTTP 요청을 의도적으로 프락시로 보낸다.
클라이언트 모르게 트래픽을 가로채서 프락시로 보낸다.
웹 서버의 이름과 IP주소를 직접 사용하는 대리 프락시(리버스 프락시) 로 보낸다.
웹 서버가 프락시로 리디렉션 하는 명령을 클라이언트에게 응답으로 보낸다.
클라이언트가 서버로 요청을 보내면, 요청 URI는 스킴, 호스트, 포트번호를 생략할 수 있다.
옛날에는 클라이언트 - 서버의 단일 커넥션만 고려했다.
서버는 자신의 호스트, 포트번호를 알고 있으므로 부분 URI로 충분하다.
GET /index.html HTTP/1.0
...
부분 URI로 충분
클라이언트가 프락시로 (명시적인) 요청을 보낼땐 완전한 URI를 갖는다.
프락시는 클라이언트의 요청을 받아 목적지 서버와 커넥션을 맺어야 한다.
따라서 프락시는 목적지 서버의 정보를 갖는 완전한 URI가 필요하다.
GET http://www.marys-antiques.com/index.html HTTP/1.0
...
완전한 URI 필요
클라이언트 단에서, 명시적인 프락시로의 요청 메시지는 완전한 URI를 보낸다.
대리 프락시나 인터셉트 프락시는 클라이언트에게 보이지 않는다.
명시적인 프락시 요청 X
클라이언트는 서버와 통신한다 생각하고 부분 URI를 보낸다.
따라서 부분 URI에 대해 규칙을 적용해 목적지 서버를 알아낼 수 있어야 한다.
명시적인 프락시가 없는 경우 부분 호스트명 자동 확장
- 브라우저가 부분 호스트명을 자동 확장하지 않는다.
http://oreilly/
로 요청을 보낸다.
- DNS 동작 과정은 프락시가 없는 경우와 같다.
(5b)
단계에서, 인터셉트 프록시가 클라이언트 요청이 다운된 서버를 가리킴을 알게 되면, 장애를 해결하기 위해 다른 IP 주소로 요청을 시도한다.
프락시가 흔해지며, 프락시를 넘나드는 메시지의 흐름을 추적하고 문제점을 찾아내는 것이 중요해졌다.
Via
헤더
메시지가 지나는 중개자들의 정보를 나열한다.
각 노드는 (프로토콜 이름)
프로토콜 버전
노드 이름
(코멘트)
로 이루어진다.
정확한 호스트명을 알리고 싶지 않으면 가명으로 교체할 수 있다.
노드들은 쉼표로 구분한다.
응답의
Via
헤더는 요청의Via
헤더와 반대다.
TRACE
메서드
프락시 서버는 전달되는 메시지를 바꿀 수 있다.
프락시 네트워크를 쉽게 진단하기 위해 홉에서 홉으로 전달될 때마다 메시지 내용이 어떻게 변하는지 관찰하기 위한 메서드
TRACE
요청이 목적지 서버에 도착하면, 전체 요청 메시지를 HTTP 응답 메시지의 본문에 포함시켜 클라이언트에게 돌려보낸다.
Max-Forwards
헤더를 통해 이동하는 홉수를 제한할 수 있다.
Max-Forwards
값이 0이 되면 더 이상 전달하지 않고 클라이언트에게 돌려준다.
- 홉 이동시 1씩 감소
- 목적지 서버에 도착하지 않더라도
Max-Forwards
값이 0이 되면 되돌아간다.
a. 제한된 콘텐츠에 대한 요청이 프락시 서버에 도착
b. 프락시 서버는 접근 자격을 요구하는 407 상태코드와 자격을 어떻게 제출할 수 있는지 설명해주는Proxy-Authenticate
헤더를 응답으로 반환
c. 클라이언트는 요구되는 자격을 수집한 뒤 해당 자격을Proxy-Authenticate
헤더에 담아 요청을 다시 보낸다.
d. 자격이 유효하다면 요청을 통과시키고, 자격 미달이면 407 응답을 다시 보낸다.
불필요한 데이터 전송을 줄인다.
최초의 서버 응답을 캐시에 보관하고 뒤이은 요청들에 대한 응답은 캐시된 사본을 사용할 수 있다.
네트워크 대역폭을 잡아 먹지 않고, 웹 서버에 부하를 줄여 비용을 아낀다.
네트워크 병목을 줄인다.
요청에 대한 응답을 속도가 느린 광역통신망 (WAN) 이 아닌
속도가 빠른 근거리 통신망 (LAN) 에서 얻을 수 있다.
origin server 에 대한 요청을 줄여준다.
거리로 인한 지연을 줄여준다.
요청 응답을 먼 곳에서 받아올수록 시간이 많이 걸린다.
근거리에 캐시를 설치해 요청 응답의 전송 거리를 줄일 수 있다.
캐시에 세상 모든 문서의 사본을 저장할 수 없다.
캐시에 요청이 왔을 때, 대응하는 사본이 있어 캐시 사본을 반환 ➔ Cache hit
캐시에 요청이 왔을 때, 대응하는 사본이 없는 경우 origin server 로 요청 전달 ➔ Cache miss
origin server 의 데이터와 대응되는 캐시 사본이 같은 지 점검하는 것을 재검사라 한다.
재검사를 위해 If-Modified-Since
헤더 같은 도구를 사용한다.
캐시 사본이 충분히 오래된 경우에만 재검사를 수행한다.
재검사 결과 origin server 의 데이터가 변경되지 않았다면 (재검사 적중)
서버는 304 Not Modified
응답을 보낸다.
캐시는 캐시 사본을 그대로 클라이언트에게 제공한다.
재검사 결과 origin server 의 데이터가 변경되었다면
서버는 200 OK
응답과 데이터를 보낸다.
캐시는 서버로부터 받은 응답을 저장하고, 그대로 클라이언트에게 제공한다.
재검사 결과 origin server 의 데이터가 삭제되었다면
서버는 404 Not Found
응답을 보낸다.
캐시는 사본을 삭제한다.
캐시가 요청을 처리하는 비율을 캐시 적중률이라 한다.
문서 적중률은 캐시 문서 단위로 얼마나 적중했는지를 의미한다.
외부로 트랜잭션을 내보내지 않은 비율을 의미
트랜잭션 당 TCP handshaking
같은 고정된 소요시간이 필요하다.
문서 적중률을 높이면 이러한 전체 대기시간을 줄일 수 있다.
바이트 단위 적중률은 캐시를 통해 제공된 바이트의 비율을 의미한다.
외부에서 얼마나 많은 바이트를 받아 왔는지 보여준다.
바이트 단위 적중률을 높이면 대역폭을 절약할 수 있다.
적중과 부적중을 구별하는 방법은 응답의 Date
헤더나 Age
헤더를 이용하는 것이다.
Date
헤더
HTTP 메시지를 만들어 보낸 시각을 알려준다.
응답의 Date
값이 현재 시각보다 옛날이면 캐시된 값임을 알 수 있다.
Age
헤더
Private cache
한 명의 사용자에게만 할당
웹 브라우저는 Private cache
를 내장한다.
Public cache
여러명의 사용자들이 공유한다.
공유된 프락시 서버 (프락시 캐시) 이다.
여러 클라이언트들에게 공유된 사본을 제공하여 불필요한 트래픽을 줄인다.
cache miss
발생 시
- 클라이언트 주위엔 작고 저렴한 캐시를
- 계층 상단에는 많은 양을 처리하기 위한 크고 비싼 캐시를 사용한다.
요청 URL에 대응되는 로컬 복사본이 있는지 검사한다.
없으면 origin server 나 부모 캐시에서 사본을 가져오거나
실패를 반환한다.
일정 시간이 지난 로컬 복사본은 신선하지 않은 것으로 간주된다.
새로운 헤더와 캐시된 본문으로 응답 메시지를 만든다.
이를 통해 캐시된 응답은 원 서버에서 온 것처럼 보인다.
캐시는 클라이언트에 맞게 헤더를 조정해야 한다.
Date
헤더는 조정해선 안된다.
Date
헤더는 객체가 origin server 에서 최초로 생겨난 일시를 표현하기 때문이다.
Expires
& Cache-Control: max-age=시간
응답 헤더
문서의 유효기간을 의미한다.
유효기간이 지난 문서는, 반드시 서버로부터 검사받아야 한다.
만료기간을 너무 길게 설정하면 안된다.
Expires
는 만료 날짜를 제공한다.Cache-Control: max-age=(시간)
은 초 단위의 만료 시간을 제공한다.- 모든 컴퓨터의 시계가 올바르게 맞추어졌다는 보장이 없으므로 후자의 방법이 낫다.
If-Modified-Since
& If-None-Match
재검사를 효율적으로 만들어주는 헤더
If-Modified-Since : 날짜
IMS 요청으로도 불린다.
문서가 주어진 날짜 이후로 수정되었다면 서버가 변경된 최신 문서를 응답 (200 OK
)
수정되지 않았다면 본문 없이 필요한 응답 헤더만 반환 (304 Not Modified
)
수정 날짜는 응답 헤더 Last-Modified
값을 통해 알 수 있다.
If-None-Match : 태그
캐시 사본의 태그와 서버의 원본의 태그가 다를 때만 요청을 처리한다.
서버의 데이터를 수정은 했지만 실제 변경 내용은 없는 경우나
1초보다 작은 간격으로 문서가 갱신되는 경우를 처리하기 위해 사용한다.
여러개의 엔티티 태그를 사용할 수 있다.
태그는 응답헤더 ETag
값을 통해 알 수 있다.
클라이언트와 서버는 요청/응답 문서의 캐시 정책을 설정할 수 있다.
Cache-Control: no-store
응답의 사본을 캐시에 저장하는 것을 금지한다.
캐시는 응답을 클라이언트에게 그대로 전달 후, 사본을 삭제한다.
클라이언트가 사용 시, 요청 문서를 캐시에서 삭제한다.
Cache-Control: no-cache
응답의 사본을 캐시 저장소에 저장할 수 있다.
해당 응답은 요청시마다 서버와 재검사를 한 뒤, 클라이언트에게 제공해야 한다.
클라이언트가 사용 시, 서버로부터 재검사한 캐시만 받아들인다.
Cache-Control: must-revalidate
신선하지 않은 캐시 사본을 반드시 서버와 재검사 하도록 한다.
no-cache
는 신선도와 상관없이 재검사 하도록 한다.
캐시 무효화를 하려는 경우, 3가지를 모두 사용한다.
서버는 수천개의 클라이언트와 동시에 통신한다.
상황에 따라 서버는 클라이언트를 식별할 필요가 있다.
HTTP는 무상태, 익명의 프로토콜이다.
사용자에게 특화된 페이지 제공
사용자 정보 저장 및 제공
세션 추적
HTTP 트랜잭션은 무상태이며, 독립적으로 일어난다.
그러나 특정 웹사이트에서는 사용자의 상태를 유지해야 한다.
클라이언트 IP 주소 추적
사용자 로그인 인증 헤더 사용
URL에 식별자를 포함하는 fat URL
식별정보를 지속 & 유지하는 쿠키 사용
초기의 사용자 식별 방식
클라이언트가 확실하고 고정된 IP를 가져야 문제없이 동작
웹 서버는 HTTP 요청을 보내는 클라이언트의 IP 주소를 알아낼 수 있다.
한계점
IP는 컴퓨터를 가리키므로, 여러 사용자가 같은 컴퓨터를 사용시 식별 불가
많은 ISP (인터넷 서비스 제공자) 는 동적으로 IP 주소를 제공하므로 식별이 어렵다.
NAT (Network Address Translation) 방화벽 사용 시, 클라이언트의 실제 IP 대신 방화벽 IP 주소로 변환하므로 식별이 어렵다.
- (a) 정보 요청
- (b) 401 응답 코드와
WWW-Authenticate
헤더를 반환하며 로그인을 요청- (c) 사용자가 로그인을 수정하고, 로그인 정보를
Authorization
헤더에 넣어 요청한다.
- 이 사이트에 대한 모든 요청에
Authorization
헤더를 전달한다.- 세션 유지
사용자 식별번호
002-1145265-8016838
가 URL 에 추가된다.
URL마다 사용자를 식별하기 위한 상태정보를 추가해 확장한다.
한계점
URL에 사용자 식별 정보가 포함되므로 주소를 공유하면 보안에 문제가 생긴다.
URL이 사용자별로 달라지기 때문에 기존 캐시에 접근할 수 없다.
사용자가 다른 사이트로 이탈하거나 특정 URL을 요청해 뚱뚱한 URL을 이탈시 지금까지의 진척사항들이 전부 사라진다.
현재 가장 널리 사용되는 방식
일종의 상태 정보
쿠키의 타입
세션 쿠키
지속 쿠키
파기되는 시점을 명시
브라우저를 닫거나 컴퓨터를 꺼도 더 길게 유지될 수 있다.
디스크에 저장
쿠키는 브라우저의 쿠키 데이터베이스에 저장된다.
- 구글 크롬은 쿠키를
Cookies
에 저장한다.
- SQLite 파일
- (b) 서버는 응답으로 사용자를 식별하기 위한 정보를
Set-cookie
헤더에 담아 보낸다.- (c) 클라이언트는 해당 도메인의 모든 요청에
Cookie
헤더를 포함한다.
브라우저가 갖고 있는 수백, 수천개의 쿠키를 모든 사이트에 모두 보내지 않는다.
모두 전달 시 성능 저하
쿠키는 생성한 서버에 특화되므로 다른 서버에선 무의미
이름=값
필수적으로 존재해야 하는 속성
ex) Set-Cookie: customer=Mary
Domain
ex) Set-Cookie: user=mary17; domain="airtravelbargains.com"
해당 사이트 방문 시 쿠키 헤더가 적용된다.
어떤 사이트가 해당 쿠키를 읽을 수 있는지 제어한다.
생략 시 쿠키 생성 서버의 호스트명을 사용
Path
ex) Set-Cookie: pref=compact; domain="airtravelbargains.com"; path=/autos/
pref=compact
쿠키는/autos/
가 포함된 URL 경로에서 사용된다.
사용자가 http://www.airtravelbargains.com/specials.html
에 접근 시
pref=compact
쿠키를 사용하지 않는다.
사용자가 http://www.airtravelbargains.com/autos/cheapo/index.html
에 접근 시
pref=compact
쿠키를 사용한다.
Expires
쿠키의 생명주기를나타내는 날짜 정보
생략 시 세션이 종료되면 파기한다.
ex) Set-Cookie: foo=bar; expires=Wednesday, 09-Nov-99 23:12:40 GMT
해당 날짜가 지나면 쿠키는 파기된다.
해당 속성들은 Version 0 쿠키
의 필드들이다.
만약 응답이 Set-Cookie
헤더를 갖는다면 본문을 캐시할 때 주의를 기울여야 한다.
캐시를 사용하는 여러 사용자에게 같은 Set-Cookie
헤더를 보내면 사용자 추적에 실패한다.
특정 사용자의 개인정보가 불특정 다수에게 노출될 수 있다.
Set-Cookie
헤더를 제외하고 캐시를 하고 싶다면
Cache-Control: no-cahce="Set-Cookie"
를 보내 Set-Cookie
만 무효화한다. Set-Cookie
헤더가 있는 경우 해당 응답 전부를 캐시하지 않고 싶다면
서버에서 캐시를 무효화하는 Cache-Control
헤더를 보낸다.
보수적인 캐싱 정책
내가 누구인지 증명하는 것
신분증을 보여주는 것
아이디, 비밀번호를 입력하는 것
인증 요구
WWW-Authenticate
서버가 만드는 응답헤더
클라이언트에게 인증 정보를 요청하기 위해 사용한다.
인증
Authorization
클라이언트가 만드는 요청헤더
서버에게 인증 정보를 보낸다.
만약 인증 정보가 유효하면 서버는 리소스를 제공한다.
(c) 인증 정보는 인코딩해서
Authorization
에 담는다.
Authorization
에 담기는 인코딩된 사용자 정보는 쉽게 디코딩할 수 있다.
사용자가 가짜 서버에 연결되어 있는데도, 기본 인증을 수행하는 검증된 서버에 연결되어 있다고 믿는다면
보안을 강화한 요즘 웹사이트 대부분은 HTTP 자체 인증 기능보다는 각각의 인증 모듈을 이용해 인증 기능을 직접 구현한다.