본문 바로가기

CS/네트워크

[HTTP] 05. 웹 서버

이 포스팅은 "HTTP-완벽 가이드" 책을 학습하고 정리한 것입니다.

https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=49731592

 

HTTP 완벽 가이드

HTTP 규약이 어떻게 동작하고 웹 기반 애플리케이션을 개발하는 데 어떻게 사용하는지 설명한다. 하지만 이 책은 단순히 HTTP에 대해서만 다루지는 않는다. HTTP가 효율적으로 동작하도록 함께 사

www.aladin.co.kr

 

 

 

 


 

 

 

5.1 다채로운 웹 서버

 웹 서버는 HTTP 요청을 처리하고 응답을 제공하는 서버를 말한다. ‘웹 서버’라는 용어는 웹 서버 소프트웨어와 웹페이지 제공에 특화된 장비(ex. 컴퓨터) 양쪽 모두를 가리킨다. 웹 서버마다 기능은 다르더라도, 리소스에 대한 HTTP 요청을 받아서 콘텐츠를 클라이언트에게 돌려준다는 점에서 동일하다.

5.1.1 웹 서버 구현

웹 서버는 HTTP 및 그와 관련된 TCP 처리를 구현한 것이다. 웹 서버는 자신이 제공하는 리소스를 관리하고 웹 서버를 설정, 통제, 확장하기 위한 관리 기능을 제공한다. TCP 커넥션 관리에 대해서는, 운영체제와 책임을 나눠 갖는다.

  • 다목적 소프트웨어 웹 서버 : 네트워크에 연결된 표준 컴퓨터 시스템에서 동작. (ex. 아파치, nginx)
  • 임베디드 웹 서버 : 일반 소비자용 제품에 내장될 목적으로 만들어진 작은 웹 서버. (ex. 프린터나 가전제품). 관리용 인터페이스 목적.

 

5.3 진짜 웹 서버가 하는 일

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

 

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

 

 클라이언트가 웹 서버에 TCP 커넥션을 요청하면, 웹 서버는 그 커넥션을 맺고 TCP 커넥션에서 IP 주소를 추출하여 커넥션 맞은편에 어떤 클라이언트가 있는지 확인한다. 웹 서버는 새 커넥션을 커넥션 목록에 추가하고, 요청을 기다린다. 모든 클라이언트와 커넥션을 맺는 거은 아니며, 비인가된 클라이언트일 경우 커넥션을 맺지 않을 수도 있다.

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

 대부분의 웹 서버는 ‘역방향 DNS(reverse DNS)’를 사용해서 클라이언트의 IP 주소를 클라이언트의 호스트 명으로 변환하도록 설정되어 있다. 그러나 웹 트랜잭션을 느려지게 할 수 있어, 호스트명 분석을 꺼두거나, 특정 컨텐츠에 대해서만 켜놓기도 한다.

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

 몇몇 웹 서버는 IETF ident 프로토콜을 지원한다. ident 프로토콜은 서버에게 어떤 사용자 이름이 HTTP 커넥션을 초기화했는지 찾아낼 수 있게 한다. 웹 서버는 클라이언트에게 ident 요청을 전달하여, 클라리언트의 정보를 얻는다.

다만, 조직 내부가 아닌 경우에는 잘 사용하지 않는 것으로 보인다.

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

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

  • 요청 메시지의 시작줄을 파싱하여 메서드, URI, HTTP 버전 번호를 찾는다. 각 부분은 “ “로 구분되며, 마지막 끝은 CRLF로 끝난다.
  • 메시지 헤더를 읽는다. 마찬가지로 CRLF로 끝난다.
  • 헤더의 끝을 의미하는 CRLF로 되있는 빈 줄을 찾는다.(없을 수도 있다)
  • 요청의 본문을 읽어 들인다.

 네트워크 커넥션은 언제라도 끊어질 수 있기 때문에, 웹 서버는 파싱해서 이해가 가능해질 때 까지, 입력 받은 데이터를 메모리에 임시로 저장해둘 필요가 있다.

