이 글에서는 개발자의 관점에서 HTTP 요청이 어떻게 이루어지는지 살펴보도록 하겠습니다.

우선 시작은 브라우저를 열고 URL을 입력하는 순간부터 HTTP 요청이 시작이 됩니다.

그 순간 브라우저는 사용자가 입력한 URL의 주소에 해당하는 목적지에 도착해서 데이터를 요청하고
그 목적지에서 응답한 데이터를 받아서 화면에 보여주게 되는것이죠.

아래 그림은 일반적인 HTTP 요청을 매우 단순화한 그림입니다.

HTTP Request 요약
HTTP Request 요약

만약 당신이 브라우저의 주소창에 app.mydomain.com/me 을 입력한다면 브라우저는 자동으로 http:// 를 URL 앞에 추가하여 입력한 URL로 이동합니다.

그리고 최종적으로 브라우저에 입력된 URL인 http://app.mydomain.com/me 를 세부적으로 살펴보면 아래와 같습니다.

  • http:// : 인터넷 통신을 위한 프로토콜
  • mydomain.com : 서버의 도메인
  • app : 서버의 서브 도메인 ( 2차 도메인 )
  • /me : 경로

HTTP 프로토콜은 영어가 국제적인 공용어로 쓰이는 것처럼 인터넷에서의 의사소통을 위한 표준으로 정의된 규칙입니다.


그렇다면 요청이 어떻게 서버에 도달하는가?

인터넷은 네트워크에 연결된 장치가 네트워크에 연결된 다른 장치와 통신할 수 있게 연결되어있는 네트워크 입니다.

아래 이미지는 세계가 해저 케이블로 연결된 모습인데, 이처럼 전 세계가 해저 케이블과 이미지에는 보이지 않지만 육지 케이블을 통해 연결되어있습니다.

해저 케이블
해저 케이블

만약 당신이 런던에 있고 미국에 있는 서버에 접속하고 싶다면 대륙을 연결하고 있는 해저 케이블이 당신의 요청을 런던에서 미국으로 전송해줄 겁니다.

그러나 여기서 알아야 하는 건, 패킷이나 데이터를 전달하려면 도메인 이름(URL)이 아닌 IP 주소를 알아야 한다는 것입니다.
편지를 보낼 때 당신의 이름이 아닌 당신의 집 주소로 보내야 하는 것처럼 말입니다.


그래서 어떻게 도메인의 IP 주소를 알 수 있는가?

그건 바로 인터넷 세상의 주소록을 가지고 있는 DNS ( Domain Name System ) 서버 (=네임서버 )를 통해서 가능합니다.

만약 app.mydomain.com 도메인 주소에 접속하려 한다면 우리는 네임 서버에게 app.mydomain.com 의 IP 주소를 알려달라고 요청해서 IP주소를 알려달라고 요청해야 합니다. 그리고 우리의 요청에 네임서버는 알고 있는 주소라면 IP 주소를 응답해줄 것이고 모르는 주소라면 존재하지 않는 주소라고 응답할 것입니다.

그렇다면 여기서 드는 의문은 “DNS 서버(=네임서버)의 IP 주소는 어떻게 알 수 있는가?” 인데요.

우리는 기본적으로 인터넷에 연결하려면 고유한 IP 주소를 부여받아야 하는데요.
IP 주소를 부여받을때 인터넷 제공자의 DNS 서버의 주소도 함께 설정이 되기 때문입니다.
( 물론 자동으로 설정되지만 수동으로 다른 DNS 서버로 변경해 줄 수도 있습니다. )

그렇다면 DNS 서버는 요청받은 도메인에 대한 IP 주소를 어떻게 알아낼까요?

우리가 접속하려는 URL을 먼저 인터넷 제공자(ISP)의 DNS 서버(1)에게 IP 조회를 요청하고, 인터넷 제공자의 DNS 서버는 최상위 도메인(TLD) DNS 서버에게 그리고 최상위 도메인 DNS 서버가 최종적으로 mydomain.com 의 DNS 서버에게 요청을해서 mydomain.com 의 DNS 서버가 알고있는 IP를 요청자에게 전달해주게 됩니다.

URL의 IP를 조회하는 순서를 정리해보면

  • 내가 이용하고있는 인터넷 제공자(ISP)의 DNS 서버(=네임서버)에게 app.mydomain.com 의 IP 주소를 알려달라고 요청.
  • 인터넷 제공자의 네임서버는 .com 으로 끝나는 URL 이므로 .com 도메인을 관리하는 네임서버에게 mydomain.com 의 IP 주소를 요청.
  • .com 도메인을 관리하는 TLD 네임서버가 mydomain.com 을 관리하는 네임서버에게 IP 주소 조회를 요청.
  • mydomain.com 의 네임서버가 IP 주소를 요청자에게 전달.
  • 요청의 역순으로 요청자들에게 IP 주소가 전달되어 최초 요청자에게 IP 주소가 전달됨.
네임서버의 도메인 IP 조회
네임서버의 도메인 IP 조회

이처럼 DNS 서버가 URL을 IP로 변환을 해주므로 우리는 URL만으로 서버의 실제 IP로 접속할 수 있게 되는 겁니다.


