Computer Science/Network

[Network] 유선 환경에서의 대략적인 웹 통신 원리

나죽못고나강뿐 2023. 2. 22. 16:34
"개발자라면 어느 분야로 나가던 네트워크 지식은 필수다"

어느정도 개발 공부를 해본 사람이라면 위에서 언급한 말을 적어도 한 번쯤은 들어보았을 것이라 생각한다.

나는 비록 재미와 호기심으로 네트워크를 공부했었지만, 해보고 나서야 왜 그런 이야기를 했었는지 알게 되었다.

이번 포스팅은 자세한 이야기는 모두 건너 뛰고 유선 환경에서 웹 통신을 할 때 발생하는 네트워크 원리에 대해 알아보고, 그래서 왜 네트워크 지식이 필요한지에 대해서 정리해보려 한다.

 

목차
1. What is Network?
2. 아주 많은 내용들이 생략된 클라이언트와 서버 간의 통신
3. Protocol Stack
4. TCP/IP 5 Layer 동작
5. Summary

1. What is Network?

 

Network는 Net + Work의 합성어로 두 개 이상 컴퓨터나 장치가 연결되어 데이터를 주고 받을 수 있는 상호 연결 시스템을 말한다.

매우 광범위한 의미로 사용될 수 있는 용어라서 네트워크 기기 사이에서 데이터를 주고받는 데 사용하는 하드웨어, 소프트웨어, 프로토콜을 모두 포함한다.

 

몇 가지 용어를 조금만 더 짚고 넘어가면 이렇다.

  • 프로토콜(Protocol): 네크워크에서의 통신 규약으로써 데이터를 주고 받을 때 지켜야하는 약속이다.
  • 웹(Web): World Wide Web의 약어로, 인터넷 상에서 정보를 공유 및 검색할 수 있는 공간을 의미한다.
  • 운영체제(OS, Operating System): 하드웨어와 응용 프로그램 중재자 역할 및 컴퓨터 시스템 전체를 관리
  • 커널(Kernel): 운영체제의 일부분이자 핵심 요소이다. 하드웨어나 응용 프로그램 간의 인터페이스 역할을 수행한다.

베이스으로 깔고 넘어가야 하는 내용이다.

하나하나가 정말 많은 내용을 포함하고 있지만, 지금 당장은 이 정도만 알아도 아래 내용을 이해하는데 큰 어려움은 없다.


2. 아주 많은 내용들이 생략된 클라이언트와 서버 간의 통신

 

클라이언트가 서버에 request를 보내면 Server는 이에 해당하는 자원을 response로 돌려준다.

정말 매우 단순하게 이야기하면 클라이언트와 서버 간의 통신은 이게 끝이다.

하지만 당연히 그 내부 과정은 매우 복잡하다.

 

Client를 '나'의 PC고 Server를 네이버라고 가정해보자.

Client가 "https://www.naver.com"이라고 브라우저에 입력하면, 누구나 알고 있듯이 naver 메인 화면이 렌더링된다.

네이버 메인 화면과 관련된 정보가 내 PC에 저장되어 있는 것은 아닐테니, 해당 화면을 표시하기 위해서 Naver 서버에 접근하여 메인 화면 정보를 받아왔다고 생각하는 것이 맞다.

 

네이버 메인 화면에서 '개발자 도구-네트워크'를 열고 'www.naver.com'을 찾아보면 어떤 요청과 응답이 오고 갔는지 알 수 있다.

요청 url로 'https://www.naver.com/"은 https 프로토콜을 사용하여 통신을 하였으며, 필요 자원은 com-naver-www 순서로 DNS Server라는 곳을 조회해 얻어낸 자원의 IP 주소를 탐색 후 request를 보낸다.

그럼 정상적으로 요청을 받은 Naver Server에서 이에 상응하는 자원들을 response하여 Client에 도착하면, 파일들을 잘 정렬하여 화면에 띄운 것을 사용자가 볼 수 있게 되는 것이다.

 

url, https, DNS Server, IP 주소 등등 낯선 용어가 많더라도 지금은 그렇구나 하고 넘어가자.

이 모든 내용은 이후 포스팅에서 차례대로 다루면서 익히는 것이 정리하기 쉽다.


3. Protocol Stack

 

서버와 클라이언트의 내부 작업은 매우 비슷하나 차이가 있다.

클라이언트는 서버와 1:1로 통신을 시도하지만, 서버 입장에선 1:1 통신을 N개의 Client와 진행하므로 내부적으로 작동 순서나 방식이 다를 수밖에 없다.

그래도 정말정말 기초적인 내용들로만 정리해보자. (할 수 있다. 나 자신 😊)

 

📌 TCP/IP 5계층

 

 

