컨테이너 시대의 이상한 조언

컨테이너 환경에서 애플리케이션을 처음 운영해 본 개발자라면 대부분 한 번쯤은 비슷한 조언을 듣게 된다. Docker나 Kubernetes 관련 문서를 읽다 보면 거의 예외 없이 등장하는 권장사항이 있기 때문이다. 바로 애플리케이션 로그를 파일에 기록하지 말고 stdout으로 출력하라는 것이다. 전통적인 서버 환경에 익숙한 개발자라면 이 문장을 처음 접했을 때 약간의 위화감을 느낄 가능성이 크다. 서버 애플리케이션의 로그는 당연히 파일로 남기는 것이라고 생각해 왔기 때문이다. 실제로 수십 년 동안 대부분의 서버 소프트웨어는 로그 파일을 중심으로 운영되었고, 운영자 역시 로그 파일을 기준으로 시스템을 관리해 왔다.

하지만 컨테이너 환경에서는 그 관점이 조금 달라진다. 애플리케이션은 여전히 로그를 생성하지만, 그 로그를 저장하는 방식은 더 이상 애플리케이션 내부의 책임이 아니다. 대신 컨테이너 런타임이나 오케스트레이션 시스템이 로그를 수집하고 저장하는 역할을 맡는다. 애플리케이션은 단지 stdout과 stderr로 로그를 출력하기만 하면 되고, 그 이후의 처리는 플랫폼이 담당한다. 처음 보면 단순한 운영상의 편의처럼 보일 수도 있지만, 사실 이 방식은 매우 오래된 시스템 설계와 깊이 연결되어 있다.

이 지점에서 한 가지 흥미로운 질문이 등장한다. 왜 컨테이너 플랫폼은 로그 파일을 직접 관리하도록 애플리케이션에 맡기지 않고, stdout을 통해 로그를 출력하도록 권장할까. 단순히 컨테이너 환경이 특별하기 때문일까, 아니면 그보다 더 오래된 이유가 있는 것일까. 이 질문을 조금 더 깊이 따라가 보면 결국 우리는 Unix라는 운영체제가 설계된 방식으로 돌아가게 된다. stdout과 stderr라는 개념은 단순히 콘솔 출력을 의미하는 것이 아니라, 프로그램과 시스템이 데이터를 교환하는 기본 인터페이스이기 때문이다. 그리고 바로 그 인터페이스가 컨테이너 환경에서도 그대로 활용되고 있다.

이 글은 바로 그 지점에서 시작된다. 왜 Docker 로그는 stdout을 기반으로 동작하는가, 그리고 그 구조가 왜 자연스럽게 받아들여지는가. 이 질문에 대한 답을 찾기 위해서는 먼저 우리가 오랫동안 사용해 왔던 로그 파일 중심의 운영 방식을 다시 살펴볼 필요가 있다. 컨테이너 환경의 로그 구조를 이해하려면, 먼저 우리가 무엇을 당연하게 여겨 왔는지를 이해해야 하기 때문이다.

로그 파일의 시대

컨테이너 기술이 등장하기 훨씬 이전부터 서버 운영의 기본 도구는 로그 파일이었다. 웹 서버, 데이터베이스, 메시지 큐, 애플리케이션 서버 등 거의 모든 서버 소프트웨어는 실행 중에 다양한 로그를 생성하고 이를 파일로 기록한다. 예를 들어 Apache 웹 서버는 요청 로그와 오류 로그를 각각 별도의 파일에 기록하며, Nginx 역시 접근 로그와 에러 로그를 명확하게 구분해 관리한다. 이러한 로그 파일은 일반적으로 /var/log 디렉터리 아래에 저장되며, 운영자는 이 파일들을 분석하여 시스템 상태를 파악하고 문제를 진단한다.

이러한 방식은 매우 오랜 시간 동안 안정적으로 사용되어 왔다. 서버는 보통 하나의 물리 머신 또는 가상 머신에서 장기간 실행되기 때문에 로그 파일이 해당 시스템에 저장되는 것이 자연스러웠다. 운영자는 SSH로 서버에 접속하여 로그 파일을 직접 확인하거나, tail 같은 명령어를 사용해 실시간 로그를 모니터링할 수 있었다. 또한 로그 파일이 일정 크기 이상 커지면 자동으로 새 파일로 교체하는 logrotate 같은 도구도 널리 사용되었다. 이 모든 도구들은 로그 파일이라는 전제를 중심으로 만들어진 것들이다.

