'URI'에 해당되는 글 1건

  1. 2018.11.18 Apache 서버 이해하기 #1 - 웹 세계 이해하기

워드프레스에서 티스토리로 옮기면서 새로운 주제를 하게 되었습니다.

웹 개발자로서 업무에 대한 지식을 정리하는게 주 목적이긴 하지만, 잘 정리해서 모두에게 도움이 되었으면 하네요.

가급적 쉽게 설명하고 업무에 바로 적용할 정도로 정리하는게 목표이긴 한데... みんなさん、がんばりましょう!


Apache 웹 서버에 대해 스터디 발표를 준비하는데,

아무래도 단계별로 가야할거 같아서 나눠서 포스팅하려고 합니다.


Apache 웹 서버의 목적 - HTTP 프로토콜 처리

Apache 웹 서버는 결국 웹 요청을 처리하기 위해 웹 상에서 작동하는 서버 프로그램입니다.

그렇다면 웹 에서의 요청과 응답이 어떤 것인지 먼저 알아볼 필요가 있을거 같은데요.


HTTP는 World Wide Web 이라는 전세계의 컴퓨터를 인터넷으로 연결해서 정보를 공유하는 일종의 가상 공간 안에서, 

정보를 요청하고 응답을 주기 위한 프로토콜, 즉, 통신 양식에 대한 명세(Spec)입니다. 

이 말인 즉슨, HTTP 명세를 벗어난 요청/응답은 웹 상에서 처리될 수 없다는 것이죠.


그렇다면 HTTP 명세라는 건 어떻게 생겨먹었나 봐야죠.

우선, 가장 큰 구분은 요청이냐 응답이냐 인데요.

HTTP는 웹 상에서 일어나는 행동을 요청과 응답 두 가지로 정의합니다.

정보가 필요한 쪽에서는 정보를 얻기 위해 요청을 보내고,

정보를 가진 쪽에서는 요청을 통해 어떤 정보에 대한 요청인지 확인한 다음 알맞은 정보를 응답으로 보내는거죠.


* 사실 요청과 응답이라는 패러다임은 모든 통신의 행동 방식이죠.

전화도 마찬가지이고, TCP/UDP도 결국은 요청 - 응답의 반복입니다.

다만, 컴퓨터에서는 디지털화된 데이터가 이동하면서 요청 - 응답 메시지에 이전보다 더 많은 정보를 실을수 있게된거고,

정보를 가진 쪽에서 어떤 정보에 대한 요청인지 구분이 용이하도록 header, body 등

명세가 더 세분화되었다고 생각하시면 될거 같습니다.


그럼 요청을 어떻게 하고, 응답은 또 어떻게 받는걸까요?

정답은 메시지 입니다.

메시지에 목적지 주소와 원하는 정보의 위치, 요청하는 정보에 대한 상세 설명, 인증정보 (정보를 가진 쪽에서 요구할 경우), 요청 명세의 버전 등을 적어서 보내면

정보를 가진 쪽에서 메시지를 받고 어떤 정보인지 찾아서

있으면 정보와 상세 설명을, 없으면 왜 없는지(?)를 처리결과와 함께 새로운 메시지로 실어서 요청한 곳으로 다시 보내는거죠.


HTTP 요청/응답 메시지

HTTP 프로토콜은 인터넷 상에서의 통신 규약이므로 구체적으로 알아보려면 RFC문서를 보는게 좋습니다.

