WeniVooks

검색

웹/네트워크/HTTP 베이스캠프

TCP/IP 4계층(Layer)

TCP/IP는 인터넷 통신을 위한 기본 프로토콜 스위트(Protocol Suite, 프로토콜 모음)입니다. 이는 데이터를 패킷으로 나누어 전송하고, 수신 측에서 이를 받아 재조립하는 과정을 담당합니다. TCP/IP는 네 개의 계층으로 구성되어 있습니다.

이러한 표준을 정립함으로 회사가 다른 장비간에 호환 문제를 해결할 수 있었습니다. 처음에는 이러한 표준을 지키지 않아서 호환이 되지 않았었어요. OSI 7 레이어와 같은 표준을 위한 모델도 있지만 실무에서는 TCP/IP 모델로 설명드리는 것이 좀 더 적합하기에 TCP/IP로 설명을 드리도록 하겠습니다.

웹 통신은 OSI 7 레이어 모델과 TCP/IP 모델 모두를 사용하여 설명할 수 있습니다. 두 모델은 네트워크 통신을 설명하는 다른 방식일 뿐, 실제 통신 프로세스는 동일합니다.

이 과정을 설명하기 위해 편지 예시를 사용해보겠습니다.

송신 측

  1. 애플리케이션 계층 (편지 작성)
    • 긴 편지를 작성합니다. 이는 전송해야 할 큰 데이터를 나타냅니다.
  2. 트랜스포트 계층 (편지를 페이지로 나누기)
    • TCP: 편지를 일정한 크기의 페이지로 나눕니다. UDP보다는 느립니다. 신뢰성을 보장합니다.
    • UDP: 편지를 나누되, 페이지 크기가 일정하지 않을 수 있습니다. TCP보다는 빠릅니다. 신뢰성을 보장하지 않습니다.
  3. 인터넷 계층 (봉투에 넣어 주소 붙이기)
    • 각 페이지를 봉투에 넣고, 봉투에 받는 사람 주소 (IP 주소)를 씁니다.
  4. 네트워크 인터페이스 계층 (편지 발송)
    • 봉투를 우체국 (라우터)에 전달하여 발송합니다.

수신 측

  1. 네트워크 인터페이스 계층 (편지 수신)
    • 봉투를 받습니다.
  2. 인터넷 계층 (봉투에서 페이지 꺼내기)
    • 봉투를 열어 페이지를 꺼냅니다.
  3. 트랜스포트 계층 (페이지 재조립)
    • TCP: 페이지 번호 (시퀀스 번호)를 사용하여 페이지를 원래 순서대로 재조립합니다.
    • UDP: 페이지를 받은 순서대로 재조립합니다. 순서가 바뀌거나 페이지가 유실될 수 있습니다.
  4. 애플리케이션 계층 (편지 읽기)
    • 재조립된 편지를 읽습니다. 이는 수신된 데이터를 처리하는 것을 나타냅니다.

특징 요약

  • 인터넷에 관련된 다양한 프로토콜의 집합을 총칭합니다.
  • 우리가 배웠던 HTTP는 TCP/IP 중 하나입니다. HTTP는 데이터의 교환을 담당하는 애플리케이션 계층에 속합니다.
  • HTMP, FTP, SNMP, TCP, IP, UDP 등이 ‘TCP/IP’에 포함됩니다.

7.1 TCP/IP 4계층(Layer)

  • 4계층 - 애플리케이션 계층: 사용자와 직접 상호작용 하는 계층으로 수신하거나 송신할 데이터를 생성합니다. 이 계층에서는 웹 브라우저, 이메일 클라이언트, 메신저 등의 애플리케이션이 동작하며, 사용자가 입력한 데이터나 애플리케이션이 생성한 데이터를 송신하거나, 수신한 데이터를 사용자에게 표시합니다.

