개요
이론(Architecture) →
구현(Modern Concurrency) →
성능(Performance) →
안정성(Reliability & Security) →
관측(Observability)
TCP
- 신뢰성과 순서 보장이 핵심
- 3-Way Handshake
- 데이터를 잘게 쪼개서 순서대로 번호를 매김 (스트림으로 계속 쭉쭉쭉)
- 한번 연결하면 그 경로로 계속 보냄
- 받는 사람의 처리 능력을 확인해서 보내는 속도 조절 및 혼잡 제어
- 1번 패킷이 늦게 오면 뒤의 순번의 패킷은 1번 올때까지 기다려야됨
UDP
- 속도와 효율이 핵심
- 연결과정이 없고 주소보고 그냥 보냄
- 그냥 그때 빠른 경로로 보냄
- 데이터가 독립적인 패킷으로 날아감
- 헤더가 매우 가벼움
HTTP
- 웹 브라우저가 서버와 대화하는 규칙
- 무상태성임, 직전에 무엇을 요청했는지 모름, 로그인이 되어있는지 기억하지 않음 따라서 쿠키 세션 토큰을 활용함
- 용건이 끝나면 바로 연결을 끊어버림
- 요청은
GET /index.html HTTP/1.1이런식으로 시작해서 헤더와 바디로 이루어져있다 - 응답은
HTTP/1.1 200 OK와 헤더와 바디로 이루어져있다
HTTP/1.1
- 이 프로토콜은 TCP 기반으로 동작하여 3way Handshake가 있음. 근데 기본적으로 비연결성이라 요청이 끝나면 연결을 끝내버려 오버헤드발생
- keep alive 기능으로 한번 연결되면 계속 유지하였음
- 텍스트 기반으로 전송 헤더와 바디등 구분은 줄바꿈문자로 진행하여 파싱하는 오버헤드
- 하나의 차선을 가진 고속도로
- 이미지 AAAAAAAAA~~~~~~~
- 텍스트 BBBBBB
- 스타일 CC
- 이런 데이터들이 있으면 이미지 수신 끝날때까지 짧은 데이터인 텍스트와 스타일은 로드가 되지않고 기다려야됨
- HOLB(Head Of Line Blocking)문제가 있음
- TCP 연결의 한계로 이전 순위 패킷이 늦게오면 이후 순위가 먼저와도 기다려야됨
- 헤더가 매번 중복되어서 전송되어 패킷이 무거움
HTTP/2.0
- SPDY 프로토콜을 기반으로 동작 HTTP 1.1에서 성능 향상에 초점을 맞춤
- HOLB문제를 해결하기 위해 멀티플렉싱이라는 기술을 활용하였음
- 바이너리로 전송하여 문자열 파싱이 필요없이 여기서부터 10바이트는 제목~ 이런식으로 쪼개서 사용가능
- 여러개의 차선을 가진 고속도로로 응답을 수많은 프레임으로 쪼개서 번호표를 붙여 와다다 보냄
- 이미지 AAAAAAAAA~~~~~~~
- 텍스트 BBBBBB
- 스타일 CC
- 이런 데이터들이 있으면 AA BB CC 이렇게 프레임 단위로 쪼개서 번호표를 붙임
- 프레임을 여러 스트림으로 와다다다 보냄
- 수신하는 측은 도착하는 프레임들을 모아서 렌더링함
- 하나의 연결에 여러 요청과 응답이 뒤섞여 순서가 엉망이 됨 따라서 앱은 서버로 보낼때 요청마다 우선순위를 매기고 서버는 그거대로 우선처리
- 중복된 헤더는 안보내는 HPACK 압축하여 보냄
- 멀티플렉싱으로 응용 계층의 HOLB는 해결 그러나 커넥션 안에서 하나의 패킷이라도 유실되면 수습될때까지 나머지 친구들도 대기함(전송계층에서는 해결못함)
HTTP/3.0
- 핸드쉐이크 과정의 오버헤드와 패킷 유실할 때 HOLB문제는 그대로임
- 이전 세대의 문제들은 TCP가 문제임 따라서 UDP 기반의 QUIC 프로토콜(전송계층)로 새로운 판을 짬
- UDP 위에 TCP의 장점인 신뢰성을 소프트웨어적으로 구현한것임
- TCP의 가장 큰 문제는 보낸순서와 데이터 순서를 하나의 번호로 관리함
- QUIC는 이 두개를 분리함 예를들어 이건 2번째로 보냈지만 데이터는 이미지의 100번째 위치에 있는 바이너리야
- TCP는 ACK를 보내서 ㅇㅋ 받았음 정도만 알려주지만 QUIC는 뭐를 못받은지도 알려줌
- TCP는 하나라도 유실되면 그뒤는 기다리지만 QUIC는 그 유실된 Stream만 재전송하고 나머지는 계속 보냄
- TCP의 신뢰성은 운영체제 커널이 담당하지만 QUIC는 응용 계층(앱)의 프로세스 메모리 안에서 실행됨
- TCP는 클라이언트와 서버를 구분하기 위해 각각의 IP, PORT 총 4개가 필요하지만 QUIC는 ConnectionID를 사용해서 그게 같으면 ip나 포트가 달라져도 같은것으로 인식
- 기존에는 osi 계층별로 역할이 명확하였으나 QUIC는 전송계층의 역할을 하면서 내부적으로 TLS를 내장하여 연결과 동시에 보안 키를 교환
- 또한 멀티플렉싱도 QUIC가 담당한다. HTTP2가 데이터 쪼개고 순서 번호 붙여서 TCP한테 줬다면 QUIC가 그것도 담당해서 HTTP3는 그냥 데이터만 넘김
URLSession
- 앱 레벨의 HTTP(S)/FTP등 고수준 API
- OSI 7 Layer에서 응용계층의 개념을 담당
- 주로 REST API 통신, 파일 다운로드등에서 사용
- SessionConfiguration(default / ephemeral / background)를 통해 세션을 설정할 수 있음
- Task 타입
- dataTask : 메모리로 응답을 모아서 전달
- downloadTask : 디스크로 스트리밍 저장, 큰 파일을 수신할 때 사용, 백그라운드 지원
- uploadTask : 업로드 전용으로 큰 파일을 보낼때 사용, 백그라운드 지원
- streamTask : TCP 연결용
- 일반 통신
- 실제 통신은 nsurlsessionnd가 담당한다. 패킷도 나르고 TCP 연결도 한다.
- 그러나 생명주기가 앱 프로세스에 종속되어있어 앱이 비활성화중이면 연결을 끊는다.
- 백그라운드 다운로드는 Out-of-Process 구조임
- XPC로 시스템 프로세스인 nsurlsessiond로 전달
- nsurlsessiond는 실제 데이터 송수신을 하고 버퍼에 데이터를 쌓음
- 데이터 수신이 완료되면 다시 XPC를 통해 앱의 URLSessionDelegate를 호출함
- 이런 구조때문에 백그라운드에서는 클로저를 이용할 수 없는데 클로저는 앱 프로세스의 힙 영역에 있기 때문, 델리겟으로 응답을 받음
- URLSession은 같은 호스트/포트/프로토콜에 대해 한번 연결한 커넥션을 재사용한다(핸드쉐이크 안해도됨)
- data.resume()을 하면 일어나는 일
- Network.framework가 앱 메모리(User Space)에서 패킷을 처리할 준비
- Smart Connection이 IPv4/IPv6/wifi/cellular중 가장 빠른 경로를 경주시켜 찾아냄
- 기존에 뚫어놓은 Connection Pool이 있다면 재사용하고 없다면 HTTP/2,3연결을 새로 뚫음
- 응용계층의 HTTP/HTTPS 전용이며 일반적인 앱개발의 99%는 이거 사용함, Network 프레임워크로 구현되어있음
- Network 프레임워크는 전송계층에서 TCP, UDP, TLS, QUIC등을 직접 제어함
URLSessionConfiguration
- 네트워크 동작을 정의하는 control center 역할, 세션을 만들때 같이 설정하며 이후 수정 불가능