IP(Internet Protocol)

가상의 인터넷 환경에서 메세지를 주고받기 위해선 상호간의 위치를 지정할수 있는 주소가 필요한데 이를 IP주소라고 칭한다.

초기의 인터넷 환경이 작았을땐 다이렉트로 연결하면 무방했지만 점차 웹은 더 넓은 영역을 갖게되었고 이를 보완하고자 나타난것이 IP 프로토콜이다.

IP는 지정한 주소에 데이터를 전달 및 패킷이란 단위로 데이터를 전달한다.(출발 및 목적지 IP, 기타 정보로 통상적으로 1500byte로 전달)



IP프로토콜의 한계

1. 비연결성(Connectionless)

  • 클라이언트와 서버가 한번 연결을 맺은후 서버가 응답을 마치면 연결을 끊는것(쉽게 말해 줄서있던사람이 용건이 끝나면 보내되 추가적인 용건이 생긴다면 줄 맨뒤로 보내버리는것) -> 그때마다 핸드쉐이킹을 진행해야 하기에 오버헤드가 발생할 여지가 있다.
  • 만일 연결을 유지할경우 서버는 이를 위해 지속적인 자원을 할애해야하며 이는 곧 서버의 효율저하를 초래한다. (서버 자원의 효율화)
  • 오버헤드를 줄이기 위해서 HTTP의 KeepAlive속성을 사용할수 있다 (일정 시간동안 서버-클라이언트간 패킷 교환이 없을경우 상대방에게 패킷을 주기적으로 보내며 이에 대한 응답이 없을경우 연결을 끊어버리는것 )
  • 요청을 받을경우 상대의 상태가 어떻든(꺼져있거나 주소가 다르거나 하여도) 일단 보내고 연결을 끊어버리기에 의도한 순서나 결과에 맞지 않는 결과가 출력된다.

2. 비신뢰성

  • 중간에 패킷이 사라지거나(패킷소실), 패킷의 순서가 다를경우(1500Byte가 초과될경우 패킷을 분할하여 보내나 모두가 동일한 경로로 가지 않기 때문에 순서가 다르게 도착할 우려가있다.)

3. 프로그램 구분 불가능

  • 동일한 IP를 사용하는 서버에서 통신하는 애플리케이션이 2개 이상일경우 어떤 애플리케이션으로 전달해야할지 구분이 어렵다 

이러한 문제는 후술할 TCP/UDP를 통하여 해결하였다.

 

오버헤드 -  어떤 처리를 하기위해 들어가는 간접적인 처리시간


TCP/UDP

Transmission Control Protocol (TCP) - 전송 제어 프로토콜

  • 데이터를 보내는데 연결이 필요하다. ->핸드쉐이크를 통한 목적지 상태를 점검 (IP프로토콜 3번)
  • 자료가 스트림 형태로 전송되며 타 컴퓨터에서 수신되어 링크가 생성되는 연결기반이다. 
  • 3way-hanshake를 통한 작업이 많기에 신뢰성, 연결성이 보장되나 속도가 떨어진다 (실질적인 데이터 전송이 이뤄지기전 진행하는 과정으로 목적지의 상태가 멀쩡한지 확인하는 과정이 추가된다. -> IP프로토콜 1번 해결)
  • 데이터 전달 보증 - 패킷소실이 일어나도 클라이언트가 해당 사실을 인지할수 있도록 알려준다(Sequence number 참조) -> IP프로토콜 2번 해결
  • 가상회선 방식 - 데이터 전송전 논리적인 연결이 설정되는데 각 패킷마다 가상회선 식별번호(VCI, Virtual Circuit Identifier)가 포함되어 모든 패킷이 전송되면 가상회선이 사라지고 패킷들은 전송된 순서대로 도착한다. (하단의 Acknowledgment Number 참조)
  • 서버에서 내부적으로 최적화가 가능하지만 서버 자원측면에서 안좋기에 가급적 클라이언트에 재요청하는 방식

TCP 헤더의 모습

 