하지만 로그 파일 방식에도 분명한 한계가 존재했다. 서버 수가 증가하면 각 서버의 로그 파일을 개별적으로 관리해야 했고, 여러 시스템에서 생성된 로그를 한곳에 모아 분석하는 작업도 쉽지 않았다. 대규모 서비스 환경에서는 로그 수집 시스템을 별도로 구축해야 했고, 이를 위해 syslog 서버나 로그 수집 에이전트를 각 서버에 설치하는 경우도 많았다. 즉 로그 파일 방식은 단일 서버 환경에서는 효율적이지만, 시스템 규모가 커질수록 관리 부담이 점점 증가하는 구조였다.

그럼에도 불구하고 이 방식은 오랫동안 유지되었다. 이유는 단순하다. 서버가 비교적 안정적인 환경에서 장기간 실행되었기 때문이다. 애플리케이션은 특정 머신에 설치되고, 로그 역시 그 머신에 남아 있다. 운영자는 그 머신에 접근해 로그를 확인하면 된다. 이런 환경에서는 로그 파일 기반 운영이 큰 문제를 만들지 않았다. 그러나 시스템 구조가 변하면서 상황도 함께 바뀌기 시작한다.

컨테이너가 등장하면서 바뀐 운영 모델

Docker와 같은 컨테이너 기술이 등장하면서 애플리케이션을 실행하는 방식은 이전과 크게 달라졌다. 전통적인 서버 환경에서는 하나의 서버에 애플리케이션이 설치되고 오랫동안 실행된다. 로그 파일 역시 그 서버에 계속 누적된다. 하지만 컨테이너 환경에서는 애플리케이션이 더 이상 고정된 서버에 묶여 있지 않다. 컨테이너는 필요할 때 생성되고, 필요 없어지면 언제든지 삭제될 수 있는 일시적인 실행 환경이다.

이러한 특성은 로그 관리 방식에도 직접적인 영향을 미친다. 만약 애플리케이션이 로그를 파일로 기록한다면, 그 로그 파일은 컨테이너 내부의 파일 시스템에 저장된다. 그런데 컨테이너가 종료되거나 삭제되면 그 파일 시스템 역시 함께 사라질 수 있다. 즉 로그가 애플리케이션과 동일한 생명주기를 가지게 되는 것이다. 운영자의 입장에서 이는 상당히 불편한 상황이다. 문제가 발생한 뒤 로그를 확인하려고 했을 때 이미 컨테이너가 삭제되어 로그 파일이 존재하지 않을 수도 있기 때문이다.

또 다른 문제는 확장성이다. 컨테이너 기반 시스템에서는 하나의 서비스가 동시에 수십 개 또는 수백 개의 컨테이너로 실행될 수 있다. 이 경우 각 컨테이너 내부에 로그 파일이 생성된다면 운영자는 수많은 파일을 각각 관리해야 한다. 컨테이너가 새로운 노드로 이동하거나 재시작될 때마다 로그 위치도 달라질 수 있다. 이러한 환경에서는 전통적인 로그 파일 관리 방식이 더 이상 효과적으로 작동하지 않는다.

결국 컨테이너 환경에서는 로그 관리의 책임을 애플리케이션이 아니라 플랫폼이 맡는 것이 더 합리적인 선택이 된다. 애플리케이션은 단지 자신의 실행 결과를 출력하기만 하면 되고, 그 출력은 컨테이너 런타임이 수집하여 저장하거나 외부 시스템으로 전달한다. 바로 이 지점에서 stdout이라는 오래된 Unix 개념이 다시 등장한다. 프로그램이 stdout으로 데이터를 출력하고, 시스템이 그 출력을 처리하는 구조는 이미 수십 년 전에 Unix에서 설계된 방식이기 때문이다.

컨테이너 로그 구조는 결국 그 오래된 모델을 새로운 환경에 적용한 것이라고 볼 수 있다. 애플리케이션이 stdout으로 로그를 출력하면, 컨테이너 런타임은 그 출력을 캡처하고 이를 로그 시스템으로 전달한다. 이 방식은 컨테이너의 생명주기와 로그의 생명주기를 분리하며, 동시에 대규모 환경에서도 로그를 안정적으로 수집할 수 있도록 만들어 준다. 그리고 이 모든 과정은 우리가 이미 알고 있는 Unix I/O 모델 위에서 자연스럽게 동작한다.