인터넷 프로토콜 스위트 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 인터넷 프로토콜 스위트(영어: Internet Protocol Suite)는 인터넷에서 컴퓨터들이 서로 정보를 주고받는 데 쓰이는 통신규약(프로토콜)의 모음이다. 인터넷 프로토콜

ko.wikipedia.org

https://ko.wikipedia.org/wiki/%EC%9D%B8%ED%84%B0%EB%84%B7_%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C_%EC%8A%A4%EC%9C%84%ED%8A%B8

논리적으로는 7계층으로 나뉘지만, 이미 5계층으로 장치들이 만들어진 후에 나온 개념이라 실제로는 5계층이 사용된다.

(OSI 7계층, TCP/IP 4계층이라 하는데 나는 Network Access Layer을 두 개로 분리한 5계층으로 학습했다.)

  • L5(Application): 사용자와 가장 가까운 계층. HTTP/SMTP/FTP 같은 사용자-소프트웨어 간 소통을 담당한다.
  • L4(Transport): TCP/UDP(P는 Protocol)을 선택하여 신뢰선 있는 데이터 송수신 방식을 결정한다.
  • L3(Network): 인터넷에 연결된 모든 네트워크 장치를 구분하기 위해 IP 주소 이용. (인터넷에서 주소 찾기)
  • L2(Data Link): 각 기기에 부여된 고유 주소(Mac Addr)를 할당한다. (해당 네트워크 에서 주소 찾기)
  • L1(Physical): 여기까지 오면 전자과 레벨. 데이터를 신호로 바꾸어 케이블 및 무선 전파로 bit를 주고 받는다.

위 내용을 그림으로 표현하면 다음과 같다.

(좌)Client, (우)Server

요샌 대부분 TCP/IP 통신을 쓰기도 하고, 애초에 TCP/IP 5계층을 예시로 들기로 했으니 Kernel에도 TCP와 IP가 역할을 수행할 것이다.

참고로 IP는 Internet Protocol의 약자로, IP 주소를 사용하여 인터넷 상에서 목적지를 알아내는 역할을 수행하는 것이다.

(혹시나 네트워크 지식에 무지하던 과거의 나처럼 읽다가 혼동하지 않았으면 해서,,,🥲)

 

📌 계층 분리 목적

 

이렇게 계층을 분리해서 얻을 수 있는 가장 큰 이점은 '역할 분담'이다.

 

교수님께서 재밌는 예시를 들어주셨었는데, Client가 CEO인 '나'고 Server가 거래처의 CEO라고 가정하자.

내가 상대측 CEO에게 메일을 주려고 하면 우선 내용을 작성하고, 편지 봉투에 넣고, 봉투에 받는이/보내는 이를 쓰고 우체국에 편지 봉투를 맡겨야 한다.

상대측 CEO 또한 편지 봉투를 받아서 자신에게 온 편지가 맞는지 확인을 하고, 편지 봉투를 뜯은 다음, 내용을 확인한다. 

그런데 CEO가 동네 구멍 가게 사장님도 아니고 하는 일이 얼마나 많은데 이런 걸 다 하고 있겠는가.

그래서 체계적으로 분업을 하기 시작했다.

  • L5: 편지 내용을 쓰고 L4 비서에게 건넨다.. 
  • L4: 편지 종류에 따라 담을 편지 봉투를 선택한다.
  • L3: 봉투에 보내는 이와 받는 이의 회사 주소를 적는다.
  • L2: 봉투에 보내는 이와 받는 이의 회사 내의 직책(주소)를 적는다.
  • L1: 우체국에 맡겨 편지를 송/수신한다.

이렇게 하면 CEO인 나는 편지를 쓰고 밑으로 건네주기만 하면, 답장이 돌아오는 것을 기다리다가 받기만 하면 된다.

비서실은 편지 내용을 알 수도 없고 관심도 없다.  그저 어떤 편지 봉투를 고를지만 결정하면 되고, 이는 다른 계층 또한 마찬가지다.

만약, 비서실에 문제가 생기면 비서실 인력만 바꾸면 그만이기 때문에 해당 계층만 수정하여 전체 시스템에 미치는 영향 또한 적어진다.

또한 편지를 송/수신 방식이 서로 다른 우체국 종류가 많아지더라도 각 부서의 직무를 적절히 조합하여 처리한다면, 어떠한 우체국을 사용하더라도 송/수신이 가능해진다.

 

