왜 C가 최고의 파일 API를 가지고 있나요
Source: Hacker News
2026-02-28 (Programming) (Rants)
Memory Mapping in C
많은 좋은 프로그래밍 언어가 있지만, 파일은 언제나 부수적인 생각처럼 보입니다. 보통 read(), write()와 어떤 종류의 직렬화 라이브러리만 제공됩니다.
C에서는 파일을 메모리의 데이터와 정확히 같은 방식으로 접근할 수 있습니다:
#include
#include
#include
#include
#include
int main(void) {
// Create/open a file containing 1000 unsigned integers,
// initialized to all zeros.
int len = 1000 * sizeof(uint32_t);
int file = open("numbers.u32", O_RDWR | O_CREAT, 0600);
ftruncate(file, len);
// Map it into memory.
uint32_t *numbers = mmap(NULL, len,
PROT_READ | PROT_WRITE, MAP_SHARED,
file, 0);
// Do something:
printf("%d\n", numbers[42]);
numbers[42] = numbers[42] + 1;
// Clean up
munmap(numbers, len);
close(file);
return 0;
}
How Memory Mapping Differs from Loading
메모리 매핑은 파일을 메모리로 로드하는 것과 동일하지 않습니다: 파일이 RAM에 들어가지 않아도 작동합니다. 데이터는 필요할 때마다 로드되므로 테라바이트 규모의 파일을 여는 데 하루가 걸리지 않습니다. 모든 데이터 타입에 대해 동작하고 자동으로 캐시되며, 시스템이 다른 용도로 메모리가 필요하면 캐시가 비워집니다.
Limitations in Other Languages
하지만 대부분의 다른 언어에서는 read()를 작은 청크 단위로 읽고, 파싱하고, 처리하고, 직렬화한 뒤 최종적으로 write()를 디스크에 다시 써야 합니다. 이는 번거롭고 순차 접근에만 제한됩니다—컴퓨터는 수십 년 전부터 테이프를 사용하지 않았습니다.
메모리 매핑을 사용할 수 있더라도 보통 바이트 배열에만 제한되며, 여전히 명시적인 파싱/직렬화가 필요합니다. 결국 read()와 write()를 호출하는 더 깔끔한 방법에 불과합니다.
Performance and Overhead
C의 구현이 완벽한 것은 아닙니다: 메모리 매핑은 오버헤드(페이지 폴트, TLB 플러시)를 발생시키고 C는 엔디언을 처리해 주지 않지만, 직접 접근이 전혀 없는 것보다 여전히 빠릅니다.
물론 파싱과 검증을 하고 싶을 수도 있지만, 데이터가 디스크를 떠날 때마다 매번 그렇게 해야 할 필요는 없습니다. 메모리가 부족해 모든 데이터를 RAM에 파싱할 수 없는 경우가 흔합니다. 코드를 복잡하게 만들지 않고 데이터를 오프로드할 수 있다는 점은 매우 유용합니다.
Security and Serialization
Python의 pickle을 한 번 보세요: 완전히 안전하지 않은 직렬화 포맷입니다. 파일을 로드하면 단순히 숫자 몇 개만 원하더라도 코드 실행이 발생할 수 있는데, 여전히 널리 사용되는 이유는 Python의 코드‑데이터 혼합 모델에 맞기 때문입니다. 많은 파일이 신뢰할 수 없는 것이 아닙니다.
Filesystem as a Database
파일 조작도 비슷하게 소홀히 다뤄집니다. 파일 시스템은 원래 NoSQL 데이터베이스였지만, 보통 C의 readdir()를 감싸는 래퍼 이상을 얻지 못합니다. 이 때문에 사람들은 파일 시스템 위에 SQLite와 같은 또 다른 데이터베이스를 올려 쓰지만, 관계형 데이터베이스는 프로그램에 딱 맞지는 않습니다.
…그리고 SQL은 파일보다도 더 안 맞습니다: 모든 데이터를 직렬화해야 할 뿐만 아니라, 접근하기 위해 완전히 별도의 언어로 코드를 작성해야 합니다! 대부분의 프로그래머는 이를 키‑밸류 저장소처럼 사용하고 자체 인덱스를 구현해, 기이한 삼중‑중첩 데이터베이스를 만들게 됩니다.
Conclusion
제목에 답하자면, 이것은 잘못된 가정의 결과라고 생각합니다: 파일에서 읽은 데이터는 어디선가 온 것이고 파싱이 필요하며, 디스크에 쓰는 데이터는 어디엔가 전송되는 것이고 표준 포맷으로 직렬화가 필요하다는 가정 말이죠. 메모리가 제한된 시스템에서는 이것이 전혀 사실이 아니며, 100 GB 파일이라면 모든 시스템이 메모리 제한에 직면합니다.