Source port - 출발지의 포트 번호

Destination Port - 목적지 포트번호

Sequence number -  바이트 단위로 순서화되는 번호로 TCP 세그먼트 첫번째 byte에 부여되며 이를통해 3way handshake가 이뤄지고 흐름제어 기능을 제공한다 -> 데이터 첫 번째 비트에 할당되는 임의의 32비트, 한번의 연결에서 한번만 사용되며 동일한 연결에서 다른 데이터 전송을 위해 다른 시퀀스 번호를 사용해야한다.

Acknowledgment Number(확인번호) - 수신을 기다리는 다음 byte번호 (마지막으로 수신에 성공한 번호의 +1)

Reserved - 에약된 필드 (현재는 미사용)

Window - 자신의 수신 버퍼 여유용량 크기를 통보하여 얼만큼의 데이터를 받을수 있는지 보여줌

Offset - 헤더 길이 필드이며 Ipv4와 동일하게 /4를 진행한후 2진수로 작성됨

Urgent Pointer - 어디서부터 긴급값인지 알려주는 플래그 (TCP Flags의 U와 세트!)

TCP Flags

  • U (Urgent, 긴급비트) - 내가 지금 보내는 데이터의 우선순위가 높음 (Urgent Pointer과 세트)
  • S (SYN 비트, 동기화비트) - 동기화 비트, 상대방과 연결을 시작할떄 사용되는 플래그 (핸드쉐이크에 사용)
  • A (ACK 비트, 승인 비트) 요청에 대한 응답을 진행할때 사용되는 플래그 (핸드쉐이크에 사용)
  • P (Push 비트) - Tcp 버퍼가 일정한 크기만큼 쌓여야 넘기는데 이에 상관없이 계속 데이터를 밀어넣겠다 (유튜브 버퍼링)
  • R (Reset 비트) -  초기화 비트, 연결된 상태에서 어떤 문제가 발생했을때 연결을 리셋하게됨
  • F (Fin비트, 종료비트)

 

User Datagram Protocol (UDP)

  • 비연결성 - 데이터를 보내는데 연결이 필요하지 않다. -> 핸드쉐이크를 통한 연결상태 점검과정을 생락하고 일방적으로 보냄
  • UDP의 경우 단순하게 테이터만 보내기 때문에 신뢰성을 보장하지 않으나 가볍고 속도가 빠르다 -> 데이터를 효율적으로 보내야하는 응용프로그램, 게임은 직접적인 기능떄문에 UDP를 사용한다.
  • IP와 비슷하되 Port와 체크섬이 추가된다
  • 데이터그램 방식 - 데이터 전송 전에 송/수신자 사이에 가상 회선 (논리적 경로)를 설정하지 않고, 패킷들이 각기 독립적으로 전송되는 방식 -> 이로인해 전송되는 순서가 바뀔 여지가 있다.

체크섬 - 중복검사의 일종으로 송신된 자료의 무결성을 보호하는 방법이다. 주로 해쉬값 비교를 통해 이뤄지며 

 

 


3way handshake 연결과정

1. SYN 요청 (클라이언트 -> 서버) -> 클라이언트가 서버에 연결 요청을 하기위해 SYN 데이터를 보낸다

  • SYN -1, ACK - 0
  • 해당 과정에서 window크기, 최대 세그먼트 크기 등 정보를 같이 보낸다 (window가 2000비트, 최대 세그먼트 크기가 200비트인경우 최대 10개의 세그먼트가 전송된다)

2. SYN + ACK (서버 -> 클라이언트) -> 요청을 받은 서버는 접속요청에 응답하기 위해 (SYN + ACK) 데이터를 보낸다. 해당 포트상태

  • 서버측 클라이언트는 SYN, ACK로 응답한다
  • ACK는 여기에 window크기, 최대 세그먼트 크기 등 정보를 같이 보낸다 -> window가 2000비트, 최대 세그먼트 크기가 200비트인경우 최대 10개의 세그먼트가 전송된다
  • SYN에서 사용되는 시퀀스 번호와 클라이언트의 SYN과 다르며 서버는 자신의 window와 최대 세그먼트 크기를 클라이언트에 전달한다. (ACK의 승인번호는 수신된 시퀀스 번호보다 1만큼 크다)
  • ACK - 1, SYN - 1 (SYN이 1인 이유는 자신도 정상적으로 받았음을 의미하면 동시에 ACK를 1로 바꿔 응답할 준비가 되었음을 알림)

