목차
- TCP/IP 소켓 통신 이란?
- 소켓이 왜 필요한가
- 소켓(Socket) 이란?
- 소켓 종류
- 스트림 소켓(TCP) 통신 흐름
- Network 프레임워크
- 현대의 소켓 통신의 문제점
- 기존의 소켓 통신과의 연결 설정 단계 비교
- 기본 객체
- 연결 생명주기
소켓이 왜 필요한가
먼저 클라이언트-서버 간의 통신을 생각해보자.
클라이언트 입장에서는 1:1 통신이지만, 서버 입장에서는 1:N 통신을 수행해야 한다.
서버는 트래픽이 증폭해도 이를 견딜 수 있는 견고한 시스템을 구축해야 하는데, 이걸 가능하게 해주는 것이 소켓이다. (실시간 양방향 통신을 가능하게 해주는 WebSocket과는 개념이 다르다.)
우선 N명의 클라이언트로부터 요청이 들어올 때, 동시에 요청을 처리할 수 있는 방법은 무엇이 있을까?
가장 쉽게 생각할 수 있는 방법으로는 Thread를 N개 생성하는 것이다.
하지만 Thread를 그림자 분신술하여 다수의 클라이언트 요청을 처리하는 것은 위험한 발상이다.
- 쓰레드 간 공유자원 관리: 쓰레드 간의 공유 자원을 관리하기 위해 복잡한 동기화 문제가 발생할 것이며, race condition 등의 문제가 발생할 수 있다.
- 오버헤드: 쓰레드를 생성하고 관리하는 것은 굉장히 큰 비용을 지불해야 한다. 쓰레드를 사용할 것이라면 쓰레드 풀과 같은 방법들을 사용해야 하는데, 까다로울 것이다.
- 확장성 제한: 쓰레드는 CPU 코어 수에 제한을 받는다. 공간 복잡도 측면에서 봤을때 N개의 쓰레드를 만든다는 것은 제한적이며, 리소스를 많이 잡아먹는다.
소켓이라는 건 서버와 클라이언트의 IP 주소, 포트 번호, 연결 상태 등을 기록해 놓은 하나의 파일이다.
연결 정보들을 소켓들이 관리해줌으로써, 클라이언트의 요청마다 매번 새로운 프로세스 혹은 쓰레드를 생성하지 않아도 된다.
만약, 병렬적으로 작업을 처리하고 싶어진다면 멀티플렉싱(Multiplexing) 구현을 위해 소켓의 별도 쓰레드를 생성해주면 된다.
소켓(Socket) 이란?
네트워크를 경유하는 프로세스 간 통신의 종착점.
OSI 7계층 중 응용 계층에 속하는 프로세스들은 데이터 송수신을 위해 반드시 소켓을 거쳐 전송 계층으로 데이터를 전달해야한다.
즉, 소켓은 전송 계층과 응용 프로그램 사이의 인터페이스 역할을 하며 떨어져 있는 두 호스트를 연결해준다.
말을 어렵게 했지만, 소켓은 아래의 요소들을 담고 있는 하나의 파일인 것이다.
- 프로토콜
- 상대와 자신의 IP 주소
- Port 번호
- 통신 동작 진행 상태
소켓 종류
소켓은 프로토콜에 따라 두가지로 나뉜다.
- 스트림 소켓
- TCP 방식을 사용하는 연결지향방식의 소켓
- 송수신자의 연결을 보장하여 신뢰성있는 데이터 송수신이 가능
- 데이터의 순서 보장
- 소량의 데이터보다 대량 데이터 전송에 적합
- 점대점 연결
- 데이터그램 소켓
- UDP 방식을 사용하는 비연결 방식의 소켓
- 데이터의 순서와 신뢰성을 보장하기 어려움
- 점대점 뿐만 아니라 일대다 연결도 가능
- accept 과정 없이 소켓 생성 후 바로 데이터 송수신
스트림 소켓(TCP) 통신 흐름
서버는 아래와 같은 흐름으로 진행된다.
- 소켓 생성
- 바인딩(ip, port 번호 설정)
- listen()으로 클라이언트 요청에 대기열을 만들어 몇개의 클라이언트를 대기시킬지 결정
- accept(): 소켓 연결 요청이 오면, 3way-handshake 과정이 진행되고 클라이언트와 연결
- 데이터 송수신
- 소켓 닫기
클라이언트는 아래와 같은 흐름으로 진행된다.
- 소켓 생성
- listen 상태인 서버의 소켓에 연결 요청
- 3way-handshake 과정이 진행되고, 완료되면 소켓 상태가 Established로 바뀜
- 데이터 송수신
- 소켓 닫기
스트림 소켓(TCP) 통신 흐름에서 가장 중요한 것은 accept()
Netwrok.framework란?
WWDC에서는 소켓의 현대적인 대안이라고 소개한다.
Network.framework는 보안 및 전송 프로토콜을 사용하여 네트워크 연결을 설정하고 데이터를 주고받을 수 있다.
TLS, TCP, UDP와 같은 프로토콜에 직접 접근해야 하는 커스텀 앱 프로토콜을 사용할 때 해당 프레임워크를 사용할 수 있다.
현대의 소켓 통신
소켓은 30년간 발전해왔고, 오늘날의 인터넷을 위한 앱을 만들 때 불편함이 있다.
- 연결 설정
- 소켓은 주소에 연결됨. 따라서 대부분의 경우 호스트 이름이 존재. 이 호스트 이름을 주소로 전환해야 함.
- 현대에는 IPv4, IPv6 주소 체계가 있으므로 어떤 주소로 연결할 지, 어떤 순서로 시도할 지 결정해야 함.
- 주소 해석, 다중 주소 처리 등 연결 설정이 복잡
- 이러한 복잡성을 해결하는데 많은 노력이 듦.
- 데이터 전송
- 블로킹 소켓: 간단하지만 스레드를 점유
- 비블로킹 소켓: state machine 구축해야함. 보안 프로토콜을 지원하는 데 추가적인 복잡성
- 이동성 문제
- 현대의 모바일 장치는 네트워크 간 전환이 빈번.
기존의 소켓 통신과 연결 설정 단계 비교
- 기존 소켓통신에서의 연결 단계
- DNS 해석 진행: 호스트 이름을 IP 주소로 변환하기 위해 DNS(Domain Name System) 해석을 진행한다.
- 소켓 생성: 적절한 address family를 사용하여 소켓을 생성한다. 이 과정에서 TCP, UDP 같은 통신 프로토콜을 지정한다.
- addrss family?: 소켓 프로그래밍에서 사용되는 주소 체계 유형. IPv4, IPv6 등
- 소켓 옵션 설정: 예) 소켓을 비블로킹 모드로 설정하거나, 재사용 가능한 포트로 설정할 수 있음.
- TCP 연결 시작: 설정한 IP 주소를 사용해 서버에 연결을 시도한다. TCP 소켓은 이 과정에서 SYN 패킷을 서버에 전송한다.
writable event
대기: 연결이 완료될 때 까지 대기한다. 비블로킹 소켓의 경우 연결이 완료되면 쓰기 가능 이벤트를 대기한다.Writable Event
: non-blocking 소켓에서 주로 사용되는 개념. I/O 작업 시 스레드를 블로킹 하지 않고 즉시 리턴되는데, 이때 소켓이 데이터를 쓸 준비가 되었을 때 발생하는 이벤트.- non-blocking 모드에서
connect()
함수를 호출하면 즉시 리턴. - 실제로 연결이 완료되었는지 여부를 확인하기 위해서는
writable event
대기해야 함. writable event
발생 후, 소켓은 데이터가 쓸 준비가 된 상태임을 의미하며, 이후 데이터 전송 작업을 수행.
- non-blocking 모드에서
- network.framework를 사용한다면? → 간단하게 3단계!
- 셋업:
NWEndpoint
,NWParameters
사용하여 연결 생성한다. 연결할 서버의 엔드포인트(호스트 이름과 호스트 번호), 사용할 프로토콜을 이 단계에서 정하고,NWConnection
객체를 생성한다. - 연결 시작:
connection.start()
를 호출하여 연결을 시작한다. 내부적으로 네트워크 환경을 평가하고 최적의 연결을 시도한다. - 준비 완료 상태가 될 때까지 대기: 연결이 설정되었고, 준비 완료 상태가 될 때까지 대기한다. 이 단계에서는 TCP 핸드셰이크가 완료된 상태!
연결 설정하기 - 1. 연결 설정하기
위에서 언급한 세가지 단계의 코드를 살펴보자.
- 네트워크 모듈 임포트
- NWConnection 객체 생성
- 위 예시에서는 호스트와 포트를 사용해 엔드포인트를 초기화하는 생성자 사용!
- 포트에 예시처럼 말고도 숫자 리터럴 사용 가능
- 상태 업데이트 핸들러 설정 - 연결이 겪을 수 있는? 모든 전환을 처리
- 연결 시작
연결 설정하기 - 2. 기본 객체 살펴보기
NWEndPoint
: Network.framework에서 네트워크 통신의 종단점을 나타내는 객체이다.
서버, 클라이언트가 연결하고자 하는 대상의 주소와 포트 번호를 포함한다.
//종단 설정
let host = NWEndpoint.Host("example.com")
let port = NWEndpoint.Port("999999")!
let endpoint = NWEndpoint.hostPort(host: host, port: port)
NWParameters
: 네트워크 연결에 필요한 설정을 정의하는 객체이다. 프로토콜(TCP, UDP, TLS 등), 연결 옵션, 네트워크 경로 등을 포함한다.
let parameters = NWParameters(tls: .init(), tcp: .init())
NWConnection
: 데이터 읽기, 쓰기의 기본 객체- 네트워크 연결 설정, 데이터 송수신, 연결 상태 관리, 네트워크 경로 평가 및 선택, 네트워크 전환(WiFi ↔ 셀룰러) 및 이동성(예. 건물 나가면 다른 네트워크 연결되는 상황)
// 생성자 1 - 아래 wwdc 예제 코드
// 생성자 2
let connection = NWConnection(to: endpoint, using: parameters)
connection.start(queue: .main)
NWConnection
은 두 가지 생성자가 존재.init(host:port:using:)
: 주로 도메인 이름과 포트를 알고 있을 때 사용. 생성자 내부에서 도메인 이름을 IP 주소로 변환하는 과정 포함.- 간단!
init(to:using:)
: 각 파라미터에NWEndpoint
,NWParameter
타입이 들어감.NWEndpoint
객체를 직접 생성하여 사용할 때 유용.
연결 생명주기
- setup
- 연결 객체는 초기화되었지만, 아직 연결 설정 작업이 시작되지 않은 상태
- wating
- 네트워크가 사용 불가능한 상태 - 예) 와이파이나 셀룰러 사용 불가능할 때
- 혹은 연결 시도는 실패하지 않았지만, 네트워크가 사용 가능해질 때까지 대기 중.
- preparing
- 연결 설정이 진행중인 상태 - 네트워크 경로 평가, DNS 해석, 프록시 설정 등
- Smart Connection Establishment
- ready
- 연결이 성공적으로 설정되고, 데이터를 주고받을 준비 완료된 상태
- TCP 또는 TLS 핸드셰이크 완료된 상태
- failed
- 연결 설정이 실패한 상태 - 네트워크 문제 구성 오류 등으로 연결이 설정되지 않은 경우
- 다시 시도하거나 에러 처러 필요함.
- canclled
- 연결이 명시적으로 취소된 상태. 더 이상 데이터 송수신 불가능
- 연결 객체는 더 이상 유효하지 않음.
상태 전환 흐름
- setup → preparing
- NWConnection 객체 생성 후
start
메서드 호출하면 전환됨.
- NWConnection 객체 생성 후
- preparing → ready
- 연결 설정 과정이 완료 되면, 상태 변경됨. 데이터 송수신 가능
- preparing → wating
- 연결 설정 과정 중 네트워크 사용이 불가능하거나 다른 이유로 일시적 대기가 필요할 때
- 네트워크가 사용 가능해지면 자동으로 다시 연결 시도
- wating → preparing
- 대기 중이던 네트워크가 사용가능해질 때, 상태가 다시
preparing
으로 전환되고 연결 설정을 계속 진행.
- 대기 중이던 네트워크가 사용가능해질 때, 상태가 다시
- preparing → failed
- 연결 설정 중 오류 발생 or 네트워크 문제로 인해 연결 실패 시
- ready → failed
- 연결이 설정된 후 데이터 송수신 중에 오류 발생
- ready → cancelled
- 연결이 설정된 후 사용자가 연결을 명시적으로 취소.
참고 링크
https://juyoung-1008.tistory.com/19
https://jaeseo0519.tistory.com/168
https://velog.io/@newdana01/소켓이란-종류-통신-흐름-HTTP통신과의-차이
https://velog.io/@ssw123/네트워크-Socket-통신
https://developer.apple.com/documentation/network
https://developer.apple.com/wwdc18/715
https://vapor3965.tistory.com/33
https://ghis22130.github.io/2021-02-02-Network-Framework/
'부스트캠프' 카테고리의 다른 글
View(ViewController) Life Cycle (0) | 2024.08.21 |
---|---|
네이버 부스트캠프 웹・모바일 9기 챌린지 과정을 마치며 (0) | 2024.08.11 |
HTTP Request, Response 구조 (0) | 2024.08.05 |
네이버 부스트캠프 웹・모바일 9기 챌린지 과정 3주차 회고 (0) | 2024.08.02 |
Git 동작 방식 (0) | 2024.07.31 |