서버는 HTTP 요청에 어떻게 응답하는가?

서버에 웹서버가 실행되고 있다면 HTTP 요청에 대한 응답을 처리할 수 있습니다.

많이 사용하는 웹서버로는 Apache와 Nginx 가 있고, 이 웹서버들이 서버에서 프로세스로 작동하며 요청이 오기를 기다리고 있다가 HTTP 요청이 오면 그에 따른 적절한 응답을 하게 되는 것입니다.

그렇다면 서버에는 웹서버 이외에도 다양한 프로세스들이 작동하고 있을텐데 어떻게 요청이 웹서버에게 바로 전달될까요?

그 이유는 Apache나 Nginx 같은 웹서버들은 일반적으로 80 포트로 네트워크 요청을 받도록 실행되고, HTTP 요청은 서버의 80포트로 요청되기 때문입니다. 즉, http://app.mydomain.com 은 http://app.mydomain.com:80 과 동일합니다.

그리고 포트를 생략하면 80포트이지만 별도의 포트를 사용하는 경우 포트를 명시적으로 지정해주면 해당 포트로 요청합니다. ( ex: http://app.mydomain.com:8080 )


Apache/Nginx 는 HTTP 요청을 어떻게 받을까?

일반적인 웹서버의 작동방식은 두 가지입니다.

  • 요청한 경로와 일치하는 서버의 경로에 저장된 정적 파일의 내용을 응답한다.
  • 요청을 별도의 프로세스에 전달하여 처리된 결과를 응답한다.

정적파일 내용을 응답

<VirtualHost *:80>
    ServerName app.mydomain.com
    DocumentRoot "/var/www/my-static-website"
    ServerAdmin admin@mydomain.com
</VirtualHost>

HTTP 요청이 app.mydomain.com/me 라면 웹서버는 /var/www/my-static-website/me/index.html 파일을 응답하게 될 것입니다.

해당 HTTP 요청의 경로는 /me 이므로 웹서버에 설정된 기본 DocumentRoot 폴더를 기준으로 동일한 경로(/me)의 index.html 을 찾도록 설정되어있기 때문이죠. ( 물론 설정을 통해 작동방식을 다르게 변경할 수 있습니다. )

다른 프로세스에 전달하여 처리된 결과로 응답

만약 PHP, Java, Node, Python 같은 서버가 4000 포트로 작동하고 있다면, 웹서버의 설정을 통해 HTTP 요청을 해당 프로세스로 전달 할 수 있습니다.

아래는 Apache 의 proxy 설정을 통해 처리하는 방법입니다.

<VirtualHost *:80>
    ServerName app.mydomain.com
    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:4000/
    ProxyPassReverse / http://127.0.0.1:4000/
</VirtualHost>

proxy 설정을 통해 요청을 특정 포트(4000)로 전달하고 그에 대한 응답을 apache 프로세스가 다시 받아서 최종적으로 응답을 해주게 됩니다.


왜 PHP, Java, Node, Python 프로세스로 80 포트에 서비스하지 않는가?

일반적인 시나리오는 한 대의 서버에서 두 개 이상의 웹 사이트가 실행될 수 있다는 것입니다. 그러나 둘 이상의 프로세스가 하나의 포트를 점유할 수 없기 때문에 ServerName 기반으로 여러개의 요청을 처리할 수 있는 Apache와 같은 웹서버를 사용하는 것입니다.

그러나 만약 하나의 웹 사이트만 운영하는 경우에는 PHP, Java, Node, Python 을 80 포트로 실행해서 웹서버를 구성해도 무방합니다.


HTTP는 알겠는데 HTTPS는 뭔가요?

HTTPS는 HTTP 보다 보안적인 측면을 강화한 프로토콜입니다.

일단 인터넷으로 주고받는 모든 데이터는 제 3자가 중간에서 얼마든지 가로채서 볼 수 있는데, 기존의 HTTP 요청은 데이터를 주고 받을 때 별도 처리 없이 있는 그대로 서버에 전송하므로 제 3자가 마음만 먹으면 나와 서버가 주고 받은 민감한 데이터(ex: 패스워드)를 그대로 탈취해서 악용할 소지가 있습니다.

바로 이런 HTTP의 단점을 보완하기 위해 요청/응답 데이터를 암호화해주는 HTTPS 프로토콜은 데이터를 안전하게 암호화하여 제3자가 요청/응답 내용을 중간에서 탈취하여도 암호화 데이터이기 때문에 민감한 데이터를 안전하게 지킬 수 있습니다.

대부분의 서비스들은 민감한 데이터를 주고 받는 경우가 많으므로 특별한 이유가 없다면 보안을 위해 HTTPS 사용을 권장합니다.


마치며…

브라우저에 URL 을 입력하는 순간부터 서버에서 응답을 보내주기까지의 일어나는 일들을 간략하게 정리해보았는데요.

HTTP 요청이 다양한 경로를 거쳐 우리에게 다시 돌아오기까지 생각보다 많은 일들이 벌어지지 않나요? ㅎㅎ

또 이런 작업들이 눈깜짝할 사이에 이루어진다는것도 참 신기한 세상인것 같습니다.

감사합니다. 😄