이 내용을 다시 TCP/IP 5계층 분리 목적으로 설명하면 이렇다.

  첫째, 계층을 분리함으로써 각 계층은 서로 독립적으로 설계될 수 있다. 즉, 각 계층은 자신의 기능에만 집중하면 되므로 복잡도가 낮아지고, 유지보수 및 업그레이드가 쉬워진다.
  둘째, 계층을 분리하면 다른 계층과의 인터페이스를 통해 상호작용할 수 있다. 예를 들어, 전송 계층의 프로토콜인 TCP는 인터넷 계층의 프로토콜인 IP를 사용하여 데이터를 전송한다. 이러한 인터페이스를 통해 각 계층은 자신이 관리하는 일부 기능을 다른 계층에게 위임할 수 있다.
  셋째, 계층을 분리함으로써 프로토콜을 교체하거나 추가하기 쉬워진다. 새로운 프로토콜을 추가하거나 기존의 프로토콜을 변경하려면 해당하는 계층만 수정하면 되므로, 전체 시스템에 미치는 영향이 최소화된다.
  마지막으로, 계층을 분리함으로써 네트워크를 구성하는 다양한 기술들을 조합하여 사용할 수 있다. 예를 들어, 이더넷, Wi-Fi, DSL 등 다양한 물리 계층 기술을 사용하여 네트워크를 구성하고, 인터넷 계층과 전송 계층에서는 이러한 기술들을 추상화하여 사용할 수 있다. 이를 통해 다양한 환경에서 동작하는 네트워크 시스템을 구축할 수 있다.

 

📌 Flow

 

 

역할 분리 목적을 이해했다면 Client의 Request가 Server로 가기 위해서 어떤 흐름으로 가야하는지 이해했을 것이다.

Client의 NIC을 거쳐 Server의 NIC에 도달하면 우선 편지 봉투를 뜯어야 한다.

즉, 송신 과정은 수신 과정의 역순으로 진행되며, 각 계층이 서로 소통하고 있다.

(Client의 Data Link Layer가 한 작업은 Server의 Data Link Layer만이 해석할 수 있다.)


4. TCP/IP 5 Layer 동작

 

클라이언트가 메시지를 송신하는 과정부터 살펴보자.

도메인 주소로 부터 IP 주소를 획득하는 DNS 관련 내용은 생략한다.

여기서는 IP주소를 이미 알아냈다는 가정 하에 진행된다.

 

1️⃣ Application Layer

예시는 naver 포털 검색창에 "Hello, Naver"라는 검색어를 입력했을 때를 예시로 들 것이다.

우선 "Hello, Naver"라는 단어에 대한 결과를 조회하기 위해 서버로 문자열을 전송해야 한다.

그러기 위해서는 첫 번째로 네이버 서버와 클라이언트를 연결하는 작업이 필요하다.

유저는 커널에 직접적인 접근이 불가능하다. (커널은 운영체제의 매우 핵심적인 부분이므로 잘못 접근했다가 손상이 되면 치명적인 에러가 발생할 수 있기 때문)

그래서 Socket 라이브러리의 socket 함수를 호출하여 IP주소와 TCP 프로토콜 사용 정보(여기선 tcp를 사용하기로 했으므로) 등을 넘겨주면 소켓을 작성한다.

✒️ 구분을 위한 용어 정리
• 소켓: 일종의 파일. 제어 정보가 기록되어 있다.
• Socket: 라이브러리. 네트워크 통신을 위한  API를 제공하고, 다른 컴퓨터와 통신하기 위한 프로그램을 작성.
• socket: Socket 라이브러리 안의 소켓 생성 함수
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

 

작성된 소켓

서버 측에서는 약속된 규정에 따라 포트를 열어놓고 포트와 매칭된 소켓을 열어놓고 대기하고 있기 때문에, Request payload를 보내기 전에 우선 소켓 정보를 서버와 일치시키는 작업이 필요하다. (이후에 깊게 다룰 예정)

여기서는 일단 어떻게 소켓을 잘 연결했다고 치고 메시지를 보내는 작업만 설명할 것이다.

 

우측의 ⨿ 모양은 버퍼를 의미한다.

소켓이 연결되면 서버 측과 정상적으로 송/수신이 가능한 상태가 되었으므로 "https Request message"를 작성하여 Kernel의 TCP에 넘긴다.

 

💻 실제 메시지 내용

query에 "안녕하세요"라는 문자열 정보가 넘어간다.

 

2️⃣ Transport Layer

Client Memory에 있던 메시지가 TCP Memory에 적재가 되면, 이제 TCP는 상대 TCP와 대화하기 위한 헤더를 덧붙인다.

TCP 헤더는 소켓 제어 정보를 담는 것이 목적인데, 정보로는 송/수신처 각각의 포트 번호, 시퀀스 번호, ACK 번호 등을 보낸다. (모르겠으면 지금은 일단 "TCP끼리만의 정보가 필요하구나!" 정도로 넘어가시면 됩니다.)

 

계층이 내려갈 때마다 IP에서는 IP헤더를 붙이고 Data Link Layer에서는 Mac 헤더를 붙이는 식으로 이어지게 된다.

