[HTTP 완벽 가이드] 5. 웹 서버

Jinyongmin·2024년 8월 4일

HTTP 완벽 가이드

목록 보기
5/5
post-thumbnail

이 글은 'HTTP 완벽 가이드' 책을 읽고 정리한 내용입니다.

[이번 장에서]

  • 여러 종류의 소프트웨어 및 하드웨어 웹 서버에 대해 조사한다.
  • 어떻게 웹 서버가 HTTP 트랜잭션을 처리하는지 단계별로 설명한다.

다채로운 웹 서버

[웹 서버의 역할]

  • 웹 서버는 HTTP 요청을 처리하고 응답을 제공한다.
  • 웹 서버는 자신이 제공하는 리소스를 관리하고 웹 서버를 설정, 통제, 확장하기 위한 관리 기능을 제공한다.

아파치 톰캣?

  • 아파치(Apache)
    • 웹 서버 프로그램 - 오픈 소스 소프트웨어
  • 톰캣 WAS(web application server)
    • JSP와 Servlet을 구동하기 위한 서블릿 컨테이너 역할 수행
    • 아파치 서버와는 다르게 DB연결, 다른 응용프로그램과 상호 작용 등 동적인 기능들을 사용할 수 있다.
  • 아파치 톰캣이라고 불리는 이유가 뭐지?

  • 기본적으로 위처럼 아파치와 톰캣의 기능은 나뉘어져 있지만, 톰캣 안에 있는 컨테이너를 통해 일부 아파치의 기능을 발휘하기 때문에 보통 아파치 톰캣으로 합쳐서 부르곤 한다.
  • 참고 블로그

임베디드 웹 서버

  • 일반 소비자용 제품에 내장될 목적으로 만들어진 작은 웹 서버(프린터, 가전제품)
  • 일반 소바자용 기기를 웹 브라우저 인터페이스로 관리할 수 있게 해준다.

웹 서버가 하는 일

  1. 커넥션을 맺는다 : 클라이언트의 접속 허용 및 차단
  2. 요청을 받는다 : HTTP 요청 메세지를 읽기
  3. 요청을 처리한다 : 요청 메세지 해석 및 처리
  4. 리소스에 접근한다 : 메세지에서 지정한 리소스에 접근
  5. 응답을 만든다 : HTTP 응답 메세지 생성
  6. 응답을 보낸다 : 클라이언트에게 응답 반환
  7. 트랜잭션을 로그로 남긴다 : 로그파일에 트랜잭션 완료에 대한 기록

1. 클라이언트 커넥션 수락

웹 서버가 클라이언트의 커넥션을 수락하는 단계

지속적 커넥션이 있다면 해당 커넥션으로 요청이 가능하고 없다면 새로운 커넥션을 열어야 한다.

새 커넥션 다루기

  1. 클라이언트의 TCP 커넥션 요청
  2. 웹 서버의 TCP 커넥션 수락 및 클라이언트 IP 확인
  3. 웹 서버의 데이터 수신 대기
  • 웹 서버는 어떤 커넥션이든 마음대로 거절하거나 즉시 닫을 수 있다.
    • 클라이언트 IP 주소 혹은 호스트 명이 인가되지 않은 경우

웹 서버의 클라이언트 식별

역방향 DNS

  • 클라이언트의 IP에 해당하는 도메인이 있는지 검사하는 과정으로 호스트 명을 반환하여 확인한다.
  • IP -> 도메인 (정방향으로는 도메인 -> IP 이다.)
  • 웹 서버는 클라이언트 호스트 명을 구체적인 접근 제어, 로깅을 위해 사용할 수 있다.
  • 호스트 명 룩업은 시간이 많이 걸려 트랜잭션을 느력지게 할 수 있다.

IETF ident 프로토콜

  • 서버에게 어떤 사용자 이름이 HTTP 커넥션을 초기화 했는지 찾아낼 수 있게 해준다.

한마디로, TCP 커넥션 이후 ident 커넥션을 열어 웹서버가 클라이언트의 정보를 요청하는 과정을 통해 클라이언트 정보를 얻는다.

ident는 조직 내부에서는 잘 사용 가능하지만, 공용 네트워크에서는 여러가지 이유로 잘 동작하지 않는다.

  • ident는 HTTP 트랜잭션을 유의미하게 지연시킨다.
  • 방화벽이 ident 트래픽이 들어오는 것을 막는 경우가 많다.

2. 요청 메세지 수신

커넥션 데이터를 읽고 파싱하여 요청 메세지를 구성하는 단계

