정글사관학교 개발일지/웹 서버

정글사관학교 48일차 TIL: 웹브라우저 요청 흐름, HTTP

Woonys 2021. 12. 20. 01:37
반응형

웹브라우저 요청 흐름(중요!)

면접 단골 질문이니 잘 정리해두자.

 

자, 구글에 접속해보자.

 

 

이제 면접관이 질문을 한다.

지금부터 구글에 "hello"를 검색할 거예요. 검색창이 뜨기까지, 컴퓨터에서는 무슨 일이 벌어지고 있는지 설명해주세요.

 

검색창에 hello를 적고 enter를 누르는 순간부터 시작한다.

 

1. HTTP 요청 메시지 생성

 

 

구글 창에서 입력을 받으면 웹브라우저는 URI를 위와 같이 변경하며, 이 URI를 parsing해 HTTP 요청 메시지를 생성한다. 이때 DNS를 조회해 해당 호스트 주소의 IP를 가져온다. 저 메시지 안에는 아래와 같은 내용이 들어있다. 검색한 내용을 조회하는 요청이니 GET 요청에 해당되며, 검색 내용(q=hello)과 언어(hl=ko), HTTP 버전, 그리고 호스트 주소가 들어있다.

 

 

 

2. HTTP 메시지 전송

 

 

1에서 웹브라우저가 HTTP 메시지를 생성하면 애플리케이션에서는 이를 소켓 라이브러리를 통해 OS로 전달한다. 이때 소켓의 역할은 A) TCP/IP를 연결하고(IP, PORT 주소 가져오기) B) 데이터를 전달한다. 이후에는 OS 커널에서 TCP/IP 패킷을 생성하는데, 이때 위의 애플리케이션에서 만든 HTTP 메시지가 이 패킷에 포함된다. 이후에는 네트워크 인터페이스를 통해 인터넷으로 전달되어 최종적으로 서버로 전송된다. 우리가 보내는 패킷을 좀 더 자세히 살펴보자.

 

위와 같이 출발지/도착지의 IP와 PORT 주소가 들어있으며, 전송 데이터에 해당하는 HTTP 메시지가 들어있는 것을 확인할 수 있다.

 

 

그러면 클라이언트 측에서는 웹브라우저로부터 OS를 거쳐 만들어진 이 요청 패킷을 네트워크 인터페이스, LAN과 라우터를 거쳐 인터넷 상으로 전송한다.

 

3. 서버 응답

서버는 웹브라우저로부터 요청을 받으면 그 내용을 열어서 해당 요청에 맞는 정보를 반환해준다. 이때, 서버에서는 클라이언트에게 응답 메시지를 전송한다. 이 응답 메시지에는 응답하는 정보와 관련한 내용이 들어있다. 짧게 설명하면  HTTP 헤더와 HTTP 바디로 나뉘며, HTTP 헤더에는 HTTP 버전, HTTP 상태 코드, 정보의 타입과 길이가 들어간다. HTTP 바디에는 HTML 코드가 들어간다.

 

 

 

 

그러면 서버 측에서는 아까 클라이언트 단에서 애플리케이션 -> OS -> 네트워크 인터페이스를 거쳤던 과정과 동일한 방식을 거쳐 응답 패킷을 생성한 뒤 이를 클라이언트에게 전달한다.

 

4.클라이언트 렌더링

최종적으로 클라이언트의 웹브라우저는 서버로부터 전달받은 HTML 코드를 웹브라우저 상에 렌더링하여 화면을 띄운다.

 

 

 

HTTP(HyperText Transfer Protocol)

HTTP는 원래 하이퍼텍스트를 전송하는 통신 규약으로 그 시작을 알렸으나 요즘에는 HTML, 텍스트, 이미지, 음성, 영상, 파일, JSON, XML 등 거의 모든 것을 전부 HTTP 메시지로 전송한다고 생각하면 된다. 심지어 서버 간에 데이터를 주고 받을 때도 대부분 HTTP를 사용하니 지금은 HTTP의 시대라고 해도 과언이 아니다.

 

HTTP는 다양한 버전으로 그 역사를 알 수 있는데, 우리가 알아둬야 할 것은 HTTP/1.1 버전이다. 이게 가장 많이 사용하는 버전이기 때문. 기반 프로토콜은 HTTP/1.1, HTTP/2는 TCP, HTTP/3은 UDP이다.

 

HTTP 특징

1. HTTP는 클라이언트-서버 구조로 이뤄져있다. 프론트/백으로 직군이 나뉘게 된 결정적인 원인은 여기서 출발한다. 양쪽이 독립적으로 발전할 수 있기 때문에 문제해결에 훨씬 용이해진다는 장점이 있다.

