1 분 소요

네트워크 프로그래밍 책을 둘러보던 중 소켓 생성할 때 PF_INET으로 생성하는 것을 보고 이게 뭔가 싶었다. 내가 배울 때는 항상 AF_INET으로 배웠기 때문. 책에도 이에 대한 내용이 부족해서 검색해보니 여기에 대한 정보가 많았다.

원래 의도된 구분

PF_INETAF_INET은 둘 다 상수값 2로 같은 값을 나타내지만, 원래 의도상 PF_*(Protocol Family)는 socket()의 첫 번째 인자로 통신 프로토콜의 종류를 지정할 때, AF_*(Address Family)는 sockaddr_insin_family처럼 주소 체계를 지정할 때 쓰도록 설계되었다.

int fd = socket( PF_INET, SOCK_STREAM, 0 );   // 원래 의도상의 구분

struct sockaddr_in addr;
addr.sin_family = AF_INET;

이렇게 나뉜 이유는, socket()을 설계할 당시 하나의 프로토콜 패밀리 안에서 여러 개의 서로 다른 주소 체계를 쓸 수 있게 될 것이라 예상했기 때문이다. 즉 프로토콜(어떻게 통신할지)과 주소 체계(상대를 어떻게 식별할지)를 개념적으로 분리해둔 것이다. 하지만 실제로는 이 예상이 실현되지 않았고, IPv4 세계에서는 PF_INET을 쓰는 프로토콜이 AF_INET 주소 체계만 쓰는 1:1 관계로 굳어져 두 상수가 사실상 같은 값을 갖게 됐다.

2026년 수정 안내 이 글에는 “socket()에는 PF_INET을 쓰는 것이 좋다”고 적었는데, 현재 기준으로는 이 권고가 뒤집혔다. 지금은 POSIX 표준과 리눅스 man page 모두 socket()에도 AF_INET을 쓰도록 명시하고 있다.

지금은 socket()에도 AF_INET을 쓴다

POSIX(sys/socket.h)는 socket()의 첫 번째 인자를 address family로 명시하고 있다. 리눅스 커널 헤더도 AF_INETPF_INET을 완전히 같은 값으로 정의해 실질적으로 구분이 없고, 리눅스 socket(2) man page의 NOTES 절에도 BSD 관례상 socket()에는 AF_*를 쓰는 것이 옳지만 실무에서는 PF_*도 섞여 쓰인다는 취지의 설명이 있다.

// linux/socket.h
#define PF_INET     AF_INET

실무에서 통용되는 대부분의 예제 코드(Beej’s Guide 등)도 socket()AF_INET을 쓴다.

int fd = socket( AF_INET, SOCK_STREAM, 0 );   // 현재 권장되는 형태

struct sockaddr_in addr;
addr.sin_family = AF_INET;

정리

  • 두 상수는 리눅스를 포함한 사실상 모든 구현에서 같은 값이라, 어느 쪽을 써도 동작에는 차이가 없다.
  • 역사적으로는 PF_*socket()용, AF_*가 주소 구조체용으로 나뉘어 설계되었다.
  • 하지만 실제로 그 구분이 실현되지 못했고, 지금은 관례와 문서 모두 socket()을 포함해 전부 AF_INET으로 통일하는 쪽을 권장한다.
  • 오래된 책이나 예제에서 PF_INET이 보이더라도, 새로 작성하는 코드라면 AF_INET으로 통일하는 것이 낫다.

참고자료

댓글 남기기