인프라/네트워크

1.4MB 사진 파일이 서버에서 클라이언트로 전송되는 방식

EVO. 2023. 12. 31. 16:42

예를들어, 네이버라는 서버가 있고 한 클라이언트가 네이버서버에 사진 파일 (약 1.4MB 정도의 크기. 패킷 MTU 보다 약 1400배 큰 크기)을 요청 한다고  하자.


네이버 서버는 먼저 HDD / SDD 에 저장된 1.4MB 파일을 애플리케이션에 올린다. 그러나 보통은 1.4MB라는 방대한 크기를 한꺼번에 읽어서 올리지는 않는다. 예를들면 애플리케이션 내에 버퍼 (자료구조 중 하나를 이용할거라 추측된다) 크기가 15바이트 정도라면 1.4MB의 사진 파일 중 5픽셀 정도(RGB 채널 이라면 1픽셀당 3바이트 이기 때문에) 만큼 NIO Buffer를 활용해서 copy 작업을 한다. 

 

 

 


이제 socket 파일의 출력 스트림에 버퍼에 저장되있던 데이터를 I/O Copy를 한다. (Send / Receive 작업)


소켓 버퍼의 크기는 데이터 단위가 Stream이기 때문에 긴 데이터가 저장되있다고 추측한다. (아무튼 몇 mb일수도 있고 굉장히 크다) 하지만 L4 계층인 TCP에 데이터를 보내려면 최대 크기가 MSS, 약 1460바이트 크기인 Segment 단위이기 때문에 소켓에서 이들을 세그먼트 단위로 분해하는 작업인 세그멘테이션 작업을 수행한 후 L4계층으로 보낸다. + 추가적으로 세그먼트의 번호도 부여한다. 그리고나서 세그먼트를 TCP 헤더 까지 붙이는 작업을 수행한다. 그리고 이 세그먼트를 L3 계층으로 보내서 세그먼트 하나를 패킷화 (IP 관련 헤더도 부착하는 작업)한다.

 

 

 


 

L2 계층으로 가고 최종적으로 네트워크 상에 보내기 위한 Frame 형태로 만든다.(Mac 주소등을 추가적으로 부착) 그리고 나서 스위치를 통해 목적지까지 전달된다.

트럭으로 여러 host에서 받은 Frame들을 전달하는 것을 비유해서 표현했다

 


수신 측에서는 정반대의 일이 일어난다. (decapsulation)

 

 

 

 


1세그먼트를 소켓 버퍼에 채우는 작업을 한다. 이때 소켓 버퍼에 채우면서 상대적으로 여유공간이 줄어든다(여유공간이 매우 중요) 크롬도 역시 버퍼가 있다. 그래서 소켓 버퍼에서 read(receive) 작업을 한다. 즉 네트워크에서 계속 소켓버퍼는 채우고 크롬은 퍼내는 행위를 계속한다. 

 

 


수신 측은 해당 패킷을 잘 받았다고 ACK을 날리며 다음 세그먼트 번호와 여유크기를 같이 보낸다. 한편, 송신측은 일정 크기의 세그먼트들을 각각 보내고 수신측이 잘받았다는 ACK이 올때까지 기다리는 Wait for ACK 행위를 한다. 

 

 


전체적인 그림을 보면 다음과 같다.

 

 

 


 

 

 

이러한 과정에서 네트워크 장애가 일어날 가능성이 있다.

 

- Loss(유실) : 네트워크 오류. 패킷이 1,2,3 순서대로 받아야하는데 4번 패킷만을 받은 경우 손실이 일어났음을 알수가 있다.

 

- 일정시간안에 ACK이 오지않으면 송신측에서 다시 패킷을 보낸다. 그런데 간발의 차이로 다시 패킷을 보내자마자 ACK이라는 신호가 오게되면 결론적으로 중복된 패킷을 수신측에서 받는 문제가 생길 수 있다 : 엔드포인트끼리 합이 안맞는 경우이다.

 

- Out of order : 1->3->2 번 패킷. 순서가 잘못된 경우로 네트워크 문제이다.

 

- zero window : 여유공간의 메모리 크기를 window size라 부르는데 이 여유공간이 0인 경우이다. 이때는 애플리케이션이 소켓버퍼에 있는 데이터를 제대로 퍼올리지 않아서 생기는 이슈로 프로그램을 잘 수정해야 한다.

 

 

지금까지 전체적인 그림을 봤다. 이 그림을 머리속에 넣고 네트워크 공부를 하면 수월하게 공부가 될 것 같다.

 

 

 

레퍼런스

https://www.inflearn.com/course/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%ED%95%B5%EC%8B%AC%EC%9D%B4%EB%A1%A0-%EA%B8%B0%EC%B4%88/dashboard