이제 질문은 조금 더 명확해진다. 컨테이너 환경에서 stdout 기반 로그가 자연스럽게 작동하는 이유는 무엇일까. 그리고 Docker는 어떻게 이 구조를 실제 시스템으로 구현했을까. 다음 섹션에서는 바로 그 구조를 좀 더 구체적으로 살펴보게 된다.

Docker가 선택한 방식 — stdout을 로그로 사용하기

컨테이너 환경에서 로그를 처리하는 방식은 전통적인 서버 운영 모델과는 상당히 다른 접근을 취한다. Docker는 애플리케이션 로그를 파일로 남기도록 권장하지 않는다. 대신 애플리케이션이 stdout과 stderr로 로그를 출력하도록 유도하고, 컨테이너 런타임이 그 스트림을 직접 수집하는 방식을 선택했다. 이 구조는 처음 보면 단순한 구현 선택처럼 보이지만, 실제로는 컨테이너라는 실행 환경의 특성과 매우 밀접하게 연결되어 있다.

Docker에서 컨테이너는 결국 하나의 프로세스다. 컨테이너를 실행한다는 것은 사실상 특정 프로세스를 격리된 환경에서 실행하는 것에 가깝다. 이 프로세스 역시 Unix 프로그램과 동일하게 stdin, stdout, stderr 세 개의 기본 스트림을 가지고 시작한다. Docker는 바로 이 점에 주목했다. 컨테이너 내부의 프로세스가 stdout으로 출력하는 모든 데이터를 Docker 엔진이 직접 가로채고, 이를 로그 시스템으로 전달하는 것이다. 다시 말해 애플리케이션이 stdout으로 로그를 출력하면 Docker가 그 데이터를 자동으로 수집한다.

이 구조를 조금 더 구체적으로 생각해 보면, 컨테이너 로그 시스템은 사실상 프로세스의 표준 출력 스트림을 플랫폼 레벨에서 캡처하는 구조라고 볼 수 있다. 애플리케이션은 단순히 로그를 출력하기만 하면 되고, Docker는 그 출력 스트림을 읽어 파일로 저장하거나 외부 로그 시스템으로 전달한다. 이때 Docker는 여러 종류의 로그 드라이버를 사용할 수 있다. 기본적으로는 JSON 형식의 로그 파일로 저장되지만, 필요하다면 syslog, Fluentd, journald 같은 외부 로그 시스템으로 바로 전달하는 것도 가능하다. 중요한 점은 로그 저장 방식이 애플리케이션이 아니라 플랫폼 설정에 의해 결정된다는 것이다.

이 구조는 컨테이너 환경에서 매우 큰 장점을 가진다. 애플리케이션은 로그 저장 위치나 형식을 신경 쓸 필요가 없다. 단지 stdout으로 로그를 출력하면 된다. 로그를 파일로 저장할지, 중앙 로그 시스템으로 보낼지, 아니면 모니터링 플랫폼으로 전달할지는 Docker 설정이 결정한다. 이러한 분리는 애플리케이션과 운영 플랫폼 사이의 역할을 명확하게 나누는 효과를 만든다. 그리고 이 설계 덕분에 컨테이너 환경에서는 로그 관리가 훨씬 유연해진다.

이 지점에서 흥미로운 사실이 하나 드러난다. Docker는 새로운 로그 시스템을 발명한 것이 아니다. 단지 Unix 프로그램이 원래 가지고 있던 stdout이라는 인터페이스를 플랫폼 수준에서 활용했을 뿐이다. 이 구조는 이후 Kubernetes 같은 오케스트레이션 시스템에서도 거의 동일하게 사용된다. 그리고 바로 그 지점에서 Docker 로그 구조는 더 큰 시스템 아키텍처와 연결되기 시작한다.

Kubernetes와 클라우드 환경의 로그 수집 구조

Docker가 단일 컨테이너 환경에서 stdout 기반 로그 구조를 정립했다면, Kubernetes는 그 모델을 대규모 분산 시스템 환경으로 확장했다. Kubernetes 클러스터에서는 수많은 컨테이너가 여러 노드에서 동시에 실행된다. 이러한 환경에서는 단순히 로그를 저장하는 것보다, 여러 노드에서 생성되는 로그를 안정적으로 수집하고 중앙 시스템으로 전달하는 것이 훨씬 중요한 문제가 된다.

