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장 프로토콜의 특징 - 상태