5.5.1 메시지의 내부 표현

 몇몇 웹 서버는 메시지의 각 부분을 내부 자료구조에 저장하여 관리한다. 요청 메시지에 대한 각 조각을 포인터와 길이를 담을 수 있는 구조에 저장한다. 헤더의 경우 빠른 조회를 위해 룩업테이블에 저장한다.

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

  • 단일 스레드 웹 서버(a) : 한 번에 하나씩 요청을 처리한다. 구현하기 간단하지만, 처리 도중에 들어오는 다른 커넥션들은 무시된다.
  • 멀티프로세스와 멀티스레드 웹 서버(b) : 여러 요청을 동시에 처리하기 위해 여러 개의 프로세스 혹은 고효율 스레드를 할당한다. 스레드/프로세스는 필요할 때 만들어질 수도 있고, 미리 만들어질 수도 있다(이를 작업자 풀(worker pool) 시스템이라고 한다.) 많은 멀티스레드 웹 서비스는 스레드/프로세스의 최대 개수에 제한을 건다.
  • 다중 I/O 서버(c) : 모든 커넥션은 동시에 그 활동을 감시당한다. 커넥션에서의 동작이 탐지되면, 처리가 수행되고, 이후 다음번 상태 변경을 위해 열린 커넥션 목록으로 돌아간다. 이를 통해, 유휴 상태의 커넥션에 매여 기다리느라 리소스를 낭비하는 것을 방지한다.
  • 다중 멀티스레드 웹 서버 : CPU 여러 개의 이점을 살리기 위해 멀티스레딩과 멀티플렉싱을 결합한다. 여러 개의 스테드는 각각 열려있는 커넥션을 감시하고 작업을 수행한다.

 

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

 

 웹 서버는 기본적으로 리소스 서버이므로, 요청 메시지의 URI에 대응하는 컨텐츠를 찾아서 제공해야 한다.

5.7.1 Docroot

 웹 서버는 여러 종류의 리소스 매핑을 지원한다. 그 중 가장 간단한 형태는, 요청 URI를 파일 시스템 안에 있는 파일 이름으로 사용하는 것이다. 이 때 root 폴더가 되는 폴더를 docroot라고 부른다.

 예를 들어, docroot가 “/home/files” 일때, 아래 요청에 대한 리소스는 “/home/files/saw-blade.git”에 매핑된다.

GET /saw-blade.gif HTTP/1.1
Host : localhost

 아파치에서는 httpd.conf 설정파일을 수정하여 docroot를 지정할 수 있다.

DocumentRoot와 관련하여, 서로다른 호스트명을 하나의 웹 서버에서 동시에 지원하는 방법도 가능하다.

5.7.2 디렉토리 목록

경로가 파일(/home/home.html)이 아닌 디렉토리(/home)을 가리키는 요청을 받을 수 있다. 이 경우 웹 서버는 다음과 같이 반응하도록 설정할 수 있다.

  • 에러 반환
  • 디렉토리 대신, 특별한 색인 목록 반환
  • 디렉토리에 속한 파일 리스트를 담은 HTML 페이지 반환

대부분의 웹 서버에서는 해당 디렉토리에서 index.html 파일이 있는지 확인한다. 만약, 기본 thml 파일을 변경하려면 DirectoryIndex 설정 지시자를 사용할 수 있다. 아파치에서는 index.html을 기본으로 설정하고 있다.

 

5.8 단계 5 : 응답 만들기

 응답 메시지는 ‘응답 상태 코드’, ‘응답 헤더’, ‘응답 본문(생성되었다면)’을 포함한다.

5.8.1 응답 엔터티

 응답 메시지에 본문이 포함되있다면 응답 메시지는 아래 내용을 주로 포함한다.

  • 응답 본문의 MIME 타입을 서술하는 Content-Type 헤더
  • 응답 본문의 길이를 서술하는 Content-Length 헤더
  • 실제 응답 본문의 내용