2. 무상태(stateless)프로토콜이며 비연결성을 지향한다.

3. HTTP 메시지를 이용해 전송한다.

4. HTTP는 단순하며 확장 가능성이 높다.

 

무상태 프로토콜(Stateless)

무상태 프로토콜이란, 서버가 클라이언트의 상태를 보존하지 않는 것을 뜻한다. 이게 무슨 말이냐, 예시를 보자. 고객이 매장에서 노트북을 사는 상황을 가정하자. 직원에게 질문한다. 먼저, 아래는 상태를 보존(=유지)하는 stateful에 대한 예시다.

 

 

아무런 이상함을 느끼지 못할 텐데, 이는 한 점원과 계속 이야기를 이어가고 있는 상황이기 때문이다. 만약 중간에 점원이 바뀐다면 어떨까? 아래 상황처럼 점원 A와 했던 얘기를 점원 B는 전혀 기억하고 있지 않기 때문에(=state가 보존되지 않은 상황) 대화가 원활하게 이뤄지지 않는다.

 

 

 

다시 처음 이미지를 살펴보자. 상태를 유지한다는 말은 맥락에 대한 정보를 서버가 계속해서 들고 있다는 뜻이다. 

 

 

 

그냥 보면 읭? 이게 왜 문제가 되지? 꼭 점원이 바뀌어야 되나?라고 생각할 수 있다. 그러면 이제 stateless 케이스를 살펴보자.

 

 

이제는 점원이 맥락에 대한 정보를 들고 있는게 아니라 고객이 들고 있는 것을 볼 수 있다. 이렇게 되면 점원이 바뀌어도 전혀 문제가 되지 않는다.

 

 

이렇게 Stateless 프로토콜을 차용하면 무엇이 좋나, stateless에서는 클라이언트-서버가 꼭 특정 서버로 일대일 대응하지 않고 다른 서버로 바뀌어도 상관이 없다. 따라서, 클라이언트 요청이 갑자기 증가하는 유동적인 상황에서 서버를 그에 맞게 대거 늘림으로써 유연한 대응이 가능해진다. 아래 예시를 보자. 아까 매장에서 노트북을 사는 상황을 온라인으로 옮긴 케이스다. 아래 이미지처럼 stateful 프로토콜에서는 특정 서버가 일대일 대응되어야 한다. 만약 이 서버1이 고장나거나 하면 클라이언트는 처음부터 다시 결제를 진행해야 한다. 얼마나 비효율적인가.

 

하지만 stateless에서는 연결되어 있던 서버에 장애가 발생해도 결제 관련 정보를 클라이언트가 들고 있기 때문에 바로 다른 서버로 이관해 진행해도 아무런 차질이 없다.

따라서 트래픽이 갑자기 몰리는 특정 상황(ex. 이벤트 등)에서 유연하게 대처하기 좋은 방식은 stateless 프로토콜 기반에서 서버를 아주 많이 늘려 이에 대응하는 것이다.

하지만 늘 stateless만으로 설계하지는 않는데, 상태를 유지해야 하는 경우도 있기 때문이다. 대표적인 것이 바로 로그인이다. 로그인한 사용자의 경우 로그인했다는 상태를 서버에 유지시켜줘야 한다. 이 경우, 일반적으로 브라우저 쿠키 혹은 서버 세션 등을 사용해서 상태를 유지한다. 하지만 상태는 최소한으로 유지하는 것이 중요하다.

 

비연결성(Connectless)

HTTP는 연결을 유지하지 않는 모델이다. 무슨 말이냐, 클라이언트에서 요청을 하면 서버는 응답을 하는데, 이 요청-응답의 상태가 연결이 되어 있는 상태에서 계속 왔다갔다 하는 것이 아니라 각 요청과 응답이 분절되어 있다. 끈으로 연결되어 있는 상태에서 계속 주고받는 게 아니라 서로 편지를 주고받는 것처럼 단절되어 있다는 의미이다. 이렇게 하는 이유는 자원을 효율적으로 쓰기 위해서이다. 만약, 항상 연결되어 있는 상태라면 그 유지시간만큼 자원을 낭비하게 될 것이다. 이를 방지하기 위해 비연결성을 지향한다.

 

하지만 이렇게 비연결성을 지니면 한계점이 생기는데, 매번 요청할 때마다 TCP/IP 연결을 새로 맺어야 한다. 그만큼 3 way handshake 시간이 추가된다. 또한 웹 브라우저로 사이트를 요청하면 한 번에 다 보내주는 게 좋으니 필요 없는 다른 수많은 자원 역시 함께 클라이언트로 전송되어 다운로드된다. 이를 지금은 HTTP 지속 연결 방식으로 문제를 해결했다.

 

 

 

 

반응형