지금은 헤더에 어떤 정보가 담기느냐는 알 필요 없고, 계층이 내려갈 때마다 헤더가 붙고 반대로 수신동작에서는 헤더가 벗겨지는 걸 이해해도 충분하다.

 

이렇게 Message + TCP Header가 결합되면 여기서 부턴 Segment라고 부른다.

 

3️⃣ Network Layer

TCP에서 IP로 데이터를 내리면 마찬가지로 IP에서는 자신이 담당하고 있는 필요 정보를 IP 헤더로 덧붙인다.

(마찬가지로 지금 헤더 정보에 대해서 알 필요는 없다.)

Segment + IP 헤더가 붙으면 이제 Packet이라고 부른다.

 

이쯤에서 알고 넘어가면 좋은 개념이 있는데, 바로 Fragmentation(조각 나누기) 동작이다.

✒️ Fragment

TCP에서 IP로 데이터를 내릴 때, 조각으로 분할하여 보내는 것이다.
데이터는 어찌됐건 케이블이나 무선 신호와 같은 물리적인 매개체를 거쳐야 하기 때문에 전송 가능한 최대/최소 크기가 정해져 있다.
만약, 서버에서 클라이언트로 방대한 양의 자원을 보내야 하는 경우 데이터를 작게 분할한다.
(혹은 네트워크 환경에 따라서 의도적으로 데이터를 잘게 쪼개어 보내는 경우도 있다.)
잘게 쪼개진 데이터를 IP가 내려 받으면 각각의 조각에 IP 헤더를 붙이는데, 이때 붙는 헤더 정보는 모두 동일하다.

 

4️⃣ Data Link Layer & Physical

Packet을 전달받으면 해당 기기의 고유 주소인 Mac 주소와 one-hop만큼 떨어진 라우터의 Mac 주소와 관련된 정보를 담은 MAC 헤더를 덧붙여 Frame을 완성시킨다. (위에서 언급하면 용어가 혼동될까봐 언급하지 않았지만, 관용적으로 Segment, Frame을 모두 Packet이라 하는 경우가 있다. 문맥에 따라 Packet이 어느 계층의 데이터를 언급하는지 판단해야 할 수도 있다.)

one-hop만큼 떨어진 Router가 뭔지도 지금은 알 필요가 없다. 어차피 플로우만 알면 되니까.

 

이렇게 완성된 프레임을 물리적인 장치(케이블)로 보내기 위해서 전기 신호로 바꾸어 송신을 한다.

그런데 케이블은 아무래도 물리적인 요소다 보니 전기 신호가 이동하다가 열 손실 등으로 인해, 데이터가 손상되거나 사라질 수도 있다.

또한 전기 신호는 다른 기기와 겹쳐질 경우 충돌(Collision)이 발생할 수 있으므로 이를 중재할 중재자가 필요하다.

따라서 중간중간 허브나 라우터 같은 기기들이 신호를 전달받아 목적지까지 잘 도착할 수 있도록 전달하는 역할을 한다.

 


5. Summary

 

여기까지 읽은 사람이 있을까 싶긴 하지만 여튼 서두에서 언급했던 "개발자가 Network 지식을 알아야 하는 이유"에 대해서 아주 짧게 소개하고자 한다.

서버의 데이터 수신 과정은 클라이언트의 역과정이라고 생각하면 된다.

헤더를 보고 주소를 판단하고, 목적지가 내가 맞다면 데이터를 위 계층으로 올려보내 정상적으로 수신할 수 있도록 만들어야 하는 것이다.

문제는 여기서 발생한다.

 

수신 측이 데이터를 받는 속도는 Network 속도보다 언제나 빨라야 한다.

만약 패킷을 다시 조립하여 데이터를 재구성하는 과정에서 속도 차이가 발생해 Receive 속도가 느려진다면, 제때 수신되지 못한 패킷은 버려지고, 그로인하여 전체 전송 속도 또한 떨어지게 되기 때문이다.

또한, 패킷 재구성 시간이 오래 걸리게 되면, 패킷 일부가 유효하지 않은 데이터로 처리되어 버릴 수 있는데, 이 경우 전체 데이터의 무결성 문제로 이어질 수도 있다.

 

트래픽이 증가하여 서버 응답 속도가 지연된다면 개발자는 로우 레벨로 내려가 문제를 개선해야 하는 때가 올 것이다.

그 때 네트워크 지식을 알고 있는 개발자와 전혀 이해조차 못하고 코드만 짤 수 있는 개발자.

과연 실무에서는 어떤 인재를 원할까?

 

+ API 개발을 해보면 Port, IP 같은 기본적인 지식을 알아야 클라우드 배포가 가능하다.