대부분의 언어에서 파일 API가 어색하게 느껴지는 이유와, C의 메모리 매핑 기반 접근이 왜 강력한지, 그리고 다른 언어들이 흔히 바이트 배열 수준에 머무르는 한계를 다룬다.
Navigation:Homepage
2026-02-28 — 2026-03-01 (Programming) (Rants) 제목은 농담 섞인 말이지만, 대부분의 언어에서는 파일에 대해 깊이 생각한 흔적이 거의 없다. 항상 어딘가 어색하게 느껴진다... C만 빼고. 사실 보통은 C의 더 나쁜 버전을 얻게 된다.
C에서는 파일을 메모리와 같은 방식으로 접근할 수 있다:
#include <sys/mman.h> #include <stdio.h> #include <stdint.h> #include <fcntl.h> #include <unistd.h>
void main() { // 1000개의 부호 없는 정수를 담는 파일을 생성/열기 // 모두 0으로 초기화됨. int len = 1000 * sizeof(uint32_t); int file = open("numbers.u32", O_RDWR | O_CREAT, 0600); ftruncate(file, len);
// 메모리에 매핑.
uint32_t* numbers = mmap(NULL, len,
PROT_READ | PROT_WRITE, MAP_SHARED,
file, 0);
// 무언가 하기:
printf("%d\n", numbers[42]);
numbers[42] = numbers[42] + 1;
// 정리
munmap(numbers, len);
close(file);
}
메모리 매핑은 파일을 메모리로 ‘로딩’하는 것과는 다르다. 파일이 RAM에 다 들어가지 않아도 여전히 동작한다. 데이터는 필요할 때 로드되므로, 테라바이트짜리 파일을 여는 데 하루 종일 걸리지 않는다.
모든 데이터 타입에 대해 동작하며 자동으로 캐시된다. 이 캐시는 시스템이 다른 일을 위해 메모리가 필요해지면 비워진다.
_mmap()은 사실 OS 기능_이라서 다른 많은 언어에도 있다. 하지만 거의 항상 바이트 배열로만 제한된다. 데이터 덩어리를 가져와서 파싱하고 처리한 다음, 디스크에 다시 쓰기 전에 직렬화해야 한다. read()와 write()를 수동으로 호출하는 것보다는 낫지만, 크게 낫지는 않다.
이런 언어들은 메모리 안의 데이터를 다루기 위한 멋진 기능을 잔뜩 가지고 있지만, 디스크 위의 데이터를 다루기 위한 기능은 없다. 메모리에서는 동적으로 크기가 변하는 문자열과 벡터, 열거형 타입, 객체 등등을 얻는다. 디스크에서는... 바이트 덩어리뿐이다.
대부분이 커스텀 할당자 같은 것도 이미 지원한다는 점을 생각하면, 파일에 접근하는 더 나은 방식을 추가하는 건 충분히 가능해 보이는데도 실제로 해낸 사람은 없다. ‘불편한 언어’로 유명한 C가 이걸 가장 잘한다는 게 내게는 정말 이상하다.
C의 구현이 아주 좋기만 한 것도 아니다. 메모리 매핑에는 오버헤드(페이지 폴트, TLB 플러시)가 좀 있고, C는 엔디언이나 오류 처리를 전혀 도와주지 않는다... 하지만 ‘아무것도 없음’을 이기려면 많은 게 필요하진 않다.
물론 어느 정도 파싱과 검증을 하고 싶을 수는 있다. 하지만 데이터가 디스크를 떠날 때마다 매번 필수여서는 안 된다. RAM은 디스크보다 훨씬 작아서, 전부를 메모리로 파싱해 넣는 건 종종 불가능하다.
많은 파일은 신뢰할 수 없는 데이터가 아니다.
바이너리 파일의 경우, 파싱은 보통 중복 작업이다. 코드가 온디스크 표현을 직접 조작하지 못할 이유가 없고, “스크래치패드” 같은 임시 파일이라면 RAM에 존재하는 형태 그대로 저장하면 된다. 물론 JSON을 직접 조작하고 싶지는 않겠지만, 정수 몇 개 저장하려고 일을 한바탕 할 이유는 없다.
파일 조작 역시 비슷하게 방치되어 있다. 파일시스템은 원조 NoSQL 데이터베이스지만, 보통은 C의 readdir() 주변에 감싼 래퍼 이상을 제공받기 어렵다.
그래서 사람들은 대개 SQLite 같은 다른 데이터베이스를 파일시스템 위에 올려서 돌리게 되지만, 관계형 데이터베이스는 프로그램에 완벽하게 들어맞는 경우가 거의 없다.
... 그리고 SQL은 파일보다 통합이 더 끔찍하다. 모든 데이터를 직렬화해야 하는 것에 더해, 접근하기 위해 아예 별도의 언어로 코드를 작성해야 한다!
대부분의 프로그래머는 결국 이를 키-값 저장소로만 쓰고, 자기만의 인덱싱을 구현하게 된다. 기묘한 삼중 중첩 데이터베이스를 만드는 셈이다.
Site wide RSS feed.
Proudly supporting IPv6! Check your network
You may use this content under the CC BY-NC-SA 4.0 License. This website is not licensed for ML/LLM training or content creation.
Questions, comments, and technical issues can be sent in by email.