3. ACK (클라이언트 -> 서버) -> 서버의 승인이 떨어졌으니 자신이 필요로 하는 데이터를 보낸다.

  • SYN에서 사용되는 시퀀스 번호와 클라이언트의 SYN과 다르며 서버는 window와 최대 세그먼트 크기를 클라이언트에 전달한다. (ACK의 승인번호는 수신된 시퀀스 번호보다 1만큼 크다)
  • ACK - 1, SYN - 0 (연결이 완료되었기에 SYN은 0으로 바꿔버리고 연결간 데이터 전송을 위해 ACK는 1 유지)

 

3way handshake 종료과정

 

1. FIN (클라이언트 -> 서버) -> 사용이 끝났으니 종료할거라 플래그를 보냄.

  • 임의의 시퀀스 번호로 메시지를 서버로 전달
  • FIN - 1, ACK - 0 (FIN은 끝임을 알리기 위해 1로 변경, 연결을 끊기 위해 ACK는 0으로 변경)

2. ACK + FIN (서버 -> 클라이언트) -> FIN에 대한 응답을 잘 수신했고 나도 끊기위해 FIN 플래그를 보냄

  • SYN에서 사용되는 시퀀스 번호와 클라이언트의 SYN과 다르며 서버는 window와 최대 세그먼트 크기를 클라이언트에 전달한다. (ACK의 승인번호는 수신된 시퀀스 번호보다 1만큼 크다)
  • 서버는 클라이언트의 플래그를 FIN - 1, ACK - 1 (ACK는 클라이언트가 보낸 FIN을 정상적으로 받았음을 알리기 위해 1로 변환, FIN은 서버도 클라이언트와 끊음을 알리기 위해 1로 변환)
  • 해당 과정이 끝날경우 클라이언트에서 서버측 연결은 종료된다

3. ACK (클라이언트 -> 서버) -> 연결 정지에 대한 서버의 승인이 떨어졌으니 윗단계에서 끊고 동시에 정상적으로 종료됨을 알리는 데이터를 보낸다.

  • 클라이언트는 FIN을 수신후 ACK 플래그 1 설정, 서버의 FIN 시퀀스 번호보다 1만큼 큰 승인버호를 클라이언트로 보낸다 (진짜 끝낸다고 요청을 보내면서 클라이언트의 FIN플래그도 0으로 바꾼다)


상단의 이론을 진행하며 IP가 어떤식으로 소통하는지 확인하였다.
그렇다면 우리는 실질적으로 100.100.100.1이 아닌 naver.com과 같은 형태로 진행되는데 이에 대해서도 설명하겠다.


DNS(Domain Name System)

 

IP만 알면 되는데 DNS를 사용하는 이유 - IP는 기억하기 어렵고 IP는 변경될 우려가 있다

  • 서버에서 망 사용료를 연체하여 해지됬으나 이후 다시 IP를 개설하여도 이 사실을 모르는 사람들은 대다수가 기존의 사이트로 돌아오지 못할것이다.
  • google에 접속하려고 할때 200.200.200.2라고 할경우 이것이 어떤 사이트인지 구분이 어렵고 google과 연관된 사이트라고 해도 IP를 다른곳에서 가져가버릴경우 200.200.123.4.. 220.324.123.2.. 이런식으로 연결해놔야 하기에 굉장히 불편하다.

그리하여 DNS라는 시스템을 고안하였으며 단순한 도메인명(google.com)만 입력할경우 이에 알맞는 IP로 찾아가게 되는것이다.

 

 

