웹 서버
웹 서버는 HTTP 요청을 처리하고 응답을 제공합니다.
1. 공통적으로 웹 서버가 하는 일
- 커넥션 맺기
- 요청 받기
- 요청 처리
- 리소스 접근
- 응답 만들기
- 응답 보내기
- 트랜잭션을 로그로 남기기
1.1 커넥션 맺기
클라이언트가 이미 서버에 대해 열려있는 지속적 커넥션을 갖고 있다면, 클라이언트는 요청을 보내기 위해 그 커넥션을 사용할 수 있습니다.
그렇지 않다면, 클라이언트는 서버에 대한 새 커넥션을 열어야 합니다.
1.1.1 새 커넥션 다루기
클라이언트가 웹 서버에 TCP 커넥션을 요청하면, 웹 서버는 그 커넥션을 맺고 TCP 커넥션에서 IP 주소를 추출하여 커넥션 맞은편에 어떤 클라이언트가 있는지 확인합니다.
일단 새 커넥션이 맺어지고 받아들여지면, 서버는 새 커넥션을 커넥션 목록에 추가하고 커넥션에서 오가는 데이터를 지켜보기 위한 준비를 합니다.
웹 서버는 어떤 커넥션이든 마음대로 거절하거나 즉시 닫을 수 있습니다.
그래서 어떤 웹 서버들은 클라이언트의 IP 주소나 호스트 명이 인가되지 않았거나 악의적이라고 알려진 것인 경우 커넥션을 닫습니다.
1.2 요청 받기
커넥션에 데이터가 도착하면, 웹 서버는 네트워크 커넥션에서 그 데이터를 읽어 들이고 파싱하여 요청 메시지를 구성합니다.
요청 메시지를 파싱할 때, 웹 서버는 다음과 같은 일을 합니다.
- 요청줄을 파싱하여 요청 메서드, 지정된 리소스의 식별자(URI), 버전 번호를 찾습니다.
- 메시지 헤더들을 읽습니다.
- 헤더의 끝을 의미하는 CRLF로 끝나는 빈 줄이 있다면 찾아냅니다.
- 요청 본문이 있다면, 읽어 들입니다.(길이는 Content-Length 헤더로 정의)
요청 메시지를 파싱할 때, 웹 서버는 입력 데이터를 네트워크로부터 불규칙적으로 받습니다.
네트워크 커넥션은 언제라도 무효화될 수 있기 때문에, 웹 서버는 파싱해서 이해하는 것이 가능한 수준의 분량을 확보할 때까지 데이터를 네트워크로부터 읽어서 메시지 일부분을 메모리에 임시로 저장해 둘 필요가 있습니다.
1.2.1 메시지의 내부 표현
몇몇 웹 서버는 요청 메시지를 쉽게 다룰 수 있도록 내부의 자료 구조에 저장합니다.
예를 들어, 헤더는 속도가 빠른 룩업 테이블에 저장되어 각 필드에 신속하게 접근할 수 있습니다.
1.2.2 커넥션 입력/출력 처리 아키텍처
커넥션 입출력 처리 아키텍처는 다음과 같이 있습니다.
a) 단일-스레드 I/O 아키텍처
한 번에 하나씩 요청을 처리합니다.
즉, 현재 커넥션의 트랜잭션이 완료되어야 다음 커넥션이 처리됩니다.
이 아키텍처는 구현이 간단하지만 심각한 성능 문제를 만듭니다.
b) 멀티스레드 I/O 아키텍처
멀티 스레드로 여러 요청을 한번에 처리합니다.
즉, 매 커넥션마다 스레드 하나를 할당하여, 여러 커넥션을 동시에 처리합니다.
이 아키텍처는 많은 수의 커넥션을 동시에 처리하게 되면, 너무 많은 메모리나 시스템 리소스를 소비합니다.
그렇기에 스레드의 최대 개수에 제한을 둡니다.
c) 다중 I/O 아키텍처
다중 아키텍처에서는 모든 커넥션은 동시에 그 활동을 감시당합니다.
커넥션의 상태가 바뀌면, 그 커넥션에 대해 작은 양의 처리가 수행됩니다.
그 처리가 완료되면, 커넥션은 다음번 상태 변경을 위해 열린 커넥션 목록으로 돌아갑니다.
이로써, 스레드는 유휴 상태의 커넥션에 매여 기다리느라 리소스를 낭비하지 않습니다.
※ 커넥션의 효율이 높아진다고 보시면 될 것 같습니다.
d) 다중, 멀티스레드 I/O 아키텍처
멀티스레딩과 다중화를 결합한 것입니다.
1.3 요청 처리
웹 서버가 요청을 받으면, 서버는 요청으로부터 메서드, 리소스, 헤더, 본문을 얻어내어 처리합니다.
1.4 리소스의 매핑과 접근
웹 서버는 리소스 서버입니다.
웹 서버가 클라이언트에 콘텐츠를 전달하려면, 요청 메시지의 URI에 대응하는 알맞은 콘텐츠나 콘텐츠 생성기를 웹 서버에서 찾아서 그 콘텐츠의 원천을 식별해야 합니다.
웹 서버는 여러 종류의 리소스 매핑을 지원합니다.
- Docroot : 가장 단순한 형태로 요청 URI를 웹 서버의 파일 시스템 안에 있는 파일 이름으로 사용하는 것입니다.
- 디렉토리 목록 : 파일 이름이 아닌 디렉토리 이름을 사용함으로써 디렉토리 안에 있는 특별한 색인 파일을 반환합니다.
- 동적 콘텐츠 리소스 매핑 : 콘텐츠를 생성하는 프로그램에 URI를 매핑하는 것입니다.
- 서버사이드 인클루드(SSI) : 리소스의 콘텐츠를 클라이언트에게 보내기 전에 처리합니다.
웹 서버는 각각의 리소스에 접근 제어를 할당 할 수 있습니다.
1.5 응답 만들기
서버는 요청 메서드로 서술되는 동작을 수행한 뒤 응답 메시지를 반환합니다.
응답 메시지는 응답 상태 코드, 응답 헤더, 그리고 응답 본문(있다면)을 포함합니다.
1.6 응답 보내기
만들어진 응답 메시지를 커넥션 너머로 데이터를 보냅니다.
웹 서버는 종종 성공 메시지 대신 리다이렉션 응답을 반환합니다.
리다이렉트는 다음의 경우에 유용합니다.
- 영구히 리소스가 옮겨진 경우
- 임시로 리소스가 옮겨진 경우
- URL 증강
- 부하 균형
- 친밀한 다른 서버가 있을 때
- 디렉터리 이름 정규화
1.7 로깅
트랜잭션이 완료되었을 때 웹 서버는 트랜잭션이 어떻게 수행되었는 지에 대한 로그를 로그 파일에 기록합니다.
마치며..
이 글은 웹 서버에 대해 간략히 적은 글입니다.
저는 이번 공부에서
- 웹 서버가 하는 일이 무엇이 있는지,
- 어떤 순서로 하는지,
- 각 순서에 어떤 일을 하는지,
- 커넥션 입출력 처리 아키텍처에 무엇이 있는지
를 알아 갔습니다.
이번엔 커넥션 입출력 처리 아키텍처를 제외하고 가볍게 읽었습니다.