사전 프로토콜
개념

프로토콜

gabury1고친 사람 github-actions[bot]

프로토콜은 두 프로그램이 서로 말을 주고받을 때 지키는 약속입니다. 무엇을 먼저 보내고 받은 쪽이 어떻게 답하는지를 미리 정해 둡니다. 다른 사람이 만든 프로그램끼리도 같은 약속을 따르면 말이 통합니다. 프로그래밍 언어에서는 같은 이름을 인터페이스와 비슷한 뜻으로도 씁니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 네트워크 너머의 두 프로그램이 대화하는 규칙을 정합니다. 브라우저가 웹 서버에 페이지를 달라고 하고 서버가 페이지를 돌려주는 것도 정해진 약속을 따른 대화입니다.

왜 이렇게 하나 — 약속이 없으면 받은 바이트가 무슨 뜻인지 받는 쪽이 알 수 없습니다. 약속을 글로 적어 두면 누가 만든 프로그램이든 그 글만 보고 상대와 대화할 수 있습니다.

어떻게 도나

  1. 메시지가 어떤 모양인지 정합니다
  2. 메시지의 각 부분이 무슨 뜻인지 정합니다
  3. 누가 먼저 보내고 어떤 순서로 답하는지 정합니다

대가 — 약속은 쉽게 못 바꿉니다. 한쪽만 바꾸면 상대와 말이 안 통해서, 새 규칙을 넣을 때도 옛 프로그램과 함께 도는 방법을 따로 마련해야 합니다.

상세

이 절은 프로토콜이 무엇을 정하는지, 잘못될 때 어떻게 하는지, 왜 계층으로 쌓는지를 차례로 봅니다. 브라우저와 웹 서버가 주고받는 요청 한 번을 예로 씁니다. 끝에서 프로그래밍 언어가 쓰는 뜻을 가릅니다.

무전 교신을 떠올리면 쉽습니다. 부르는 쪽이 먼저 상대의 호출 부호를 댑니다. 말을 마치면 「오버」라고 해서 차례를 넘깁니다. 대화를 끝낼 때는 「아웃」이라고 합니다. 두 사람이 이 약속을 알고 있어서 한 채널에서 말이 겹치지 않습니다.

프로토콜이 정하는 세 가지

프로토콜이 정하는 내용은 흔히 셋으로 나눠 봅니다. 메시지의 모양을 정하는 문법, 그 모양의 뜻을 정하는 의미, 누가 언제 보내는지를 정하는 순서와 시간입니다.

정하는 것 묻는 질문 예
문법 메시지가 어떤 모양인가 첫 줄에 명령과 경로를 적고 줄바꿈으로 끝낸다
의미 각 부분이 무슨 뜻인가 숫자 404 는 찾는 것이 없다는 뜻이다
순서와 시간 누가 언제 보내나 요청이 먼저 가고 응답이 뒤따른다 · 정한 시간 안에 답이 없으면 포기한다

셋 중 하나라도 빠지면 대화가 안 됩니다. 모양은 맞는데 뜻을 모르면 받은 메시지를 해석할 수 없습니다. 모양과 뜻을 알아도 순서를 모르면 두 쪽이 서로 상대가 먼저 말하기를 기다리며 멈춥니다.

받는 쪽은 약속한 모양을 그대로 기대합니다. 바이트 하나만 어긋나도 메시지를 버리거나 오류로 답합니다.

요청과 응답 한 번

웹에서 쓰는 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)로 한 번의 왕복을 봅니다. 브라우저가 클라이언트이고 웹 서버가 서버입니다. 클라이언트가 먼저 요청을 보내고 서버가 응답을 돌려줍니다.

먼저 클라이언트가 보내는 요청입니다.

GET /users/42 HTTP/1.1
Host: api.example.com

첫 줄의 GET 은 가져오라는 명령이고 /users/42 는 가져올 대상입니다. 둘째 줄의 Host 는 어느 사이트에 묻는지를 적습니다. 첫 줄 아래에 이름: 값 꼴로 붙는 이런 안내 줄을 헤더라고 합니다. 서버는 이 모양을 알고 있어서 줄을 나눠 읽기만 하면 요청을 이해합니다.

