본문 바로가기

Computer Science/통신

5장 웹 서버

HTTP 완벽 가이드(웹은 어떻게 동작하는가)를 참조하여 작성하였습니다.

 


5장 웹 서버

1. 여러 종류의 소프트웨어 및 하드웨어 웹 서버에 대해 조사
2.HTTP 통신을 진단해주는 간단한 웹 서버를 Perl(펄)로 작성
3. 어떻게 웹 서버가 HTTP 트랜잭션을 처리하는지 단계별로 설명

5.1 다채로운 웹서버

웹 서버는 HTTP 요청을 처리하고 응답을 제공한다. '웹 서버'라는 용어는 웹 서버 소프트웨어와 웹페이지 제공에 특화된 장비(컴퓨터 같이) 모두를 가리킨다.

5.1.1 웹 서버 구현

  • 웹 서버는 HTTP 및 그와 관련된 TCP 처리를 구현한 것.
  • 웹 서버는 HTTP 프로토콜을 구현하고, 웹 리소스를 관리하고, 웹 서버 관리 기능을 제공한다.

5.2 간단한 펄 웹 서버

완벽한 기능을 갖춘 HTTP 서버를 만들려면 몇만 줄의 코드가 필요하지만 최소한의 기능의 HTTP 서버는 30줄 이하의 펄 코드로도 가능하다.

type-o-serve 펄 프로그램

  • 클라이언트와 프락시 간의 상호작용 테스트에 유용한 진단 툴

5.3 진짜 웹서버가 하는 일

최신식의 상용 웹서버들이 공통적으로 수행하는 일

  1. 커넥션을 맺는다. ==> 클라이언트의 접속을 받아들이거나, 원치 않는 클라이언트라면 닫는다.
  2. 요청을 받는다. ==> HTTP 요청 메시지를 네트워크로부터 읽어드린다.
  3. 요청을 처리한다. ==> 요청 메시지를 해석하고 행동을 취한다.
  4. 리소스에 접근한다. ==> 메시지에서 지정한 리소스에 접근한다.
  5. 응답을 만든다. ==> 올바른 헤더를 포함한 HTTP 응답 메시지를 생성한다.
  6. 응답을 보낸다. ==> 응답을 클라이언트에게 돌려준다.
  7. 트랜잭션을 로그로 남긴다. ==> 로그파일에 트랜잭션 완료에 대한 기록을 남긴다.

5.4 단계 1: 클라이언트 커넥션 수락

클라이언트가 이미 서버에 대해 열려있는 지속적 커넥션을 갖고 있다면 클라이언트는 요청을 보내기 위해 그 커넥션을 사용할 수 있다. 그렇지 않으면 새 커넥션을 열어야 한다.

5.4.1 새 커넥션 다루기

  • 클라이언트가 웹 서버에 TCP 커넥션을 요청하면, 웹 서버는 그 커넥션을 맺고 TCP 커넥션에 IP 주소를 추출하여 클라이언트를 확인한다.
  • 웹 서버는 어떤 커넥션이든 마음대로 거절하거나 닫을 수 있으므로 악의적인 의도가 있거나 인가되지 않는 커넥션을 닫을 수 있다.

5.4.2 클라이언트 호스트 명 식별

  • 대부분의 웹 서버는 역방향 DNS를 사용해 클라이언트의 IP주소를 클라이언트의 호스트명으로 변환하도록 설정되어 있다.
  • 호스트명 룩업은 많은 시간이 걸릴 수 있어 트랜잭션을 느려지게 할 수 있으므로 많은 대용량 웹 서버는 호스트 명 분석을 꺼두거나 특정 콘텐츠에만 켜놓는다.

아파치는 HostnameLookups 설정으로 호스트명 룩업을 켤 수 있다.

HostnameLookups off
<Files ~ "\.(html|htm|cgi)$">
  HostnameLookups on
</Files>

 

 

5.4.3 ident를 통해 클라이언트 사용자 알아내기

  • 몇몇 웹 서버는 IETF ident 프로토콜을 지원한다.
  • ident 프로토콜은 서버에게 어떤 사용자 이름이 HTTP 커넥션을 초기화했는지 찾아낼 수 있게 해 준다.
  • 웹서버 로깅에 유용하나 많은 클라이언트 PC가 ident 프로토콜 소프트웨어를 실행하지 않고 트랜잭션을 지연시킬 수 있는 등 문제가 있어 조직 내부에서 주로 사용한다.

5.5 단계 2: 요청 메시지 수신

커넥션에 데이터가 도착하면, 웹 서버는 네트워크 커넥션에서 그 데이터를 읽어 들이고 파싱 하여 요청 메시지를 구성한다.
요청 메시지 파싱 시 다음과 같은 일을 한다

  • 요청 줄을 파싱 하여 요청 메서드, URI, HTTP 버전을 찾는다.
  • 메시지 헤더를 읽는다. 각 헤더는 CRLF로 끝난다.
  • 헤더 끝을 의미하는 CRLF로 끝나는 빈 줄을 찾아낸다.
  • 요청 본문이 있으면 읽어 드린다.(길이는 Content-Length 헤더에 정의되어 있음)