HTTP, FTP 등의 프로토콜이 이 계층에 속합니다. Python의 soket 모듈을 사용하면 FTP, HTTP, SMTP 등 다양한 애플리케이션 계층 프로토콜을 직접 구현할 수 있습니다. 하지만 이런 프로토콜들은 이미 잘 구현된 라이브러리 또는 프레임워크가 많이 있으므로 (ftplib, http.client, smtplib 등), 이런 라이브러리나 프레임워크를 사용하는 것이 더 일반적입니다.

  • 아래 코드는 HTTP를 구현한 예제입니다.

    import socket
     
    def handle_request(request):
        headers = request.split('\n')
        filename = headers[0].split()[1]
     
        if filename == '/':
            filename = '/index.html'
     
        try:
            with open(filename[1:], 'r') as file:
                content = file.read()
            response = 'HTTP/1.0 200 OK\n\n' + content # 이 부분이 프로토콜 규칙을 지키는 부분입니다.
            # 이 규칙(HTTP)을 깨면 브라우저가 데이터를 해석하지 못합니다.
        except FileNotFoundError:
            response = 'HTTP/1.0 404 NOT FOUND\n\nFile Not Found' # 이 부분이 프로토콜 규칙을 지키는 부분입니다.
     
        return response
     
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('localhost', 8888))
    server_socket.listen(1)
     
    print('Server is ready to receive...')
     
    while True:
        connection, address = server_socket.accept()
        request = connection.recv(1024).decode('utf-8')
        print(request)
     
        response = handle_request(request)
        connection.sendall(response.encode('utf-8'))
        connection.close()
    import socket
     
    def handle_request(request):
        headers = request.split('\n')
        filename = headers[0].split()[1]
     
        if filename == '/':
            filename = '/index.html'
     
        try:
            with open(filename[1:], 'r') as file:
                content = file.read()
            response = 'HTTP/1.0 200 OK\n\n' + content # 이 부분이 프로토콜 규칙을 지키는 부분입니다.
            # 이 규칙(HTTP)을 깨면 브라우저가 데이터를 해석하지 못합니다.
        except FileNotFoundError:
            response = 'HTTP/1.0 404 NOT FOUND\n\nFile Not Found' # 이 부분이 프로토콜 규칙을 지키는 부분입니다.
     
        return response
     
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('localhost', 8888))
    server_socket.listen(1)
     
    print('Server is ready to receive...')
     
    while True:
        connection, address = server_socket.accept()
        request = connection.recv(1024).decode('utf-8')
        print(request)
     
        response = handle_request(request)
        connection.sendall(response.encode('utf-8'))
        connection.close()
  • 이를 통해 생성된 문자열 예시입니다.

    HTTP/1.0 200 OK
     
    abcdef
    HTTP/1.0 200 OK
     
    abcdef
  • 3계층 - 트랜스포트 계층(전송 계층): 트랜스포트 계층은 상위 계층인 애플리케이션 계층으로부터 데이터를 받아, 하위 계층인 인터넷 계층으로 전달하는 역할을 합니다. 트랜스포트 계층의 주요 프로토콜은 TCP(Transmission Control Protocol)와 UDP(User Datagram Protocol)입니다.

    1. TCP (Transmission Control Protocol)
      • 연결 지향적 프로토콜입니다.
      • 데이터의 신뢰성, 순서, 무결성을 보장합니다.
      • 데이터 전송 속도는 UDP보다 느리지만, 데이터 손실이 없어야 하는 애플리케이션(예: 이메일, 파일 전송 등)에 적합합니다.
      • 3-way handshake를 통해 연결을 설정합니다.
      • 흐름 제어, 혼잡 제어, 오류 제어 등의 기능을 제공합니다.
      • 혼잡 제어를 하여 안전하게 데이터 흐름을 보장합니다. 야구에서 상대방이 준비된 것을 사인으로 확인하고 공을 차례차례 던지는 것과 같습니다.
    2. UDP (User Datagram Protocol)
      • 비연결 지향적 프로토콜입니다.

      • TCP에 비해 간단하고 빠르지만, 데이터의 신뢰성을 보장하지 않습니다.

      • 데이터의 순서나 무결성도 보장하지 않습니다.

      • 실시간 스트리밍, 온라인 게임 등 속도가 중요하고 일부 데이터 손실이 허용되는 애플리케이션에 적합합니다.

      • 혼잡 제어를 하지 않아 상대방이 받을 준비가 되었는지 확인하지 않고 보냅니다. 야구에서 상대방이 있는 것만 확인하고 사인 없이 계속해서 공을 던지는 것과 같습니다. 상대방이 공을 못받았어도 다음 공을 그냥 던집니다.

    • python 코드로는 아래와 같이 표현 가능합니다.

      # python 프로그래밍에서는 아래와 같이 socket에 정의되어 있습니다.
      server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP
      server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
      # python 프로그래밍에서는 아래와 같이 socket에 정의되어 있습니다.
      server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP
      server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
    • TCP 세그먼트가 잘려지는 예시입니다. 각 세그먼트의 크기를 4바이트로 가정하고, 출발지 포트는 1234, 목적지 포트는 80, 시퀀스 번호는 각 세그먼트의 첫 바이트 위치라고 가정하겠습니다.(UDP는 애플리케이션 계층에서 받은 데이터 그대로 헤더만 추가(데이터그램)가하여 전송)

      • 원본

        HTTP/1.0 200 OK
        
        abcdef
        HTTP/1.0 200 OK
        
        abcdef
      1. 세그먼트 1

        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 1
        확인 응답 번호: 0
        데이터: "HTTP"
        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 1
        확인 응답 번호: 0
        데이터: "HTTP"
      2. 세그먼트 2

        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 5
        확인 응답 번호: 0
        데이터: "/1.0"
        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 5
        확인 응답 번호: 0
        데이터: "/1.0"
      3. 세그먼트 3

        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 9
        확인 응답 번호: 0
        데이터: " 200"
        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 9
        확인 응답 번호: 0
        데이터: " 200"
      4. 세그먼트 4

        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 13
        확인 응답 번호: 0
        데이터: " OK\\n"
        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 13
        확인 응답 번호: 0
        데이터: " OK\\n"
      5. 세그먼트 5

        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 17
        확인 응답 번호: 0
        데이터: "\\nabc"
        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 17
        확인 응답 번호: 0
        데이터: "\\nabc"
      6. 세그먼트 6

        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 21
        확인 응답 번호: 0
        데이터: "def"
        출발지 포트: 1234
        목적지 포트: 80
        시퀀스 번호: 21
        확인 응답 번호: 0
        데이터: "def"

        이 예시에서는 TCP 헤더의 주요 필드인 출발지 포트, 목적지 포트, 시퀀스 번호, 확인 응답 번호만 포함하였습니다. 실제 TCP 헤더에는 이외에도 헤더 길이, 플래그, 윈도우 크기, 체크섬 등의 필드가 포함됩니다. 각 세그먼트는 TCP 헤더와 데이터로 구성되며, 시퀀스 번호는 세그먼트의 첫 바이트 위치를 나타냅니다. 이렇게 구성된 세그먼트는 인터넷 계층으로 전달되어 IP 패킷에 encapsulation됩니다. 수신 측에서는 시퀀스 번호를 사용하여 세그먼트를 재조립하고, 최종적으로 원래의 HTTP 응답 데이터를 복원합니다.

  • 2계층 - 네트워크 계층(인터넷 계층): 네트워크상에서 패킷의 이동을 다룹니다. 여러 가지 길 중에서 하나의 길을 결정하는 것이 네트워크 계층의 역할입니다.

    • 패킷 : 전송하는 데이터의 최소단위(IP 헤더 + TCP 세그먼트)

    • 패킷이 만들어지는 예시는 아래와 같습니다.

    • IP만 알아도 어느 정도 국가와 지역을 알 수 있습니다. 내 ip 주소 확인을 검색해보세요. python에서는 pygeoip와 같은 라이브러리로 확인이 가능합니다.

    • IPv4 주소에서 사용할 수 있는 IP는 43억개로 우리가 필요한 IP 갯수에 한참 부족합니다. 이러한 고갈 문제를 해결하기 위해 NAT, IPv6 등 여러 해결책이 나옵니다.

      1. IP 패킷 1:

        버전: IPv4
        헤더 길이: 20바이트
        서비스 유형 (ToS): 0x00
        전체 길이: 40바이트
        식별자: 0x1234
        플래그: 0x02 (Don't Fragment)
        단편화 오프셋: 0
        TTL: 64
        프로토콜: TCP (0x06)
        헤더 체크섬: (계산된 값)
        출발지 IP 주소: 192.168.0.1
        목적지 IP 주소: 192.168.0.2
        TCP 세그먼트:
          출발지 포트: 1234
          목적지 포트: 80
          시퀀스 번호: 1
          확인 응답 번호: 0
          데이터: "HTTP"
        버전: IPv4
        헤더 길이: 20바이트
        서비스 유형 (ToS): 0x00
        전체 길이: 40바이트
        식별자: 0x1234
        플래그: 0x02 (Don't Fragment)
        단편화 오프셋: 0
        TTL: 64
        프로토콜: TCP (0x06)
        헤더 체크섬: (계산된 값)
        출발지 IP 주소: 192.168.0.1
        목적지 IP 주소: 192.168.0.2
        TCP 세그먼트:
          출발지 포트: 1234
          목적지 포트: 80
          시퀀스 번호: 1
          확인 응답 번호: 0
          데이터: "HTTP"
      2. IP 패킷 2:

        버전: IPv4
        헤더 길이: 20바이트
        서비스 유형 (ToS): 0x00
        전체 길이: 40바이트
        식별자: 0x1234
        플래그: 0x02 (Don't Fragment)
        단편화 오프셋: 0
        TTL: 64
        프로토콜: TCP (0x06)
        헤더 체크섬: (계산된 값)
        출발지 IP 주소: 192.168.0.1
        목적지 IP 주소: 192.168.0.2
        TCP 세그먼트:
          출발지 포트: 1234
          목적지 포트: 80
          시퀀스 번호: 5
          확인 응답 번호: 0
          데이터: "/1.0"
        버전: IPv4
        헤더 길이: 20바이트
        서비스 유형 (ToS): 0x00
        전체 길이: 40바이트
        식별자: 0x1234
        플래그: 0x02 (Don't Fragment)
        단편화 오프셋: 0
        TTL: 64
        프로토콜: TCP (0x06)
        헤더 체크섬: (계산된 값)
        출발지 IP 주소: 192.168.0.1
        목적지 IP 주소: 192.168.0.2
        TCP 세그먼트:
          출발지 포트: 1234
          목적지 포트: 80
          시퀀스 번호: 5
          확인 응답 번호: 0
          데이터: "/1.0"

        나머지 IP 패킷도 유사한 구조로 구성됩니다.

  • 1계층 - 링크 계층(데이터 링크 계층/네트워크 인터페이스 계층): 네트워크에 접속하는 하드웨어적인 면을 다룹니다. 이렇게 만들어진 데이터는 수신측으로 전송됩니다.

    프리앰블: 10101010 10101010 10101010 10101010 10101010 10101010 10101010
    목적지 MAC 주소: 00:11:22:33:44:55
    소스 MAC 주소: AA:BB:CC:DD:EE:FF
    유형: IPv4 (0x0800)
    페이로드:
      IP 패킷:
        버전: IPv4
        헤더 길이: 20바이트
        서비스 유형 (ToS): 0x00
        전체 길이: 40바이트
        식별자: 0x1234
        플래그: 0x02 (Don't Fragment)
        단편화 오프셋: 0
        TTL: 64
        프로토콜: TCP (0x06)
        헤더 체크섬: (계산된 값)
        출발지 IP 주소: 192.168.0.1
        목적지 IP 주소: 192.168.0.2
        TCP 세그먼트:
          출발지 포트: 1234
          목적지 포트: 80
          시퀀스 번호: 1
          확인 응답 번호: 0
          데이터: "HTTP"
    FCS: (계산된 값)
    프리앰블: 10101010 10101010 10101010 10101010 10101010 10101010 10101010
    목적지 MAC 주소: 00:11:22:33:44:55
    소스 MAC 주소: AA:BB:CC:DD:EE:FF
    유형: IPv4 (0x0800)
    페이로드:
      IP 패킷:
        버전: IPv4
        헤더 길이: 20바이트
        서비스 유형 (ToS): 0x00
        전체 길이: 40바이트
        식별자: 0x1234
        플래그: 0x02 (Don't Fragment)
        단편화 오프셋: 0
        TTL: 64
        프로토콜: TCP (0x06)
        헤더 체크섬: (계산된 값)
        출발지 IP 주소: 192.168.0.1
        목적지 IP 주소: 192.168.0.2
        TCP 세그먼트:
          출발지 포트: 1234
          목적지 포트: 80
          시퀀스 번호: 1
          확인 응답 번호: 0
          데이터: "HTTP"
    FCS: (계산된 값)

    이 예시는 이더넷 프레임의 구조를 단순화하여 설명한 것으로, 실제 이더넷 프레임에는 VLAN 태그, 우선순위 정보 등 추가적인 필드가 포함될 수 있습니다.

  • 참고사항

    OSI 7계층(표준화 목적)TCP/IP 4계층(실용성)
    응용 계층응용 계층
    표현 계층응용 계층
    세션 계층응용 계층
    전송 계층전송 계층
    네트워크 계층인터넷 계층
    데이터링크 계층네트워크 액세스 계층
    물리 계층네트워크 액세스 계층
7.1.1 정보를 감싸는 캡슐화를 통해 계층간 정보 전달
7.1.2 Response(응답)과 Request(요청) 과정
  • 이미지 아래 링크를 클릭하시면 크게 보실 수 있습니다.
응답과 요청 과정
7장 TCP/IP8장 프로토콜의 특징 - 상태