웹 서버의 요청 메세지 파싱

  • 요청줄을 파싱하여 요청 메서드, URL, 버전 번호(프로토콜) 정보를 읽는다.
  • CRLF를 기준으로 각 헤더와 본문의 내용을 읽는다.

요청 메세지 파싱 과정에서 입력 데이터를 불규칙적으로 받기 때문에 커넥션이 무효화 될 수 있다.

  • 웹 서버는 파싱해서 이해 가능한 수준을 확보할때까지 메세지 일부를 메모리에 저장해둘 필요가 있다.

위 사진과 같이 요청 메세지에서 정보를 내부 자료 구조에 따라 저장한다.

  • 이는 요청 메세지를 쉽게 다루기 위한 웹 서버의 기능이다.

커넥션 I/O 처리 아키텍처

클라이언트로부터 동시에 들어오는 수많은 커넥션 요청을 처리하기 위해 4가지 아키텍처가 있다.

1. 단일 스레드 웹서버

  • 한번에 하나의 요청을 처리하며 트랜잭션 완료후, 다음 커넥션을 처리한다.
  • 처리 과정 중 다른 커넥션은 무시된다.

2.멀티 프로세스와 멀티 스레드 웹 서버

  • 여러개의 프로세스 혹은 스레드가 여러 요청을 동시에 처리한다.
  • 프로세스/스레드는 미리 만들어 질 수 있고 매 커넥션마다 한개를 할당한다.
    + 너무 많이 생성될 경우 리소스를 많이 소비하기 때문에 최대 개수 제한을 건다.
    3. 다중 I/O 서버
  • 많은 커넥션을 처리하기 위해 대부분의 웹 서버가 해당 아키텍처를 채택
  • 모든 커넥션의 활동을 감시해 상태가 바뀔때(데이터 사용가능 및 에러 발생) 작은 양의 처리를 수행한다.
  • 처리 완료 후, 상태 변경을 위해 '열린 커넥션 목록'으로 돌아가 다시 차례를 기다린다.

4. 다중 멀티스레드 웹 서버

  • 멀티 스레딩과 다중화를 결합한 경우로 여러 개의 CPU의 이점을 살릴 수 있다.
  • 여러 개의 스레드가 각 열려있는 커넥션을 감시하고 조금씩 작업을 수행한다.

3. 요청 처리

웹 서버가 받은 요청을 메서드, 리소스, 헤더, 본문을 얻어 처리하는 단계

  • 요청 메서드에 따라 엔터티 본문이 있을 것을 요구한다.(POST, OPTIONS 등은 허용하되 요구하진 않음)

4. 리소스의 매핑과 접근

HTML 페이지, JPEG 와 같은 정적 콘텐츠 및 서버 위에서 동작하는 생성 애플리케이션을 통해 만들어진 동적 콘텐츠를 제공

Docroot

요청 URL을 웹 서버의 파일 시스템 안에 있는 파일 이름으로 사용하는 것으로 웹 콘텐츠를 위해 예약해둔 특별한 폴더를 문서 루트 혹은 docroot라고 한다.

요청 URL : /specials/saw-blade.gif
docroot : /usr/local/httpd/files

웹 서버의 반환 : /usr/local/httpd/files/specials/saw-blade.gif

  • 서버는 상대적인 url이 docroot를 벗어나 docroot 이외 부분이 노출되는 일이 생기지 않도록 주의해야한다.

가상 호스팅된 docroot

분리된 docroot를 주는 방법으로 하나의 웹 서버 위에 두 개의 사이트가 완전히 분리된 콘텐츠를 갖고 호스팅 되도록 할 수 있다.

요청에 따라 다른 docroot를 통해 다른 파일을 반환할 수 있다.
요청 A : /docs/joe/index.html
요청 B : /docs/marry/index.html

사용자 홈 디렉터리 docroot

사용자들이 하나의 웹 서버에서 개인 웹 사이트를 만들 수 있도록 해주는 것

  • **/~(사용자 이름)/index.html"
  • 개인 docroot는 주로 사용자의 홈 디렉터리 안에 있는 public_html로 불리는 디렉터리이다.(설정에 따라 다를 수 있다.)

[파일이 아닌 디렉터리를 가리키는 경로에 대한 요청]
일반적으로 서버는 다음과 같은 행동을 취한다.
1. 에러 반환
2. 디렉터리 대신 특별한 '색인 파일' 반환
3. 디텍터리 탐색 후 그 내용을 담은 HTML 페이지 반환

  • 아파치에선 DirectoryIndex 설정을 통해 기본 디렉터리 파일로 사용될 파일 이름 집합을 설정할 수 있다.
    • 이에 따라 나열된 파일 중 하나를 반환하게 되는 것
  • 하지만, 2,3번과 같이 할 경우, 일반적으로 발견할 수 없는 파일이 드러날 수 있기 때문에 해당 기능을 끌 수 있다.