요청 메시지를 파싱 할 때 웹 서버는 입력 데이터를 네트워크로부터 불규칙으로 받고 그 커넥션은 언제라도 무효화될 수 있으므로 메모리에 임시 저장해둘 필요가 있다

5.5.1 메시지 내부 표현

  • 몇몇 웹 서버는 요청 메시지를 쉽게 다룰 수 있도록 내부의 자료 구조에 저장한다.

5.5.2 커넥션 입력/출력 처리 아키텍처

  • 고성능 웹 서버는 수천 개의 커넥션을 동시에 열 수 있도록 지원한다.
  • 웹 서버들은 항상 새 요청을 주시하고 있다. 왜냐하면 요청은 언제라도 도착할 수 있기 때문이다.
  • 단일 스레드 웹서버 방식:한 번에 한 번의 요청을 처리하므로 트랜잭션이 완료되면 다음 커넥션을 처리하므로 처리 도중에 온 커넥션은 무시된다. 그러므로 로드가 작은 서버나 type-o-serve와 같은 진단 도구에서만 적당하다.
  • 멀티 프로세스와 멀티스레드 웹서버:여러 개의 프로세스나 고효율 스레드를 할당한다. 커넥션 마다 스레드를 할당하면 너무 많은 메모리나 시스템 리소스를 소비하므로 최대 개수에 제한을 건다.
  • 다중 I/O 서버:대량의 커넥션 처리를 위해 많은 웹서버가 선택한 방식이다. 모든 커넥션은 하나의 프로세스에 감시당하며 실제로 해야 할 일이 있을 때만 커넥션을 열어준다.
  • 다중 멀티스레드 웹 서버:멀티스레딩과 다중화를 결합한 방식

5.6 단계 3: 요청 처리

웹 서버가 요청을 받으면, 서버는 요청으로부터 메서드, 리소스, 헤더, 본문을 얻어내어 처리한다.
뒤 쪽에 많은 설명이 있을 것이므로 생략한다.

5.7 단계 4: 리소스의 매핑과 접근

웹 서버는 리소스 서버다. HTML 페이지나 JEPG 이미지 같이 미리 만들어진 콘텐츠를 제공하며, 마찬가지로 서버 위에서 동작하는 리소스 생성 앱을 통해 만들어진 동적 콘텐츠도 제공한다.

5.7.1 Docroot

  • 웹 서버는 여러 종류의 리소스 매핑을 지원한다.
  • 가장 단순한 요청은 URI에 파일 이름을 넣어 요청하는 것이다.
  • 일반적으로 웹 서버 파일 시스템의 특별한 폴더를 웹 콘텐츠를 위해 예약해두는데 이 폴더를Docroot라고부른다.
  • DocumentRoot /usr/local/httpd/files 이런 식으로 httpd.conf 설정 파일에 문서 루트를 설정할 수 있다.

가상 호스팅 된 docroot
가상 호스팅 웹서버는 아래와 같이 VirtualHost 설정을 통해 docroot를 설정할 수 있다.www.asd.com에접속하면 /docs/asd/index.html을 보여줄 것이고
www.qwe.com에접속하면 /docs/qwe/index.html을 보여줄 것이다.

<VirtualHost www.asd.com>
  ServerName www.asd.com
  DocumentRoot /docs/asd
  TransferLog /logs/asd.access_log
  ErrorLog /logs/asd.error_log
</VirtualHost>

<VirtualHost www.qwe.com>
  ServerName www.qwe.com
  DocumentRoot /docs/qwe
  TransferLog /logs/qwe.access_log
  ErrorLog /logs/qwe.error_log
</VirtualHost>

 

 

5.7.2 디렉터리 목록

  • 웹서버는 경로가 파일이 아닌 디렉터리를 가리키는 URL 요청을 받을 수 있다.
  • 그 경우 보통 다음과 같은 행동을 취한다.
    • 에러를 반환한다.
    • 디렉터리 대신 특별한 '색인 파일'을 반환한다.
    • 디렉터리를 탐색해서 그 내용을 담은 HTML 페이지를 반환한다.
    • 보통 그 디렉터리 안의 index.html을 반환한다.
    • DirectoryIndex index.html home.html ==> 이런 식으로 설정이 가능하다.
    • Options -Indexes를 통해 디렉터리 색인 파일 자동 생성을 끌 수도 있다.

5.7.3 동적 콘텐츠 리소스 매핑

  • 웹서버는 URI를 동적 리소스에 매핑할 수 있다.
  • ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-programs/ ==> 이런 식으로 동적 매핑이 가능하다.
  • /cgi-bin/으로 경로가 시작하면 뒤쪽의 경로의 프로그램을 찾아 실행하라는 뜻이다.
  • AddHandlercgi-script .cgi==> 핸들러를 통해 특정 확장자의 파일만 실행하도록 설정할 수 있다.
  • CGI는 웹 초장기에 쓰였던 서버사이드 애플리케이션을 실행하기 위한 간단한 인터페이스로 오늘날은 마이크로소프트의 액티브 서버 페이지와 자바 서블릿과 같은 한층 더 강력하고 효과적인 서버사이드 동적 콘텐츠 지원 기능을 갖고 있다.