URL, URN, URI

URI (Uniform Resource Identifier) - 통합 자원 식별자를 의미한다.

  • 인터넷에 있는 자원을 나타내는 유일한 주소를 의미하며 쉽게 말해서 URN + URL 두개를 합친 상위의 개념이다.

URN (Uniform Resource Name) 

  • URI의 표준 포맷중 하나로 이름으로 리소스를 특정하는 URI이다.
  • URN은 리소스를 영구적이며 유일하게 식별이 가능한 URI다.
  • 실제 자원을 찾기 위해선 URN을 URL로 변환해 이용한다.
  • 리소스에 어떻게 접근할지 명시하지 않고 경로와 리소스 자체를 특정하는것 -> 크롬에 PDF 파일 같은걸 던져보면 알것이다. (file://0.0.0.123/)

URL (Uniform Resource Locator)

  • 네트워크 상에서 웹페이지 ,이미지, 동영상등 파일이 위치한 정보를 나타낸다.
  • 어떻게 리소스를 얻고 어디서 가져올지 명시
  • www.google.com

HTTP의 역사

HTTP/0.9 - GET 메서드만 지원, HTTP 헤더X

HTTP/1.0 - 메서드(post,get,delete...), 헤더, 상태코드(200,300...) 추가

  • 요청헤더 - http 버전이 생김
  • 응답헤더 - 상태코드와 content-type이 생겨 html파일 외의 다른 타입의 파일도 전송가능
  • 단기 커넥션 - connection 하나당 1개의 요청, 1개의 응답만 처리가능 -> 상단의 비연결성과 비슷한 맥락 

HTTP/1.1 - 가장 범용적으로 사용됨

  • Persistent connection - 지정된 timeout 동안 연속적인 요청 사이에 커넥션을 닫지 않음 -> 비 연결성에 약간의 여유를 주었다
  • Pipelining - 커넥션에서 응답을 기다리지 않고 순차적으로 여러 요청을 연속적으로 보내 그 순서에 맞춰 응답받아 지연시간을 줄이는 방식 -> Head of Line Blocking같은 문제점이 많아 사장됨.
  • Head of Line Blocking - 우선순위로 들어온 응답시간이 길어질경우 그 뒤에 있는 응답시간도 길어진다.

HTTP/2.0 - HTTP 1.1 성능개선 + 확장

  • 메시지 전송방식의 변화 : 바이너리 프레이밍 계층 사용
  • 파싱, 전송속도 증가
  • 오류 발생 가능성 저하
  • 멀티플랙싱
  • HPACK 압축 - 헤더 중복값 개선

HTTP/3.0 - TCP대신 UDP를 이용한 QuIC 프로토콜 사용

  • 3.0 미만은 전부 TCP 프로토콜을 활용했으나 해당 버전부턴 UDP를 사용

 

클라이언트와 서버를 구분해야 하는 이유 -> 각자의 역할에 집중(독립적인 발전) 가능하기 때문이다.

  • 리퀘스트, 리스폰 구조로 클라이언트는 서버에 요청을 보내고 응답을 대기하다 메시지가 오면 확인만 하면 된다
  • 이것은 곧 서로 독립성을 의미하며 단적인 예시로 서버가 방금까지 JAVA를 쓰다 C로 넘어가도 클라이언트는 이것과 상관없이 그냥 요청만 하면 서버에선 이를 확인하고 보내줄수 있다
  • 서버에선 비즈니스 로직 및 서비스만 구현하고 만일 문제가 발생할경우 클라이언트는 문제가 고쳐지기 전까지 다른작업을 진행하다 추후 완료되었을때 다시 접속만 하면 된다.

 

'CS' 카테고리의 다른 글

JS파일 가져오기 로컬, 원격 차이  (0) 2024.08.03
크로스 도메인,SOP, CORS, XSS,  (0) 2024.01.25
HTTP 헤더  (0) 2023.05.06
난독화  (0) 2023.05.03
개발방법론  (0) 2023.05.02

+ Recent posts