5.8.2 MIME 타입 결정하기

 웹 서버에게는 응답 본문의 MIME 타입을 결정해야 하는 책임이 있다.

  • mime.types : 아래 이미지는 아파치의 mime.types 파일이다. 웹 서버는 해당 파일에 있는 파일 확장자를 보고 MIME type을 결정할 수 있다.

  • 매직 타이핑 : 이 방식은 웹 서버에서 직접 파일의 내용을 검사해서, 패턴을 파악하고 해당 패턴과 매핑되는 MIME type을 결정하는 방식이다. 아래 이미지는 아파치의 magic 파일의 내용 중 일부이다.
  • 그 외에는 유형 명시(특정 디렉토리 하위 파일들을 모두 동일한 MIME type으로 명시), 유형 협상(클라이언트가 사용하기 좋은 형식으로 MIME type을 설정하도록, 클라이언트와 협상하여 결정)하는 방식이 있다.

5.8.3 리다이렉션

웹 서버는 종종 성공 메시지 대신 리다이렉션 응답을 반환한다. 리다이렉션 응답은 3xx의 상태 코드로 지칭되며, Location 응답 헤더에 옮겨지길 원하는 URI가 담겨진다. 리다이렉션이 발생하는 경우는 다음과 같다.

  • 영구히 리소스가 옮겨진 경우 : 리소스가 새 URL이 부여되어 위치가 옮겨지거나 이름이 바뀌었을 수 있다. 이때는 301 상태코드를 사용한다.
  • 임시로 리소스가 옮겨진 경우 : 말 그대로 임시로 옮겨졌을 수 있다. 서버는 해당 리소스의 URL에 대해 영구적인 변경을 원치 않기 때문에 303 or 307 상태코드를 사용한다.
  • URL 증강 : 클라이언트가 요청한 URL에 추가적인 정보를 부여하여 새 URL을 만들고 싶을 때 사용한다. 303 or 307 상태코드를 사용한다.
  • 부하 균형 : 만약 과부하된 서버가 요청을 받으면, 웹 서버는 클라이언트에게 좀 덜 부하가 걸린 서버로 리다이렉트할 수 있다. 303 or 307 상태코드를 사용한다.
  • 친밀한 다른 서버가 있을 때 : 클라이언트의 정보를 다루고 있는 다른 서버가 존재할 경우, 웹 서버는 해당 서버로 클라이언트를 리다이렉트한다. 303 or 307 상태코드를 사용한다.
  • 디렉토리 이름 정규화 : 클라이언트가 실수로 URL 경로에 “/”를 빼먹을 수 있다. 상대경로가 정상적으로 동작할 수 있게 URL을 변경하여 새 URL로 리다이렉트한다. 303 or 307 상태코드를 사용한다.

 

5.9 단계 6 : 응답 보내기

 

 웹 서버는 커넥션 상태를 추적해야 하며 지속적인 커넥션은 특별히 주의해서 다룰 필요가 있다. 비지속 커넥션이라면, 서버는 모든 메시지를 전송했을 때 자신쪽의 커넥션을 닫을 것이다. 지속적인 커넥션이라면, 서버가 Content-Length 헤더를 바르게 계산하기 위해 특별한 주의를 필요로 하는 경우나, 클라이언트가 응답이 언제 끝나는지 알 수 없는 경우에, 커넥션은 열리 상태를 유지할 것이다.

 

'CS > 네트워크' 카테고리의 다른 글

[HTTP] 07. 캐시 (1)  (0) 2024.01.07
[HTTP] 06. 프락시  (2) 2024.01.07
[HTTP] 04. 커넥션 관리  (2) 2024.01.05
[HTTP] 03. HTTP 메시지  (0) 2024.01.02
[HTTP] 02. URL과 리소스  (0) 2024.01.02