네트워크 공부에 앞서…
이론에는 추상적 개념(Abstraction)과 사실(implementation)이 존재한다. 객체 지향 프로그래밍을 이해한다면 위 문장을 쉽게 이해할 수 있을 것이다. class는 객체의 추상적 개념을 정의하며, instance는 실제로 구현된 실체라는 점을 이미 알고 있을 테니 말이다.
네트워크도 마찬가지다. OSI 7계층 모델은 추상적 개념일 뿐 네트워크 통신의 실체는 아니다. 따라서 실제 게임 서버를 만들기 위해선 TCP/IP, HTTP처럼 실제로 구현된 통신 프로토콜에 대해 공부할 필요가 있겠다.
HTTP
HTTP는 웹에서 데이터를 주고받는 데 사용되는 프로토콜이다. OSI 7계층에서 살펴보자면, Application Layer 위에서 동작하는 프로토콜이다. 예를 들어 우리가 웹사이트를 방문하거나 API를 호출할 때, 바로 이 HTTP를 사용하게 된다.
요청-응답 구조
(이미지 출처 : [Network] HTTP란 무엇인가요? 무상태와 비연결성 정리하기)
HTTP 통신은 요청-응답 구조로 이루어진다. 클라이언트(브라우저)가 요청(Request)을 보낼 때에만 서버가 응답(Response)을 반환한다는 뜻이다.
예를 들어 구글에 접속할 때를 떠올려 보자. 주소창에 구글의 도메인 주소를 입력해야만 구글 메인 사이트가 열릴 것이다. 즉, 서버는 요청이 없으면 응답하지 않는다.
무상태(Stateless), 비연결성(Connectionless)
또한, HTTP는 무상태, 비연결성 프로토콜이다. 요청과 응답이 끝나면 연결이 종료(비연결성)되기 때문에 이전에 일어났던 상태를 저장하고 있지 않는다(무상태).
예를 들어 어젯밤에 구글에서 '강아지'를 검색하고 인터넷을 종료한 뒤 잠이 들었다고 가정하자. 오늘 다시 인터넷 브라우저를 열고 구글에 접속을 한다면 빈 검색창이 우리를 반길 것이다. 어젯밤의 연결은 어젯밤에 이미 종료가 되었기 때문에, 구글은 '강아지'를 검색했던 클라이언트(웹 브라우저)의 상태를 저장해주지 않는다.(물론 검색 기록은 저장해주지만, 그건 어디까지나 별개의 처리과정이다.)
👻 참고 사항
기본적으로 HTTP는 요청과 응답이 끝나면 연결이 종료(비연결성)되지만, HTTP/1.1부터는 지속 연결(Persistent Connection)을 지원하여 다수의 요청-응답을 하나의 연결에서 처리할 수 있다. 그러나 요청 간의 상태는 여전히 저장되지 않기 때문에 무상태로 간주된다.
메시지 구조
HTTP 프로토콜의 헤더에는 아주 많은 양의 정보가 들어있다.
프로토콜 간 헤더 비교
보통의 HTTP Request Header의 일부분
GET /data HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/90.0.4430.212
Accept: application/json
Cookie: sessionToken=abcdef; userID=12345
연결 이후 데이터 교환할 때의 websocket의 헤더
0x81 0x05
이런 구조를 가지고 있기 때문에 HTTP로 지속적인 연결을 맺게 된다면 매우 많은 리소스를 잡아먹게 될 것이다.
TCP
TCP는 데이터를 네트워크를 통해 안정적으로 전달하기 위한 프로토콜이다. OSI 7계층에서 살펴보자면, Transport Layer 위에서 동작하는 프로토콜이다. 비록 HTTP는 비연결성 프로토콜이지만, 이를 전송하기 위한 기반 프로토콜인 TCP는 연결 지향적이다. 따라서 HTTP 요청과 응답이 발생할 때마다 TCP 연결이 설정되고, 데이터가 교환되면 연결이 종료된다.(참고 키워드 : 3-way handshake)
TCP통신은 어떻게 이루어질까?
양방향 통신 (Full-Duplex) 순서
- 서버는 접속 요청을 받기 위한 소켓을 연다. → Listen
- 클라이언트는 소켓을 만들고, 서버에 접속을 요청한다. → Connect
- 서버는 접속 요청을 받아서 클라이언트와 통신할 소켓을 따로 만든다. → Accept
- 소켓을 통해 서로 데이터를 주고 받는다. → Send & Receive ⇒ 반복!
- 통신을 마치면 소켓을 닫는다. → Close ⇒ 상대방은 Receive로 인지할 수 있다.
만약 양방향 통신을 하고 싶을 땐?
그런데 우리가 실시간 대전 게임을 만든다면 어떨까. 아주 작은 규모의 체스 대전 게임을 만든다고 가정해보자. 웹 서버로 체스 게임을 구현한다면 아마 상대가 기물을 옮길 때마다 새로고침을 해야만 게임이 가능해질 것이다.
이건 아무래도 게임이라고 보긴 어렵다. 그렇다면 어떡해야 할까? 연결지향적인 TCP 통신을 이용하면 되는 걸까? 하지만 여기에도 커다란 문제가 있다. 응용 계층에서 TCP를 직접 사용하려면 개발자가 데이터 구조, 프로토콜 설계 등을 모두 직접 구현해야 한다는 점이다. 기존 웹 서버 인프라에선 이미 HTTP 프로토콜이 표준화되어 있으니 말이다.
→ 이럴 때 우리를 구원해 주는 것이 웹소켓이다.
웹소켓
- 웹소켓은 클라이언트와 서버 간에 실시간 양방향 통신을 가능하게 하는 프로토콜이다.
- HTTP와 다르게 한 번 연결이 이루어지면 지속적인 통신이 가능하다.
- 웹소켓은 데이터 패킷의 헤더가 작고, 요청-응답 구조 없이도 지속적인 통신이 가능하기 때문에 네트워크 자원을 더 효율적으로 사용할 수 있다.
- 웹소켓은 HTTP와의 호환성을 고려하여 설계되었다. 초기 연결을 설정할 때 HTTP 요청을 사용(핸드셰이크)하기 때문에 기존 웹 인프라를 그대로 활용할 수 있다.
정리
웹소켓은 TCP의 강력함을 기반으로 웹 환경에서 실시간 양방향 통신을 쉽게 구현할 수 있도록 설계된 응용 계층 프로토콜이다. TCP만으로도 동일한 기능을 구현할 수 있지만, 복잡성과 웹 표준과의 비호환성을 해결하기 위해 웹소켓이 필요하다. 따라서 "웹소켓은 TCP의 상위 개념에서 실시간 통신의 편의성을 제공하는 툴" 로 이해하면 된다.
웹소켓은 HTTP와의 호환성을 위해 초기 연결 시 HTTP 요청을 사용하며, 연결이 수립되면 HTTP에서 웹소켓 프로토콜로 전환된다. 이를 통해 기존 웹 인프라와 호환성을 유지하며, 지속적이고 효율적인 실시간 양방향 통신을 제공한다.
출처
[네트워크를 배우려는 사람들을 위해](https://www.youtube.com/watch?v=k1gyh9BlOT8&list=PLXvgR_grOs1BFH-TuqFsfHqbh-gpMbFoy)
[스파르타코딩클럽](https://online.spartacodingclub.kr/enrolleds/675679531e6a48cfb4a611e0/rounds/671717996b070ca0779980e1/roadmap)
[[10분 테코톡] ✨ 아론의 웹소켓&스프링](https://www.youtube.com/watch?v=rvss-_t6gzg&t=869s)
'개발일지 > TIL(Today I Learned)' 카테고리의 다른 글
2024-12-12 (0) | 2024.12.12 |
---|---|
2024-12-11 (0) | 2024.12.11 |
2024-12-09 (4) | 2024.12.09 |
2024-12-06 (2) | 2024.12.06 |
2024-12-05 (0) | 2024.12.05 |
댓글