Kubernetes는 Docker와 동일하게 컨테이너의 stdout과 stderr를 기본 로그 소스로 사용한다. 컨테이너 내부에서 애플리케이션이 stdout으로 로그를 출력하면, 그 로그는 노드의 컨테이너 런타임에 의해 캡처된다. 이후 이 로그는 노드 파일 시스템에 기록되거나 로그 수집 에이전트에 의해 읽혀 중앙 로그 시스템으로 전달된다. 이 과정에서 애플리케이션은 로그 수집 시스템에 대해 전혀 알 필요가 없다. 애플리케이션은 단지 stdout으로 로그를 출력하기만 하면 된다.

Kubernetes 환경에서는 보통 로그 에이전트가 각 노드에서 실행된다. 이 에이전트는 노드에 기록된 컨테이너 로그 파일을 읽어 중앙 로그 시스템으로 전달한다. 대표적인 예로 Fluentd나 Fluent Bit 같은 도구가 사용된다. 이러한 에이전트는 로그를 Elasticsearch, Loki, Splunk 같은 중앙 로그 플랫폼으로 전송한다. 이 구조 덕분에 운영자는 수백 개의 컨테이너에서 생성되는 로그를 하나의 인터페이스에서 조회할 수 있다.

Kubernetes 로그 구조의 핵심은 애플리케이션 로그와 로그 수집 시스템을 완전히 분리했다는 점이다. 애플리케이션은 로그를 어디에 저장할지 고민할 필요가 없다. stdout으로 출력된 로그는 자동으로 플랫폼에 의해 수집되고 처리된다. 이러한 구조는 컨테이너가 계속 생성되고 삭제되는 환경에서도 안정적으로 동작한다. 로그는 컨테이너 내부가 아니라 플랫폼에 의해 관리되기 때문이다.

이 지점에서 우리는 한 가지 중요한 사실을 깨닫게 된다. Kubernetes 로그 시스템이 동작하는 방식은 사실 새로운 아이디어가 아니다. 그것은 단지 Unix의 오래된 스트림 기반 I/O 모델을 현대 분산 시스템에 적용한 것일 뿐이다. 그리고 이 사실은 다음 질문으로 자연스럽게 이어진다. 왜 Unix의 I/O 모델은 이렇게 오랜 시간이 지나도 여전히 유효할까.

사실 Docker가 새로 만든 것이 아니다

Docker와 Kubernetes의 로그 시스템을 자세히 살펴보면, 그 구조가 의외로 단순하다는 것을 알 수 있다. 컨테이너 프로세스가 stdout으로 로그를 출력하고, 플랫폼이 그 스트림을 수집한다. 이 구조는 처음 보면 컨테이너 환경을 위해 새롭게 만들어진 설계처럼 보일 수 있다. 하지만 조금만 더 깊이 들여다보면 이 구조는 사실 Unix I/O 모델의 직접적인 확장이라는 사실을 알 수 있다.

Unix에서 프로그램은 원래부터 stdout으로 결과를 출력하도록 설계되어 있었다. 그리고 그 출력은 다른 프로그램으로 전달될 수 있었다. 예를 들어 grep, sort, awk 같은 도구들은 모두 stdout으로 결과를 출력하고, 그 결과는 pipe를 통해 다음 프로그램으로 전달된다. 이러한 구조는 Unix 시스템의 핵심 철학 중 하나다. 프로그램은 단지 데이터를 입력받고 출력할 뿐이며, 그 데이터 흐름은 시스템이 자유롭게 연결할 수 있다.

Docker가 선택한 로그 구조는 바로 이 모델을 그대로 사용한 것이다. 컨테이너 내부의 애플리케이션은 stdout으로 로그를 출력한다. Docker는 그 stdout 스트림을 가로채어 로그 시스템으로 전달한다. 즉 Docker는 새로운 인터페이스를 만든 것이 아니라 Unix 프로그램이 원래 사용하던 인터페이스를 활용한 것이다. 이 점이 바로 Docker 로그 시스템이 매우 자연스럽게 동작하는 이유다.

이러한 관점에서 보면 Docker 로그 구조는 새로운 기술이라기보다는 오래된 설계의 재활용이라고 할 수 있다. Unix는 프로그램이 stdout으로 말하도록 설계되었고, Docker는 그 stdout을 로그로 활용했다. 그 결과 Unix의 단순한 I/O 모델은 컨테이너 환경에서도 그대로 살아남게 되었다.