(HTTP 프로토콜의 RFC 문서 링크 - https://tools.ietf.org/html/rfc2616)

다만 개발자 입장에서 당장 필요한 것은 HTTP를 처리하는 웹 서버에 요청을 어떻게 주는지,

응답은 어떤 모양으로 오는지 이해하는 거겠죠.


요청 메시지는 다음과 같은 모양입니다.

GET /restapi/v1.0 HTTP/1.1
Accept: application/json
Authorization: Bearer UExBMDFUMDRQV1MwMnzpdvtYYNWMSJ7CL8h0zM6q6a9ntw

(출처 : 위키백과, https://ko.wikipedia.org/wiki/HTTP)


첫번째 줄은 start-line으로 정의 되어 있는데, 요청 메시지일 경우는 request-line으로 부르고, METHOD / URI / HTTP버전 으로 구성됩니다.

정보를 요청하고 응답받는 입장에서만 보면 URI가 정보 자원의 위치를 가리키는 것이므로 가장 중요하죠.

HTTP METHOD는 정보 자원이 처리되는 방식을 가리키는 걸로 GET/POST/PUT/PATCH/DELETE/OPTION 등등을 RFC문서에서 정의하고 있지만,

웹 브라우저에서는 GET으로 지정해서 요청 자원을 그대로 받는 형태로 쓰고 있습니다.

이 부분은 다음 포스트에서 다시 설명드리겠습니다.

HTTP버전은 말 그대로 프로토콜의 버전인데, HTTP의 경우 아직은 1.1로 지정해서 사용합니다.


두번째 줄 부터는 헤더라고 해서 요청이나 클라이언트 자신에 대한 부가적인 정보를 나타내는 역할로 사용합니다.

예제 같은 경우는 응답을 JSON형식으로 전달하라는 것이고, 요청하는 정보 자원의 유형을 미리 알고 있으면 저렇게 기재하는 것입니다.

헤더 부분의 Authorization 필드는 인증정보를 요구하는 것이고, 저렇게 자기자신의 개인키를 넣어서 자기자신을 알리는 것이죠.

헤더부분은 저렇게 두번째 줄부터 CRLF(HTTP 메시지 상에서의 개행문자)가 두번 연속으로 들어간 곳 까지입니다.


응답 메시지의 예시는 다음과 같습니다.

HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Encoding: UTF-8
Content-Length: 138
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
ETag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Connection: close

<html>
<head>
  <title>An Example Page</title>
</head>
<body>
  Hello World, this is a very simple HTML document.
</body>
</html>

(출처 : 위키백과, https://ko.wikipedia.org/wiki/HTTP)


첫번째 줄은 요청과 마찬가지로 start-line으로 시작하지만, 응답 메시지일 경우는 status-line으로 다르게 부릅니다.

구성은 요청받은 HTTP버전 / 처리상태 로 이루어집니다.

처리상태는 상태코드와 상태에 대한 설명으로 이루어지는데, 종류가 좀 많습니다.

크게 100 ~ 500 클래스로 구분하죠.

1XX - 요청을 계속 처리중임, 일반적으로는 사용되지 않음

2XX - 요청이 잘 처리되었고, 처리된 정보의 종류를 설명하지만, 보통은 200 코드만 사용됨

3XX -  요청을 처리하기 위한 다음 Action을 나타냄 (즉, Redirection)

4XX - Client Error, 즉 요청 메시지에 오류가 있음을 나타냄

5XX - Server Error, 즉 서버가 어떤 이유로 요청을 처리할 수 없는 상태인지를 나타냄


세부적인 코드는 검색해보시길 바랍니다.

예를 들어, 응답받은 상태코드가 403이면 요청을 서버가 이해하지 못한다는 것인데, 보통은 헤더나 파라미터 같은 필수값이 일부 빠진 상태로 요청을 보내서 그렇죠.

404는 URI가 가리키는 정보가 유효하지 않다는 거니까, 경로가 잘못된게 되는거고요.

반대로 500 클래스가 응답으로 나오면 운영팀에 비상등이 켜졌다고 보면 됩니다. 빼박 서버 문제니까요.


두번째 줄 부터 헤더영역인 것 까지는 동일한데, 이때 헤더의 내용은 응답에 대한 부가정보로 요청때보다 내용이 많아지게 됩니다.

그리고 개행문자를 두번쳐서 헤더를 끝낸다음, 응답하는 정보(데이터)가 이어서 응답 메시지에 들어갑니다.

이때 정보가 들어가는 영역을 message-body라고 부릅니다.

요청때도 이 message-body가 들어갈 수는 있으나, REST 방식 같은 특수 케이스에만 쓰이죠.

일반적인 HTTP 요청 메시지에는 message-body가 들어가지 않는다고 생각하시면 됩니다.


URL과 URI의 차이는?

브라우저에서는 웹 요청을 보낼때는 URL만 이용했습니다.

그럼 저 HTTP 요청/응답 메시지는 어떻게 만들어지고 처리되는 걸까요?

브라우저에서의 처리 절차는 다음과 같습니다.

  1. URL을 입력받으면, 파싱해서 HTTP 요청 메시지를 만든 다음 URL에 명시된 도메인(혹은 IP주소)로 보냄
  2. 응답을 기다림
  3. 응답 상태가 정상이면 메시지에서 message-body 부분을 뽑아서 브라우저 창에 보여줍니다.


그럼 파싱은 어떻게 하는 걸까요?

일반적으로 사용하는 URL의 예를 들어 보면

https://www.sample.com/resource1/sample1.html?param1=xx

이런 식인데,

'://' 을 기준으로 왼쪽은 프로토콜, 오른쪽은 도메인(혹은 IP:PORT)이 됩니다.

도메인 바로 오른쪽의 / 다음 부터는 요청하는 자원의 위치가 되는 거죠.

(물음표 다음부터는 파라미터로 활용하고요)


여기서 URL과 URI을 구별할수 있는데,

URL은 도메인을 포함한 웹 상에서 정보자원의 위치이고, URI는 정보자원의 식별자가 되는겁니다.

즉 URL안에서 프로토콜과 도메인을 제거한 'resource1/sample1.html?param1=xx' 가 자원의 식별자인 URI인거죠.


요청 메시지의 request-line을 구성할때 URI와 프로토콜 버전을 URL로부터 이렇게 뽑아냅니다.

그럼 나머지는?

HTTP METHOD 같은 경우 웹 브라우저에서는 GET으로만 보냅니다.

자원을 받아서 화면에 보여줘야 되니까요.

당연히 헤더 부분도 HTML이나 파일 같은 정적 자원을 요청하는다는 걸로 채워지는 거죠.


Posted by kevin.jeong.
,