[동적 콘텐츠 리소스 매핑]
웹 서버는 URL을 요청에 맞게 콘텐츠를 생성하는 프로그램에 매핑할 수 있다.

  • 아파치는 서버가 실행 가능한 경로명을 포함한 URL로 요청을 받으면, 그 경로에 대응하는 디렉터리에서 프로그램을 찾아 실행하려 시도한다.
  • 특정 확장자의 파일만 실행하도록 설정이 가능하다.

많은 웹 서버가 서버사이드 인클루드도 지원하고 이는 '#include' 지시문을 사용하여 하나 이상의 파일 내용을 웹 서버의 웹 페이지에 포함 시키는데 유용하다. (참고)
서버는 콘텐츠에 변수 이름, 내장된 스크립트가 될 수 있는 특별한 패턴이 있는지 검사 받고 이는 변수 값, 실행 가능한 스크립트의 출력 값으로 치환된다. 이는 동적 콘텐츠를 만드는 쉬운 방법이다.
(코드 상에서 변수 이름과 같이 선언된 것을 값으로 치환하여 클라이언트에게 제공한다는 의미인 것 같다.)
(동적 콘텐츠란 DB 상태에 따라 다르게 출력이 되는 콘텐츠 같은 것을 의미)

5. 응답 만들기

서버가 리소스 식별 후, 요청 메서드로 서술되는 동작을 수행한 뒤 응답 메세지를 반환하는 단계

  • 응답 메세지의 구성요소
  1. 응답 상태 코드
  2. 응답 헤더
  3. 응답 본문(있다면)

응답 본문이 있다면 다음과 같은 내용을 포함한다.

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

MIME 타입 결정

MIME 타입과 리소스를 연결하는 여러 가지 방법은 다음과 같다.
(MIME는 미디어 타입으로 문서, 파일, 바이트 집합의 특징을 나타내는 것이다.)

mime.types

  • 확장자별 MIME 타입이 담겨 있는 파일을 탐색하여 리소스의 타입을 계산

매직 타이핑(Magic typing)

  • 아파치 웹 서버는 파일의 내용을 검사해 알려진 패턴에 대한 테이블에 해당하는 패턴이 있는지 찾아 결정할 수 있다.
  • 느리지만 파일이 표준 확장자 없이 이름이 지어진 경우에는 특히 편리하다.

유형 명시(Explicit typing)

  • 특정 파일, 디렉터리 안의 파일들이 확장자나 내용에 상관없이 어떤 MIME 타입을 갖도록 웹 서버를 설정할 수 있다.

유형 협상(Type negotiation)

  • 한 리소스가 여러 종류의 문서 형식에 속하도록 설정하는 것으로 서버가 사용자와 협상 과정을 통해 사용하기 가장 좋은 형식을 판별한 것인지 여부도 설정이 가능하다.
  • 웹 서버는 특정 파일이 특정 MIME 타입을 갖게끔 설정할 수도 있다.

리다이렉션

요청을 수행하기 위해 종종 다른 브라우저로 가도록 리다이렉트 할 수 있다.

  • 응답 코드 : 3XX

다음과 같은 상황에서 유용하다.

  • 영구적으로 리소스가 옮겨진 경우
  • 임시로 리소스가 옮겨진 경우
  • URL 증강 - 문맥 종보를 포함시키기 위해 재 작성된 URL로 리다이렉트
  • 부하 균형 - 과부화된 서버에 대한 요청을 다른 서버로 리다이렉트(좀 더 자세히 공부해야 할 부분인 것 같다.)
  • 디렉터리 이름 정규화
    • 클라이언트가 URL 요청 시 빗금('/')을 빠뜨렸다면, 대부분의 웹 서버는 상대경로가 정상적으로 동작할 수 있도록 빗금('/')을 추가한 URL로 리다이렉트한다.

6. 응답 보내기

서버가 생성한 응답을 클라이언트로 보내는 단계

  • 서버는 여러 커넥션을 맺고 있기 때문에 커넥션 상태를 추적해야한다.
    • 지속 커넥션이라면 특별히 주의해서 다뤄야한다.(Content-Length 헤더를 바르게 계산해야한다.)
    • 비지속 커넥션이라면 모든 메세지 전송 후 커넥션을 닫아야한다.

7. 로깅

트랜잭션이 완료되었을 때 트랜잭션이 어떻게 수행되었는지에 대한 로그를 로그파일에 기록하는 단계
(자세한 내용은 21장에서 다룬다.)

0개의 댓글