이제 우리는 조금 더 큰 질문에 도달하게 된다. 왜 Unix의 이 단순한 모델은 수십 년이 지난 지금까지도 유효할까. 그리고 이 모델이 어떻게 현대 인프라의 기본 구조로 확장될 수 있었을까. 다음 섹션에서는 바로 그 질문을 중심으로 Unix I/O 모델의 확장성과 설계 철학을 조금 더 깊이 살펴보게 된다.

Unix I/O 모델의 놀라운 확장성

지금까지의 이야기를 따라오다 보면 자연스럽게 하나의 질문이 떠오른다. 왜 Unix의 I/O 모델은 이렇게 오랜 시간 동안 거의 변하지 않고 살아남을 수 있었을까. 컴퓨팅 환경은 수십 년 동안 극적으로 변화했다. 메인프레임에서 개인용 컴퓨터로, 다시 인터넷 서버와 클라우드 인프라로 확장되었다. 그럼에도 불구하고 프로그램이 stdin, stdout, stderr라는 세 개의 스트림을 통해 데이터를 주고받는 구조는 여전히 그대로 유지되고 있다. Docker와 Kubernetes의 로그 시스템 역시 이 오래된 모델을 거의 그대로 활용하고 있다.

이러한 지속성의 이유는 Unix I/O 모델이 지나치게 단순하면서도 동시에 매우 일반적인 문제를 해결하도록 설계되었기 때문이다. 프로그램은 데이터를 입력받고, 처리하고, 결과를 출력한다. 이 구조는 특정 기술이나 특정 환경에 의존하지 않는다. 파일이든 터미널이든 네트워크 소켓이든 관계없이 동일한 인터페이스로 데이터를 읽고 쓸 수 있다. 이러한 추상화 덕분에 Unix 프로그램은 다양한 환경에서 재사용될 수 있었다. 프로그램은 데이터의 출처나 목적지를 알 필요 없이 단지 스트림을 통해 데이터를 처리하면 된다.

스트림 기반 I/O 모델은 또한 데이터 흐름을 자연스럽게 연결할 수 있게 만든다. Unix에서 파이프(|)가 등장했을 때, 그것은 단순히 두 프로그램을 연결하는 기능 이상이었다. 그것은 프로그램을 데이터 처리 파이프라인의 구성 요소로 바꾸는 기능이었다. 한 프로그램의 stdout이 다른 프로그램의 stdin으로 연결되면서 프로그램들은 마치 하나의 거대한 시스템처럼 동작하게 된다. 이 모델은 이후 데이터 처리 시스템과 스트림 처리 시스템에도 영향을 미쳤다. 현대의 로그 처리 시스템이나 데이터 파이프라인 역시 기본적으로 동일한 개념을 사용한다.

이러한 관점에서 보면 Unix I/O 모델은 단순한 운영체제 기능이 아니라 데이터 흐름을 다루는 보편적인 방식이라고 볼 수 있다. 프로그램은 데이터를 입력받아 처리하고 출력한다. 그 출력은 다른 프로그램의 입력이 될 수 있다. 이 구조는 특정 시대의 기술이 아니라 거의 모든 소프트웨어 시스템에 적용될 수 있는 일반적인 모델이다. Docker 로그 구조가 stdout 기반으로 설계된 것도 바로 이 모델이 이미 검증된 방식이기 때문이다.

작은 Unix 설계가 만든 현대 인프라

Docker와 Kubernetes의 로그 시스템을 이해하면 한 가지 흥미로운 사실이 드러난다. 우리가 현대적인 클라우드 인프라라고 부르는 많은 기술들이 사실은 완전히 새로운 발명이라기보다는 기존 개념을 다른 규모에서 재사용한 결과라는 점이다. Docker가 컨테이너 프로세스의 stdout을 캡처해 로그 시스템으로 전달하는 방식은, 본질적으로 Unix에서 프로그램 출력을 파이프로 전달하는 방식과 크게 다르지 않다. 단지 연결 대상이 다른 프로그램이 아니라 로그 수집 시스템일 뿐이다.

