우리가 사용하는 인터넷은 브라우저에 URL 주소를 입력하는 순간부터 시작된다. 이때 브라우저에서 웹 서버에 요청하게 되는 HTTP 리퀘스트 메시지가 생성되는 과정을 좀더 세심히 들여다 보도록 하자.
그림 출처: http://www.oreilly.com/openbook/webclient/ch03.html
1. 브라우저에 URL 입력
기본적으로 사용하는 http: 프로토콜 이외에도 ftp:, file:, mailto: 등의 프로토콜 모두 웹 브라우저에서 사용 가능한 프로토콜이다.
HTTP 프로토콜로 웹 서버에 액세스하는 경우
http://user:password@www.uzuro.com:80/wordpress/index.html
http://사용자명(생략가능):패스워드(생략가능)@웹서버의 도메인명:포트번호(생략가능)/파일의 경로명
FTP 프로토콜로 파일을 다운로드하거나 업로드하는 경우
ftp://user:password@ftp.uzuro.com:21/wordpress/index.html
ftp://사용자명(생략가능):패스워드(생략가능)@FTP 서버의 도메인명:포트번호(생략가능)/파일의 경로명
로컬 PC 자체의 파일에서 데이터를 읽어오는 경우
file://localhost/c:/path/wordpress/index.html
file://컴퓨터명(생략가능)/파일의 경로명
메일을 송신하는 경우
mailto:webmaster@uzuro.com
mailto:메일 주소
뉴스그룹의 기사를 읽는 경우
news:comp.protocols.tcp-ip
news:뉴스그룹명
2. 브라우저의 URL 해독
브라우저가 처음 하는 일은 웹 서버에 보내는 리퀘스트의 메시지를 작성하기 위해 이 URL을 해독하는 것이다. 이때 파일명을 생략하는 경우들에 대해 살펴본다.
파일명만 생략
http://www.uzuro.com/wordpress/
wordpress 라는 디렉토리에 서버가 정해둔 index.html 등을 자동으로 액세스한다.
도메인명만 있는 경우
http://www.uzuro.com/
끝에 /가 있으므로 /(루트) 디렉토리가 지정되고 파일명은 생략되어 서버에서 정한 index.html등에 액세스한다.
도메인명 있으며 / 까지 생략된 경우
http://www.uzuro.com
디렉토리 명까지 생략되어 버리면 무엇을 요청하고 있는지 알지 못하게 되므로 너무 지나친 생략이다. 하지만 이렇게 쓰는 것도 인정되고 있으며 이 또한 /(루트) 디렉토리 아래의 서버가 정해둔 index.html 등에 액세스한다.
파일명인지, 디렉토리인지 구분이 어려운 경우
http://www.uzuro.com/myblog
맨 끝에 /가 없으므로 myblog를 파일명으로 보는게 맞으나 실제로는 파일명을 생략하는 규칙을 정확히 이해하지 못하고 디렉토리의 끝에 있는 /까지 생략해 버리는 경우가 많다. 이럴때는 myblog를 파일명과 결부시키지 않는 것이 좋기 때문에 일반적으로 myblog라는 파일이 잇으면 myblog를 파일명으로 보고, myblog라는 디렉토리가 있으면 디렉토리명으로 본다.
3. HTTP의 기본 개념
URL을 해독하면 어디에 액세스해야 하는지 판명된다. 그런 후에 브라우저는 HTTP 프로토콜을 사용하여 웹 서버에 액세스하는데 그 동작을 살펴보기 전에 먼저 HTTP 프로토콜이 어떤 것인지 알아보도록 하자.
클라이언트에서 서버를 향해 리퀘스트 메시지를 보낸다. 리퀘스트 메시지 안에는 '무엇을','어떻게 해서' 하겠다는 내용이 쓰여져 있다. '무엇을'에 해당하는 것을 URI라고 하는데, 보통 페이지 데이터를 저장한 파일의 파일명을 URI로 쓴다.
그 다음의 '어떻게 해서'에 해당하는 것이 메소드로, 이 메소드에 의해 웹 서버에 어떤 동작을 하고 싶은지를 전달한다. URI로 나타낸 데이터를 읽고 싶다거나 클라이언트측에서 입력한 데이터를 URI로 나타낸 프로그램에 전달하고 싶다는 식의 동작이 대표적이다.
메소드 | HTTP의 버전 | 의미 | ||
---|---|---|---|---|
1.0 | 1.1 | |||
GET | O | O | URI로 지정한 정보를 도출한다. 파일의 경우 해당 파일의 내용을 되돌려 보내고, CGI 프로그램의 경우 해당 프로그램의 출력 데이터를 그대로 반송한다. | |
POST | O | O | 클라이언트에서 서버로 데이터를 송신한다. 폼에 입력한 데이터를 송신하는 경우에 사용한다 | |
HEAD | O | O | GET과 거의 같다. 단 HTTP 메시지 헤더만 반송하고 데이터의 내용을 돌려보내지 않는다. 파일의 최종 갱신 일시와 같은 속성 정보를 조사할 때 사용한다. | |
OPTIONS | O | 통신 옵션을 통지하거나 조사할때 사용한다. | ||
PUT | △ | O | URI로 지정한 서버의 파일을 치환한다. URI로 지정한 파일이 없는 경우에는 새로 파일을 작성한다. | |
DELETE | △ | O | URI로 지정한 서버의 파일을 삭제한다. | |
TRACE | O | 서버측에서 받은 리퀘스트 라인과 헤더를 그대로 클라이언트에 반송한다. 프록시 서버등을 사용하는 환경에서 리퀘스트가 치환되는 상태를 조사할때 사용한다. | ||
CONNECT | O | 암호화한 메시지를 프록시로 전송할 때 이용하는 메소드이다. |
O : 각 버전에서 '사용'으로 정의되어 있는 것
△ : 정식으로 사양이 아니라 부가 기능으로 사양의 부록에 기술되어 있는 것
리퀘스트 메시지가 웹 서버에 도착하면 웹 서버는 그 속에 쓰여있는 내용을 해독한다. 그리고 URI와 메시지를 조사하여 '무엇을', '어떻게 하는지' 판단한 후 요구에 따라 동작하고, 결과 데이터를 응답 메시지에 저장한다. 응답 메시지의 맨 앞부분에는 실행 결과가 정상 종료되었는지 또는 이상이 발생했는지를 나타내는 스테이스 코드가 있다. 웹 서버에 액세스했을때 파일이 발견되지 않고 '404 Not Found'와 같이 표시될 수 있는데, 이것이 '스테이스코드'이다. 그후 헤더 파일과 페이지의 데이터가 이어지고, 이 응답 메시지를 클라이언트에 반송한다. 그러면 이것이 클라이언트에 도착하여 브라우저가 메시지의 안에서 데이터를 추출하여 화면에 표시하면서 HTTP의 동작은 끝나게 된다.
4. HTTP 리퀘스트 메시지를 만들기
URL을 해독하고 웹 서버와 파일명을 판단하면 브라우저는 이것을 바탕으로 HTTP의 리퀘스트 메시지를 포맷에 맞게 만들게 된다.
리퀘스트(요청) 메시지
첫 행을 '리퀘스트 라인' 이라하며 아래와 같은 형태를 갖는다.
GET /test/test.html HTTP/1.1
<메소드><공백><URI><공백><HTTP버전>
이후의 필드와 필드값으로 이루어진 행들을 '메시지 헤더' 라고 부르며 한 행에 한 개의 헤더 필드를 가지게 된다. 이를 통해 리퀘스트의 부가적인 정보를 나타내며, 행의 수는 상황에 따라 달라지며 공백 행까지가 메시지 헤더가 된다.
Accept:*/*
Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4
<필드명>:<필드값>
...
<공백 행>
<메시지 본문>
메시지 본문의 내용은 클라이언트에서 서버에 송신하는 데이터, 폼 페이지에 입력한 데이터를 POST 메소드로 웹 서버에 보낼 때 등에 데이터가 들어간다.
리스폰드(응답) 메시지
응답 메시지의 첫행은 스테이터스 라인이라 부르며 스테이스 코드의 내용을 나타내는 짧은 설명문을 포함한다.
HTTP/1.1 200 OK
<HTTP버전><공백><스테이터스코드><공백><응답문구>
이후는 리퀘스트 요청과 같은 구조로 메시지헤더가 위치하며 마지막에 메시지 본문이 들어간다. 응답 메시지의 메시지 본문값은 서버에서 클라이언트에 송신하는 데이터, 파일에서 읽은 데이터나 CGI 애플리케이션이 출력한 데이터가 들어간다. 메시지 본문은 바이너리 데이터로 취급한다.
헤더 필드의 종류와 설명
메시지 헤더에 쓰는 내용ㅇ은 브라우저의 종류나 버전, 설정 등에 따라 달라지고, 몇 행에서 열 줄이 상의 메시지 헤더를 쓰는 경우가 많다.
헤더 필드의 종류 | HTTP의 버전 | 설명 | ||
---|---|---|---|---|
1.0 | 1.1 | |||
제너럴 헤더 : 리퀘스트와 응답 양쪽에 모두 사용하는 헤더 필드 | ||||
Date | O | O | 리퀘스트나 응답이 작성된 날짜를 나타낸다. | |
Pragma | O | O | 데이터의 캐시를 허용할지의 여부를 나타내는 통신 옵션을 지정한다. | |
Cache-Control | O | 캐시를 제어하기 위한 정보 | ||
Connection | O | 응답 송신 후에 TCP에 계속 접속할지, 아니면 연결을 끊을지를 나타내는 통신 옵션을 지정한다. | ||
Transfer-Encoding | O | 메시지 본문의 인코딩 방식을 나타낸다. | ||
Via | O | 도중에 경유한 프록시나 게이트웨이를 기록한다. | ||
리퀘스트 헤더 : 리퀘스트의 부가 정보로 사용하는 헤더 필드 | ||||
Authorization | O | O | 사용자 인증용 데이터 | |
Form | O | O | 리퀘스트 발신자의 메일 주소 | |
If-Modified-Since | O | O | 지정한 날짜 이후 정보가 갱신된 경우에만 리퀘스트를 실행하려고 필드값으로 이 날짜를 지정한다. 보통 클라이언트측에서 캐시에 저장한 정보를 비교하고, 이것이 오래된 경우에 새 정보를 받으려고 할 때 사용한다. | |
Referer | O | O | 하이퍼링크를 거쳐 어느 페이지를 읽은 경우 등에 링크 대상인 URI를 나타낸다. | |
User-Agent | O | O | 클라이언트 소프트웨어의 명칭이나 버전에 관한 정보 | |
Accept | △ | O | 클라이언트측이 Content-Type으로 받는 데이터의 종류, MIME 사양의 데이터 타입으로 표현한 것이다. | |
Accept-Charset | △ | O | 클라이언트측이 받은 문자 코드 세트 | |
Accept-Encoding | △ | O | 클라이언트측이 Content-Encoding으로 받은 인코딩 방식. 보통 데이터 압축 형식을 나타낸다. | |
Accept-Language | △ | O | 클라이언트측이 받은 언어의 종류. 한국어는 ko, 영어는 en 이다. | |
Host | O | 리퀘스트를 받는 서버의 IP 주소와 포트 번호 | ||
If-Match | O | Etag 참조 | ||
If-None-Match | O | Etag 참조 | ||
If-Unmodified-Since | O | 지정한 날짜 이후 갱신되지 않은 경우에만 리퀘스트를 실행한다. | ||
Range | O | 데이터의 전체가 아니라 일부만 읽을 때 해당 범위를 지정한다. | ||
응답 헤더 : 응답의 부가 정보로 사용되는 헤더 필드 | ||||
Location | O | O | 정보의 정확한 장소를 나타낸다. 리퀘스트의 URI가 상대 이름(relative name)으로 지정된 경우 절대 이름으로 했을 때의 정보의 위치를 통지하기 위해 사용한다. | |
Server | O | O | 서버 소포트웨어의 명칭이나 버전에 관한 정보 | |
WWW-Authenticate | O | O | 리퀘스트한(요청한) 정보에 대한 액세스가 제한되어 있는 경우 사용자 인증용 데이터(첼린지 등)를 반송한다. | |
Accept-Ranges | O | 데이터의 일부만 리퀘스트하는 Range를 지정한 경우 서버가 해당 기능을 가지고 있는지의 여부를 클라이언트에 통지한다 | ||
엔티티 헤더 : 엔티티(메시지 본문)의 부가 정보로 사용하는 헤더 필드 | ||||
Allow | O | O | 지정한 URI로 사용 가능한 메소드를 나타낸다. | |
Content-Encoding | O | O | 메시지 본문에 압축등의 인코딩 처리가 되어 있는 경우 해당 방식을 나타낸다. | |
Content-Length | O | O | 메시지 본문의 길이를 나타낸다. | |
Content-Type | O | O | 메시지 본문이 어떤 데이터인지 종류를 나타낸다. MIME 사양으로 정의된 데이터 타입으로 데이터의 종류를 나타낸다. | |
Expires | O | O | 메시지 본문의 유효 기간을 나타낸다. | |
Last-Modified | O | 정보를 최종 변경한 일시 | ||
Content-Location | O | 메시지 본문이 서버의 어디에 놓여 있는지 위치를 URI로 나타낸다. | ||
Content-Range | O | 데이터의 전체가 아니라 일부가 리퀘스트된 경우 메시지 본문에 어느 범위의 데이터가 포함되어 있는지를 나타낸다. | ||
Etag | O | 갱신 처리 등에서 이전 리퀘스트의 응답을 바탕으로 한 갱신 데이터를 다음 리퀘스트에서 송신하는 경우가 있는데, 이때 이전 응답과 다음 리퀘스트를 관련시키기 위해 사용하는 정보이다. 이전 응답에서 서버가 Etag에 따라 고유한 값을 클라이언트에 건네주고, 다음 번 리퀘스트의 'If-Match', 'If-None-Match', 'If-Range' 필드에서 값을 서버에 통지하면 서버는 이전 회의 걔속이라고 인식한다. 쿠키라는 필드와 역할이 같은데, 쿠키는 넷스케이프의 독자적인 사양이며, Etag는 이것을 표준화한 것이다. |
O : 사용으로 정의되어 있는 것
△ : 정식으로는 사양이 아니고 부가 기능으로 Appendix에 기술되어 있는 것
리퀘스트 메시지에 쓰는 URL은 하나뿐으로, 복수의 파일을 읽을 때는 웹 서버에 별도의 리퀘스트 메시지를 보낸다.
참고 : 성공과 실패를 결정하는 1%의 네트워크 원리
'네트워크' 카테고리의 다른 글
프로토콜 스택에 메시지 송신을 의뢰 (0) | 2013.12.03 |
---|---|
TCP/IP, Socket 라이브러리, 리졸버 (0) | 2013.12.03 |
패킷이 거치는 경로 (1) | 2013.12.02 |
네트워크 개요 (0) | 2013.12.01 |
DNS서버(네임서버) (0) | 2013.06.21 |