Writing C for the Web in 2026 Isn't Insane. It Might Be the Future
2026년에 웹을 C로 만든다고요? 미친 선택이 아니라 미래일 수도 있습니다
C와 CGI로 만든 상용 웹 앱 사례를 바탕으로, 의존성 최소화와 코드 이해 가능성이 공급망 공격 및 AI 생성 코드 시대에 실용적인 선택이 될 수 있다고 주장합니다. 다만 C의 메모리 안전성과 팀 규모에 따른 한계도 짚으며, 요점은 C 자체보다 복잡성을 기본값으로 삼지 않는 데 있다고 설명합니다.
- 주제
에디터 노트
단순한 스택은 의존성 수와 운영 층을 줄이지만, 보안 위험을 없애지는 않습니다. 댓글에서 지적했듯 SQLite와 TLS 구현, 운영체제는 여전히 신뢰해야 하며 C의 메모리 안전성 문제도 남습니다. 따라서 의존성을 줄인다는 주장은 위험을 제거한다기보다 검토할 대상을 좁힌다는 설명일 때 더 정확합니다. 본문은 CGI가 현대 커널에서 충분히 빠를 수 있다고 주장하지만 성능 측정값은 제시하지 않습니다. 반면 바이너리 하나로 배포하고 코드 전체를 파악하기 쉽다는 운영상의 이점은 구체적입니다. 댓글은 팀이 커질수록 코드 공유와 이해가 어려워질 수 있다고 덧붙입니다. 이 사례가 뒷받침하는 범위는 특정 스택의 보편적 우월성이 아니라, 작은 서비스에서 단순성을 선택지로 검토할 근거입니다.
AI 요약
계정, Stripe 결제, 검색 대시보드, 거래 이메일을 제공하는 상용 웹 제품이 C와 CGI로 만들어졌습니다. Corey Prophitt의 marketyour.games는 SQLite와 OpenBSD를 사용하고, 세 개의 라이브러리만 의존합니다. 정적 링크한 바이너리 하나를 배포 폴더에 넣고 교체하는 방식이며, 깨끗한 빌드에는 몇 초가 걸립니다. 글쓴이는 이를 주말 실험이나 향수에 기댄 선택이 아니라 실제 결제를 받는 서비스라고 강조합니다.
CGI와 단일 바이너리
CGI는 요청마다 프로세스를 새로 띄운다는 이유로 느리다는 비판을 받아 왔습니다. 글쓴이는 현대 커널의 프로세스 생성 비용이 과거보다 낮아졌으며, 병목이 생기면 FastCGI로 옮길 수 있다고 설명합니다. 과거에는 타당했던 성능 반론을 지금도 검증 없이 반복하는 것은 아닌지 묻습니다. 다만 본문에는 CGI 성능을 직접 측정한 수치가 제시되지 않습니다.
단순한 구성은 운영 부담도 줄입니다. 데이터베이스 서버를 따로 관리하거나 여러 서비스 사이에서 요청을 추적할 필요가 없습니다. 애플리케이션은 하나의 프로그램으로 실행되며 배포는 바이너리 교체로 끝납니다. 요청을 입력하고 프로그램의 출력을 확인하거나 디버거로 코드를 살펴보는 방식도 단순해집니다. 라우팅, 요청 파싱, 유효성 검사, 출력 이스케이프 같은 기능은 프레임워크가 제공하지 않으므로 직접 구현해야 합니다.
의존성, AI 생성 코드, 복잡성
글쓴이는 현대 웹 앱의 의존성 그래프가 공격 표면이라고 봅니다. 직접 추가한 패키지 몇 개가 수백 개의 전이 의존성으로 늘어나며, 그중에는 관리가 중단됐거나 낯선 관리자가 맡은 패키지도 있습니다. 패키지 저장소 공격과 오타 또는 AI 환각을 노린 패키지 이름이 등장하고, 코딩 에이전트는 사람이 코드를 확인하지 않은 채 의존성을 설치할 수 있다고 설명합니다. 이에 비해 사례의 공급망은 C 컴파일러와 세 개 라이브러리로 좁아집니다. 글쓴이는 세계적으로 감시받는 프로젝트와 주간 다운로드가 적은 패키지의 위험을 같은 수준으로 볼 수 없다고 주장합니다.
두 번째 변화로 AI를 듭니다. 코드와 추상화를 빠르게 만들어 내는 일이 저렴해지면서 병목은 생산보다 이해와 검증으로 옮겨갔다는 설명입니다. 전체 시스템을 파악하고 실제 동작을 확인할 수 있는 작은 코드베이스가 생성 코드가 넘치는 환경에서 가치가 커진다고 봅니다.
세 번째로 웹 서버와 애플리케이션 서버, 컨테이너, 오케스트레이터, 빌드 파이프라인처럼 여러 층을 쌓아 온 관행을 지적합니다. 각 층은 실제 문제를 해결하지만, 앞선 층이 만든 문제를 다음 층이 해결하는 경우도 있습니다. 글쓴이는 복잡성을 더 잘 관리하는 대신 애초에 필요한 층을 줄이는 선택을 제안합니다. 프레임워크와 생태계의 속도가 중요한 빠른 프로토타이핑, 대규모 팀의 공동 개발, 상호작용이 많은 프런트엔드, 극단적인 규모에는 기존 스택이 더 적합할 수 있다고 덧붙입니다.
C를 선택할 때 남는 비용
글쓴이는 C의 메모리 안전성 문제를 인정합니다. 버퍼 오버플로는 느린 프레임워크보다 더 심각한 실패로 이어질 수 있습니다. 따라서 주장의 중심은 C를 쓰자는 데 있지 않고, 의존성과 추상화, 배포 단위를 필요 이상으로 늘리지 말자는 데 있다고 설명합니다. 단일 바이너리 Go 서비스나 Rust에서도 비슷한 단순성을 추구할 수 있습니다. 글의 결론은 복잡한 스택이 항상 잘못됐다는 뜻이 아니라, 복잡성을 기본값으로 선택하지 말자는 주장입니다.
dev.to 반응
- @csm18 — Neovim이 유행하기 시작했을 때는 Vim을 써 본 적이 없었습니다. 튜토리얼마다 Vim부터 시작하라고 해서 Vim을 써 봤는데, 최신 Vim은 예상보다 기본적인 코드 편집기에 가까웠습니다. 구문 강조, 파일 열기와 편집, Vim 안에서 실행하는 터미널까지 갖췄습니다.
- @james_anderson_h — 터미널과 기초 도구에 관한 이야기와 잘 맞는 사례입니다. 더 새롭고 유행하는 Neovim을 먼저 찾았다가, 그 기반인 오래된 도구만으로도 필요한 기능 대부분을 갖췄다는 걸 발견한 셈입니다. Vim에는 플러그인 하나 없이도 구문 강조, 내장 터미널, 분할 창이 있습니다. 기반 도구부터 익히면 기본 기능과 편의 기능을 구분하고 문제가 생긴 층도 찾기 쉽습니다.
- @pengeszikra — 글에 공감합니다. 의존성을 완전히 없애려면 컴퓨터를 쓰지 않아야 한다고 생각합니다. 저는 1993년식 Mazda B2200 픽업을 샀습니다. 컴퓨터도, 과도한 기술도, 필요 없는 사륜구동도 없고 기능에 충실한 작업용 차량입니다. 코딩에서도 JSDoc으로 JavaScript의 안전성을 지키며 TypeScript가 필요 없다고 주장했고, 세 함수로 만든 Proxy 기반 반응형 프레임워크, 의존성 없는 Rust/WASM 벡터 채우기 구현 등을 시도했습니다. 이제 C로 구동하는 Vim 스타일 터미널 편집기를 만들 생각입니다. 우선 Markdown부터 시작하겠습니다.
- @james_anderson_h — 1993년식 Mazda B2200은 이 논리를 현실에서 보여주는 사례 같습니다. 필요 없는 기능 없이 단순하고 직접 고칠 수 있습니다. JSDoc, 세 함수짜리 반응형 도구, 의존성 없는 Rust/WASM에서도 필요한 이점만 얻고 부가 절차는 줄이려는 흐름이 보입니다. C 기반 터미널 편집기도 Markdown부터 시작하면 작은 도구를 만들어 보며 배울 수 있겠습니다.
- @slabb — 저는 브라우저 층에서 비슷한 선택을 했습니다. navette라는 약 660KB짜리 Rust 바이너리가 운영체제에 이미 들어 있는 WebView를 구동합니다. CI 실행마다 200MB가 넘는 Puppeteer용 Chromium을 내려받지 않아도 됩니다. 따뜻한 상태에서 페이지를 여는 데 약 8ms가 걸리고 렌더링 엔진은 운영체제가 제공한다고 합니다. 다만 글의 세 번째 힘으로 메모리 안전성도 넣어야 합니다. 의존성을 줄여도 선택한 언어의 CVE 유형까지 사라지지는 않습니다. OpenBSD의 완화 기능도 다룰 만합니다.
- @james_anderson_h — navette는 같은 선택을 한 층 위에서 보여줍니다. 660KB Rust 바이너리와 운영체제 WebView를 쓰면 CI마다 218MB Chromium을 내려받는 일을 피할 수 있습니다. 약 8ms의 페이지 열기와 무료로 제공되는 렌더링은 측정으로 확인할 만한 세부 정보입니다. 메모리 안전성 지적도 필요합니다. 의존성 그래프를 줄여도 언어가 가진 취약점 유형은 남습니다. C와 OpenBSD의 완화 기능을 함께 설명해야 합니다.
- @slabb — 수정본에 그 내용을 넣어도 좋습니다. 제안과 수정이 나란히 놓이는 것보다 글 안에 들어가는 편이 낫습니다. 제 경우에는 브라우저 번들을 없애고 운영체제 엔진을 사용합니다. 의존성이 없다고 언어의 위험까지 없어지지는 않으며, 위험을 셀 수 있어야 감사도 가능합니다. navette에는 다시 실행할 수 있는 벤치마크도 포함했습니다. OpenBSD의 하드닝과 C 조합도 의존성 그래프처럼 근거를 제시해야 합니다.
- @dhruonweb — 공급망 주장이 가장 설득력 있습니다. 이름을 아는 라이브러리 세 개는 알 수 없는 전이 의존성 300개보다 보안상 낫습니다. 다만 의존성이 0개가 된 건 아닙니다. SQLite, TLS 구현, 운영체제는 여전히 사용하며 직접 감사하지 않습니다. 달라진 점은 의존하는 대상의 수입니다. 한 사람이 C 코드 전체를 이해하는 상황과 여섯 명이 같은 코드를 공유하는 상황은 다릅니다. 팀 규모가 여섯 명이면 C가 나빠져서가 아니라 공유 이해가 어려워져 계산이 달라집니다. 처리량보다 바이너리 하나를 교체하는 운영상의 이점이 더 큽니다.