다음은 서버가 돌려주는 응답입니다.

HTTP/1.1 200 OK
Content-Type: application/json

{"id": 42, "name": "유미"}

첫 줄의 200 은 요청을 잘 처리했다는 뜻의 상태 코드입니다. 빈 줄 뒤가 본문입니다. Content-Type 헤더는 본문을 JSON(JavaScript Object Notation, 자바스크립트 객체 표기법)으로 읽으라고 알려 줍니다.

앞 절의 세 가지를 이 예에 맞춰 보면 이렇습니다. 「첫 줄, 헤더, 빈 줄, 본문」으로 줄을 놓는 방식이 문법입니다. 200 이 성공이라는 것은 의미입니다. 요청이 먼저 가고 응답이 뒤따르는 것은 순서입니다. 답을 얼마나 기다릴지 같은 시간 약속은 이 몇 줄에 보이지 않습니다.

대화를 기억하는 프로토콜과 잊는 프로토콜

프로토콜마다 앞선 대화를 기억하는지가 다릅니다. 앞서 주고받은 내용을 양쪽이 기억하고 다음 메시지를 그에 맞춰 해석하면 상태 유지 프로토콜입니다.

TCP(Transmission Control Protocol, 전송 제어 프로토콜)가 그런 예입니다. TCP 는 데이터를 보내기 전에 먼저 연결을 맺습니다. 연결을 맺는 첫 주고받기를 핸드셰이크라고 합니다. 여기서 양쪽이 대화를 시작해도 된다는 데 합의합니다.

연결을 다 쓰면 닫습니다. 양쪽은 지금 연결이 어느 단계에 있는지를 기억합니다. 같은 메시지라도 단계에 따라 받아들이기도 하고 버리기도 합니다. 아래 그림은 단계를 크게 줄여 그린 것입니다.

stateDiagram-v2
    [*] --> 연결맺는중
    연결맺는중 --> 연결됨: 핸드셰이크 완료
    연결됨 --> 닫는중: 한쪽이 닫기 요청
    닫는중 --> [*]: 양쪽이 닫힘 확인

반대로 요청 하나하나가 앞선 요청과 무관하게 처리되면 무상태 프로토콜입니다. HTTP 가 이쪽입니다. 서버는 앞 요청을 기억하지 않습니다. 그래서 로그인한 사용자라는 것을 알리려면 요청마다 쿠키나 토큰을 다시 실어 보냅니다.

이 차이는 서버를 여러 대 둘 때 드러납니다. 웹 서비스는 흔히 같은 일을 하는 서버 여러 대가 요청을 나눠 받습니다. 서버가 앞 요청을 기억하지 않으면 다음 요청은 어느 서버로 가도 됩니다.

상태 유지 무상태
앞 대화를 기억하나 기억한다 안 한다
서버 한 대가 죽으면 그 서버와의 대화를 처음부터 다시 맺는다 다른 서버가 다음 요청을 받으면 된다
예 TCP HTTP

대화 도중의 단계를 지켜야 하는 일에는 상태 유지 쪽을 고릅니다. 요청을 여러 서버에 자유롭게 나눠 보내야 하는 일에는 무상태 쪽을 고릅니다.

두 방식은 서로 겹쳐 씁니다. HTTP 요청을 실어 나르는 TCP 연결은 기억하는 방식입니다. 서버가 죽으면 TCP 연결은 다른 서버와 새로 맺어야 합니다. 그래도 HTTP 요청은 앞 요청을 몰라도 되므로 새 서버가 그대로 받습니다.

틀리거나 끊겼을 때의 약속

네트워크에서는 메시지가 사라지거나 늦게 옵니다. 그래서 프로토콜은 잘 될 때의 순서뿐 아니라 잘못될 때 무엇을 할지도 정합니다.

첫째는 기다리는 한도입니다. 정한 시간 안에 답이 없으면 포기하거나 다시 보냅니다. 기다리는 한도를 타임아웃이라 합니다. 같은 메시지를 다시 보내는 일은 재전송입니다.

