웹 서버는 HTTP 요청을 처리하고 응답을 제공한다.
웹 서버는 기능, 형태, 크기가 다양하다.
그러나 기능은 달라도, 모든 웹 서버는 리소스에 대한 HTTP 요청을 받아서 콘텐츠를 클라이언트에게 돌려준다
웹 서버는 자신이 제 공하는 리소스를 관리하고 웹 서버를 설정, 통제, 확장하기 위한 관리 기능을 제공 한다.
웹 서버는 HTTP 프로토콜을 구현하고, 웹 리소스를 관리하고, 웹 서버 관리 기능 을 제공한다. 웹 서버는 TCP 커넥션 관리에 대한 책임을 운영체제와 나눠 갖는다.
운영체제는 컴퓨터 시스템의 하드웨어를 관리하고 TCP/IP 네트워크 지원, 웹 리소 스를 유지하기 위한 파일 시스템, 현재 연산 활동을 제어하기 위한 프로세스 관리 를 제공한다.
다목적 소프트웨어 웹 서버는 네트워크에 연결된 표준 컴퓨터 시스템에서 동작한 다.
아파치나 W3c의 직소 같은 오픈 소스 소프트웨어를 사용할 수도 있고, 마이크 로소프트나 아이플래닛의 웹 서버 같은 상용 소프트웨어를 사용할 수도 있다. 웹 서 버 소프트웨 어는 거 의 모든 컴퓨터와 운영체제 에서 동작한다.
HTTP/1.1 의 기능들을 지원하려면, 풍부한 리소스 지원, 가상 호스팅, 접근 제어,
로깅, 설정, 모니터링, 그 외 성능을 위한 각종 기능들이 필요하다. 그러나 최소한으 로 기능하는 HTTP 서버라면 30줄 이하의 펄(Perl) 코드로도 만들 수 있다.
type-o-serve라고 이름 붙은 작은 펄 프로그램
여느 웹 서버와 마찬가지로, type-o-serve는 HTTP 커넥션을 기다린다. type-o-serve는 요 청 메시지를 받자마자, 화면에 메시지를 출력한다. 그리고 클라이언트에게 답해줄 응답 메시지를 타이핑하기를 (혹은 붙여넣기를) 기다린다. type-o-serve가 웹 서버 를 흉내 내는 이 방식은, HTTP 요청 메시지를 정확하게 기록하고 어떤 HTTP 응답 메시지라도 돌려보내줄 수 있도록 해준다.
이 간단한 type-o-serve 유틸리티는 HTTP 기능 대부분을 구현하지는 않았지만, 예 5-1 에서 텔넷으로 클라이언트 요청 메시지를 생성했었던 것과 같은 방법으로 서버 응답 메시지를 생성할 수 있게 해 주는 유용한 도구다.
뭐야 그럼 이제까지 가짜로 하는 일 읽었던 거?
클라이언트가 이미 서버에 대해 열려있는 지속적 커넥션을 갖고 있다면, 클라이언 트는 요청을 보내기 위해 그 커넥션을 사용할 수 있다. 그렇지 않다면, 클라이언트 는 서버에 대한 새 커넥션을 열 필요가 있다(HTTP 커넥션 관리 기술에 대해 복습 하려 면 4장을 다시 보라).
클라이언트가 웹 서버 에 TCP 커넥션을 요청하면, 웹 서버는 그 커넥션을 맺고 TCP 커넥션에서 IP 주소를 추출하여 커넥션 맞은편에 어떤 클라이언트가 있는지 확인 한다.3 일단 새 커넥션이 맺어지고 받아들여지면, 서버는 새 커넥션을 커넥션 목록 에 추가하고 커넥션에서 오가는 데이터를 지켜보기 위한 준비를 한다.
웹 서버는 어떤 커넥션이든 마음대로 거절하거나 즉시 닫을 수 있다. 어떤 웹 서버들은 클라이언트의 IP 주소나 호스트 명이 인가되지 않았거나 악의적 이라고 알 려진 것인 경우 커넥션을 닫는다. 다른 신원 식별 기법 또한 사용될 수 있다.
대부분의 웹 서버는 ‘역방향 DNS(reverse DNS)’를 사용해서 클라이언트의 IP 주 소를 클라이언트의 호스트 명으로 변환하도록 설정되어 있다. 웹 서버는 클라이언 트 호스트 명을 구체적인 접근 제어와 로깅을 위해 사용할 수 있다. 호스트 명 룩 업(hostname lookup)은, 꽤 시간이 많이 걸릴 수 있어 웹 트랜잭션을 느려지게 할 수 있음을 미리 경고해두겠다. 많은 대용량 웹 서버는 호스트 명 분석(hostname resolution)을 꺼두거나 특정 콘텐츠에 대해서만 켜놓는다.
몇몇 웹 서버는 또한 IETF ident 프로토콜을 지원한다. ident 프로토콜은 서버에게 어떤 사용자 이름이 HTTP 커넥션을 초기화했는지 찾아낼 수 있게 해준다. 이 정보 는 특히 웹 서버 로깅 에서 유용하기 때문에, 널리 쓰이는 일반 로그 포맷(Common Log Format)의 두 번째 필드는 각 HTTP 요청 의 ident 사용자 이름을 담고 있다.4
만약 클라이 언트가 ident 프로토콜을 지원한다면, 클라이 언트는 ident 결과를 위 해 TCP 포트 113번을 listen한다. 그림 5-4는 어떻게 ident 프로토콜이 동작하는지 보여준다. 그림 5-4a에서 클라이언트는 HTTP 커넥션을 연다. 서버는 그 후 자신의 커넥션을 클라이언트의 identd 서버 포트(113)를 향해 열고, 새 커넥션(클라이언트 와 서버 포트 번호로 지정되는)에 대응하는 사용자 이름을 묻는 간단한 요청을 보 낸다.
ident는 조직 내부에서는 잘 사용할 수 있지만, 공공 인터넷에서는 다음을 포함한 여러 이유로 잘 동작하지 않는다.
• 많은 클라이언트 PC는 identd 신원확인 프로토콜 데몬 소프트웨어를 실행하지 않는다.
• ident 프로토콜은 HTTP 트랜잭 션을 유의 미하게 지 연시 킨다.
• 방화벽이ident트래픽이들어오는것을막는경우가많다.
• ident 프로토콜은 안전하지 않고 조작하기 쉽다.
• idem 프로토콜은 가상 IP 주소를 잘 지원하지 않는다.
• 클라이언트 사용자 이름의 노출로 인한 프라이버시 침해의 우려가 있다.
커넥션에 데이터가 도착하면, 웹 서버는 네트워크 커넥션에서 그 데이터를 읽어 들 이고 파싱하여 요청 메시지를 구성한다.
요청 메시지를 파싱할 때, 웹 서버는 다음과 같은 일을 한다.
요청줄을 파싱하여 요청 메서드, 지정된 리소스의 식별자<URI), 버전 번호5를 찾 는다. 각 값은 스페이스 한 개로 분리되어 있으며, 요청줄은 캐리지 리턴 줄바꿈 (CRLF)문자열6로 끝난다.
메시지 헤더들을 읽는다. 각 메시지 헤더는 CRLF로 끝난다.
헤더의 끝을 의미하는 CRLF로 끝나는 빈 줄을 찾아낸다. (존재한다면)
요청 본문이 있다면, 읽어 들인다(길이는 Content-Length 헤더로 정의된다).
요청 메시지를 파싱할 때, 웹 서버는 입력 데이터를 네트워크로부터 불규칙적으로 받는다. 네트워크 커넥션은 언제라도 무효화될 수 있다. 웹 서버는 파싱해서 이해 하는 것이 가능한 수준의 분량을 확보할 때까지 데이터를 네트워크로부터 읽어서 메시지 일부분을 메모리에 임시로 저장해 둘 필요가 있다.
고성능 웹 서버는 수천 개의 커넥션을 동시에 열 수 있도록 지원한다. 이 커넥션들 은 웹 서버가 전 세계의 클라이언트들과 각각 한 개 이상의 커넥션을 통해 통신할 수 있게 해준다. 어떤 커넥션들로부터는 요청이 느리게 혹은 드물게 흘러 들어오 고, 또 어떤 것들은 나중에 일어날 활동을 위해 조용히 대기하고 있는데 비해, 일부 커넥션들은 웹 서버로 급속히 요청을 보내고 있을 것이다.
웹 서버가 요청을 받으면, 서버는 요청으로부터 메서드, 리소스, 헤더, 본문(없는 경우도 있다)을 얻어내어 처리한다.
POST를 비롯한 몇몇 메서드는 요청 메시지에 엔터티 본문이 있을 것을 요구한 다. 그 외 OPTIONS를 비롯한 다수의 메서드는 요청에 본문이 있는 것을 허용하되 요구하지는 않는다. 많지는 않지만 GET과 같이 요청 메시지에 엔터티 본문이 있는 것을 금지하는 메서드도 있다.
우리는 요청 처리에 대해서는 이야기하지 않을 것이다. 왜냐하면 그건 이 책 나 머지 대부분의 주제이기 때문이다!
웹 서버는 리소스 서버다. 그들은 HTML 페이지나 JPEG 이미지 같은 미리 만들어 진 콘텐츠를 제공하며, 마찬가지로 서버 위에서 동작하는 리소스 생성 애플리케이 션을 통해 만들어진 동적 콘텐츠도 제공한다.
웹 서버가 클라이언트에 콘텐츠를 전달하려면, 그전에 요청 메시지의 URI에 대 응하는 알맞은 콘텐츠나 콘텐츠 생성기를 웹 서버에서 찾아서 그 콘텐츠의 원천을 식별해야 한다.
웹 서버는 여러 종류의 리소스 매핑을 지원한다. 하지만 리소스 매핑의 가장 단순 한 형태는 요청 URI를 웹 서버의 파일 시스템 안에 있는 파일 이름으로 사용하는 것이다. 일반적으로 웹 서버 파일 시스템의 특별한 폴더를 웹 콘텐츠를 위해 예약 해 둔다. 이 폴더는 문서 루트 혹은 docroot로 불린다. 웹 서버는 요청 메시지에서 URI를 가져와서 문서 루트 뒤에 붙인다.
그림 5-8에서, /specials/saw-blade.gif에 대한 요청이 도착했다. 이 예에서 웹 서 버는 문서 루트 /usr/local/httpd/files를 갖고 있다. 웹 서버는 /usr/local/httpd/files/ specials/saw-blade.gif 파일을 반환한다.
다음과 같이 httpd.conf 설정 파일에 DocumentRoot 줄을 주가하여 아파치 웹 서버 의 문서 루트를 설정할 수 있다.
DocumentRoot /usr/local/httpd/files
서버는 상대적인 url이 docroot를 벗어나서 파일 시스템의 docroot 이외 부분이 노 출되는 일이 생기지 않도록 주의해야 한다. 예를 들어 대부분의 성숙한 웹 서버는 Joe’s Hardware의 문서 루트 위의 파일을 보려고 하는 이와 같은 URI를 허용하지
않는다.
http://www.j oes-hardware.com/.•/
가상 호스팅 웹 서버는, 각 사이트에 그들만의 분리된 문서 루트를 주는 방법으로 한 웹 서버 에서 여러 개의 웹 사이트를 호스팅 한다. 가상 호스팅 웹 서버는 URI나 Host 헤더에서 얻은 IP 주소나 호스트 명을 이용해 올바른 문서 루트를 식별한다. 이 방법으로, 하나의 웹 서버 위에서 두 개의 사이트가 완전히 분리된 콘텐츠를 갖 고 호스팅 되도록 할 수 있다.
서버는 두 사이트 www.joes-hardware.com와 www.marys- antiques.com을 호스팅 한다. 서버는 두 웹 사이트를 HTTP Host 헤더나 서로 다른 IP 주소를 이용해 구분할 수 있다.
• 요청 A가 도착했을 때, 서버는 /docs/joe/index.html 파일을 가져온다.
• 요청 B가 도착했을 때, 서버는 /docs/mary/index.html 파일을 가져온다.
웹서버는URI를동적 리소스에매핑할수도있다.즉,요청에맞게콘텐츠를생성 하는 프로그램에 URI를 매핑하는 것이다(그림 5-11). 사실, 웹 서버들 중에서 애플 리케이션 서버라고 불리는 것들은 웹 서버를 복잡한 백엔드 애플리케이션과 연결 하는 일을 한다. 어떤 리소스가 동적 리소스라면, 애플리케이션 서버는 그에 대한 동적 콘텐츠 생성 프로그램이 어디에 있는지, 그리고 어떻게 그 프로그램을 실행하 는지 알려줄 수 있어야 한다. 대부분의 웹 서버는 동적 리소스를 식별하고 매핑할수 있는 기본적인 메커니즘을 갖고 있다.
한번 서버가 리소스를 식별하면, 서버는 요청 메서드로 서술되는 동작을 수행한 뒤 응답 메시지를 반환한다. 응답 메시지는 응답 상태 코드, 응답 헤더, 그리고 응답 본 문(생성되었다면)을 포함한다. HTTP 응답 코드에 대해서는 3장의 “상태 코드”에 자세하게 나와 있다.
만약 트랜잭션이 응답 본문을 생성한다면, 그 내용을 응답 메시지와 함께 돌려보낸 다. 만약 본문이 있다면, 응답 메시지는 주로 다음을 포함한다.
• 응답 본문의 MIME 타입을 서술하는 Content-Type 헤더
• 응답 본문의 길이를 서술하는 Content-Length 헤더 • 실제응답본문의내용
웹 서버에게는 응답 본문의 MIME 타입을 결정해야 하는 책임이 있다. 다음은 MIME 타입과 리소스를 연결하는 여러 가지 방법이다.
mime.types
웹 서버는 MIME 타입을 나타내기 위해 파일 이름의 확장자를 사용할 수 있다. 웹 서버는 각 리소스의 MIME 타입을 계산하기 위해 확장자별 MIME 타입이 담겨 있 는파일을탐색한다. 이러한확장자기반타입 연계가가장흔한방법이다. 이는그
림 5-12에 묘사되어 있다.
웹 서버는 종종 성공 메시지 대신 리다이렉션 응답을 반환한다. 웹 서버는 요청을 수행하기 위해 브라우저가 다른 곳으로 가도록 리다이렉트 할 수 있다. 리다이렉션 응답은 3XX 상태 코드로 지칭 된다. Location 응답 헤더는 콘텐츠의 새로운 혹은 선 호하는 위치 에 대한 URI를 포함한다. 리다이 렉트는 다음의 경우에 유용하다.
리소스는 새 URL이 부여되어 새로운 위치로 옮겨졌거나 이름이 바뀌었을 수 있다.
웹 서버는 클라이언트에게 리소스의 이름이 바뀌었으므로, 클라이언트는 북마크를 갱신하거나 할 수 있다고 말해줄 수 있다. 301 Moved Permanently 상태 코드는 이 런 종류의 리다이 렉트를 위해 사용된다.
만약 리소스가 임시로 옮겨지거나 이름이 변경 된 경우, 서버는 클라이언트를 새 위 치로 리다이렉트하길 원할 것이다. 그러나 이름 변경이 임시적이기 때문에, 서버는 클라이언트가 나중에는 원래 URL로 찾아오고 북마크도 갱신하지 않기를 원한다. 303 See Other와 307 Temporary Redirect 상태 코드는 이 런 종류의 리다이 렉트를 위해 사용된다.
그 외에도
웹 서버는 받을 때와 마찬가지로 커넥션 너머로 데이터를 보낼 때도 비슷한 이슈에
직면한다. 서버는 여러 클라이언트에 대한 많은 커넥션을 가질 수 있다. 그들 중 일부는 아무것도 안하고 있는 상태이괴 일부는 서버로 데이터를 보내고 있으며, 또
다른 일부는 클라이언트로 돌려줄 응답 데이터를 실어 나르고 있을 것이다.
서버는 커넥션 상태를 추적해야 하며 지속적인 커넥션은 특별히 주의해서 다룰 필요가 있다. 비지속적인 커넥션이라면, 서버는 모든 메시지를 전송했을 때 자신
쪽의 커넥션을 닫을 것이다.
지속적인 커넥션이라면, 서버가 Content-Length 헤더를 바르게 계산하기 위해
특별한 주의를 필요로 하는 경우나, 클라이언트가 응답이 언제 끝나는지 알 수 없 는 경우(4장을 보라)에, 커넥션은 열린 상태를 유지할 것이다.
마지막으로, 트랜잭션이 완료되었을 때 웹 서버는 트랜잭션이 어떻게 수행되었는 지에 대한 로그를 로그파일에 기록한다. 대부분의 웹 서버는 로깅에 대한 여러 가 지 설정 양식을 제공한다. 더 자세한 것은 21장을 보라.