PF_INET과 AF_INET의 차이
네트워크 프로그래밍 책을 둘러보던 중 소켓 생성할 때 PF_INET으로 생성하는 것을 보고 이게 뭔가 싶었다. 내가 배울 때는 항상 AF_INET으로 배웠기 때문. 책에도 이에 대한 내용이 부족해서 검색해보니 여기에 대한 정보가 많았다.
원래 의도된 구분
PF_INET과 AF_INET은 둘 다 상수값 2로 같은 값을 나타내지만, 원래 의도상 PF_*(Protocol Family)는 socket()의 첫 번째 인자로 통신 프로토콜의 종류를 지정할 때, AF_*(Address Family)는 sockaddr_in의 sin_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_INET과 PF_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으로 통일하는 것이 낫다.
댓글 남기기