
MIME 타입, 서버사이드의 동적 컨텐츠 생성이 도움이 된다. 4장의 내용이 약간 어려워, 우선 주요 내용들을 간략히 추리고 인상 깊은 내용에 하이라이트 하였다.
다채로운 웹 서버
웹서버 : 웹 서버 소프트웨어와 웹 페이지 제공에 특화된 장비 양쪽 모두
HTTP 및 그와 관련된 TCP 처리를 구현한 것. TCP 커넥션 관리에 대한 책임을 운영체제와 나눠 갖는다.
HTTP 프로토콜을 구현, 웹 리소스 관리, 웹 서버 관리 기능 제공
다목적 소프트웨어 웹 서버, 임베디드 웹 서버 등. 다양한 형태로 있을 수 있다.
웹서버가 하는 일
커넥션을 맺는다
요청을 받는다
요청을 처리한다
리소스에 접근한다
응답을 만든다
응답을 보낸다
트랜잭션을 로그로 남긴다
1 클라이언트 커넥션 수락
클라이언트가 서버에 이미 열려있는 지속적 커넥션을 갖고 있다면 요청을 보내기 위해 그 커넥션을 사용할 수 있음
아닐 시 클라이언트는 서버에 대한 새 커넥션을 열어야함
새 커넥션 다루기
클라이언트에서 서버로 TCP 커넥션을 요청하면, 서버는 그 커넥션을 맺고 TCP 커넥션에서 IP 주소를 추출하여 클라이언트 확인
받아들여 진다면, 커넥션 목록에 추가함
웹 서버는 어떤 커넥션이든 거절하거나 즉시 닫을 수 있음
클라이언트의 주소, 호스트명이 인가되지 않거나 악의적이라고 판단하는 경우. 다른 신원 파악 방법 사용 가능
클라이언트 호스트 명 식별
역방향 DNS를 사용해 사용자 IP를 클라이언트 호스트명으로 변환할 수 있음.
구체적인 접근 제어, 로깅을 위해 사용할 수 있으나, 시간이 걸려 트랜잭션을 느리게 할 수 있음. 따라서 대용량 서버는 호스트명 분석을 꺼두거나 특정 콘텐츠에만 켜놓음.
ident를 이용해 사용자 알아내기
IETF idemt 프로토콜을 사용하여 서버에게 어떤 사용자 이름이 HTTP 커넥션을 초기화했는지 알 수 있게함.
웹 서버 로깅에 유용. 일반적인 로그 포맷에서 ident 필드에 HTTP 요청 사용자 이름을 담음
성능, 보안, 대부분의 클라이언트 pc에서 identd를 사용하지 않아 잘 사용되지 않음
2 요청 메시지 수신
HTTP 메시지의 내부 표현
커넥션에 내용 도착 시, 서버는 데이터를 읽고 파싱하여 요청메시지를 구성함
요청 메시지 파싱할 때 하는 일들
요청 메서드, 리소스 URL, 프로토콜 버전을 찾음. 요청줄은 CRLF 문자열로 줄바꿈 구분
메시지 헤더를 읽음. 마찬가지로 줄바꿈 CRLF로 끝남.
헤더의 끝을 CRLF로 찾음.
본문이 있다면 읽음
요청 메시지 파싱 중 서버는 입력 데이터를 네트워크로부터 불규칙적으로 받음.
이 때 커넥션은 언제든 무효화될 수 있음.
파싱하여 이해가 가능할 정도의 분량이 될 때만큼 임시로 저장해둘 필요가 있음
몇몇 서버는 요청 메시지를 쉽게 다루도록 서버 내부의 자료 구조에 저장함.
요청 메시지의 각 조각에 대한 포인터, 길이를 담을 수 있음.
헤더는 룩업 테이블에 저장되어 각 필드에 빠르게 접근 가능.
커넥션 입/출력 처리 아키텍쳐
고성능 서버는 수 천개의 커넥션을 동시에 열 수 있도록 지원함.
서버가 전 세계의 클라이언트와 각각 한개 이상의 커넥션을 통해 통신할 수 있게 해줌.
서버는 항상 요청에 대기함. 서버 아키텍처에 따라 요청을 처리하는 방식이 다름
단일 스레드 웹 서버
한번에 하나씩 요청을 처리함. 트랜잭션 완료 시 다음 커넥션이 처리됨. 심각한 성능 저하 가능.
간단하지만 처리 도중 모든 다른 커넥션이 무시되어 진단 도구에서만 사용.
멀티 프로세스와 멀티 스레드 웹 서버
여러 요청을 동시에 처리하기 위해 여러개의 프로세스 혹은 고효율 스레드를 할당
스레드/프로세스는 필요할 때마다 혹은 미리 만들어질 수 있음.
몇몇 서버는 매 커넥션마다 스레드/프로세스 하나를 할당하지만, 수백~수만 개의 동시 커넥션을 처리할 때 너무 많은 메모리와 리소스를 소비
대다수 멀티스레드 웹 서비스는 스레드/프로세스의 최대 개수를 제한
다중 I/O 서버
대량의 커넥션을 지원하기 위해 다수의 웹서버가 채택한 다중 아키텍쳐
모든 커넥션은 동시에 활동이 감시됨
커넥션 상태가 바뀌면, 그 커넥션에 대해 작은 양의 처리가 수행됨
처리 완료 시 다음번 상태 변경을 위해 열린 커넥션 목록으로 돌아감
실제로 처리해야할 요청이 있을 때 작업이 수행됨
유휴 상태의 커넥션에 매여 기다리느라 리소스를 낭비하지 않음
다중 멀티스레드 웹서버
CPU 여러 개의 이점을 위해 멀티스레딩과 다중화를 결합
여러 개의 스레드는 각각 열려있는 커넥션을 감시하고 각 커넥션에 대해 조금씩 작업을 수행
3 요청 처리
서버는 요청으로부터 메서드, 리소스, 헤더, 본문body(없는 경우도 있음)을 얻어 처리
POST를 비롯한 몇몇 메서드는 요청 메시지에 본문이 있을 것을 요구
OPTIONS를 비롯한 다수의 메서드는 요청에 본문이 있는 것을 허용하되 요구하지 않음
GET과 같이 요청 메시지에 본문을 금지하는 메서드도 있다
HTTP 명세에 따르면 GET 요청은 리소스의 상태 변화를 변경하지 않아야 한다. get 요청의 본문은 의미가 없으며 서버에 의해 무시될 수 있다. URL에서 리소스의 일부나 필터링한 일정 결과를 얻으려면 본문 대신 쿼리(질의)를 사용
4 리소스의 매핑과 접근
웹 서버는 리소스 서버다. HTML, JPEG 이미지 같은 미리 만들어진 콘텐츠를 제공할 수 있다.
서버 위에 동작하는 리소스 생성 애플리케이션을 통해 만들어진 동적 컨텐츠도 제공한다.
요청 메시지 URI에 대응하는 알맞은 컨텐츠나 컨텐츠 생성기를 웹 서버에 찾아서 그 컨텐츠의 원천을 식별해야한다.
docroot
가장 단순한 방법은 요청 URI를 웹 서버의 파일 시스템 안에 있는 파일 이름으로 사용하는 것
일반적으로 서버 파일 시스템의 docroot 폴더를 웹 컨텐츠를 위해 예약해둠.
가상 호스팅된 docroot:
가상 호스팅 웹 서버는 각 사이트에 분리된 문서 루트를 주는 방법으로 한 웹서버에 여러 웹 사이트를 호스팅한다.
가상 호스팅 웹 서버는 URI나 Host 헤더에서 얻은 IP 주소나 호스트 명을 이용해 올바른 문서 루트를 식별
사용자 홈 디렉터리 docroots:
한 대의 웹 서버에서 여러 개인 사용자가 사이트를 사용할 때
빗금('/'), 물결('~') 다음에 사용자 이름이 오는 것으로 시작하는 URI는 그 사용자 개인 문서 루트를 가리킴.
디렉터리 목록
경로가 파일이 아닌 디렉터리를 가리키는 디렉터리 URL에 대한 요청을 받을 수 있음
디렉터리 URL 요청을 받았을 때 다른 행동을 취하도록 설정
에러를 반환
디렉터리 대신 특별한 '색인 파일'을 반환
디렉터리를 탐색하여 그 내용을 담은 HTML 페이지를 반환
대부분의 웹서버는 요청한 URL에 대응하는 디렉터리 안에서 index.html로 이름 붙은 파일을 찾는다.
디렉터리에 index.html이란 이름의 파일이 있다면 이를 반환할 것이다.
Directoryindex 설정 지시자를 사용해 기본 디렉터리 파일로 사용될 파일 이름의 집합을 설정할 수 있다.
동적 컨텐츠 리소스 매핑
요청에 맞게 컨텐츠를 생성하는 프로그램에 URL을 매핑하는 것
어떤 리소스가 동적이라면, 그에 대한 동적 컨첸츠 생성 프로그램이 어디있고, 어떻게 실행하는지 알려줄 수 있어야한다.
대부분의 웹서버는 동적 리소스를 식별하고 매핑할 수 있는 기본적인 메커니즘을 갖고 있다.
서버사이드 인클루드
만약 어떤 리소스가 서버사이드 인클루드를 포함하고 있는 것으로 설정된다면, 서버는 그 리소스의 콘텐츠를 클라이언트에게 보내기 전에 처리한다.
쉬운 동적 컨텐츠 생성: 서버는 컨텐츠에 변수 이름이나 내장된 스크립트가 될 수 있는 어떤 특별한 패턴이 있는지 검사를 받는다. 특별한 패턴은 변수 값이나 실행 가능한 스크립트의 출력 값으로 치환된다.
접근 제어
각 리소스에 접근 제어를 할당할 수 있다.
접근 제어되는 리소스에 대한 요청이 도착하면, 서버는 클라이언트 IP 주소에 근거하여 접근을 제어하거나 비밀번호를 요구할 수 있다.
5 응답 만들기
응답 엔터티
트랜잭션이 응답 본문을 생성한다면, 그 내용을 응답 메시지와 함께 돌려보냄
본문이 있다면 응답 메시지는 주로 MIME 타입을 서술하는 Content-Type 헤더, 응답 본문의 길이를 서술하는 Content-Length 헤더, 실제 응답 본문 내용 을 포함한다.
MIME 타입 결정
웹 서버는 응답 본문의 MIME 타입을 결정해야 하는 책임이 있다.
서버는 특정 파일이 특정 MIME 타입을 갖게끔 설정할 수 있다.
MIME 타입과 리소스를 연결하는 여러가지 방법들이 있다.
mime:types: MIME 타입을 나타내기 윟 파일 이름 확장자를 사용. 각 리소스의 MIME 타입을 계산하기 위한 확장자별 MIME 타입이 담겨 있는 파일을 탐색. 확장자 기반 타입 연계가 가장 흔한 방법이다.
매직 타이핑: 아파티 웹 서버는 각 파일의 MIME 타입을 알아내기 위해 파일의 내용을 검사하여 알려지 패턴에 대한 테이블에 해당하는 패턴이 있는지 찾아볼 수 있다. 느리지만, 표준 확장자 없이 이름 지어진 경우에 편리.
유형 명시: 특정 파일이나 디렉터리 안의 파일들이 확장자 내용에 상관없이 어떤 MIME 타입을 갖도록 서버를 설정할 수 있다.
유형 협상: 한 리소스가 여러 종류의 문서 형식에 속하도록 설정할 수 있다. 서버가 사용자와 협상 과정을 통해 사용하기 가장 좋은 형식(과 대응하는 MIME 타입)을 판별할 것인지 여부를 설정할 수 있다.
리다이렉션
요청에 따라 3XX 상태 코드의 리다이렉션 응답을 내려줄 때가 있다. Location 응답 헤더는 컨텐츠의 새로운 / 선호하는 위치에 대한 URI를 포함한다. 다음의 경우에 유용하다.
영구히 리소스가 옮겨진 경우: 리소스가 새로운 URL이 부여되어 새 위치로 옮겨지거나 이름이 바뀌었을 때. 서버는 리다이렉트를 위해 클라이언트에 301 Moved Permanently 상태 코드를 보낸다.
임시로 리소스가 옮겨진 경우: 임시로 리소스가 옮겨지거나 이름이 변경된 경우 리다이렉트 한다. 303 see other, 307 Temporary Redirect 상태 코드 사용.
URL 증강: 서버가 문맥 정보를 포함시키기 위해 재 작성된 URL로 리다이렉트한다. 요청이 도착했을 때, 서버는 상태 정보를 내포한 새 URL을 생성하고 사용자를 이 URL로 리다이렉트 한다. 클라이언트는 리다이렉트 이후 상태정보가 추가된 완전한 URL을 포함한 요청을 다시 보낸다. 트랜잭션 간 상태를 유지하는 유용한 방법이다. 303, 307 상태 코드를 사용한다.
부하 균형: 과부화된 서버가 요청을 받으면, 서버는 부하가 덜한 서버로 클라이언트를 리다이렉트할 수 있다. 303, 307 상태 코드를 사용한다.
익숙한 다른 서버가 있을 때: 서버는 사용자에 대한 정보를 갖을 수 있다. 해당 클라이언트를 그 클라이언트에 대한 정보를 갖고 있는 다른 서버로 리다이렉트 할 수 있다. 303, 307 상태코드를 사용.
디렉터리 이름 정규화: 클라이언트가 디렉터리 이름에 대한 요청을 하는데 끝에 빗금(/)을 빠뜨렸다면, 대부분의 웹 서버는 상대경로가 정상적으로 작동하게끔 추가한 URL로 리다이렉트 한다.
6 응답 보내기
커넥션을 받을 때와 마찬가지로 데이터를 보낼 때도 비슷한 이슈가 있을 수 있다.
서버는 여러 클라이언트에 대한 많은 커넥션을 가질 수 있다.
그들 중 일부는 아무것도 안하는 상태고, 일부는 서버로 데이터를 보내며, 일부는 클라이언트로 돌려줄 응답 데이터를 보내고 있다.
서버는 커넥션 상태를 추적해야 하며, 지속적인 커넥션은 특별히 주의해서 다뤄야한다.
지속적인 커넥션이라면, 서버가 Content-Length 헤더를 바르게 계산하기 위해 주의를 필요로 하는 경우, 클라이언트 응답이 언제 끝나는지 알 수 없는 경우에 커넥션을 열어둘 것이다.
비지속적인 커넥션이라면, 서버는 모든 메시지를 전송하고 자신 쪽의 커넥션을 닫는다.
7 로깅
트랜잭션이 완료되었을 때 어떻게 수행됐는 지에 대한 로그를 로그 파일에 기록한다.
서버는 로깅에 대한 여러 설정 양식을 제공한다.