5.7.4 서버사이드 인클루드(Server-Side Includes, SSI)

  • 많은 웹서버가 SSI를 지원한다.
  • 만약 어떤 리소스가 SSI를 포함하고 있으면 서버는 그 리소스의 콘텐츠를 클라이언트에게 보내기 전에 처리한다.

5.7.5 접근제어

  • 웹 서버는 또한 각각의 리소스에 접근 제어를 할당할 수 있다.

5.8 단계 5: 응답 만들기

한번 서버가 리소스를 식별하면, 서버는 요청 메서드로 서술되는 동작을 수행한 뒤 응답 메시지를 반환한다. 응답 메시지는 응답 상태 코드, 응답 헤더, 응답 본문 등을 포함한다.

5.8.1 응답 엔티티

  • 만약 트랜잭션이 응답 본문을 생성하면 그 내용을 응답 메시지와 함께 돌려보낸다. 본문이 있을 경우 주로 다음을 포함시킨다
  • Content-Type 헤더(응답 본문의 MIME 타입을 서술)
  • Content-Length 헤더 (응답 본문의 길이를 서술)
  • 실제 응답 본문 내용

5.8.2 MIME 타입 결정하기

  • 웹 서버에게는 응답 본문의 MIME 타입을 결정해야 하는 책임이 있다.
  • MIME 타입과 리소스를 연결하는 여러 가지 방법들이 있다.
  • mime.types:파일 확장자를 통해 파일을 탐색하는 방법으로 가장 흔한 방법이다.
  • 매직 타이핑(Magic typing):파일 내용을 검사해서 알려진 패턴에 대한 테이블(매직 파일)에 해당하는 패턴이 있는지 검사하여 타입을 결정한다. 표준 확장자가 없을 경우 유용하다.
  • 유형 명시(Explicit typing):유형을 명시하면 확장자나 내용에 상관없이 어떤 MIME 타입을 갖도록 웹 서버를 설정할 수 있다.
  • 유형 협상(Type negotiation):웹 서버는 한 리소스가 여러 종류의 문서 형식에 속하도록 설정할 수 있다.

5.8.3 리다이렉션

  • 웹 서버는 종종 성공 메시지 대신 리다이렉션 응답을 반환한다.
  • 리다이렉션 응답은 3XX 상태 코드로 지칭된다.
  • Location 응답 헤더는 콘텐츠의 새로운 혹은 선호하는 위치에 대한 URI를 포함한다.
  • 리다이렉트의 유용한 부분들
    • 영구히 리소스가 옮겨진 경우: 301(Moved Permanently) 상태 코드를 사용
    • 임시로 리소스가 옮겨진 경우: 임시적이므로 서버는 클라이언트가 나중에 원래 URL로 찾아올 수 있도록 북마크를 갱신하지 않기를 원한다. 303(See Other), 307(Temporary Redirect) 상태 코드가 주로 이럴 때 사용된다.
    • URL 증강: 303, 307 상태 코드를 사용하며 보통 상태 정보를 내포한 채 새 URL을 생성하는 것
    • 부하 균형: 과부하된 서버 요청을 받으면 부하가 적은 서버로 리다이렉트 시켜주는 것으로 303, 307을 사용한다.
    • 친밀한 다른 서버가 있을 때: 이 또한 303, 307을 주로 사용한다.
    • 디렉터리 이름 정규화: 클라이언트가 / 를 빠뜨렸다면 대부분 웹서버는 정상적으로 동작할 수 있도록 /를 붙인 URL로 리다이렉트 해준다.

5.9 단계 6: 응답 보내기

웹 서버는 받을 때와 마찬가지로 커넥션 너머로 데이터를 보낼 때도 비슷한 이슈에 직면한다. 서버는 여러 클라이언트의 커넥션을 가질 수 있다. 그들 중 일부는 아무것도 하지 않고, 일부는 데이터를 요청하고 있고, 일부는 응답 데이터를 전송하고 있을 것이다.
그러므로 서버는 커넥션 상태를 추적해야 하며 지속적인 커넥션은 특별히 주의해서 다룰 필요가 있다. 비지속적인 커넥션이라면, 서버는 모든 메시지를 전송했을 때 자신 쪽의 커넥션을 닫을 것이다.

5.10 단계 7: 로깅

마지막으로 트랜잭션이 완료되었을 때 웹 서버는 트랜잭션이 어떻게 수행되었는지에 대한 로그를 로그파일에 기록한다.

5.11 추가 정보

Apache: The Definitive Guide
Professional Apache
http://www.w3c.org/Jigsaw/
http://www.ietf.org/rfc/rfc1413.txt