둘째는 오류를 알리는 방법입니다. HTTP 서버는 찾는 것이 없으면 404 를, 서버 안에서 처리가 실패하면 500 을 돌려줍니다. HTTP 는 400번대를 요청한 쪽 잘못으로, 500번대를 서버 쪽 잘못으로 나눕니다. 그래서 받은 쪽은 숫자의 앞자리만 보고 어느 쪽 잘못인지 가립니다.

다시 보내기에는 함정이 있습니다. 요청은 잘 처리됐는데 응답만 사라졌다면, 다시 보낸 요청이 같은 일을 두 번 하게 됩니다. 그래서 여러 번 받아도 결과가 한 번과 같도록 설계합니다. 이 성질이 멱등성입니다.

계층으로 쌓는 까닭

프로토콜 하나가 모든 일을 맡지 않습니다. 일을 여러 계층으로 나누고 계층마다 프로토콜을 따로 둡니다. 위 계층은 아래 계층이 제 일을 해 준다고 믿고 자기 일만 합니다. 아래 그림의 화살표는 위 계층이 아래 계층에 일을 맡긴다는 뜻입니다.

flowchart TD
    A["HTTP · 무엇을 요청하고 어떻게 답하나"]
    B["TCP · 빠짐없이 순서대로 전하나"]
    C["IP · 어느 컴퓨터로 가나"]
    D["이더넷 · 옆 장비까지 신호를 나르나"]
    A --> B --> C --> D

위에서 아래로 읽습니다. HTTP 는 요청의 뜻만 신경 씁니다. 바이트가 빠지는지는 TCP 에 맡깁니다. TCP 는 순서와 누락만 챙깁니다. 목적지까지 가는 길은 IP(Internet Protocol, 인터넷 프로토콜)에 맡깁니다.

맨 아래 이더넷은 유선으로 옆 장비까지 신호를 나르는 프로토콜입니다. 이렇게 나누면 한 계층을 바꿔도 다른 계층은 손대지 않아도 됩니다. 집의 선이 이더넷에서 와이파이로 바뀌어도 HTTP 코드는 한 줄도 안 고칩니다.

대신 계층마다 앞에 자기 몫의 안내 정보, 곧 헤더를 붙입니다. HTTP 요청 앞에 TCP 헤더가 붙습니다. 그 앞에 다시 IP 헤더가 붙습니다. 이렇게 위 계층의 데이터를 아래 계층의 데이터 안에 넣는 일을 캡슐화라고 합니다. 헤더가 겹겹이 붙으므로 보내는 바이트가 조금씩 늘어납니다.

계층마다 주고받는 데이터 단위의 이름도 다릅니다. TCP 가 나르는 단위는 세그먼트입니다. IP 가 나르는 단위는 패킷입니다.

약속을 적은 문서

프로토콜은 코드가 아니라 문서로 존재합니다. 문서가 메시지의 모양과 뜻과 순서를 적습니다. 여러 사람이 그 문서를 읽고 각자 프로그램을 만듭니다. 인터넷 프로토콜의 문서는 대개 RFC(Request for Comments, 의견 요청)라는 이름의 번호 붙은 문서로 나옵니다.

같은 문서를 따라 만든 프로그램은 서로 다른 언어로 짰어도 대화할 수 있습니다. 서로 다른 구현이 함께 도는 이 성질이 상호운용성입니다. 어느 브라우저든 어느 회사가 만든 웹 서버와도 대화하는 것이 이 덕분입니다.

문서는 판을 올리며 바뀝니다. HTTP 에도 1.1 과 2 와 3 이 있습니다. 새 판을 낼 때는 옛 판만 아는 프로그램과도 대화가 끊기지 않게 하는 방법을 함께 정합니다. 이 성질은 하위 호환성입니다.

텍스트 프로토콜과 바이너리 프로토콜

메시지를 사람이 읽는 글자로 적는 프로토콜이 있습니다. 정해진 위치에 숫자를 채운 바이트로 적는 프로토콜도 있습니다.