컨테이너 플랫폼은 애플리케이션을 작은 실행 단위로 나누고, 이 단위들을 네트워크와 메시지 스트림으로 연결한다. 이 구조는 언뜻 보면 매우 복잡한 분산 시스템처럼 보이지만, 실제로는 Unix가 오래전부터 사용해 온 철학과 매우 유사하다. 프로그램은 단일 기능을 수행하고, 서로 연결되어 더 큰 시스템을 구성한다. Unix에서 grep, sort, awk 같은 도구들이 파이프로 연결되듯이, 현대의 마이크로서비스도 API나 메시지 스트림을 통해 연결된다.

컨테이너 로그 역시 같은 원리로 동작한다. 애플리케이션은 단지 stdout으로 메시지를 출력한다. 그 메시지는 컨테이너 런타임에 의해 수집되고, 이후 로그 수집 시스템을 통해 중앙 로그 플랫폼으로 전달된다. 이 과정에서 애플리케이션은 로그 저장 위치나 로그 수집 방식에 대해 전혀 알 필요가 없다. 이러한 분리는 시스템 설계에서 매우 중요한 특징이다. 애플리케이션과 운영 인프라 사이의 책임을 명확하게 분리하기 때문이다.

이러한 유사성은 우연이 아니다. Unix는 처음부터 프로그램을 작은 구성 요소로 나누고, 이들을 데이터 스트림으로 연결하는 방식으로 설계되었다. Docker와 Kubernetes 역시 동일한 철학을 다른 규모에서 적용하고 있을 뿐이다. 프로그램은 데이터를 출력하고, 시스템은 그 데이터를 전달한다. 그 단순한 모델이 수십 년 동안 계속 확장되면서 오늘날의 클라우드 인프라까지 이어진 것이다.

결론 — 50년을 살아남은 인터페이스

지금까지의 이야기를 다시 돌아보면 하나의 흐름이 보인다. 우리는 처음에 Docker 로그가 왜 stdout을 사용하는지라는 질문에서 출발했다. 그리고 그 질문을 따라가다 보니 결국 Unix I/O 모델로 돌아오게 되었다. Docker 로그 구조는 새로운 로그 시스템이라기보다 Unix의 표준 출력 모델을 플랫폼 수준에서 확장한 것에 가깝다. 프로그램이 stdout으로 데이터를 출력하고 시스템이 그 데이터를 처리하는 방식은 이미 1970년대에 등장한 개념이다.

이 구조가 오늘날까지 살아남은 이유는 단순하다. 그것이 충분히 일반적인 문제를 해결하는 방식이기 때문이다. 프로그램은 입력을 받고 결과를 출력한다. 시스템은 그 출력이 어디로 전달될지 결정한다. 이러한 역할 분리는 시간이 지나도 쉽게 깨지지 않는다. 오히려 새로운 기술이 등장할수록 이 단순한 인터페이스는 더욱 강력한 도구가 된다. Docker 로그 시스템 역시 이러한 단순한 인터페이스 덕분에 복잡한 분산 환경에서도 자연스럽게 작동할 수 있다.

Unix 설계자들은 프로그램이 데이터를 출력하는 방법만 정의했다. 그 데이터가 어떻게 사용될지는 시스템과 사용자가 결정하도록 남겨 두었다. 이러한 설계는 놀라울 정도로 유연했다. stdout은 파일로 저장될 수도 있고, 다른 프로그램으로 전달될 수도 있으며, 네트워크를 통해 다른 시스템으로 전송될 수도 있다. 그리고 이제는 컨테이너 플랫폼이 그 stdout을 로그 시스템으로 전달한다.

이 시리즈의 처음에서 우리는 2>&1이라는 작은 셸 문장에서 출발했다. 그 문장은 stdout과 stderr라는 개념을 이해하는 단서였다. 이후 파이프와 프로세스 I/O 모델을 살펴보면서 Unix가 어떻게 프로그램을 연결 가능한 도구로 만들었는지 확인했다. 그리고 마지막으로 Docker 로그 구조를 통해 그 설계가 현대 클라우드 인프라에서도 여전히 사용되고 있다는 사실을 보았다. 결국 우리는 하나의 결론에 도달하게 된다.

Unix의 작은 인터페이스들은 단순했지만, 그 단순함 덕분에 수십 년 동안 확장될 수 있었다. 우리가 오늘날 사용하는 많은 시스템은 겉보기에는 완전히 새로운 기술처럼 보이지만, 그 안을 들여다보면 여전히 오래된 Unix 설계 철학이 흐르고 있다. 그리고 stdout이라는 아주 작은 개념 역시 그 철학의 일부로서 지금까지 살아남아 있다.