리눅스 소켓 프로그래밍에서, IP(인터넷 프로토콜)을 지정하기 위해 AF_INETPF_INET 중 어느 것을 사용해도 상관이 없습니다. 왜 소켓 프로그래밍 설계자들은 이처럼 아무런 차이도 없는 상수를 두 개나 만들었을까요? 둘 사이에 숨겨진 의미라도 있는 걸까요?

원래 의도 🔗

아주 오래 전 소켓 프로그래밍을 설계할 당시에는, 확장성을 위해 한 종류의 ‘주소 체계’가 여러 ‘프로토콜’을 지원할 것을 염두에 두고 만들었습니다[bgnet-1]. 이를테면 192.168.0.1, 8.8.4.4같은 IP 주소가 IP뿐만 아니라 다른 프로토콜도 지원하는 식입니다.

물론 하나의 주소 체계가 여러 프로토콜을 지원하는 일은 실제로 일어나지 않았습니다[bgnet-2]. 오늘날까지도 IP 주소 체계는 오직 IP 프로토콜에서만 사용되고 있습니다.

어찌되었든 당시의 설계자들은 주소 체계와 프로토콜을 서로 다른 개념으로 바라보길 원했습니다. 개념이 다르면 이를 지칭하는 용어도 달라야 합니다. 설계자들은 두 개념을 다음과 같이 구분했습니다:

  • 소켓 주소를 담는 sockaddr_in 구조체에서는 주소를 지정하기 위해 사용할 ‘주소 체계’를 요구합니다. 여기서는 AF_INET, AF_IPX처럼 AF로 시작하는 상수가 필요합니다. AF는 Address Family(주소 패밀리)의 줄임말입니다.
  • 소켓을 생성하는 socket() 함수에서는 연결을 하기 위한 ‘프로토콜’을 요구합니다. 여기서는 PF_INET, PF_IPX처럼 PF로 시작하는 상수가 필요합니다. PF는 Protocol Family(프로토콜 패밀리)의 줄임말입니다.

원래 의도대로 소켓 프로그래밍을 한다면 이런 형태가 됩니다:

struct sockaddr_in addr;
int sockfd;

addr.sin_family = AF_INET; // AF로 시작하는 상수 사용
addr.sin_port = htons(54321);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

sockfd = socket(PF_INET, SOCK_STREAM, 0); // PF로 시작하는 상수 사용

AF와 PF의 구분은 무의미 🔗

그러나, 앞서 말씀드렸듯 AF와 PF의 구분은 설계 당시의 전략일 뿐, 정말로 두 개념이 구분되어 사용되는 일은 없었습니다.

리눅스 커널에서도 PF로 시작하는 상수와 AF로 시작하는 상수가 서로 같은 값을 가지도록 정의하고 있습니다:

/* Protocol families, same as address families. */
#define PF_UNSPEC	AF_UNSPEC
#define PF_UNIX		AF_UNIX
#define PF_LOCAL	AF_LOCAL
#define PF_INET		AF_INET

권장 방법 🔗

AF와 PF는 서로 아무런 차이가 없다는 것을 알았습니다. 그렇다면 둘 중 어느 것을 사용하는 것이 좋을까요? 원래 의도를 존중하여 AF를 쓸 자리에는 AF를, PF를 쓸 자리에는 PF를 써야 할까요? 아니면 단순히 AF와 PF 중 하나만 골라서 사용할까요?

유명한 소켓 프로그래밍 입문서인 <Beej’s Guide to Network Programming>에서는 AF_INET과 PF_INET을 설계 당시의 의도대로 구별하여 사용하고 있습니다:

So the most correct thing to do is to use AF_INET in your struct sockaddr_in and PF_INET in your call to socket().

반면, 리눅스 man 페이지에서는 모든 곳에 AF를 사용하길 권장합니다:

… already the BSD man page promises: “The protocol family generally is the same as the address family”, and subsequent standards use AF_* everywhere.

참고 🔗

  • [bgnet-1]: http://beej.us/guide/bgnet/html/#socket

    Once upon a time, a long time ago, it was thought that maybe an address family (what the “AF” in “AF_INET” stands for) might support several protocols that were referred to by their protocol family (what the “PF” in “PF_INET” stands for).

  • [bgnet-2]: http://beej.us/guide/bgnet/html/#socket

    That didn’t happen. And they all lived happily ever after, The End.