텍스트 프로토콜 바이너리 프로토콜
메시지 모양 글자와 줄바꿈 정해진 칸에 숫자를 채운 바이트
사람이 눈으로 읽기 쉽다 도구가 있어야 한다
받는 쪽이 읽는 법 줄바꿈과 구분 문자를 찾아 가며 자른다 정해진 위치의 바이트를 바로 꺼낸다
같은 내용의 크기 숫자도 글자로 적어 바이트가 늘어난다 숫자를 바이트 그대로 담아 덜 든다
예 HTTP/1.1 TCP · IP · HTTP/2

사람이 메시지를 직접 읽고 고쳐 보내며 확인하기 쉬워야 하면 텍스트 쪽을 고릅니다. 메시지 크기를 줄이고 받는 쪽이 빨리 잘라 읽어야 하면 바이너리 쪽을 고릅니다.

앞 절에서 본 HTTP/1.1 요청은 텍스트 쪽이라 그대로 읽혔습니다. TCP 헤더는 바이너리 쪽이라, 몇 번째 비트부터 몇 비트가 무슨 값인지를 문서가 정합니다. HTTP/2 는 요청과 헤더의 뜻은 그대로 두고 메시지를 담는 모양만 바이너리로 바꿨습니다. 그래서 같은 HTTP 가 판에 따라 표의 다른 칸에 놓입니다.

프로그래밍 언어가 쓰는 프로토콜

프로그래밍 언어에서는 이 낱말을 다른 뜻으로 씁니다. 어떤 타입이 갖춰야 할 메서드 목록을 프로토콜이라 부릅니다. 자바의 인터페이스와 같은 역할입니다.

Swift 는 이 목록을 protocol 키워드로 선언합니다. 타입이 그 목록의 메서드를 모두 구현하면 그 프로토콜을 따른다고 봅니다.

파이썬은 메서드 이름으로 동작을 약속합니다. 객체에 __len__ 이 있으면 len() 으로 길이를 물을 수 있습니다. __iter__ 가 있으면 for 문으로 돌 수 있습니다. 이런 메서드 묶음을 프로토콜이라 부릅니다. typing.Protocol 로 이 묶음을 타입에 적을 수도 있습니다.

두 뜻의 뿌리는 같습니다. 양쪽 다 「이 약속을 지키면 서로 몰라도 함께 동작한다」는 뜻입니다. 네트워크 프로토콜은 두 프로그램 사이의 약속입니다. 언어의 프로토콜은 한 프로그램 안에서 두 코드 조각 사이의 약속입니다. 문서에서 이 낱말을 만나면 네트워크 이야기인지 타입 이야기인지를 먼저 봅니다.

관련 항목

프로토콜이 정하는 구성 요소

메시지 · 헤더 · 페이로드 · 상태 코드 · 핸드셰이크 · 직렬화

프로토콜을 실어 나르는 단위

패킷 · 세그먼트 · 데이터그램 · 프레임 · 바이트 스트림

계층마다 쌓이는 대표 프로토콜

HTTP · TCP · UDP · IP · 이더넷 · TLS · DNS · NTP · MQTT · WebSocket · gRPC

프로토콜을 계층으로 나누는 모델

계층 · 캡슐화 · OSI 모델 · 네트워크

프로토콜이 지키거나 고르는 성질

상태 유지 · 무상태 · 멱등성 · 상호운용성 · 하위 호환성

끊기거나 틀렸을 때 프로토콜이 쓰는 수단

타임아웃 · 재전송 · 오류 검출 · 체크섬 · 흐름 제어 · 혼잡 제어

프로토콜을 정의하는 문서와 기관

RFC · IETF · 표준 · 명세

프로토콜로 대화하는 주체와 창구

클라이언트 · 서버 · 소켓 · 포트 번호 · API

같은 이름을 쓰는 언어 쪽 개념

인터페이스 · 덕 타이핑 · 구조적 타이핑 · 추상 클래스

다른 이름: protocol